Index: clang/lib/AST/Interp/ByteCodeStmtGen.cpp =================================================================== --- clang/lib/AST/Interp/ByteCodeStmtGen.cpp +++ clang/lib/AST/Interp/ByteCodeStmtGen.cpp @@ -98,7 +98,8 @@ if (const auto Ctor = dyn_cast(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(); Index: clang/lib/AST/Interp/Program.h =================================================================== --- clang/lib/AST/Interp/Program.h +++ clang/lib/AST/Interp/Program.h @@ -45,8 +45,10 @@ // 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(); + } // Manually destroy all the blocks. They are almost all harmless, // but primitive arrays might have an InitMap* heap allocated and Index: clang/lib/AST/Interp/Program.cpp =================================================================== --- clang/lib/AST/Interp/Program.cpp +++ clang/lib/AST/Interp/Program.cpp @@ -224,6 +224,11 @@ 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. @@ -298,7 +303,7 @@ 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; } Index: clang/test/AST/Interp/records.cpp =================================================================== --- clang/test/AST/Interp/records.cpp +++ clang/test/AST/Interp/records.cpp @@ -133,6 +133,19 @@ 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 int locals() { C c; c.a = 10;