diff --git a/clang/lib/Sema/AnalysisBasedWarnings.cpp b/clang/lib/Sema/AnalysisBasedWarnings.cpp --- a/clang/lib/Sema/AnalysisBasedWarnings.cpp +++ b/clang/lib/Sema/AnalysisBasedWarnings.cpp @@ -1149,6 +1149,15 @@ continue; // Fallthrough annotation, good. } + // If next statment in P's successor is a break with no other + // statements, no issue. + if (P->succ_size() == 1) { + const CFGBlock::AdjacentBlock &Succ = *P->succ_begin(); + const Stmt *Term = B.getTerminatorStmt(); + if (Succ->size() == 0 && Term && isa(Term)) + continue; + } + if (!LastStmt) { // This block contains no executable statements. // Traverse its predecessors. std::copy(P->pred_begin(), P->pred_end(), diff --git a/clang/test/SemaCXX/switch-implicit-fallthrough-blocks.cpp b/clang/test/SemaCXX/switch-implicit-fallthrough-blocks.cpp --- a/clang/test/SemaCXX/switch-implicit-fallthrough-blocks.cpp +++ b/clang/test/SemaCXX/switch-implicit-fallthrough-blocks.cpp @@ -7,11 +7,17 @@ case 0: x++; [[clang::fallthrough]]; // no diagnostics + case 2: + x++; + case 3: // no diagnostics + break; case 1: x++; default: // \ expected-warning{{unannotated fall-through between switch labels}} \ + expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} \ expected-note{{insert 'break;' to avoid fall-through}} + x++; break; } }; diff --git a/clang/test/SemaCXX/switch-implicit-fallthrough.cpp b/clang/test/SemaCXX/switch-implicit-fallthrough.cpp --- a/clang/test/SemaCXX/switch-implicit-fallthrough.cpp +++ b/clang/test/SemaCXX/switch-implicit-fallthrough.cpp @@ -151,23 +151,23 @@ #define MY_CASE2(X, Y, U, V) case X: Y; case U: V int fallthrough_macro1(int n) { - MY_SWITCH(n, 13, n *= 2, 14, break) // expected-warning{{unannotated fall-through between switch labels}} + MY_SWITCH(n, 13, n *= 2, 14, break) switch (n + 1) { MY_CASE(33, n += 2); - MY_CASE(44, break); // expected-warning{{unannotated fall-through between switch labels}} - MY_CASE(55, n += 3); + MY_CASE(44, n += 3); // expected-warning{{unannotated fall-through between switch labels}} + MY_CASE(55, break); } switch (n + 3) { MY_CASE(333, return 333); - MY_CASE2(444, n += 44, 4444, break); // expected-warning{{unannotated fall-through between switch labels}} + MY_CASE2(444, n += 44, 4444, break); MY_CASE(555, n += 33); } - MY_SWITCH2(n + 4, MY_CASE(17, n *= 3), MY_CASE(19, break)) // expected-warning{{unannotated fall-through between switch labels}} + MY_SWITCH2(n + 4, MY_CASE(17, n *= 3), MY_CASE(19, break)) - MY_SWITCH2(n + 5, MY_CASE(21, break), MY_CASE2(23, n *= 7, 25, break)) // expected-warning{{unannotated fall-through between switch labels}} + MY_SWITCH2(n + 5, MY_CASE(21, break), MY_CASE2(23, n *= 7, 25, break)) return n; } @@ -237,9 +237,15 @@ [[clang::fallthrough]]; // no diagnostics case 1: x++; + case 2: // no diagnostics + break; + case 3: + x++; default: // \ expected-warning{{unannotated fall-through between switch labels}} \ + expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} \ expected-note{{insert 'break;' to avoid fall-through}} + x++; break; } } @@ -257,9 +263,15 @@ [[clang::fallthrough]]; // no diagnostics case 1: x++; + case 2: // no diagnostics + break; + case 3: + x++; default: // \ expected-warning{{unannotated fall-through between switch labels}} \ + expected-note{{insert '[[clang::fallthrough]];' to silence this warning}} \ expected-note{{insert 'break;' to avoid fall-through}} + x++; break; } };