]> granicus.if.org Git - clang/commitdiff
Don't warn about unreachable code if the block starts with __builtin_unreachable().
authorJordy Rose <jediknil@belkadan.com>
Tue, 27 Jul 2010 03:39:53 +0000 (03:39 +0000)
committerJordy Rose <jediknil@belkadan.com>
Tue, 27 Jul 2010 03:39:53 +0000 (03:39 +0000)
The next step is to warn if a block labeled unreachable is, in fact, reachable. Somewhat related to PR810.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109487 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Checker/UnreachableCodeChecker.cpp
test/Analysis/unreachable-code-path.c

index 0af49a33fb0cb2ba66c1b70b4fe667f038b9cbd1..9ee3d02d2663d2c4cfa5cb9ca2d9ac2744f83aee 100644 (file)
@@ -10,7 +10,7 @@
 // path-sensitive analysis. We mark any path visited, and then walk the CFG as a
 // post-analysis to determine what was never visited.
 //
-// A similar flow-sensitive only check exists in Analysis/UnreachableCode.cpp
+// A similar flow-sensitive only check exists in Analysis/ReachableCode.cpp
 //===----------------------------------------------------------------------===//
 
 #include "clang/Checker/PathSensitive/CheckerVisitor.h"
@@ -19,6 +19,7 @@
 #include "clang/Checker/BugReporter/BugReporter.h"
 #include "GRExprEngineExperimentalChecks.h"
 #include "clang/AST/StmtCXX.h"
+#include "clang/Basic/Builtins.h"
 #include "llvm/ADT/SmallPtrSet.h"
 
 // The number of CFGBlock pointers we want to reserve memory for. This is used
@@ -79,6 +80,8 @@ void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G,
   if (!C)
     return;
 
+  ASTContext &Ctx = B.getContext();
+
   // Find CFGBlocks that were not covered by any node
   for (CFG::const_iterator I = C->begin(); I != C->end(); ++I) {
     const CFGBlock *CB = *I;
@@ -96,6 +99,18 @@ void UnreachableCodeChecker::VisitEndAnalysis(ExplodedGraph &G,
       if (S.getBegin().isMacroID() || S.getEnd().isMacroID() || S.isInvalid()
           || SL.isInvalid())
         continue;
+
+      // Special case for __builtin_unreachable.
+      // FIXME: This should be extended to include other unreachable markers,
+      // such as llvm_unreachable.
+      if (!CB->empty()) {
+        const Stmt *First = CB->front();
+        if (const CallExpr *CE = dyn_cast<CallExpr>(First)) {
+          if (CE->isBuiltinCall(Ctx) == Builtin::BI__builtin_unreachable)
+            continue;
+        }
+      }
+
       B.EmitBasicReport("Unreachable code", "This statement is never executed",
           SL, S);
     }
index cfe0408c3fe3bb2ebd7ceb73249c2d8e74efb099..e7e1d0b3ebca39c3b044d4c54832ed6c1b0ee581 100644 (file)
@@ -53,3 +53,9 @@ void test5(const char *c) {
   }
 }
 
+void test6(const char *c) {
+  if (c) return;
+  if (!c) return;
+  __builtin_unreachable(); // no-warning
+}
+