@@ -114,31 +114,25 @@ template <class Emitter> class LoopScope final {
114114public:
115115 using LabelTy = typename Compiler<Emitter>::LabelTy;
116116 using OptLabelTy = typename Compiler<Emitter>::OptLabelTy;
117+ using LabelInfo = typename Compiler<Emitter>::LabelInfo;
117118
118- LoopScope (Compiler<Emitter> *Ctx, LabelTy BreakLabel, LabelTy ContinueLabel)
119- : Ctx(Ctx), OldBreakLabel(Ctx->BreakLabel),
120- OldContinueLabel (Ctx->ContinueLabel),
121- OldBreakVarScope(Ctx->BreakVarScope),
122- OldContinueVarScope(Ctx->ContinueVarScope) {
123- this ->Ctx ->BreakLabel = BreakLabel;
124- this ->Ctx ->ContinueLabel = ContinueLabel;
125- this ->Ctx ->BreakVarScope = this ->Ctx ->VarScope ;
126- this ->Ctx ->ContinueVarScope = this ->Ctx ->VarScope ;
127- }
119+ LoopScope (Compiler<Emitter> *Ctx, const Stmt *Name, LabelTy BreakLabel,
120+ LabelTy ContinueLabel)
121+ : Ctx(Ctx) {
122+ #ifndef NDEBUG
123+ for (const LabelInfo &LI : Ctx->LabelInfoStack )
124+ assert (LI.Name != Name);
125+ #endif
128126
129- ~LoopScope () {
130- this ->Ctx ->BreakLabel = OldBreakLabel;
131- this ->Ctx ->ContinueLabel = OldContinueLabel;
132- this ->Ctx ->ContinueVarScope = OldContinueVarScope;
133- this ->Ctx ->BreakVarScope = OldBreakVarScope;
127+ this ->Ctx ->LabelInfoStack .emplace_back (Name, BreakLabel, ContinueLabel,
128+ /* DefaultLabel=*/ std::nullopt ,
129+ Ctx->VarScope );
134130 }
135131
132+ ~LoopScope () { this ->Ctx ->LabelInfoStack .pop_back (); }
133+
136134private:
137135 Compiler<Emitter> *Ctx;
138- OptLabelTy OldBreakLabel;
139- OptLabelTy OldContinueLabel;
140- VariableScope<Emitter> *OldBreakVarScope;
141- VariableScope<Emitter> *OldContinueVarScope;
142136};
143137
144138// Sets the context for a switch scope, mapping labels.
@@ -147,32 +141,30 @@ template <class Emitter> class SwitchScope final {
147141 using LabelTy = typename Compiler<Emitter>::LabelTy;
148142 using OptLabelTy = typename Compiler<Emitter>::OptLabelTy;
149143 using CaseMap = typename Compiler<Emitter>::CaseMap;
144+ using LabelInfo = typename Compiler<Emitter>::LabelInfo;
145+
146+ SwitchScope (Compiler<Emitter> *Ctx, const Stmt *Name, CaseMap &&CaseLabels,
147+ LabelTy BreakLabel, OptLabelTy DefaultLabel)
148+ : Ctx(Ctx), OldCaseLabels(std::move(this ->Ctx->CaseLabels)) {
149+ #ifndef NDEBUG
150+ for (const LabelInfo &LI : Ctx->LabelInfoStack )
151+ assert (LI.Name != Name);
152+ #endif
150153
151- SwitchScope (Compiler<Emitter> *Ctx, CaseMap &&CaseLabels, LabelTy BreakLabel,
152- OptLabelTy DefaultLabel)
153- : Ctx(Ctx), OldBreakLabel(Ctx->BreakLabel),
154- OldDefaultLabel (this ->Ctx->DefaultLabel),
155- OldCaseLabels(std::move(this ->Ctx->CaseLabels)),
156- OldLabelVarScope(Ctx->BreakVarScope) {
157- this ->Ctx ->BreakLabel = BreakLabel;
158- this ->Ctx ->DefaultLabel = DefaultLabel;
159154 this ->Ctx ->CaseLabels = std::move (CaseLabels);
160- this ->Ctx ->BreakVarScope = this ->Ctx ->VarScope ;
155+ this ->Ctx ->LabelInfoStack .emplace_back (Name, BreakLabel,
156+ /* ContinueLabel=*/ std::nullopt ,
157+ DefaultLabel, Ctx->VarScope );
161158 }
162159
163160 ~SwitchScope () {
164- this ->Ctx ->BreakLabel = OldBreakLabel;
165- this ->Ctx ->DefaultLabel = OldDefaultLabel;
166161 this ->Ctx ->CaseLabels = std::move (OldCaseLabels);
167- this ->Ctx ->BreakVarScope = OldLabelVarScope ;
162+ this ->Ctx ->LabelInfoStack . pop_back () ;
168163 }
169164
170165private:
171166 Compiler<Emitter> *Ctx;
172- OptLabelTy OldBreakLabel;
173- OptLabelTy OldDefaultLabel;
174167 CaseMap OldCaseLabels;
175- VariableScope<Emitter> *OldLabelVarScope;
176168};
177169
178170template <class Emitter > class StmtExprScope final {
@@ -5685,7 +5677,8 @@ bool Compiler<Emitter>::visitWhileStmt(const WhileStmt *S) {
56855677
56865678 LabelTy CondLabel = this ->getLabel (); // Label before the condition.
56875679 LabelTy EndLabel = this ->getLabel (); // Label after the loop.
5688- LoopScope<Emitter> LS (this , EndLabel, CondLabel);
5680+ LocalScope<Emitter> WholeLoopScope (this );
5681+ LoopScope<Emitter> LS (this , S, EndLabel, CondLabel);
56895682
56905683 this ->fallthrough (CondLabel);
56915684 this ->emitLabel (CondLabel);
@@ -5715,8 +5708,7 @@ bool Compiler<Emitter>::visitWhileStmt(const WhileStmt *S) {
57155708 return false ;
57165709 this ->fallthrough (EndLabel);
57175710 this ->emitLabel (EndLabel);
5718-
5719- return true ;
5711+ return WholeLoopScope.destroyLocals ();
57205712}
57215713
57225714template <class Emitter > bool Compiler<Emitter>::visitDoStmt(const DoStmt *S) {
@@ -5726,7 +5718,8 @@ template <class Emitter> bool Compiler<Emitter>::visitDoStmt(const DoStmt *S) {
57265718 LabelTy StartLabel = this ->getLabel ();
57275719 LabelTy EndLabel = this ->getLabel ();
57285720 LabelTy CondLabel = this ->getLabel ();
5729- LoopScope<Emitter> LS (this , EndLabel, CondLabel);
5721+ LocalScope<Emitter> WholeLoopScope (this );
5722+ LoopScope<Emitter> LS (this , S, EndLabel, CondLabel);
57305723
57315724 this ->fallthrough (StartLabel);
57325725 this ->emitLabel (StartLabel);
@@ -5748,7 +5741,7 @@ template <class Emitter> bool Compiler<Emitter>::visitDoStmt(const DoStmt *S) {
57485741
57495742 this ->fallthrough (EndLabel);
57505743 this ->emitLabel (EndLabel);
5751- return true ;
5744+ return WholeLoopScope. destroyLocals () ;
57525745}
57535746
57545747template <class Emitter >
@@ -5762,19 +5755,21 @@ bool Compiler<Emitter>::visitForStmt(const ForStmt *S) {
57625755 LabelTy EndLabel = this ->getLabel ();
57635756 LabelTy CondLabel = this ->getLabel ();
57645757 LabelTy IncLabel = this ->getLabel ();
5765- LoopScope<Emitter> LS (this , EndLabel, IncLabel);
57665758
5759+ LocalScope<Emitter> WholeLoopScope (this );
57675760 if (Init && !this ->visitStmt (Init))
57685761 return false ;
57695762
5763+ // Start of the loop body {
57705764 this ->fallthrough (CondLabel);
57715765 this ->emitLabel (CondLabel);
57725766
5773- // Start of loop body.
57745767 LocalScope<Emitter> CondScope (this );
5775- if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt ())
5768+ LoopScope<Emitter> LS (this , S, EndLabel, IncLabel);
5769+ if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt ()) {
57765770 if (!visitDeclStmt (CondDecl))
57775771 return false ;
5772+ }
57785773
57795774 if (Cond) {
57805775 if (!this ->visitBool (Cond))
@@ -5797,12 +5792,12 @@ bool Compiler<Emitter>::visitForStmt(const ForStmt *S) {
57975792 return false ;
57985793 if (!this ->jump (CondLabel))
57995794 return false ;
5800- // End of loop body.
5795+ // } End of loop body.
58015796
58025797 this ->emitLabel (EndLabel);
58035798 // If we jumped out of the loop above, we still need to clean up the condition
58045799 // scope.
5805- return CondScope.destroyLocals ();
5800+ return CondScope.destroyLocals () && WholeLoopScope. destroyLocals () ;
58065801}
58075802
58085803template <class Emitter >
@@ -5818,7 +5813,8 @@ bool Compiler<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {
58185813 LabelTy EndLabel = this ->getLabel ();
58195814 LabelTy CondLabel = this ->getLabel ();
58205815 LabelTy IncLabel = this ->getLabel ();
5821- LoopScope<Emitter> LS (this , EndLabel, IncLabel);
5816+ LocalScope<Emitter> WholeLoopScope (this );
5817+ LoopScope<Emitter> LS (this , S, EndLabel, IncLabel);
58225818
58235819 // Emit declarations needed in the loop.
58245820 if (Init && !this ->visitStmt (Init))
@@ -5857,29 +5853,78 @@ bool Compiler<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {
58575853
58585854 this ->fallthrough (EndLabel);
58595855 this ->emitLabel (EndLabel);
5860- return true ;
5856+ return WholeLoopScope. destroyLocals () ;
58615857}
58625858
58635859template <class Emitter >
58645860bool Compiler<Emitter>::visitBreakStmt(const BreakStmt *S) {
5865- if (!BreakLabel )
5861+ if (LabelInfoStack. empty () )
58665862 return false ;
58675863
5868- for (VariableScope<Emitter> *C = VarScope; C != BreakVarScope;
5864+ OptLabelTy TargetLabel = std::nullopt ;
5865+ const Stmt *TargetLoop = S->getNamedLoopOrSwitch ();
5866+ const VariableScope<Emitter> *BreakScope = nullptr ;
5867+
5868+ if (!TargetLoop) {
5869+ for (const auto &LI : llvm::reverse (LabelInfoStack)) {
5870+ if (LI.BreakLabel ) {
5871+ TargetLabel = *LI.BreakLabel ;
5872+ BreakScope = LI.BreakOrContinueScope ;
5873+ break ;
5874+ }
5875+ }
5876+ } else {
5877+ for (auto LI : LabelInfoStack) {
5878+ if (LI.Name == TargetLoop) {
5879+ TargetLabel = *LI.BreakLabel ;
5880+ BreakScope = LI.BreakOrContinueScope ;
5881+ break ;
5882+ }
5883+ }
5884+ }
5885+
5886+ assert (TargetLabel);
5887+
5888+ for (VariableScope<Emitter> *C = this ->VarScope ; C != BreakScope;
58695889 C = C->getParent ())
58705890 C->emitDestruction ();
5871- return this ->jump (*BreakLabel);
5891+
5892+ return this ->jump (*TargetLabel);
58725893}
58735894
58745895template <class Emitter >
58755896bool Compiler<Emitter>::visitContinueStmt(const ContinueStmt *S) {
5876- if (!ContinueLabel )
5897+ if (LabelInfoStack. empty () )
58775898 return false ;
58785899
5879- for (VariableScope<Emitter> *C = VarScope;
5880- C && C->getParent () != ContinueVarScope; C = C->getParent ())
5900+ OptLabelTy TargetLabel = std::nullopt ;
5901+ const Stmt *TargetLoop = S->getNamedLoopOrSwitch ();
5902+ const VariableScope<Emitter> *ContinueScope = nullptr ;
5903+
5904+ if (!TargetLoop) {
5905+ for (const auto &LI : llvm::reverse (LabelInfoStack)) {
5906+ if (LI.ContinueLabel ) {
5907+ TargetLabel = *LI.ContinueLabel ;
5908+ ContinueScope = LI.BreakOrContinueScope ;
5909+ break ;
5910+ }
5911+ }
5912+ } else {
5913+ for (auto LI : LabelInfoStack) {
5914+ if (LI.Name == TargetLoop) {
5915+ TargetLabel = *LI.ContinueLabel ;
5916+ ContinueScope = LI.BreakOrContinueScope ;
5917+ break ;
5918+ }
5919+ }
5920+ }
5921+ assert (TargetLabel);
5922+
5923+ for (VariableScope<Emitter> *C = VarScope; C != ContinueScope;
5924+ C = C->getParent ())
58815925 C->emitDestruction ();
5882- return this ->jump (*ContinueLabel);
5926+
5927+ return this ->jump (*TargetLabel);
58835928}
58845929
58855930template <class Emitter >
@@ -5892,7 +5937,7 @@ bool Compiler<Emitter>::visitSwitchStmt(const SwitchStmt *S) {
58925937 LocalScope<Emitter> LS (this );
58935938
58945939 LabelTy EndLabel = this ->getLabel ();
5895- OptLabelTy DefaultLabel = std::nullopt ;
5940+ UnsignedOrNone DefaultLabel = std::nullopt ;
58965941 unsigned CondVar =
58975942 this ->allocateLocalPrimitive (Cond, CondT, /* IsConst=*/ true );
58985943
@@ -5953,7 +5998,8 @@ bool Compiler<Emitter>::visitSwitchStmt(const SwitchStmt *S) {
59535998 return false ;
59545999 }
59556000
5956- SwitchScope<Emitter> SS (this , std::move (CaseLabels), EndLabel, DefaultLabel);
6001+ SwitchScope<Emitter> SS (this , S, std::move (CaseLabels), EndLabel,
6002+ DefaultLabel);
59576003 if (!this ->visitStmt (S->getBody ()))
59586004 return false ;
59596005 this ->emitLabel (EndLabel);
@@ -5969,7 +6015,18 @@ bool Compiler<Emitter>::visitCaseStmt(const CaseStmt *S) {
59696015
59706016template <class Emitter >
59716017bool Compiler<Emitter>::visitDefaultStmt(const DefaultStmt *S) {
5972- this ->emitLabel (*DefaultLabel);
6018+ if (LabelInfoStack.empty ())
6019+ return false ;
6020+
6021+ LabelTy DefaultLabel;
6022+ for (const LabelInfo &LI : llvm::reverse (LabelInfoStack)) {
6023+ if (LI.DefaultLabel ) {
6024+ DefaultLabel = *LI.DefaultLabel ;
6025+ break ;
6026+ }
6027+ }
6028+
6029+ this ->emitLabel (DefaultLabel);
59736030 return this ->visitStmt (S->getSubStmt ());
59746031}
59756032
0 commit comments