nickdesaulniers created this revision. nickdesaulniers added reviewers: rsmith, aaron.ballman. Herald added a project: clang. Herald added a subscriber: cfe-commits. nickdesaulniers requested review of this revision.
Clang differs slightly than GCC for the pattern: switch (x) { case 0: ++x; default: break; } Clang will warn, GCC will not. This is making it excessively painful to enable -Wimplicit-fallthrough for Linux kernel builds with Clang, see below link in which 140 patches were sent to try to fix up these differences in kernel code. Kernel and GCC developers point out that Clang should not warn in this case. Link: https://github.com/ClangBuiltLinux/linux/issues/636 Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91432 Link: https://lore.kernel.org/lkml/CANiq72=E_gEVvqUUTSqU4zegC2=yZSTM4b=4G-iofp6d3=u...@mail.gmail.com/T/#t Signed-off-by: Nick Desaulniers <ndesaulni...@google.com> Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D91895 Files: clang/lib/Sema/AnalysisBasedWarnings.cpp clang/test/SemaCXX/switch-implicit-fallthrough-blocks.cpp clang/test/SemaCXX/switch-implicit-fallthrough.cpp
Index: clang/test/SemaCXX/switch-implicit-fallthrough.cpp =================================================================== --- clang/test/SemaCXX/switch-implicit-fallthrough.cpp +++ 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; } }; Index: clang/test/SemaCXX/switch-implicit-fallthrough-blocks.cpp =================================================================== --- clang/test/SemaCXX/switch-implicit-fallthrough-blocks.cpp +++ 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; } }; Index: clang/lib/Sema/AnalysisBasedWarnings.cpp =================================================================== --- clang/lib/Sema/AnalysisBasedWarnings.cpp +++ 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<BreakStmt>(Term)) + continue; + } + if (!LastStmt) { // This block contains no executable statements. // Traverse its predecessors. std::copy(P->pred_begin(), P->pred_end(),
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits