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}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits