@@ -3022,11 +3022,14 @@ namespace {
3022
3022
// / An ASTWalker that searches for any break/continue/return statements that
3023
3023
// / jump out of the context the walker starts at.
3024
3024
class JumpOutOfContextFinder : public ASTWalker {
3025
+ const Stmt *ParentStmt;
3025
3026
TinyPtrVector<Stmt *> &Jumps;
3026
3027
SmallPtrSet<Stmt *, 4 > ParentLabeledStmts;
3028
+ SmallPtrSet<CaseStmt *, 4 > ParentCaseStmts;
3027
3029
3028
3030
public:
3029
- JumpOutOfContextFinder (TinyPtrVector<Stmt *> &jumps) : Jumps(jumps) {}
3031
+ JumpOutOfContextFinder (const Stmt *parentStmt, TinyPtrVector<Stmt *> &jumps)
3032
+ : ParentStmt(parentStmt), Jumps(jumps) {}
3030
3033
3031
3034
MacroWalking getMacroWalkingBehavior () const override {
3032
3035
return MacroWalking::Expansion;
@@ -3035,9 +3038,11 @@ class JumpOutOfContextFinder : public ASTWalker {
3035
3038
PreWalkResult<Stmt *> walkToStmtPre (Stmt *S) override {
3036
3039
if (auto *LS = dyn_cast<LabeledStmt>(S))
3037
3040
ParentLabeledStmts.insert (LS);
3041
+ if (auto *CS = dyn_cast<CaseStmt>(S))
3042
+ ParentCaseStmts.insert (CS);
3038
3043
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.
3041
3046
if (auto *BS = dyn_cast<BreakStmt>(S)) {
3042
3047
if (!ParentLabeledStmts.contains (BS->getTarget ()))
3043
3048
Jumps.push_back (BS);
@@ -3046,6 +3051,17 @@ class JumpOutOfContextFinder : public ASTWalker {
3046
3051
if (!ParentLabeledStmts.contains (CS->getTarget ()))
3047
3052
Jumps.push_back (CS);
3048
3053
}
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
+ }
3049
3065
if (isa<ReturnStmt>(S) || isa<FailStmt>(S))
3050
3066
Jumps.push_back (S);
3051
3067
@@ -3057,6 +3073,11 @@ class JumpOutOfContextFinder : public ASTWalker {
3057
3073
assert (removed);
3058
3074
(void )removed;
3059
3075
}
3076
+ if (auto *CS = dyn_cast<CaseStmt>(S)) {
3077
+ auto removed = ParentCaseStmts.erase (CS);
3078
+ assert (removed);
3079
+ (void )removed;
3080
+ }
3060
3081
return Action::Continue (S);
3061
3082
}
3062
3083
@@ -3072,10 +3093,11 @@ class JumpOutOfContextFinder : public ASTWalker {
3072
3093
} // end anonymous namespace
3073
3094
3074
3095
IsSingleValueStmtResult
3075
- areBranchesValidForSingleValueStmt (ASTContext &ctx, ArrayRef<Stmt *> branches) {
3096
+ areBranchesValidForSingleValueStmt (ASTContext &ctx, const Stmt *parentStmt,
3097
+ ArrayRef<Stmt *> branches) {
3076
3098
TinyPtrVector<Stmt *> invalidJumps;
3077
3099
TinyPtrVector<Stmt *> unterminatedBranches;
3078
- JumpOutOfContextFinder jumpFinder (invalidJumps);
3100
+ JumpOutOfContextFinder jumpFinder (parentStmt, invalidJumps);
3079
3101
3080
3102
// Must have a single expression brace, and non-single-expression branches
3081
3103
// must end with a throw.
@@ -3145,17 +3167,19 @@ IsSingleValueStmtRequest::evaluate(Evaluator &eval, const Stmt *S,
3145
3167
return IsSingleValueStmtResult::nonExhaustiveIf ();
3146
3168
3147
3169
SmallVector<Stmt *, 4 > scratch;
3148
- return areBranchesValidForSingleValueStmt (ctx, IS->getBranches (scratch));
3170
+ return areBranchesValidForSingleValueStmt (ctx, IS,
3171
+ IS->getBranches (scratch));
3149
3172
}
3150
3173
if (auto *SS = dyn_cast<SwitchStmt>(S)) {
3151
3174
SmallVector<Stmt *, 4 > scratch;
3152
- return areBranchesValidForSingleValueStmt (ctx, SS->getBranches (scratch));
3175
+ return areBranchesValidForSingleValueStmt (ctx, SS,
3176
+ SS->getBranches (scratch));
3153
3177
}
3154
3178
if (auto *DS = dyn_cast<DoStmt>(S)) {
3155
3179
if (!ctx.LangOpts .hasFeature (Feature::DoExpressions))
3156
3180
return IsSingleValueStmtResult::unhandledStmt ();
3157
3181
3158
- return areBranchesValidForSingleValueStmt (ctx, DS->getBody ());
3182
+ return areBranchesValidForSingleValueStmt (ctx, DS, DS ->getBody ());
3159
3183
}
3160
3184
if (auto *DCS = dyn_cast<DoCatchStmt>(S)) {
3161
3185
if (!ctx.LangOpts .hasFeature (Feature::DoExpressions))
@@ -3165,7 +3189,8 @@ IsSingleValueStmtRequest::evaluate(Evaluator &eval, const Stmt *S,
3165
3189
return IsSingleValueStmtResult::nonExhaustiveDoCatch ();
3166
3190
3167
3191
SmallVector<Stmt *, 4 > scratch;
3168
- return areBranchesValidForSingleValueStmt (ctx, DCS->getBranches (scratch));
3192
+ return areBranchesValidForSingleValueStmt (ctx, DCS,
3193
+ DCS->getBranches (scratch));
3169
3194
}
3170
3195
return IsSingleValueStmtResult::unhandledStmt ();
3171
3196
}
0 commit comments