Skip to content

Commit 03c356c

Browse files
authored
[clang][bytecode] Pass initializer along in evaluateAsInitializer() (#158056)
We just called `getInit()`, which isn't always correct and used the wrong initializer in the module test case.
1 parent 9d55563 commit 03c356c

File tree

9 files changed

+30
-23
lines changed

9 files changed

+30
-23
lines changed

clang/lib/AST/ByteCode/ByteCodeEmitter.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ class ByteCodeEmitter {
4646
/// Methods implemented by the compiler.
4747
virtual bool visitFunc(const FunctionDecl *E) = 0;
4848
virtual bool visitExpr(const Expr *E, bool DestroyToplevelScope) = 0;
49-
virtual bool visitDeclAndReturn(const VarDecl *E, bool ConstantContext) = 0;
49+
virtual bool visitDeclAndReturn(const VarDecl *VD, const Expr *Init,
50+
bool ConstantContext) = 0;
5051
virtual bool visit(const Expr *E) = 0;
5152
virtual bool emitBool(bool V, const Expr *E) = 0;
5253

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4714,7 +4714,8 @@ template <class Emitter>
47144714
VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD,
47154715
bool IsConstexprUnknown) {
47164716

4717-
auto R = this->visitVarDecl(VD, /*Toplevel=*/true, IsConstexprUnknown);
4717+
auto R = this->visitVarDecl(VD, VD->getInit(), /*Toplevel=*/true,
4718+
IsConstexprUnknown);
47184719

47194720
if (R.notCreated())
47204721
return R;
@@ -4740,22 +4741,20 @@ VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD,
47404741
/// We get here from evaluateAsInitializer().
47414742
/// We need to evaluate the initializer and return its value.
47424743
template <class Emitter>
4743-
bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD,
4744+
bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD, const Expr *Init,
47444745
bool ConstantContext) {
4745-
47464746
// We only create variables if we're evaluating in a constant context.
47474747
// Otherwise, just evaluate the initializer and return it.
47484748
if (!ConstantContext) {
47494749
DeclScope<Emitter> LS(this, VD);
4750-
const Expr *Init = VD->getInit();
47514750
if (!this->visit(Init))
47524751
return false;
47534752
return this->emitRet(classify(Init).value_or(PT_Ptr), VD) &&
47544753
LS.destroyLocals() && this->emitCheckAllocations(VD);
47554754
}
47564755

47574756
LocalScope<Emitter> VDScope(this, VD);
4758-
if (!this->visitVarDecl(VD, /*Toplevel=*/true))
4757+
if (!this->visitVarDecl(VD, Init, /*Toplevel=*/true))
47594758
return false;
47604759

47614760
OptPrimType VarT = classify(VD->getType());
@@ -4802,9 +4801,9 @@ bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD,
48024801
}
48034802

48044803
template <class Emitter>
4805-
VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
4806-
bool Toplevel,
4807-
bool IsConstexprUnknown) {
4804+
VarCreationState
4805+
Compiler<Emitter>::visitVarDecl(const VarDecl *VD, const Expr *Init,
4806+
bool Toplevel, bool IsConstexprUnknown) {
48084807
// We don't know what to do with these, so just return false.
48094808
if (VD->getType().isNull())
48104809
return false;
@@ -4814,7 +4813,6 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
48144813
if (!this->isActive())
48154814
return VarCreationState::NotCreated();
48164815

4817-
const Expr *Init = VD->getInit();
48184816
OptPrimType VarT = classify(VD->getType());
48194817

48204818
if (Init && Init->isValueDependent())
@@ -5488,7 +5486,8 @@ template <class Emitter>
54885486
bool Compiler<Emitter>::maybeEmitDeferredVarInit(const VarDecl *VD) {
54895487
if (auto *DD = dyn_cast_if_present<DecompositionDecl>(VD)) {
54905488
for (auto *BD : DD->flat_bindings())
5491-
if (auto *KD = BD->getHoldingVar(); KD && !this->visitVarDecl(KD))
5489+
if (auto *KD = BD->getHoldingVar();
5490+
KD && !this->visitVarDecl(KD, KD->getInit()))
54925491
return false;
54935492
}
54945493
return true;
@@ -5552,7 +5551,7 @@ bool Compiler<Emitter>::visitDeclStmt(const DeclStmt *DS,
55525551
const auto *VD = dyn_cast<VarDecl>(D);
55535552
if (!VD)
55545553
return false;
5555-
if (!this->visitVarDecl(VD))
5554+
if (!this->visitVarDecl(VD, VD->getInit()))
55565555
return false;
55575556

55585557
// Register decomposition decl holding vars.

clang/lib/AST/ByteCode/Compiler.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,8 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
251251
bool visitExpr(const Expr *E, bool DestroyToplevelScope) override;
252252
bool visitFunc(const FunctionDecl *F) override;
253253

254-
bool visitDeclAndReturn(const VarDecl *VD, bool ConstantContext) override;
254+
bool visitDeclAndReturn(const VarDecl *VD, const Expr *Init,
255+
bool ConstantContext) override;
255256

256257
protected:
257258
/// Emits scope cleanup instructions.
@@ -303,7 +304,8 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
303304
/// intact.
304305
bool delegate(const Expr *E);
305306
/// Creates and initializes a variable from the given decl.
306-
VarCreationState visitVarDecl(const VarDecl *VD, bool Toplevel = false,
307+
VarCreationState visitVarDecl(const VarDecl *VD, const Expr *Init,
308+
bool Toplevel = false,
307309
bool IsConstexprUnknown = false);
308310
VarCreationState visitDecl(const VarDecl *VD,
309311
bool IsConstexprUnknown = false);

clang/lib/AST/ByteCode/Context.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ bool Context::evaluate(State &Parent, const Expr *E, APValue &Result,
126126
}
127127

128128
bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
129-
APValue &Result) {
129+
const Expr *Init, APValue &Result) {
130130
++EvalID;
131131
bool Recursing = !Stk.empty();
132132
size_t StackSizeBefore = Stk.size();
@@ -135,7 +135,7 @@ bool Context::evaluateAsInitializer(State &Parent, const VarDecl *VD,
135135
bool CheckGlobalInitialized =
136136
shouldBeGloballyIndexed(VD) &&
137137
(VD->getType()->isRecordType() || VD->getType()->isArrayType());
138-
auto Res = C.interpretDecl(VD, CheckGlobalInitialized);
138+
auto Res = C.interpretDecl(VD, Init, CheckGlobalInitialized);
139139
if (Res.isInvalid()) {
140140
C.cleanup();
141141
Stk.clearTo(StackSizeBefore);

clang/lib/AST/ByteCode/Context.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ class Context final {
5959
ConstantExprKind Kind);
6060

6161
/// Evaluates a toplevel initializer.
62-
bool evaluateAsInitializer(State &Parent, const VarDecl *VD, APValue &Result);
62+
bool evaluateAsInitializer(State &Parent, const VarDecl *VD, const Expr *Init,
63+
APValue &Result);
6364

6465
bool evaluateCharRange(State &Parent, const Expr *SizeExpr,
6566
const Expr *PtrExpr, APValue &Result);

clang/lib/AST/ByteCode/EvalEmitter.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,15 @@ EvaluationResult EvalEmitter::interpretExpr(const Expr *E,
4949
return std::move(this->EvalResult);
5050
}
5151

52-
EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD,
52+
EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD, const Expr *Init,
5353
bool CheckFullyInitialized) {
5454
this->CheckFullyInitialized = CheckFullyInitialized;
5555
S.EvaluatingDecl = VD;
5656
S.setEvalLocation(VD->getLocation());
5757
EvalResult.setSource(VD);
5858

59-
if (const Expr *Init = VD->getAnyInitializer()) {
59+
// FIXME: I think Init is never null.
60+
if (Init) {
6061
QualType T = VD->getType();
6162
this->ConvertResultToRValue = !Init->isGLValue() && !T->isPointerType() &&
6263
!T->isObjCObjectPointerType();
@@ -65,7 +66,7 @@ EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD,
6566

6667
EvalResult.setSource(VD);
6768

68-
if (!this->visitDeclAndReturn(VD, S.inConstantContext()))
69+
if (!this->visitDeclAndReturn(VD, Init, S.inConstantContext()))
6970
EvalResult.setInvalid();
7071

7172
S.EvaluatingDecl = nullptr;

clang/lib/AST/ByteCode/EvalEmitter.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ class EvalEmitter : public SourceMapper {
3737
EvaluationResult interpretExpr(const Expr *E,
3838
bool ConvertResultToRValue = false,
3939
bool DestroyToplevelScope = false);
40-
EvaluationResult interpretDecl(const VarDecl *VD, bool CheckFullyInitialized);
40+
EvaluationResult interpretDecl(const VarDecl *VD, const Expr *Init,
41+
bool CheckFullyInitialized);
4142
/// Interpret the given Expr to a Pointer.
4243
EvaluationResult interpretAsPointer(const Expr *E, PtrCallback PtrCB);
4344
/// Interpret the given expression as if it was in the body of the given
@@ -59,7 +60,8 @@ class EvalEmitter : public SourceMapper {
5960

6061
/// Methods implemented by the compiler.
6162
virtual bool visitExpr(const Expr *E, bool DestroyToplevelScope) = 0;
62-
virtual bool visitDeclAndReturn(const VarDecl *VD, bool ConstantContext) = 0;
63+
virtual bool visitDeclAndReturn(const VarDecl *VD, const Expr *Init,
64+
bool ConstantContext) = 0;
6365
virtual bool visitFunc(const FunctionDecl *F) = 0;
6466
virtual bool visit(const Expr *E) = 0;
6567
virtual bool emitBool(bool V, const Expr *E) = 0;

clang/lib/AST/ExprConstant.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17755,7 +17755,7 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
1775517755

1775617756
if (Info.EnableNewConstInterp) {
1775717757
auto &InterpCtx = const_cast<ASTContext &>(Ctx).getInterpContext();
17758-
if (!InterpCtx.evaluateAsInitializer(Info, VD, Value))
17758+
if (!InterpCtx.evaluateAsInitializer(Info, VD, this, Value))
1775917759
return false;
1776017760

1776117761
return CheckConstantExpression(Info, DeclLoc, DeclTy, Value,

clang/test/Modules/added-visible-decls.cppm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-reduced-module-interface -o %t/b.pcm -fprebuilt-module-path=%t
66
// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-reduced-module-interface -o %t/c.pcm -fprebuilt-module-path=%t
77
// RUN: %clang_cc1 -std=c++20 %t/d.cpp -fprebuilt-module-path=%t -fsyntax-only -verify
8+
// RUN: %clang_cc1 -std=c++20 %t/d.cpp -fprebuilt-module-path=%t -fsyntax-only -verify -fexperimental-new-constant-interpreter
89

910
//--- a.h
1011
template <typename T>

0 commit comments

Comments
 (0)