diff options
author | Timm Bäder <tbaeder@redhat.com> | 2024-02-18 08:12:13 +0100 |
---|---|---|
committer | Timm Bäder <tbaeder@redhat.com> | 2024-02-18 18:07:29 +0100 |
commit | 41364051ac9380a6b62f61c794fc5978b2e703c9 (patch) | |
tree | 9feda07e1cf60f94cd064c4c8ec2a9c710e69df0 | |
parent | 54daf6af57fb15d7a51e3f4bb889199fd1453bee (diff) |
[clang][Interp] Not all record bases are of RecordType
See the attached test case.
-rw-r--r-- | clang/lib/AST/Interp/Program.cpp | 41 | ||||
-rw-r--r-- | clang/test/AST/Interp/crash-GH49103-2.cpp | 13 |
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; |