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

Reply via email to