[clang] 569222e - [clang][Interp] Only check constructors for global variables
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 2 00:23:47 PST 2023
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}}
More information about the cfe-commits
mailing list