Author: Timm Bäder Date: 2024-06-18T08:30:43+02:00 New Revision: 2d38becda8afa48a031995d67ebf9a6383e01e4f
URL: https://github.com/llvm/llvm-project/commit/2d38becda8afa48a031995d67ebf9a6383e01e4f DIFF: https://github.com/llvm/llvm-project/commit/2d38becda8afa48a031995d67ebf9a6383e01e4f.diff LOG: [clang][Interp][NFC] Don't create variables in non-constant contexts When the evaluation in a contant context fails, we would otherwise try to access and use that variable later in a (maybe) non-constant context. If the evaluation succeeds in the non-constant context, we never reported success because we reported failure from the first time we visited the variable. Added: Modified: clang/lib/AST/Interp/ByteCodeEmitter.h clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/ByteCodeExprGen.h clang/lib/AST/Interp/EvalEmitter.cpp clang/lib/AST/Interp/EvalEmitter.h clang/lib/AST/Interp/EvaluationResult.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.h b/clang/lib/AST/Interp/ByteCodeEmitter.h index 5612a8c1481a7..d797a0ab4a1c9 100644 --- a/clang/lib/AST/Interp/ByteCodeEmitter.h +++ b/clang/lib/AST/Interp/ByteCodeEmitter.h @@ -46,7 +46,7 @@ class ByteCodeEmitter { /// Methods implemented by the compiler. virtual bool visitFunc(const FunctionDecl *E) = 0; virtual bool visitExpr(const Expr *E) = 0; - virtual bool visitDecl(const VarDecl *E) = 0; + virtual bool visitDecl(const VarDecl *E, bool ConstantContext) = 0; /// Emits jumps. bool jumpTrue(const LabelTy &Label); diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 6ffa91d81d0e1..e65b2fc7ac233 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -3223,9 +3223,21 @@ bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *E) { /// We get here from evaluateAsInitializer(). /// We need to evaluate the initializer and return its value. template <class Emitter> -bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) { +bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD, + bool ConstantContext) { assert(!VD->isInvalidDecl() && "Trying to constant evaluate an invalid decl"); + std::optional<PrimType> VarT = classify(VD->getType()); + + // We only create variables if we're evaluating in a constant context. + // Otherwise, just evaluate the initializer and return it. + if (!ConstantContext) { + DeclScope<Emitter> LocalScope(this, VD); + if (!this->visit(VD->getAnyInitializer())) + return false; + return this->emitRet(VarT.value_or(PT_Ptr), VD); + } + // If we've seen the global variable already and the initializer failed, // just return false immediately. if (std::optional<unsigned> Index = P.getGlobal(VD)) { @@ -3241,7 +3253,6 @@ bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) { if (!this->visitVarDecl(VD)) return false; - std::optional<PrimType> VarT = classify(VD->getType()); // Get a pointer to the variable if (Context::shouldBeGloballyIndexed(VD)) { auto GlobalIndex = P.getGlobal(VD); diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index b0faac8020fb2..19cbbc432e4b1 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -133,7 +133,7 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>, protected: bool visitExpr(const Expr *E) override; - bool visitDecl(const VarDecl *VD) override; + bool visitDecl(const VarDecl *VD, bool ConstantContext) override; protected: /// Emits scope cleanup instructions. diff --git a/clang/lib/AST/Interp/EvalEmitter.cpp b/clang/lib/AST/Interp/EvalEmitter.cpp index 025b46b3d7886..77ff901634a46 100644 --- a/clang/lib/AST/Interp/EvalEmitter.cpp +++ b/clang/lib/AST/Interp/EvalEmitter.cpp @@ -66,7 +66,7 @@ EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD, EvalResult.setSource(VD); - if (!this->visitDecl(VD) && EvalResult.empty()) + if (!this->visitDecl(VD, S.inConstantContext()) && EvalResult.empty()) EvalResult.setInvalid(); return std::move(this->EvalResult); diff --git a/clang/lib/AST/Interp/EvalEmitter.h b/clang/lib/AST/Interp/EvalEmitter.h index 98d6026bbcce4..68accbc5214c2 100644 --- a/clang/lib/AST/Interp/EvalEmitter.h +++ b/clang/lib/AST/Interp/EvalEmitter.h @@ -55,7 +55,7 @@ class EvalEmitter : public SourceMapper { /// Methods implemented by the compiler. virtual bool visitExpr(const Expr *E) = 0; - virtual bool visitDecl(const VarDecl *VD) = 0; + virtual bool visitDecl(const VarDecl *VD, bool ConstantContext) = 0; /// Emits jumps. bool jumpTrue(const LabelTy &Label); diff --git a/clang/lib/AST/Interp/EvaluationResult.cpp b/clang/lib/AST/Interp/EvaluationResult.cpp index 395e3f5b4348d..a62f3f635e6e0 100644 --- a/clang/lib/AST/Interp/EvaluationResult.cpp +++ b/clang/lib/AST/Interp/EvaluationResult.cpp @@ -124,9 +124,16 @@ static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc, for (const Record::Base &B : R->bases()) { Pointer P = BasePtr.atField(B.Offset); if (!P.isInitialized()) { - S.FFDiag(BasePtr.getDeclDesc()->asDecl()->getLocation(), - diag::note_constexpr_uninitialized_base) - << B.Desc->getType(); + const Descriptor *Desc = BasePtr.getDeclDesc(); + if (Desc->asDecl()) + S.FFDiag(BasePtr.getDeclDesc()->asDecl()->getLocation(), + diag::note_constexpr_uninitialized_base) + << B.Desc->getType(); + else + S.FFDiag(BasePtr.getDeclDesc()->asExpr()->getExprLoc(), + diag::note_constexpr_uninitialized_base) + << B.Desc->getType(); + return false; } Result &= CheckFieldsInitialized(S, Loc, P, B.R); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits