@@ -25,10 +25,10 @@ namespace clang {
25
25
namespace interp {
26
26
27
27
// / Scope used to handle temporaries in toplevel variable declarations.
28
- template <class Emitter > class DeclScope final : public VariableScope <Emitter> {
28
+ template <class Emitter > class DeclScope final : public LocalScope <Emitter> {
29
29
public:
30
30
DeclScope (Compiler<Emitter> *Ctx, const ValueDecl *VD)
31
- : VariableScope <Emitter>(Ctx, nullptr ), Scope(Ctx->P, VD),
31
+ : LocalScope <Emitter>(Ctx, VD ), Scope(Ctx->P, VD),
32
32
OldGlobalDecl (Ctx->GlobalDecl),
33
33
OldInitializingDecl (Ctx->InitializingDecl) {
34
34
Ctx->GlobalDecl = Context::shouldBeGloballyIndexed (VD);
@@ -1794,6 +1794,8 @@ bool Compiler<Emitter>::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {
1794
1794
1795
1795
if (!this ->visitArrayElemInit (I, SubExpr))
1796
1796
return false ;
1797
+ if (!BS.destroyLocals ())
1798
+ return false ;
1797
1799
}
1798
1800
return true ;
1799
1801
}
@@ -2204,7 +2206,7 @@ bool Compiler<Emitter>::VisitCompoundAssignOperator(
2204
2206
2205
2207
template <class Emitter >
2206
2208
bool Compiler<Emitter>::VisitExprWithCleanups(const ExprWithCleanups *E) {
2207
- ExprScope <Emitter> ES (this );
2209
+ LocalScope <Emitter> ES (this );
2208
2210
const Expr *SubExpr = E->getSubExpr ();
2209
2211
2210
2212
assert (E->getNumObjects () == 0 && " TODO: Implement cleanups" );
@@ -3080,7 +3082,7 @@ bool Compiler<Emitter>::VisitStmtExpr(const StmtExpr *E) {
3080
3082
return false ;
3081
3083
}
3082
3084
3083
- return true ;
3085
+ return BS. destroyLocals () ;
3084
3086
}
3085
3087
3086
3088
template <class Emitter > bool Compiler<Emitter>::discard(const Expr *E) {
@@ -3425,7 +3427,7 @@ const Function *Compiler<Emitter>::getFunction(const FunctionDecl *FD) {
3425
3427
}
3426
3428
3427
3429
template <class Emitter > bool Compiler<Emitter>::visitExpr(const Expr *E) {
3428
- ExprScope <Emitter> RootScope (this );
3430
+ LocalScope <Emitter> RootScope (this );
3429
3431
// Void expressions.
3430
3432
if (E->getType ()->isVoidType ()) {
3431
3433
if (!visit (E))
@@ -3462,40 +3464,52 @@ template <class Emitter> bool Compiler<Emitter>::visitExpr(const Expr *E) {
3462
3464
return false ;
3463
3465
}
3464
3466
3465
- // / Toplevel visitDecl().
3467
+ template <class Emitter >
3468
+ VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD) {
3469
+
3470
+ auto R = this ->visitVarDecl (VD, /* Toplevel=*/ true );
3471
+
3472
+ if (R.notCreated ())
3473
+ return R;
3474
+
3475
+ if (R)
3476
+ return true ;
3477
+
3478
+ if (!R && Context::shouldBeGloballyIndexed (VD)) {
3479
+ if (auto GlobalIndex = P.getGlobal (VD)) {
3480
+ Block *GlobalBlock = P.getGlobal (*GlobalIndex);
3481
+ GlobalInlineDescriptor &GD =
3482
+ *reinterpret_cast <GlobalInlineDescriptor *>(GlobalBlock->rawData ());
3483
+
3484
+ GD.InitState = GlobalInitState::InitializerFailed;
3485
+ GlobalBlock->invokeDtor ();
3486
+ }
3487
+ }
3488
+
3489
+ return R;
3490
+ }
3491
+
3492
+ // / Toplevel visitDeclAndReturn().
3466
3493
// / We get here from evaluateAsInitializer().
3467
3494
// / We need to evaluate the initializer and return its value.
3468
3495
template <class Emitter >
3469
- bool Compiler<Emitter>::visitDecl(const VarDecl *VD, bool ConstantContext) {
3470
- assert (!VD->isInvalidDecl () && " Trying to constant evaluate an invalid decl" );
3471
-
3496
+ bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD,
3497
+ bool ConstantContext) {
3472
3498
std::optional<PrimType> VarT = classify (VD->getType ());
3473
3499
3474
3500
// We only create variables if we're evaluating in a constant context.
3475
3501
// Otherwise, just evaluate the initializer and return it.
3476
3502
if (!ConstantContext) {
3477
- DeclScope<Emitter> LocalScope (this , VD);
3503
+ DeclScope<Emitter> LS (this , VD);
3478
3504
if (!this ->visit (VD->getAnyInitializer ()))
3479
3505
return false ;
3480
- return this ->emitRet (VarT.value_or (PT_Ptr), VD);
3481
- }
3482
-
3483
- // If we've seen the global variable already and the initializer failed,
3484
- // just return false immediately.
3485
- if (std::optional<unsigned > Index = P.getGlobal (VD)) {
3486
- const Pointer &Ptr = P.getPtrGlobal (*Index);
3487
- const GlobalInlineDescriptor &GD =
3488
- *reinterpret_cast <const GlobalInlineDescriptor *>(
3489
- Ptr .block ()->rawData ());
3490
- if (GD.InitState == GlobalInitState::InitializerFailed)
3491
- return false ;
3506
+ return this ->emitRet (VarT.value_or (PT_Ptr), VD) && LS.destroyLocals ();
3492
3507
}
3493
3508
3494
- // Create and initialize the variable.
3509
+ LocalScope<Emitter> VDScope ( this , VD);
3495
3510
if (!this ->visitVarDecl (VD, /* Toplevel=*/ true ))
3496
3511
return false ;
3497
3512
3498
- // Get a pointer to the variable
3499
3513
if (Context::shouldBeGloballyIndexed (VD)) {
3500
3514
auto GlobalIndex = P.getGlobal (VD);
3501
3515
assert (GlobalIndex); // visitVarDecl() didn't return false.
@@ -3535,7 +3549,7 @@ bool Compiler<Emitter>::visitDecl(const VarDecl *VD, bool ConstantContext) {
3535
3549
return false ;
3536
3550
}
3537
3551
3538
- return true ;
3552
+ return VDScope. destroyLocals () ;
3539
3553
}
3540
3554
3541
3555
template <class Emitter >
@@ -3552,12 +3566,12 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, bool Topleve
3552
3566
const Expr *Init = VD->getInit ();
3553
3567
std::optional<PrimType> VarT = classify (VD->getType ());
3554
3568
3555
- auto checkDecl = [&]() -> bool {
3556
- bool NeedsOp = !Toplevel && VD->isLocalVarDecl () && VD->isStaticLocal ();
3557
- return !NeedsOp || this ->emitCheckDecl (VD, VD);
3558
- };
3559
-
3560
3569
if (Context::shouldBeGloballyIndexed (VD)) {
3570
+ auto checkDecl = [&]() -> bool {
3571
+ bool NeedsOp = !Toplevel && VD->isLocalVarDecl () && VD->isStaticLocal ();
3572
+ return !NeedsOp || this ->emitCheckDecl (VD, VD);
3573
+ };
3574
+
3561
3575
auto initGlobal = [&](unsigned GlobalIndex) -> bool {
3562
3576
assert (Init);
3563
3577
DeclScope<Emitter> LocalScope (this , VD);
@@ -3589,26 +3603,34 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD, bool Topleve
3589
3603
3590
3604
return !Init || (checkDecl () && initGlobal (*GlobalIndex));
3591
3605
} else {
3592
- VariableScope<Emitter> LocalScope (this , VD);
3593
3606
InitLinkScope<Emitter> ILS (this , InitLink::Decl (VD));
3594
3607
3595
3608
if (VarT) {
3596
3609
unsigned Offset = this ->allocateLocalPrimitive (
3597
3610
VD, *VarT, VD->getType ().isConstQualified ());
3598
3611
if (Init) {
3599
- // Compile the initializer in its own scope.
3600
- ExprScope<Emitter> Scope (this );
3601
- if (!this ->visit (Init))
3602
- return false ;
3603
-
3604
- return this ->emitSetLocal (*VarT, Offset, VD);
3612
+ // If this is a toplevel declaration, create a scope for the
3613
+ // initializer.
3614
+ if (Toplevel) {
3615
+ LocalScope<Emitter> Scope (this );
3616
+ if (!this ->visit (Init))
3617
+ return false ;
3618
+ return this ->emitSetLocal (*VarT, Offset, VD) && Scope.destroyLocals ();
3619
+ } else {
3620
+ if (!this ->visit (Init))
3621
+ return false ;
3622
+ return this ->emitSetLocal (*VarT, Offset, VD);
3623
+ }
3605
3624
}
3606
3625
} else {
3607
- if (std::optional<unsigned > Offset = this ->allocateLocal (VD))
3608
- return !Init || this ->visitLocalInitializer (Init, *Offset);
3626
+ if (std::optional<unsigned > Offset = this ->allocateLocal (VD)) {
3627
+ if (!Init)
3628
+ return true ;
3629
+
3630
+ return this ->visitLocalInitializer (Init, *Offset);
3631
+ }
3609
3632
return false ;
3610
3633
}
3611
-
3612
3634
return true ;
3613
3635
}
3614
3636
@@ -4074,7 +4096,7 @@ bool Compiler<Emitter>::visitCompoundStmt(const CompoundStmt *S) {
4074
4096
for (const auto *InnerStmt : S->body ())
4075
4097
if (!visitStmt (InnerStmt))
4076
4098
return false ;
4077
- return true ;
4099
+ return Scope. destroyLocals () ;
4078
4100
}
4079
4101
4080
4102
template <class Emitter >
@@ -4100,7 +4122,7 @@ bool Compiler<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
4100
4122
return this ->emitUnsupported (RS);
4101
4123
4102
4124
if (const Expr *RE = RS->getRetValue ()) {
4103
- ExprScope <Emitter> RetScope (this );
4125
+ LocalScope <Emitter> RetScope (this );
4104
4126
if (ReturnType) {
4105
4127
// Primitive types are simply returned.
4106
4128
if (!this ->visit (RE))
@@ -4170,7 +4192,7 @@ template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
4170
4192
this ->emitLabel (LabelEnd);
4171
4193
}
4172
4194
4173
- return true ;
4195
+ return IfScope. destroyLocals () ;
4174
4196
}
4175
4197
4176
4198
template <class Emitter >
@@ -4636,6 +4658,9 @@ bool Compiler<Emitter>::visitFunc(const FunctionDecl *F) {
4636
4658
if (!this ->emitPopPtr (InitExpr))
4637
4659
return false ;
4638
4660
}
4661
+
4662
+ if (!Scope.destroyLocals ())
4663
+ return false ;
4639
4664
}
4640
4665
}
4641
4666
@@ -5010,6 +5035,18 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
5010
5035
}
5011
5036
}
5012
5037
5038
+ // In case we need to re-visit a declaration.
5039
+ auto revisit = [&](const VarDecl *VD) -> bool {
5040
+ auto VarState = this ->visitDecl (VD);
5041
+
5042
+ if (VarState.notCreated ())
5043
+ return true ;
5044
+ if (!VarState)
5045
+ return false ;
5046
+ // Retry.
5047
+ return this ->visitDeclRef (D, E);
5048
+ };
5049
+
5013
5050
// Handle lambda captures.
5014
5051
if (auto It = this ->LambdaCaptures .find (D);
5015
5052
It != this ->LambdaCaptures .end ()) {
@@ -5020,12 +5057,8 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
5020
5057
return this ->emitGetPtrThisField (Offset, E);
5021
5058
} else if (const auto *DRE = dyn_cast<DeclRefExpr>(E);
5022
5059
DRE && DRE->refersToEnclosingVariableOrCapture ()) {
5023
- if (const auto *VD = dyn_cast<VarDecl>(D); VD && VD->isInitCapture ()) {
5024
- if (!this ->visitVarDecl (cast<VarDecl>(D)))
5025
- return false ;
5026
- // Retry.
5027
- return this ->visitDeclRef (D, E);
5028
- }
5060
+ if (const auto *VD = dyn_cast<VarDecl>(D); VD && VD->isInitCapture ())
5061
+ return revisit (VD);
5029
5062
}
5030
5063
5031
5064
if (D != InitializingDecl) {
@@ -5044,28 +5077,14 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
5044
5077
// Visit local const variables like normal.
5045
5078
if ((VD->hasGlobalStorage () || VD->isLocalVarDecl () ||
5046
5079
VD->isStaticDataMember ()) &&
5047
- typeShouldBeVisited (VD->getType ())) {
5048
- auto VarState = this ->visitVarDecl (VD, true );
5049
- if (VarState.notCreated ())
5050
- return true ;
5051
- if (!VarState)
5052
- return false ;
5053
- // Retry.
5054
- return this ->visitDeclRef (VD, E);
5055
- }
5080
+ typeShouldBeVisited (VD->getType ()))
5081
+ return revisit (VD);
5056
5082
}
5057
5083
} else {
5058
5084
if (const auto *VD = dyn_cast<VarDecl>(D);
5059
5085
VD && VD->getAnyInitializer () &&
5060
- VD->getType ().isConstant (Ctx.getASTContext ()) && !VD->isWeak ()) {
5061
- auto VarState = this ->visitVarDecl (VD, true );
5062
- if (VarState.notCreated ())
5063
- return true ;
5064
- if (!VarState)
5065
- return false ;
5066
- // Retry.
5067
- return this ->visitDeclRef (VD, E);
5068
- }
5086
+ VD->getType ().isConstant (Ctx.getASTContext ()) && !VD->isWeak ())
5087
+ return revisit (VD);
5069
5088
}
5070
5089
}
5071
5090
0 commit comments