@@ -277,24 +277,14 @@ class alignas(void *) Stmt {
277277 SourceLocation GotoLoc;
278278 };
279279
280- class ContinueStmtBitfields {
281- friend class ContinueStmt ;
280+ class LoopControlStmtBitfields {
281+ friend class LoopControlStmt ;
282282
283283 LLVM_PREFERRED_TYPE (StmtBitfields)
284284 unsigned : NumStmtBits;
285285
286- // / The location of the "continue".
287- SourceLocation ContinueLoc;
288- };
289-
290- class BreakStmtBitfields {
291- friend class BreakStmt ;
292-
293- LLVM_PREFERRED_TYPE (StmtBitfields)
294- unsigned : NumStmtBits;
295-
296- // / The location of the "break".
297- SourceLocation BreakLoc;
286+ // / The location of the "continue"/"break".
287+ SourceLocation KwLoc;
298288 };
299289
300290 class ReturnStmtBitfields {
@@ -1325,8 +1315,7 @@ class alignas(void *) Stmt {
13251315 DoStmtBitfields DoStmtBits;
13261316 ForStmtBitfields ForStmtBits;
13271317 GotoStmtBitfields GotoStmtBits;
1328- ContinueStmtBitfields ContinueStmtBits;
1329- BreakStmtBitfields BreakStmtBits;
1318+ LoopControlStmtBitfields LoopControlStmtBits;
13301319 ReturnStmtBitfields ReturnStmtBits;
13311320 SwitchCaseBitfields SwitchCaseBits;
13321321
@@ -2184,6 +2173,14 @@ class LabelStmt : public ValueStmt {
21842173 SourceLocation getBeginLoc () const { return getIdentLoc (); }
21852174 SourceLocation getEndLoc () const LLVM_READONLY { return SubStmt->getEndLoc ();}
21862175
2176+ // / Look through nested labels and return the first non-label statement; e.g.
2177+ // / if this is 'a:' in 'a: b: c: for(;;)', this returns the for loop.
2178+ const Stmt *getInnermostLabeledStmt () const ;
2179+ Stmt *getInnermostLabeledStmt () {
2180+ return const_cast <Stmt *>(
2181+ const_cast <const LabelStmt *>(this )->getInnermostLabeledStmt ());
2182+ }
2183+
21872184 child_range children () { return child_range (&SubStmt, &SubStmt + 1 ); }
21882185
21892186 const_child_range children () const {
@@ -3056,26 +3053,53 @@ class IndirectGotoStmt : public Stmt {
30563053 }
30573054};
30583055
3059- // / ContinueStmt - This represents a continue.
3060- class ContinueStmt : public Stmt {
3061- public:
3062- ContinueStmt (SourceLocation CL) : Stmt(ContinueStmtClass) {
3063- setContinueLoc (CL);
3056+ // / Base class for BreakStmt and ContinueStmt.
3057+ class LoopControlStmt : public Stmt {
3058+ // / If this is a named break/continue, the label whose statement we're
3059+ // / targeting, as well as the source location of the label after the
3060+ // / keyword; for example:
3061+ // /
3062+ // / a: // <-- TargetLabel
3063+ // / for (;;)
3064+ // / break a; // <-- LabelLoc
3065+ // /
3066+ LabelDecl *TargetLabel = nullptr ;
3067+ SourceLocation LabelLoc;
3068+
3069+ protected:
3070+ LoopControlStmt (StmtClass Class, SourceLocation Loc, SourceLocation LabelLoc,
3071+ LabelDecl *Target)
3072+ : Stmt(Class), TargetLabel(Target), LabelLoc(LabelLoc) {
3073+ setKwLoc (Loc);
30643074 }
30653075
3066- // / Build an empty continue statement.
3067- explicit ContinueStmt (EmptyShell Empty) : Stmt(ContinueStmtClass, Empty ) {}
3076+ LoopControlStmt (StmtClass Class, SourceLocation Loc)
3077+ : LoopControlStmt(Class, Loc, SourceLocation(), nullptr ) {}
30683078
3069- SourceLocation getContinueLoc () const { return ContinueStmtBits.ContinueLoc ; }
3070- void setContinueLoc (SourceLocation L) { ContinueStmtBits.ContinueLoc = L; }
3079+ LoopControlStmt (StmtClass Class, EmptyShell ES) : Stmt(Class, ES) {}
30713080
3072- SourceLocation getBeginLoc () const { return getContinueLoc (); }
3073- SourceLocation getEndLoc () const { return getContinueLoc (); }
3081+ public:
3082+ SourceLocation getKwLoc () const { return LoopControlStmtBits.KwLoc ; }
3083+ void setKwLoc (SourceLocation L) { LoopControlStmtBits.KwLoc = L; }
30743084
3075- static bool classof (const Stmt *T) {
3076- return T->getStmtClass () == ContinueStmtClass;
3085+ SourceLocation getBeginLoc () const { return getKwLoc (); }
3086+ SourceLocation getEndLoc () const {
3087+ return hasLabelTarget () ? getLabelLoc () : getKwLoc ();
30773088 }
30783089
3090+ bool hasLabelTarget () const { return TargetLabel != nullptr ; }
3091+
3092+ SourceLocation getLabelLoc () const { return LabelLoc; }
3093+ void setLabelLoc (SourceLocation L) { LabelLoc = L; }
3094+
3095+ LabelDecl *getLabelDecl () { return TargetLabel; }
3096+ const LabelDecl *getLabelDecl () const { return TargetLabel; }
3097+ void setLabelDecl (LabelDecl *S) { TargetLabel = S; }
3098+
3099+ // / If this is a named break/continue, get the loop or switch statement
3100+ // / that this targets.
3101+ const Stmt *getNamedLoopOrSwitch () const ;
3102+
30793103 // Iterators
30803104 child_range children () {
30813105 return child_range (child_iterator (), child_iterator ());
@@ -3084,35 +3108,42 @@ class ContinueStmt : public Stmt {
30843108 const_child_range children () const {
30853109 return const_child_range (const_child_iterator (), const_child_iterator ());
30863110 }
3087- };
30883111
3089- // / BreakStmt - This represents a break.
3090- class BreakStmt : public Stmt {
3091- public:
3092- BreakStmt (SourceLocation BL) : Stmt(BreakStmtClass) {
3093- setBreakLoc (BL);
3112+ static bool classof (const Stmt *T) {
3113+ StmtClass Class = T->getStmtClass ();
3114+ return Class == ContinueStmtClass || Class == BreakStmtClass;
30943115 }
3116+ };
30953117
3096- // / Build an empty break statement.
3097- explicit BreakStmt (EmptyShell Empty) : Stmt(BreakStmtClass, Empty) {}
3098-
3099- SourceLocation getBreakLoc () const { return BreakStmtBits.BreakLoc ; }
3100- void setBreakLoc (SourceLocation L) { BreakStmtBits.BreakLoc = L; }
3118+ // / ContinueStmt - This represents a continue.
3119+ class ContinueStmt : public LoopControlStmt {
3120+ public:
3121+ ContinueStmt (SourceLocation CL) : LoopControlStmt(ContinueStmtClass, CL) {}
3122+ ContinueStmt (SourceLocation CL, SourceLocation LabelLoc, LabelDecl *Target)
3123+ : LoopControlStmt(ContinueStmtClass, CL, LabelLoc, Target) {}
31013124
3102- SourceLocation getBeginLoc () const { return getBreakLoc (); }
3103- SourceLocation getEndLoc () const { return getBreakLoc (); }
3125+ // / Build an empty continue statement.
3126+ explicit ContinueStmt (EmptyShell Empty)
3127+ : LoopControlStmt(ContinueStmtClass, Empty) {}
31043128
31053129 static bool classof (const Stmt *T) {
3106- return T->getStmtClass () == BreakStmtClass ;
3130+ return T->getStmtClass () == ContinueStmtClass ;
31073131 }
3132+ };
31083133
3109- // Iterators
3110- child_range children () {
3111- return child_range (child_iterator (), child_iterator ());
3112- }
3134+ // / BreakStmt - This represents a break.
3135+ class BreakStmt : public LoopControlStmt {
3136+ public:
3137+ BreakStmt (SourceLocation BL) : LoopControlStmt(BreakStmtClass, BL) {}
3138+ BreakStmt (SourceLocation CL, SourceLocation LabelLoc, LabelDecl *Target)
3139+ : LoopControlStmt(BreakStmtClass, CL, LabelLoc, Target) {}
31133140
3114- const_child_range children () const {
3115- return const_child_range (const_child_iterator (), const_child_iterator ());
3141+ // / Build an empty break statement.
3142+ explicit BreakStmt (EmptyShell Empty)
3143+ : LoopControlStmt(BreakStmtClass, Empty) {}
3144+
3145+ static bool classof (const Stmt *T) {
3146+ return T->getStmtClass () == BreakStmtClass;
31163147 }
31173148};
31183149
0 commit comments