[cfe-commits] [PATCH] Don't warn on fall-through from unreachable code.

Alexander Kornienko alexfh at google.com
Sat Jan 26 19:55:53 PST 2013


  Fixed a stupid bug pointed out by rsmith.

  > Have you considered restructuring DiagnoseSwitchLabelsFallthrough to perform a
  > recursive walk over just the blocks reachable from the entry block, instead of
  > checking reachability with a separate pass?
  I thought about this, and I'll try. But here's a working version for backup, in
  case new code isn't much better than this.

Hi rsmith, doug.gregor,

http://llvm-reviews.chandlerc.com/D330

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D330?vs=769&id=776#toc

Files:
  lib/Sema/AnalysisBasedWarnings.cpp
  test/SemaCXX/switch-implicit-fallthrough.cpp

Index: lib/Sema/AnalysisBasedWarnings.cpp
===================================================================
--- lib/Sema/AnalysisBasedWarnings.cpp
+++ lib/Sema/AnalysisBasedWarnings.cpp
@@ -702,12 +702,29 @@
       return FallthroughStmts;
     }
 
-    bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt) {
+    bool checkFallThroughIntoBlock(const CFGBlock &B, int &AnnotatedCnt,
+                                   CFG *Cfg) {
+      std::deque<const CFGBlock *> BlockQueue;
+
+      if (ReachableBlocks.empty()) {
+        // Searching for all blocks reachable from the entry point.
+        BlockQueue.push_back(*Cfg->rbegin());
+        while (!BlockQueue.empty()) {
+          const CFGBlock *P = BlockQueue.front();
+          BlockQueue.pop_front();
+          ReachableBlocks.insert(P);
+          for (CFGBlock::const_succ_iterator I = P->succ_begin(),
+                                             E = P->succ_end();
+               I != E; ++I) {
+            if (!ReachableBlocks.count(*I))
+              BlockQueue.push_back(*I);
+          }
+        }
+      }
+
       int UnannotatedCnt = 0;
       AnnotatedCnt = 0;
 
-      std::deque<const CFGBlock*> BlockQueue;
-
       std::copy(B.pred_begin(), B.pred_end(), std::back_inserter(BlockQueue));
 
       while (!BlockQueue.empty()) {
@@ -726,8 +743,7 @@
         if (L && L->getSubStmt() == B.getLabel() && P->begin() == P->end())
           continue; // Case label is preceded with a normal label, good.
 
-        if (P->pred_begin() == P->pred_end()) {  // The block is unreachable.
-          // This only catches trivially unreachable blocks.
+        if (!ReachableBlocks.count(P)) {
           for (CFGBlock::const_iterator ElIt = P->begin(), ElEnd = P->end();
                ElIt != ElEnd; ++ElIt) {
             if (const CFGStmt *CS = ElIt->getAs<CFGStmt>()){
@@ -816,6 +832,7 @@
     bool FoundSwitchStatements;
     AttrStmts FallthroughStmts;
     Sema &S;
+    llvm::SmallPtrSet<const CFGBlock *, 16> ReachableBlocks;
   };
 }
 
@@ -856,7 +873,7 @@
     if (!Label || !isa<SwitchCase>(Label))
       continue;
 
-    if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt))
+    if (!FM.checkFallThroughIntoBlock(*B, AnnotatedCnt, Cfg))
       continue;
 
     S.Diag(Label->getLocStart(),
Index: test/SemaCXX/switch-implicit-fallthrough.cpp
===================================================================
--- test/SemaCXX/switch-implicit-fallthrough.cpp
+++ test/SemaCXX/switch-implicit-fallthrough.cpp
@@ -10,7 +10,7 @@
       } else if (n - 3) {
         n = 102;
       }
-    case -1: // 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}}
+    case -1:  // no warning here, ignore fall-through from unreachable code
       ;
     case 0: {// 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}}
     }
@@ -39,14 +39,13 @@
       break;
   }
   switch (n / 15) {
-label_case_70:
-    case 70:
+label_default:
+    default:
       n += 333;
+      if (n % 10)
+        goto label_default;
       break;
-    case 71:
-      n += 334;
-      goto label_case_70;
-    case 72:
+    case 70:
       n += 335;
       break;
   }
@@ -130,6 +129,22 @@
   }
 }
 
+void fallthrough3(int n) {
+  switch (n) {
+    case 1:
+      do {
+        return;
+      } while (0);
+    case 2:
+      do {
+        ClassWithDtor temp;
+        return;
+      } while (0);
+    case 3:
+      break;
+  }
+}
+
 #define MY_SWITCH(X, Y, Z, U, V) switch (X) { case Y: Z; case U: V; }
 #define MY_SWITCH2(X, Y, Z) switch (X) { Y; Z; }
 #define MY_CASE(X, Y) case X: Y
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D330.4.patch
Type: text/x-patch
Size: 3842 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130126/79a5f0dc/attachment.bin>


More information about the cfe-commits mailing list