]> granicus.if.org Git - clang/commitdiff
[-Wunreachable-code] Refine treating all branches of 'switch' as reachable, which...
authorTed Kremenek <kremenek@apple.com>
Thu, 6 Mar 2014 08:09:00 +0000 (08:09 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 6 Mar 2014 08:09:00 +0000 (08:09 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@203094 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/ReachableCode.cpp
test/Sema/warn-unreachable.c

index 79e8d8cb0180a533933afa37135fe83ebed2140c..45930c0e2d975067e83c762c4c2aa94205c03a3f 100644 (file)
@@ -457,6 +457,10 @@ static bool isConfigurationValue(const Stmt *S) {
 
 /// Returns true if we should always explore all successors of a block.
 static bool shouldTreatSuccessorsAsReachable(const CFGBlock *B) {
+  if (const Stmt *Term = B->getTerminator())
+    if (isa<SwitchStmt>(Term))
+      return true;
+
   return isConfigurationValue(B->getTerminatorCondition());
 }
 
@@ -500,24 +504,6 @@ unsigned ScanReachableFromBlock(const CFGBlock *Start,
           B = UB;
           break;
         }
-
-        // 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.
-        //
-        const Stmt *Label = UB->getLabel();
-        if (Label && isa<SwitchCase>(Label))
-          B = UB;
       }
       while (false);
 
index fe47e4c6b70c27b2e80942b143d74190a9a7e250..289d74336c9fe613341c9a4da37bf76211015edf 100644 (file)
@@ -226,6 +226,17 @@ MyEnum nontrivial_dead_return_enum_2(int x) {
   return calledFun(); // expected-warning {{will never be executed}}
 }
 
+enum X { A, B, C };
+
+int covered_switch(enum X x) {
+  switch (x) {
+  case A: return 1;
+  case B: return 2;
+  case C: return 3;
+  }
+  return 4; // no-warning
+}
+
 // Test unreachable code depending on configuration values
 #define CONFIG_CONSTANT 1
 int test_config_constant(int x) {