[clang] [clang][bytecode] Pass initializer along in `evaluateAsInitializer()` (PR #158056)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 11 05:24:08 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Timm Baeder (tbaederr)
<details>
<summary>Changes</summary>
We just called `getInit()`, which isn't always correct and used the wrong initializer in the module test case.
---
Full diff: https://github.com/llvm/llvm-project/pull/158056.diff
9 Files Affected:
- (modified) clang/lib/AST/ByteCode/ByteCodeEmitter.h (+2-1)
- (modified) clang/lib/AST/ByteCode/Compiler.cpp (+10-11)
- (modified) clang/lib/AST/ByteCode/Compiler.h (+4-2)
- (modified) clang/lib/AST/ByteCode/Context.cpp (+1-1)
- (modified) clang/lib/AST/ByteCode/Context.h (+2-1)
- (modified) clang/lib/AST/ByteCode/EvalEmitter.cpp (+4-3)
- (modified) clang/lib/AST/ByteCode/EvalEmitter.h (+4-2)
- (modified) clang/lib/AST/ExprConstant.cpp (+1-1)
- (modified) clang/test/Modules/added-visible-decls.cppm (+1)
``````````diff
diff --git a/clang/lib/AST/ByteCode/ByteCodeEmitter.h b/clang/lib/AST/ByteCode/ByteCodeEmitter.h
index d29db66325412..c050b299d8f61 100644
--- a/clang/lib/AST/ByteCode/ByteCodeEmitter.h
+++ b/clang/lib/AST/ByteCode/ByteCodeEmitter.h
@@ -46,7 +46,8 @@ class ByteCodeEmitter {
/// Methods implemented by the compiler.
virtual bool visitFunc(const FunctionDecl *E) = 0;
virtual bool visitExpr(const Expr *E, bool DestroyToplevelScope) = 0;
- virtual bool visitDeclAndReturn(const VarDecl *E, bool ConstantContext) = 0;
+ virtual bool visitDeclAndReturn(const VarDecl *VD, const Expr *Init,
+ bool ConstantContext) = 0;
virtual bool visit(const Expr *E) = 0;
virtual bool emitBool(bool V, const Expr *E) = 0;
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 3f7db39281358..78b74acc3789d 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -4714,7 +4714,8 @@ template <class Emitter>
VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD,
bool IsConstexprUnknown) {
- auto R = this->visitVarDecl(VD, /*Toplevel=*/true, IsConstexprUnknown);
+ auto R = this->visitVarDecl(VD, VD->getInit(), /*Toplevel=*/true,
+ IsConstexprUnknown);
if (R.notCreated())
return R;
@@ -4740,14 +4741,12 @@ VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD,
/// We get here from evaluateAsInitializer().
/// We need to evaluate the initializer and return its value.
template <class Emitter>
-bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD,
+bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD, const Expr *Init,
bool ConstantContext) {
-
// We only create variables if we're evaluating in a constant context.
// Otherwise, just evaluate the initializer and return it.
if (!ConstantContext) {
DeclScope<Emitter> LS(this, VD);
- const Expr *Init = VD->getInit();
if (!this->visit(Init))
return false;
return this->emitRet(classify(Init).value_or(PT_Ptr), VD) &&
@@ -4755,7 +4754,7 @@ bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD,
}
LocalScope<Emitter> VDScope(this, VD);
- if (!this->visitVarDecl(VD, /*Toplevel=*/true))
+ if (!this->visitVarDecl(VD, Init, /*Toplevel=*/true))
return false;
OptPrimType VarT = classify(VD->getType());
@@ -4802,9 +4801,9 @@ bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD,
}
template <class Emitter>
-VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
- bool Toplevel,
- bool IsConstexprUnknown) {
+VarCreationState
+Compiler<Emitter>::visitVarDecl(const VarDecl *VD, const Expr *Init,
+ bool Toplevel, bool IsConstexprUnknown) {
// We don't know what to do with these, so just return false.
if (VD->getType().isNull())
return false;
@@ -4814,7 +4813,6 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
if (!this->isActive())
return VarCreationState::NotCreated();
- const Expr *Init = VD->getInit();
OptPrimType VarT = classify(VD->getType());
if (Init && Init->isValueDependent())
@@ -5488,7 +5486,8 @@ template <class Emitter>
bool Compiler<Emitter>::maybeEmitDeferredVarInit(const VarDecl *VD) {
if (auto *DD = dyn_cast_if_present<DecompositionDecl>(VD)) {
for (auto *BD : DD->flat_bindings())
- if (auto *KD = BD->getHoldingVar(); KD && !this->visitVarDecl(KD))
+ if (auto *KD = BD->getHoldingVar();
+ KD && !this->visitVarDecl(KD, KD->getInit()))
return false;
}
return true;
@@ -5552,7 +5551,7 @@ bool Compiler<Emitter>::visitDeclStmt(const DeclStmt *DS,
const auto *VD = dyn_cast<VarDecl>(D);
if (!VD)
return false;
- if (!this->visitVarDecl(VD))
+ if (!this->visitVarDecl(VD, VD->getInit()))
return false;
// Register decomposition decl holding vars.
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index c97dc18656ce4..5f392964c076a 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -251,7 +251,8 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
bool visitExpr(const Expr *E, bool DestroyToplevelScope) override;
bool visitFunc(const FunctionDecl *F) override;
- bool visitDeclAndReturn(const VarDecl *VD, bool ConstantContext) override;
+ bool visitDeclAndReturn(const VarDecl *VD, const Expr *Init,
+ bool ConstantContext) override;
protected:
/// Emits scope cleanup instructions.
@@ -303,7 +304,8 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
/// intact.
bool delegate(const Expr *E);
/// Creates and initializes a variable from the given decl.
- VarCreationState visitVarDecl(const VarDecl *VD, bool Toplevel = false,
+ VarCreationState visitVarDecl(const VarDecl *VD, const Expr *Init,
+ bool Toplevel = false,
bool IsConstexprUnknown = false);
VarCreationState visitDecl(const VarDecl *VD,
bool IsConstexprUnknown = false);
diff --git a/clang/lib/AST/ByteCode/Context.cpp b/clang/lib/AST/ByteCode/Context.cpp
index 8598996681466..de3191bfcff55 100644
--- a/clang/lib/AST/ByteCode/Context.cpp
+++ b/clang/lib/AST/ByteCode/Context.cpp
@@ -135,7 +135,7 @@ bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
bool CheckGlobalInitialized =
shouldBeGloballyIndexed(VD) &&
(VD->getType()->isRecordType() || VD->getType()->isArrayType());
- auto Res = C.interpretDecl(VD, CheckGlobalInitialized);
+ auto Res = C.interpretDecl(VD, Init, CheckGlobalInitialized);
if (Res.isInvalid()) {
C.cleanup();
Stk.clearTo(StackSizeBefore);
diff --git a/clang/lib/AST/ByteCode/Context.h b/clang/lib/AST/ByteCode/Context.h
index fa98498dbe8fa..280a31725555f 100644
--- a/clang/lib/AST/ByteCode/Context.h
+++ b/clang/lib/AST/ByteCode/Context.h
@@ -59,7 +59,8 @@ class Context final {
ConstantExprKind Kind);
/// Evaluates a toplevel initializer.
- bool evaluateAsInitializer(State &Parent, const VarDecl *VD, APValue &Result);
+ bool evaluateAsInitializer(State &Parent, const VarDecl *VD, const Expr *Init,
+ APValue &Result);
bool evaluateCharRange(State &Parent, const Expr *SizeExpr,
const Expr *PtrExpr, APValue &Result);
diff --git a/clang/lib/AST/ByteCode/EvalEmitter.cpp b/clang/lib/AST/ByteCode/EvalEmitter.cpp
index e349397078aa3..1d73f0e247aa2 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.cpp
+++ b/clang/lib/AST/ByteCode/EvalEmitter.cpp
@@ -49,14 +49,15 @@ EvaluationResult EvalEmitter::interpretExpr(const Expr *E,
return std::move(this->EvalResult);
}
-EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD,
+EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD, const Expr *Init,
bool CheckFullyInitialized) {
this->CheckFullyInitialized = CheckFullyInitialized;
S.EvaluatingDecl = VD;
S.setEvalLocation(VD->getLocation());
EvalResult.setSource(VD);
- if (const Expr *Init = VD->getAnyInitializer()) {
+ // FIXME: I think Init is never null.
+ if (Init) {
QualType T = VD->getType();
this->ConvertResultToRValue = !Init->isGLValue() && !T->isPointerType() &&
!T->isObjCObjectPointerType();
@@ -65,7 +66,7 @@ EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD,
EvalResult.setSource(VD);
- if (!this->visitDeclAndReturn(VD, S.inConstantContext()))
+ if (!this->visitDeclAndReturn(VD, Init, S.inConstantContext()))
EvalResult.setInvalid();
S.EvaluatingDecl = nullptr;
diff --git a/clang/lib/AST/ByteCode/EvalEmitter.h b/clang/lib/AST/ByteCode/EvalEmitter.h
index 85a0a99fbb4b0..e81ea67adf97a 100644
--- a/clang/lib/AST/ByteCode/EvalEmitter.h
+++ b/clang/lib/AST/ByteCode/EvalEmitter.h
@@ -37,7 +37,8 @@ class EvalEmitter : public SourceMapper {
EvaluationResult interpretExpr(const Expr *E,
bool ConvertResultToRValue = false,
bool DestroyToplevelScope = false);
- EvaluationResult interpretDecl(const VarDecl *VD, bool CheckFullyInitialized);
+ EvaluationResult interpretDecl(const VarDecl *VD, const Expr *Init,
+ bool CheckFullyInitialized);
/// Interpret the given Expr to a Pointer.
EvaluationResult interpretAsPointer(const Expr *E, PtrCallback PtrCB);
/// Interpret the given expression as if it was in the body of the given
@@ -59,7 +60,8 @@ class EvalEmitter : public SourceMapper {
/// Methods implemented by the compiler.
virtual bool visitExpr(const Expr *E, bool DestroyToplevelScope) = 0;
- virtual bool visitDeclAndReturn(const VarDecl *VD, bool ConstantContext) = 0;
+ virtual bool visitDeclAndReturn(const VarDecl *VD, const Expr *Init,
+ bool ConstantContext) = 0;
virtual bool visitFunc(const FunctionDecl *F) = 0;
virtual bool visit(const Expr *E) = 0;
virtual bool emitBool(bool V, const Expr *E) = 0;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 5145896930153..820b053057067 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -17755,7 +17755,7 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
if (Info.EnableNewConstInterp) {
auto &InterpCtx = const_cast<ASTContext &>(Ctx).getInterpContext();
- if (!InterpCtx.evaluateAsInitializer(Info, VD, Value))
+ if (!InterpCtx.evaluateAsInitializer(Info, VD, this, Value))
return false;
return CheckConstantExpression(Info, DeclLoc, DeclTy, Value,
diff --git a/clang/test/Modules/added-visible-decls.cppm b/clang/test/Modules/added-visible-decls.cppm
index 2f387db452905..28df3bf6f8543 100644
--- a/clang/test/Modules/added-visible-decls.cppm
+++ b/clang/test/Modules/added-visible-decls.cppm
@@ -5,6 +5,7 @@
// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-reduced-module-interface -o %t/b.pcm -fprebuilt-module-path=%t
// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-reduced-module-interface -o %t/c.pcm -fprebuilt-module-path=%t
// RUN: %clang_cc1 -std=c++20 %t/d.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
+// RUN: %clang_cc1 -std=c++20 %t/d.cpp -fprebuilt-module-path=%t -fsyntax-only -verify -fexperimental-new-constant-interpreter
//--- a.h
template <typename T>
``````````
</details>
https://github.com/llvm/llvm-project/pull/158056
More information about the cfe-commits
mailing list