r203036 - [-Wunreachable-code] Handle idiomatic do...while() with an uninteresting condition.

Ted Kremenek kremenek at apple.com
Wed Mar 5 16:17:44 PST 2014


Author: kremenek
Date: Wed Mar  5 18:17:44 2014
New Revision: 203036

URL: http://llvm.org/viewvc/llvm-project?rev=203036&view=rev
Log:
[-Wunreachable-code] Handle idiomatic do...while() with an uninteresting condition.

Sometimes do..while() is used to create a scope that can be left early.
In such cases, the unreachable 'while()' test is not usually interesting
unless it actually does something that is observable.

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=203036&r1=203035&r2=203036&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ReachableCode.cpp (original)
+++ cfe/trunk/lib/Analysis/ReachableCode.cpp Wed Mar  5 18:17:44 2014
@@ -296,10 +296,7 @@ static bool isTrivialExpression(const Ex
          isEnumConstant(Ex);
 }
 
-static bool isTrivialReturn(const CFGBlock *B, const Stmt *S) {
-  if (B->pred_empty())
-    return false;
-
+static bool isTrivialReturnOrDoWhile(const CFGBlock *B, const Stmt *S) {
   const Expr *Ex = dyn_cast<Expr>(S);
   if (!Ex)
     return false;
@@ -307,6 +304,16 @@ static bool isTrivialReturn(const CFGBlo
   if (!isTrivialExpression(Ex))
     return false;
 
+  // Check if the block ends with a do...while() and see if 'S' is the
+  // condition.
+  if (const Stmt *Term = B->getTerminator()) {
+    if (const DoStmt *DS = dyn_cast<DoStmt>(Term))
+      if (DS->getCond() == S)
+        return true;
+  }
+
+
+
   // Look to see if the block ends with a 'return', and see if 'S'
   // is a substatement.  The 'return' may not be the last element in
   // the block because of destructors.
@@ -317,12 +324,15 @@ static bool isTrivialReturn(const CFGBlo
       if (const ReturnStmt *RS = dyn_cast<ReturnStmt>(CS->getStmt())) {
         const Expr *RE = RS->getRetValue();
         if (RE && RE->IgnoreParenCasts() == Ex)
-          return true;
+          break;
       }
-      break;
+      return false;
     }
   }
 
+  if (B->pred_size() == 1)
+    return bodyEndsWithNoReturn(*B->pred_begin());
+
   return false;
 }
 
@@ -336,7 +346,7 @@ void DeadCodeScan::reportDeadCode(const
     return;
 
   // Suppress trivial 'return' statements that are dead.
-  if (isTrivialReturn(B, S))
+  if (isTrivialReturnOrDoWhile(B, S))
     return;
 
   SourceRange R1, R2;

Modified: cfe/trunk/test/Sema/warn-unreachable.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-unreachable.c?rev=203036&r1=203035&r2=203036&view=diff
==============================================================================
--- cfe/trunk/test/Sema/warn-unreachable.c (original)
+++ cfe/trunk/test/Sema/warn-unreachable.c Wed Mar  5 18:17:44 2014
@@ -268,9 +268,31 @@ int test_MyEnum() {
     return 2; // no-warning
   if (ME_B)
     return 3;
-  // FIXME: we should only need one diagnostic here.
   if (!ME_B) // expected-warning {{will never be executed}}
-    return 4;// expected-warning {{will never be executed}}
+    return 4; // expected-warning {{will never be executed}}
   return 5;
 }
 
+// Test for idiomatic do..while.
+int test_do_while(int x) {
+  do {
+    if (x == calledFun())
+      break;
+    ++x;
+    break;
+  }
+  while (0); // no-warning
+  return x;
+}
+
+int test_do_while_nontrivial_cond(int x) {
+  do {
+    if (x == calledFun())
+      break;
+    ++x;
+    break;
+  }
+  while (calledFun()); // expected-warning {{will never be executed}}
+  return x;
+}
+





More information about the cfe-commits mailing list