@@ -3022,11 +3022,14 @@ namespace {
30223022// / An ASTWalker that searches for any break/continue/return statements that
30233023// / jump out of the context the walker starts at.
30243024class JumpOutOfContextFinder : public ASTWalker {
3025+ const Stmt *ParentStmt;
30253026 TinyPtrVector<Stmt *> &Jumps;
30263027 SmallPtrSet<Stmt *, 4 > ParentLabeledStmts;
3028+ SmallPtrSet<CaseStmt *, 4 > ParentCaseStmts;
30273029
30283030public:
3029- JumpOutOfContextFinder (TinyPtrVector<Stmt *> &jumps) : Jumps(jumps) {}
3031+ JumpOutOfContextFinder (const Stmt *parentStmt, TinyPtrVector<Stmt *> &jumps)
3032+ : ParentStmt(parentStmt), Jumps(jumps) {}
30303033
30313034 MacroWalking getMacroWalkingBehavior () const override {
30323035 return MacroWalking::Expansion;
@@ -3035,9 +3038,11 @@ class JumpOutOfContextFinder : public ASTWalker {
30353038 PreWalkResult<Stmt *> walkToStmtPre (Stmt *S) override {
30363039 if (auto *LS = dyn_cast<LabeledStmt>(S))
30373040 ParentLabeledStmts.insert (LS);
3041+ if (auto *CS = dyn_cast<CaseStmt>(S))
3042+ ParentCaseStmts.insert (CS);
30383043
3039- // Cannot 'break', 'continue', or 'return' out of the statement. A jump to
3040- // a statement within a branch however is fine.
3044+ // Cannot 'break', 'continue', 'fallthrough' or 'return' out of the
3045+ // statement. A jump to a statement within a branch however is fine.
30413046 if (auto *BS = dyn_cast<BreakStmt>(S)) {
30423047 if (!ParentLabeledStmts.contains (BS->getTarget ()))
30433048 Jumps.push_back (BS);
@@ -3046,6 +3051,17 @@ class JumpOutOfContextFinder : public ASTWalker {
30463051 if (!ParentLabeledStmts.contains (CS->getTarget ()))
30473052 Jumps.push_back (CS);
30483053 }
3054+ if (auto *FS = dyn_cast<FallthroughStmt>(S)) {
3055+ // The source must either be in the parent statement, or must be a
3056+ // nested CaseStmt we've seen. If there's no source, we will have
3057+ // already diagnosed.
3058+ if (auto *source = FS->getFallthroughSource ()) {
3059+ if (source->getParentStmt () != ParentStmt &&
3060+ !ParentCaseStmts.contains (source)) {
3061+ Jumps.push_back (FS);
3062+ }
3063+ }
3064+ }
30493065 if (isa<ReturnStmt>(S) || isa<FailStmt>(S))
30503066 Jumps.push_back (S);
30513067
@@ -3057,6 +3073,11 @@ class JumpOutOfContextFinder : public ASTWalker {
30573073 assert (removed);
30583074 (void )removed;
30593075 }
3076+ if (auto *CS = dyn_cast<CaseStmt>(S)) {
3077+ auto removed = ParentCaseStmts.erase (CS);
3078+ assert (removed);
3079+ (void )removed;
3080+ }
30603081 return Action::Continue (S);
30613082 }
30623083
@@ -3072,10 +3093,11 @@ class JumpOutOfContextFinder : public ASTWalker {
30723093} // end anonymous namespace
30733094
30743095IsSingleValueStmtResult
3075- areBranchesValidForSingleValueStmt (ASTContext &ctx, ArrayRef<Stmt *> branches) {
3096+ areBranchesValidForSingleValueStmt (ASTContext &ctx, const Stmt *parentStmt,
3097+ ArrayRef<Stmt *> branches) {
30763098 TinyPtrVector<Stmt *> invalidJumps;
30773099 TinyPtrVector<Stmt *> unterminatedBranches;
3078- JumpOutOfContextFinder jumpFinder (invalidJumps);
3100+ JumpOutOfContextFinder jumpFinder (parentStmt, invalidJumps);
30793101
30803102 // Must have a single expression brace, and non-single-expression branches
30813103 // must end with a throw.
@@ -3145,17 +3167,19 @@ IsSingleValueStmtRequest::evaluate(Evaluator &eval, const Stmt *S,
31453167 return IsSingleValueStmtResult::nonExhaustiveIf ();
31463168
31473169 SmallVector<Stmt *, 4 > scratch;
3148- return areBranchesValidForSingleValueStmt (ctx, IS->getBranches (scratch));
3170+ return areBranchesValidForSingleValueStmt (ctx, IS,
3171+ IS->getBranches (scratch));
31493172 }
31503173 if (auto *SS = dyn_cast<SwitchStmt>(S)) {
31513174 SmallVector<Stmt *, 4 > scratch;
3152- return areBranchesValidForSingleValueStmt (ctx, SS->getBranches (scratch));
3175+ return areBranchesValidForSingleValueStmt (ctx, SS,
3176+ SS->getBranches (scratch));
31533177 }
31543178 if (auto *DS = dyn_cast<DoStmt>(S)) {
31553179 if (!ctx.LangOpts .hasFeature (Feature::DoExpressions))
31563180 return IsSingleValueStmtResult::unhandledStmt ();
31573181
3158- return areBranchesValidForSingleValueStmt (ctx, DS->getBody ());
3182+ return areBranchesValidForSingleValueStmt (ctx, DS, DS ->getBody ());
31593183 }
31603184 if (auto *DCS = dyn_cast<DoCatchStmt>(S)) {
31613185 if (!ctx.LangOpts .hasFeature (Feature::DoExpressions))
@@ -3165,7 +3189,8 @@ IsSingleValueStmtRequest::evaluate(Evaluator &eval, const Stmt *S,
31653189 return IsSingleValueStmtResult::nonExhaustiveDoCatch ();
31663190
31673191 SmallVector<Stmt *, 4 > scratch;
3168- return areBranchesValidForSingleValueStmt (ctx, DCS->getBranches (scratch));
3192+ return areBranchesValidForSingleValueStmt (ctx, DCS,
3193+ DCS->getBranches (scratch));
31693194 }
31703195 return IsSingleValueStmtResult::unhandledStmt ();
31713196}
0 commit comments