@@ -399,12 +399,9 @@ static LabeledStmt *findUnlabeledBreakOrContinueStmtTarget(
399399static LabeledStmt *findBreakOrContinueStmtTarget (
400400 ASTContext &ctx, SourceFile *sourceFile,
401401 SourceLoc loc, Identifier targetName, SourceLoc targetLoc,
402- bool isContinue, DeclContext *dc,
403- ArrayRef<LabeledStmt *> oldActiveLabeledStmts) {
402+ bool isContinue, DeclContext *dc) {
404403
405404 // Retrieve the active set of labeled statements.
406- // FIXME: Once everything uses ASTScope lookup, \c oldActiveLabeledStmts
407- // can go away.
408405 SmallVector<LabeledStmt *, 4 > activeLabeledStmts;
409406 activeLabeledStmts = ASTScope::lookupLabeledStmts (sourceFile, loc);
410407
@@ -603,17 +600,13 @@ static void checkFallthroughPatternBindingsAndTypes(
603600// / Check the correctness of a 'fallthrough' statement.
604601// /
605602// / \returns true if an error occurred.
606- static bool checkFallthroughStmt (
607- DeclContext *dc, FallthroughStmt *stmt,
608- CaseStmt *oldFallthroughSource, CaseStmt *oldFallthroughDest) {
603+ static bool checkFallthroughStmt (DeclContext *dc, FallthroughStmt *stmt) {
609604 CaseStmt *fallthroughSource;
610605 CaseStmt *fallthroughDest;
611606 ASTContext &ctx = dc->getASTContext ();
612607 auto sourceFile = dc->getParentSourceFile ();
613608 std::tie (fallthroughSource, fallthroughDest) =
614609 ASTScope::lookupFallthroughSourceAndDest (sourceFile, stmt->getLoc ());
615- assert (fallthroughSource == oldFallthroughSource);
616- assert (fallthroughDest == oldFallthroughDest);
617610
618611 if (!fallthroughSource) {
619612 ctx.Diags .diagnose (stmt->getLoc (), diag::fallthrough_outside_switch);
@@ -639,88 +632,11 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
639632 // / DC - This is the current DeclContext.
640633 DeclContext *DC;
641634
642- // Scope information for control flow statements
643- // (break, continue, fallthrough).
644-
645- // / The level of loop nesting. 'break' and 'continue' are valid only in scopes
646- // / where this is greater than one.
647- // / FIXME: Only required because EnableASTScopeLookup can be false
648- SmallVector<LabeledStmt*, 2 > ActiveLabeledStmts;
649-
650- // / The destination block for a 'fallthrough' statement. Null if the switch
651- // / scope depth is zero or if we are checking the final 'case' of the current
652- // / switch.
653- // / FIXME: Only required because EnableASTScopeLookup can be false
654- CaseStmt /* nullable*/ *FallthroughSource = nullptr ;
655- CaseStmt /* nullable*/ *FallthroughDest = nullptr ;
656-
657635 // / Skip type checking any elements inside 'BraceStmt', also this is
658636 // / propagated to ConstraintSystem.
659637 bool LeaveBraceStmtBodyUnchecked = false ;
660638
661639 ASTContext &getASTContext () const { return Ctx; };
662-
663- struct AddLabeledStmt {
664- StmtChecker &SC;
665- AddLabeledStmt (StmtChecker &SC, LabeledStmt *LS) : SC(SC) {
666- // Verify that we don't have label shadowing.
667- auto sourceFile = SC.DC ->getParentSourceFile ();
668- checkLabeledStmtShadowing (SC.getASTContext (), sourceFile, LS);
669-
670- // In any case, remember that we're in this labeled statement so that
671- // break and continue are aware of it.
672- SC.ActiveLabeledStmts .push_back (LS);
673-
674- // Verify that the ASTScope-based query for active labeled statements
675- // is equivalent to what we have here.
676- if (LS->getStartLoc ().isValid () && sourceFile &&
677- !SC.getASTContext ().Diags .hadAnyError () &&
678- !SC.LeaveBraceStmtBodyUnchecked ) {
679- // The labeled statements from ASTScope lookup have the
680- // innermost labeled statement first, so reverse it to
681- // match the data structure maintained here.
682- auto activeFromASTScope = ASTScope::lookupLabeledStmts (
683- sourceFile, LS->getStartLoc ());
684- assert (activeFromASTScope.front () == LS);
685- std::reverse (activeFromASTScope.begin (), activeFromASTScope.end ());
686- if (activeFromASTScope != SC.ActiveLabeledStmts ) {
687- llvm::errs () << " Old: " ;
688- llvm::interleave (SC.ActiveLabeledStmts , [&](LabeledStmt *LS) {
689- llvm::errs () << LS;
690- }, [&] {
691- llvm::errs () << ' ' ;
692- });
693- llvm::errs () << " \n New: " ;
694- llvm::interleave (activeFromASTScope, [&](LabeledStmt *LS) {
695- llvm::errs () << LS;
696- }, [&] {
697- llvm::errs () << ' ' ;
698- });
699- llvm::errs () << " \n " ;
700- }
701- assert (activeFromASTScope == SC.ActiveLabeledStmts );
702- }
703- }
704- ~AddLabeledStmt () {
705- SC.ActiveLabeledStmts .pop_back ();
706- }
707- };
708-
709- struct AddSwitchNest {
710- StmtChecker &SC;
711- CaseStmt *OuterFallthroughSource;
712- CaseStmt *OuterFallthroughDest;
713- AddSwitchNest (StmtChecker &SC)
714- : SC(SC),
715- OuterFallthroughSource (SC.FallthroughSource),
716- OuterFallthroughDest(SC.FallthroughDest) {
717- }
718-
719- ~AddSwitchNest () {
720- SC.FallthroughSource = OuterFallthroughSource;
721- SC.FallthroughDest = OuterFallthroughDest;
722- }
723- };
724640
725641 StmtChecker (DeclContext *DC) : Ctx(DC->getASTContext ()), DC(DC) { }
726642
@@ -976,7 +892,8 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
976892 Stmt *visitIfStmt (IfStmt *IS) {
977893 typeCheckConditionForStatement (IS, DC);
978894
979- AddLabeledStmt ifNest (*this , IS);
895+ auto sourceFile = DC->getParentSourceFile ();
896+ checkLabeledStmtShadowing (getASTContext (), sourceFile, IS);
980897
981898 Stmt *S = IS->getThenStmt ();
982899 typeCheckStmt (S);
@@ -1000,7 +917,9 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
1000917 }
1001918
1002919 Stmt *visitDoStmt (DoStmt *DS) {
1003- AddLabeledStmt loopNest (*this , DS);
920+ auto sourceFile = DC->getParentSourceFile ();
921+ checkLabeledStmtShadowing (getASTContext (), sourceFile, DS);
922+
1004923 BraceStmt *S = DS->getBody ();
1005924 typeCheckStmt (S);
1006925 DS->setBody (S);
@@ -1010,20 +929,22 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
1010929 Stmt *visitWhileStmt (WhileStmt *WS) {
1011930 typeCheckConditionForStatement (WS, DC);
1012931
1013- AddLabeledStmt loopNest (*this , WS);
932+ auto sourceFile = DC->getParentSourceFile ();
933+ checkLabeledStmtShadowing (getASTContext (), sourceFile, WS);
934+
1014935 Stmt *S = WS->getBody ();
1015936 typeCheckStmt (S);
1016937 WS->setBody (S);
1017938
1018939 return WS;
1019940 }
1020941 Stmt *visitRepeatWhileStmt (RepeatWhileStmt *RWS) {
1021- {
1022- AddLabeledStmt loopNest (* this , RWS);
1023- Stmt *S = RWS-> getBody ();
1024- typeCheckStmt (S );
1025- RWS-> setBody (S);
1026- }
942+ auto sourceFile = DC-> getParentSourceFile ();
943+ checkLabeledStmtShadowing ( getASTContext (), sourceFile , RWS);
944+
945+ Stmt *S = RWS-> getBody ( );
946+ typeCheckStmt (S);
947+ RWS-> setBody (S);
1027948
1028949 Expr *E = RWS->getCond ();
1029950 TypeChecker::typeCheckCondition (E, DC);
@@ -1036,7 +957,9 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
1036957 return nullptr ;
1037958
1038959 // Type-check the body of the loop.
1039- AddLabeledStmt loopNest (*this , S);
960+ auto sourceFile = DC->getParentSourceFile ();
961+ checkLabeledStmtShadowing (getASTContext (), sourceFile, S);
962+
1040963 BraceStmt *Body = S->getBody ();
1041964 typeCheckStmt (Body);
1042965 S->setBody (Body);
@@ -1048,7 +971,7 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
1048971 if (auto target = findBreakOrContinueStmtTarget (
1049972 getASTContext (), DC->getParentSourceFile (), S->getLoc (),
1050973 S->getTargetName (), S->getTargetLoc (), /* isContinue=*/ false ,
1051- DC, ActiveLabeledStmts )) {
974+ DC)) {
1052975 S->setTarget (target);
1053976 }
1054977
@@ -1059,15 +982,15 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
1059982 if (auto target = findBreakOrContinueStmtTarget (
1060983 getASTContext (), DC->getParentSourceFile (), S->getLoc (),
1061984 S->getTargetName (), S->getTargetLoc (), /* isContinue=*/ true ,
1062- DC, ActiveLabeledStmts )) {
985+ DC)) {
1063986 S->setTarget (target);
1064987 }
1065988
1066989 return S;
1067990 }
1068991
1069992 Stmt *visitFallthroughStmt (FallthroughStmt *S) {
1070- if (checkFallthroughStmt (DC, S, FallthroughSource, FallthroughDest ))
993+ if (checkFallthroughStmt (DC, S))
1071994 return nullptr ;
1072995
1073996 return S;
@@ -1213,13 +1136,6 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
12131136 for (auto i = casesBegin; i != casesEnd; ++i) {
12141137 auto *caseBlock = *i;
12151138
1216- if (parentKind == CaseParentKind::Switch) {
1217- // Fallthrough transfers control to the next case block. In the
1218- // final case block, it is invalid. Only switch supports fallthrough.
1219- FallthroughSource = caseBlock;
1220- FallthroughDest = std::next (i) == casesEnd ? nullptr : *std::next (i);
1221- }
1222-
12231139 // Check restrictions on '@unknown'.
12241140 if (caseBlock->hasUnknownAttr ()) {
12251141 assert (parentKind == CaseParentKind::Switch &&
@@ -1246,8 +1162,8 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
12461162 Type subjectType = switchStmt->getSubjectExpr ()->getType ();
12471163
12481164 // Type-check the case blocks.
1249- AddSwitchNest switchNest (* this );
1250- AddLabeledStmt labelNest (* this , switchStmt);
1165+ auto sourceFile = DC-> getParentSourceFile ( );
1166+ checkLabeledStmtShadowing ( getASTContext (), sourceFile , switchStmt);
12511167
12521168 // Pre-emptively visit all Decls (#if/#warning/#error) that still exist in
12531169 // the list of raw cases.
@@ -1278,7 +1194,8 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
12781194 // The labels are in scope for both the 'do' and all of the catch
12791195 // clauses. This allows the user to break out of (or restart) the
12801196 // entire construct.
1281- AddLabeledStmt loopNest (*this , S);
1197+ auto sourceFile = DC->getParentSourceFile ();
1198+ checkLabeledStmtShadowing (getASTContext (), sourceFile, S);
12821199
12831200 // Type-check the 'do' body. Type failures in here will generally
12841201 // not cause type failures in the 'catch' clauses.
0 commit comments