[clang] 9ece3eb - [clang][Interp] Check ConstantExpr results for initialization
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Fri Jun 7 04:30:08 PDT 2024
Author: Timm Bäder
Date: 2024-06-07T13:29:23+02:00
New Revision: 9ece3eb1459309f9fbd18ce8ec8f771c238e8815
URL: https://github.com/llvm/llvm-project/commit/9ece3eb1459309f9fbd18ce8ec8f771c238e8815
DIFF: https://github.com/llvm/llvm-project/commit/9ece3eb1459309f9fbd18ce8ec8f771c238e8815.diff
LOG: [clang][Interp] Check ConstantExpr results for initialization
They need to be fully initialized, similar to global variables.
Added:
Modified:
clang/lib/AST/Interp/EvalEmitter.cpp
clang/lib/AST/Interp/EvaluationResult.cpp
clang/test/AST/Interp/cxx20.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/EvalEmitter.cpp b/clang/lib/AST/Interp/EvalEmitter.cpp
index 6d8aa3f20f01f..f6191d8ed6345 100644
--- a/clang/lib/AST/Interp/EvalEmitter.cpp
+++ b/clang/lib/AST/Interp/EvalEmitter.cpp
@@ -41,6 +41,7 @@ EvaluationResult EvalEmitter::interpretExpr(const Expr *E,
bool ConvertResultToRValue) {
S.setEvalLocation(E->getExprLoc());
this->ConvertResultToRValue = ConvertResultToRValue;
+ this->CheckFullyInitialized = isa<ConstantExpr>(E);
EvalResult.setSource(E);
if (!this->visitExpr(E)) {
@@ -175,6 +176,10 @@ bool EvalEmitter::emitRetVoid(const SourceInfo &Info) {
bool EvalEmitter::emitRetValue(const SourceInfo &Info) {
const auto &Ptr = S.Stk.pop<Pointer>();
+
+ if (CheckFullyInitialized && !EvalResult.checkFullyInitialized(S, Ptr))
+ return false;
+
if (std::optional<APValue> APV = Ptr.toRValue(S.getCtx())) {
EvalResult.setValue(*APV);
return true;
diff --git a/clang/lib/AST/Interp/EvaluationResult.cpp b/clang/lib/AST/Interp/EvaluationResult.cpp
index c04b0fc0a1121..29977232975fc 100644
--- a/clang/lib/AST/Interp/EvaluationResult.cpp
+++ b/clang/lib/AST/Interp/EvaluationResult.cpp
@@ -141,16 +141,14 @@ bool EvaluationResult::checkFullyInitialized(InterpState &S,
const Pointer &Ptr) const {
assert(Source);
assert(empty());
-
- // Our Source must be a VarDecl.
- const Decl *SourceDecl = Source.dyn_cast<const Decl *>();
- assert(SourceDecl);
- const auto *VD = cast<VarDecl>(SourceDecl);
- assert(VD->getType()->isRecordType() || VD->getType()->isArrayType());
- SourceLocation InitLoc = VD->getAnyInitializer()->getExprLoc();
-
assert(!Ptr.isZero());
+ SourceLocation InitLoc;
+ if (const auto *D = Source.dyn_cast<const Decl *>())
+ InitLoc = cast<VarDecl>(D)->getAnyInitializer()->getExprLoc();
+ else if (const auto *E = Source.dyn_cast<const Expr *>())
+ InitLoc = E->getExprLoc();
+
if (const Record *R = Ptr.getRecord())
return CheckFieldsInitialized(S, InitLoc, Ptr, R);
const auto *CAT =
diff --git a/clang/test/AST/Interp/cxx20.cpp b/clang/test/AST/Interp/cxx20.cpp
index c750be866ca7c..434823644a7a3 100644
--- a/clang/test/AST/Interp/cxx20.cpp
+++ b/clang/test/AST/Interp/cxx20.cpp
@@ -797,3 +797,20 @@ namespace self_referencing {
S s(1);
}
}
+
+namespace GH64949 {
+ struct f {
+ int g; // both-note {{subobject declared here}}
+ constexpr ~f() {}
+ };
+
+ class h {
+ public:
+ consteval h(char *) {}
+ f i;
+ };
+
+ void test() { h{nullptr}; } // both-error {{call to consteval function 'GH64949::h::h' is not a constant expression}} \
+ // both-note {{subobject 'g' is not initialized}} \
+ // both-warning {{expression result unused}}
+}
More information about the cfe-commits
mailing list