summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimm Bäder <tbaeder@redhat.com>2024-02-18 08:12:13 +0100
committerTimm Bäder <tbaeder@redhat.com>2024-02-18 18:07:29 +0100
commit41364051ac9380a6b62f61c794fc5978b2e703c9 (patch)
tree9feda07e1cf60f94cd064c4c8ec2a9c710e69df0
parent54daf6af57fb15d7a51e3f4bb889199fd1453bee (diff)
[clang][Interp] Not all record bases are of RecordType
See the attached test case.
-rw-r--r--clang/lib/AST/Interp/Program.cpp41
-rw-r--r--clang/test/AST/Interp/crash-GH49103-2.cpp13
2 files changed, 38 insertions, 16 deletions
diff --git a/clang/lib/AST/Interp/Program.cpp b/clang/lib/AST/Interp/Program.cpp
index 964c0377c6dc..5624d5955c04 100644
--- a/clang/lib/AST/Interp/Program.cpp
+++ b/clang/lib/AST/Interp/Program.cpp
@@ -247,7 +247,8 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
unsigned VirtSize = 0;
// Helper to get a base descriptor.
- auto GetBaseDesc = [this](const RecordDecl *BD, Record *BR) -> Descriptor * {
+ auto GetBaseDesc = [this](const RecordDecl *BD,
+ const Record *BR) -> Descriptor * {
if (!BR)
return nullptr;
return allocateDescriptor(BD, BR, std::nullopt, /*isConst=*/false,
@@ -258,31 +259,39 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
// Reserve space for base classes.
Record::BaseList Bases;
Record::VirtualBaseList VirtBases;
- if (auto *CD = dyn_cast<CXXRecordDecl>(RD)) {
+ if (const auto *CD = dyn_cast<CXXRecordDecl>(RD)) {
+
for (const CXXBaseSpecifier &Spec : CD->bases()) {
if (Spec.isVirtual())
continue;
- const RecordDecl *BD = Spec.getType()->castAs<RecordType>()->getDecl();
- Record *BR = getOrCreateRecord(BD);
- if (Descriptor *Desc = GetBaseDesc(BD, BR)) {
- BaseSize += align(sizeof(InlineDescriptor));
- Bases.push_back({BD, BaseSize, Desc, BR});
- BaseSize += align(BR->getSize());
- continue;
+ // In error cases, the base might not be a RecordType.
+ if (const auto *RT = Spec.getType()->getAs<RecordType>()) {
+ const RecordDecl *BD = RT->getDecl();
+
+ Record *BR = getOrCreateRecord(BD);
+ if (Descriptor *Desc = GetBaseDesc(BD, BR)) {
+ BaseSize += align(sizeof(InlineDescriptor));
+ Bases.push_back({BD, BaseSize, Desc, BR});
+ BaseSize += align(BR->getSize());
+ continue;
+ }
}
return nullptr;
}
for (const CXXBaseSpecifier &Spec : CD->vbases()) {
- const RecordDecl *BD = Spec.getType()->castAs<RecordType>()->getDecl();
- Record *BR = getOrCreateRecord(BD);
- if (Descriptor *Desc = GetBaseDesc(BD, BR)) {
- VirtSize += align(sizeof(InlineDescriptor));
- VirtBases.push_back({BD, VirtSize, Desc, BR});
- VirtSize += align(BR->getSize());
- continue;
+ if (const auto *RT = Spec.getType()->getAs<RecordType>()) {
+ const RecordDecl *BD = RT->getDecl();
+ Record *BR = getOrCreateRecord(BD);
+
+ if (Descriptor *Desc = GetBaseDesc(BD, BR)) {
+ VirtSize += align(sizeof(InlineDescriptor));
+ VirtBases.push_back({BD, VirtSize, Desc, BR});
+ VirtSize += align(BR->getSize());
+ continue;
+ }
}
return nullptr;
}
diff --git a/clang/test/AST/Interp/crash-GH49103-2.cpp b/clang/test/AST/Interp/crash-GH49103-2.cpp
new file mode 100644
index 000000000000..82d78e2aeab0
--- /dev/null
+++ b/clang/test/AST/Interp/crash-GH49103-2.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -verify -std=c++98 %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -verify -std=c++11 %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -verify -std=c++14 %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -verify -std=c++17 %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -verify -std=c++20 %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -verify -std=c++23 %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -verify -std=c++2c %s -fexperimental-new-constant-interpreter
+
+// https://github.com/llvm/llvm-project/issues/49103
+
+template<class> struct A; // expected-note 0+ {{}}
+struct S : __make_integer_seq<A, int, 42> { }; // expected-error 0+ {{}}
+S s;