r202436 - [-Wunreachable-code] always treat 'case:' and 'default:' cases as reachable.

Ted Kremenek kremenek at apple.com
Thu Feb 27 13:56:47 PST 2014


Author: kremenek
Date: Thu Feb 27 15:56:47 2014
New Revision: 202436

URL: http://llvm.org/viewvc/llvm-project?rev=202436&view=rev
Log:
[-Wunreachable-code] always treat 'case:' and 'default:' cases as reachable.

This is a heuristic.  Many switch statements, although they look covered
over an enum, may actually handle at runtime more values than in the enum.

This is overly conservative, as there are some cases that clearly
can be ruled as being clearly unreachable, e.g. 'switch (42) { case 1: ... }'.
We can refine this later.

Modified:
    cfe/trunk/lib/Analysis/ReachableCode.cpp
    cfe/trunk/test/Sema/warn-unreachable.c

Modified: cfe/trunk/lib/Analysis/ReachableCode.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ReachableCode.cpp?rev=202436&r1=202435&r2=202436&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ReachableCode.cpp (original)
+++ cfe/trunk/lib/Analysis/ReachableCode.cpp Thu Feb 27 15:56:47 2014
@@ -337,12 +337,6 @@ void DeadCodeScan::reportDeadCode(const
   if (isTrivialReturnPrecededByNoReturn(B, S))
     return;
 
-  // Was this an unreachable 'default' case?  Such cases are covered
-  // by -Wcovered-switch-default, if the user so desires.
-  const Stmt *Label = B->getLabel();
-  if (Label && isa<DefaultStmt>(Label))
-    return;
-
   SourceRange R1, R2;
   SourceLocation Loc = GetUnreachableLoc(S, R1, R2);
   CB.HandleUnreachable(Loc, R1, R2);
@@ -374,8 +368,32 @@ unsigned ScanReachableFromBlock(const CF
     
     // Look at the successors and mark then reachable.
     for (CFGBlock::const_succ_iterator I = item->succ_begin(), 
-         E = item->succ_end(); I != E; ++I)
-      if (const CFGBlock *B = *I) {
+         E = item->succ_end(); I != E; ++I) {
+      const CFGBlock *B = *I;
+      if (!B) {
+        //
+        // For switch statements, treat all cases as being reachable.
+        // There are many cases where a switch can contain values that
+        // are not in an enumeration but they are still reachable because
+        // other values are possible.
+        //
+        // Note that this is quite conservative.  If one saw:
+        //
+        //  switch (1) {
+        //    case 2: ...
+        //
+        // we should be able to say that 'case 2' is unreachable.  To do
+        // this we can either put more heuristics here, or possibly retain
+        // that information in the CFG itself.
+        //
+        if (const CFGBlock *UB = I->getPossiblyUnreachableBlock()) {
+          const Stmt *Label = UB->getLabel();
+          if (Label && isa<SwitchCase>(Label)) {
+            B = UB;
+          }
+        }
+      }
+      if (B) {
         unsigned blockID = B->getBlockID();
         if (!Reachable[blockID]) {
           Reachable.set(blockID);
@@ -383,6 +401,7 @@ unsigned ScanReachableFromBlock(const CF
           ++count;
         }
       }
+    }
   }
   return count;
 }

Modified: cfe/trunk/test/Sema/warn-unreachable.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-unreachable.c?rev=202436&r1=202435&r2=202436&view=diff
==============================================================================
--- cfe/trunk/test/Sema/warn-unreachable.c (original)
+++ cfe/trunk/test/Sema/warn-unreachable.c Thu Feb 27 15:56:47 2014
@@ -173,6 +173,9 @@ void unreachable_default(MyEnum e) {
   case Value1:
     calledFun();
     break;
+  case 2: // expected-warning {{case value not in enumerated type 'MyEnum'}}
+    calledFun();
+    break;
   default:
     calledFun(); // no-warning
     break;





More information about the cfe-commits mailing list