This happens only in error cases, but we need to handle it anyway.
Differential Revision: https://reviews.llvm.org/D136831
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();
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.
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;
}
// 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.
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;