Author: Timm Bäder Date: 2023-03-02T09:13:47+01:00 New Revision: 569222e172e5d28d66e9607325475b107cee20cb
URL: https://github.com/llvm/llvm-project/commit/569222e172e5d28d66e9607325475b107cee20cb DIFF: https://github.com/llvm/llvm-project/commit/569222e172e5d28d66e9607325475b107cee20cb.diff LOG: [clang][Interp] Only check constructors for global variables Local variables may be partially initialized. Differential Revision: https://reviews.llvm.org/D140723 Added: Modified: clang/lib/AST/Interp/ByteCodeExprGen.h clang/lib/AST/Interp/Interp.cpp clang/lib/AST/Interp/Interp.h clang/lib/AST/Interp/Opcodes.td clang/test/AST/Interp/cxx20.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 7b804b4cad3d..231f39ff8bd6 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -162,6 +162,9 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>, if (!visitInitializer(Init)) return false; + if (Init->getType()->isRecordType() && !this->emitCheckGlobalCtor(Init)) + return false; + return this->emitPopPtr(Init); } diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index 329cc0ff949d..554e9a8e2d20 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -431,6 +431,15 @@ static bool CheckFieldsInitialized(InterpState &S, CodePtr OpPC, 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; } diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 99c1bd58acd2..fbf74b54e330 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -1455,6 +1455,11 @@ inline bool ExpandPtr(InterpState &S, CodePtr OpPC) { 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; @@ -1480,11 +1485,6 @@ inline bool Call(InterpState &S, CodePtr &PC, const Function *Func) { 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; } diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td index d1ad7adc1edc..1e325055c417 100644 --- a/clang/lib/AST/Interp/Opcodes.td +++ b/clang/lib/AST/Interp/Opcodes.td @@ -328,6 +328,8 @@ def GetLocal : AccessOpcode { let HasCustomEval = 1; } // [] -> [Pointer] def SetLocal : AccessOpcode { let HasCustomEval = 1; } +def CheckGlobalCtor : Opcode {} + // [] -> [Value] def GetGlobal : AccessOpcode; // [Value] -> [] diff --git a/clang/test/AST/Interp/cxx20.cpp b/clang/test/AST/Interp/cxx20.cpp index 44c97dd1afcd..cc37722730fc 100644 --- a/clang/test/AST/Interp/cxx20.cpp +++ b/clang/test/AST/Interp/cxx20.cpp @@ -85,10 +85,11 @@ static_assert(initializedLocal2() == 20); // expected-error {{not an integral co // ref-note {{in call to}} -struct Int { int a; }; // expected-note {{subobject declared here}} +struct Int { int a; }; constexpr int initializedLocal3() { - Int i; // expected-note {{subobject of type 'int' is not initialized}} - return i.a; // ref-note {{read of uninitialized object is not allowed in a constant expression}} + Int i; + return i.a; // ref-note {{read of uninitialized object is not allowed in a constant expression}} \ + // expected-note {{read of object outside its lifetime}} } static_assert(initializedLocal3() == 20); // expected-error {{not an integral constant expression}} \ // expected-note {{in call to}} \ @@ -157,21 +158,19 @@ namespace UninitializedFields { 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}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits