Index: clang/lib/AST/Interp/ByteCodeExprGen.h =================================================================== --- clang/lib/AST/Interp/ByteCodeExprGen.h +++ clang/lib/AST/Interp/ByteCodeExprGen.h @@ -177,6 +177,9 @@ if (!visitInitializer(Init)) return false; + if (Init->getType()->isRecordType() && !this->emitCheckGlobalCtor(Init)) + return false; + return this->emitPopPtr(Init); } Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -1365,6 +1365,11 @@ return true; } +inline bool CheckGlobalCtor(InterpState &S, CodePtr &PC) { + const Pointer &Obj = S.Stk.peek<Pointer>(); + return CheckCtorCall(S, PC, Obj); +} + inline bool Call(InterpState &S, CodePtr &PC, const Function *Func) { auto NewFrame = std::make_unique<InterpFrame>(S, Func, PC); Pointer ThisPtr; @@ -1388,11 +1393,6 @@ if (Interpret(S, CallResult)) { NewFrame.release(); // Frame was delete'd already. assert(S.Current == FrameBefore); - - // For constructors, check that all fields have been initialized. - if (Func->isConstructor() && !CheckCtorCall(S, PC, ThisPtr)) - return false; - return true; } Index: clang/lib/AST/Interp/Interp.cpp =================================================================== --- clang/lib/AST/Interp/Interp.cpp +++ clang/lib/AST/Interp/Interp.cpp @@ -512,6 +512,15 @@ Result = false; } } + + // Check Fields in all bases + for (const Record::Base &B : R->bases()) { + Pointer P = Pointer(BasePtr.block(), B.Offset); + Result &= CheckFieldsInitialized(S, OpPC, P, B.R); + } + + // TODO: Virtual bases + return Result; } Index: clang/lib/AST/Interp/Opcodes.td =================================================================== --- clang/lib/AST/Interp/Opcodes.td +++ clang/lib/AST/Interp/Opcodes.td @@ -322,6 +322,8 @@ // [] -> [Pointer] def SetLocal : AccessOpcode { let HasCustomEval = 1; } +def CheckGlobalCtor : Opcode {} + // [] -> [Value] def GetGlobal : AccessOpcode; // [Value] -> [] Index: clang/test/AST/Interp/cxx20.cpp =================================================================== --- clang/test/AST/Interp/cxx20.cpp +++ clang/test/AST/Interp/cxx20.cpp @@ -158,21 +158,19 @@ class Derived : public Base { public: - constexpr Derived() : Base() {} // expected-note {{subobject of type 'int' is not initialized}} - }; + constexpr Derived() : Base() {} }; -constexpr Derived D; // expected-error {{must be initialized by a constant expression}} \\ - // expected-note {{in call to 'Derived()'}} \ - // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{subobject of type 'int' is not initialized}} + constexpr Derived D; // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{subobject of type 'int' is not initialized}} \ + // ref-error {{must be initialized by a constant expression}} \ + // ref-note {{subobject of type 'int' is not initialized}} class C2 { public: A a; - constexpr C2() {} // expected-note {{subobject of type 'int' is not initialized}} - }; + constexpr C2() {} }; constexpr C2 c2; // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{in call to 'C2()'}} \ + // expected-note {{subobject of type 'int' is not initialized}} \ // ref-error {{must be initialized by a constant expression}} \ // ref-note {{subobject of type 'int' is not initialized}}