[clang] 2d38bec - [clang][Interp][NFC] Don't create variables in non-constant contexts
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 17 23:30:57 PDT 2024
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);
More information about the cfe-commits
mailing list