[clang][Interp] Protect Record creation against infinite recursion
This happens only in error cases, but we need to handle it anyway. Differential Revision: https://reviews.llvm.org/D136831
This commit is contained in:
parent
0dcfd0ce02
commit
99d3ead44c
|
@ -98,7 +98,8 @@ bool ByteCodeStmtGen<Emitter>::visitFunc(const FunctionDecl *F) {
|
|||
if (const auto Ctor = dyn_cast<CXXConstructorDecl>(F)) {
|
||||
const RecordDecl *RD = Ctor->getParent();
|
||||
const Record *R = this->getRecord(RD);
|
||||
assert(R);
|
||||
if (!R)
|
||||
return false;
|
||||
|
||||
for (const auto *Init : Ctor->inits()) {
|
||||
const Expr *InitExpr = Init->getInit();
|
||||
|
|
|
@ -221,6 +221,11 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
|
|||
return It->second;
|
||||
}
|
||||
|
||||
// We insert nullptr now and replace that later, so recursive calls
|
||||
// to this function with the same RecordDecl don't run into
|
||||
// infinite recursion.
|
||||
Records.insert({RD, nullptr});
|
||||
|
||||
// Number of bytes required by fields and base classes.
|
||||
unsigned BaseSize = 0;
|
||||
// Number of bytes required by virtual base.
|
||||
|
@ -294,7 +299,7 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
|
|||
|
||||
Record *R = new (Allocator) Record(RD, std::move(Bases), std::move(Fields),
|
||||
std::move(VirtBases), VirtSize, BaseSize);
|
||||
Records.insert({RD, R});
|
||||
Records[RD] = R;
|
||||
return R;
|
||||
}
|
||||
|
||||
|
|
|
@ -51,8 +51,10 @@ public:
|
|||
// Records might actually allocate memory themselves, but they
|
||||
// are allocated using a BumpPtrAllocator. Call their desctructors
|
||||
// here manually so they are properly freeing their resources.
|
||||
for (auto RecordPair : Records)
|
||||
RecordPair.second->~Record();
|
||||
for (auto RecordPair : Records) {
|
||||
if (Record *R = RecordPair.second)
|
||||
R->~Record();
|
||||
}
|
||||
}
|
||||
|
||||
/// Marshals a native pointer to an ID for embedding in bytecode.
|
||||
|
|
|
@ -133,6 +133,20 @@ constexpr C RVOAndParams(const C *c) {
|
|||
constexpr C RVOAndParamsResult = RVOAndParams(&c);
|
||||
#endif
|
||||
|
||||
class Bar { // expected-note {{definition of 'Bar' is not complete}} \
|
||||
// ref-note {{definition of 'Bar' is not complete}}
|
||||
public:
|
||||
constexpr Bar(){}
|
||||
constexpr Bar b; // expected-error {{cannot be constexpr}} \
|
||||
// expected-error {{has incomplete type 'const Bar'}} \
|
||||
// ref-error {{cannot be constexpr}} \
|
||||
// ref-error {{has incomplete type 'const Bar'}}
|
||||
};
|
||||
constexpr Bar B; // expected-error {{must be initialized by a constant expression}} \
|
||||
// expected-error {{failed to evaluate an expression}} \
|
||||
// ref-error {{must be initialized by a constant expression}}
|
||||
constexpr Bar *pb = nullptr;
|
||||
|
||||
constexpr int locals() {
|
||||
C c;
|
||||
c.a = 10;
|
||||
|
|
Loading…
Reference in New Issue