thakis created this revision.
thakis added reviewers: rsmith, rnk.
Herald added a subscriber: whisperity.

Fixes PR29134.


https://reviews.llvm.org/D43221

Files:
  include/clang/AST/Expr.h
  lib/AST/Expr.cpp
  lib/Analysis/CFG.cpp
  lib/Analysis/ReachableCode.cpp
  lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
  test/Analysis/unreachable-code-path.c
  test/Sema/return.c
  test/Sema/warn-unreachable.c

Index: test/Sema/warn-unreachable.c
===================================================================
--- test/Sema/warn-unreachable.c
+++ test/Sema/warn-unreachable.c
@@ -468,6 +468,7 @@
   else
     return x;
   __builtin_unreachable(); // expected no warning
+  __builtin_assume(0); // expected no warning
 }
 
 int pr13910_bar(int x) {
@@ -485,16 +486,19 @@
     return x;
   pr13910_foo(x);          // expected-warning {{code will never be executed}}
   __builtin_unreachable(); // expected no warning
+  __builtin_assume(0);     // expected no warning
   pr13910_foo(x);          // expected-warning {{code will never be executed}}
 }
 
 void pr13910_noreturn() {
   raze();
   __builtin_unreachable(); // expected no warning
+  __builtin_assume(0); // expected no warning
 }
 
 void pr13910_assert() {
   myassert(0 && "unreachable");
   return;
   __builtin_unreachable(); // expected no warning
+  __builtin_assume(0); // expected no warning
 }
Index: test/Sema/return.c
===================================================================
--- test/Sema/return.c
+++ test/Sema/return.c
@@ -283,6 +283,18 @@
     goto lbl;
 }
 
+int test36a(int b) {
+  if (b)
+    return 43;
+  __builtin_unreachable();
+}
+
+int test36b(int b) {
+  if (b)
+    return 43;
+  __builtin_assume(0);
+}
+
 // PR19074.
 void abort(void) __attribute__((noreturn));
 #define av_assert0(cond) do {\
Index: test/Analysis/unreachable-code-path.c
===================================================================
--- test/Analysis/unreachable-code-path.c
+++ test/Analysis/unreachable-code-path.c
@@ -63,6 +63,7 @@
   if (c) return;
   if (!c) return;
   __builtin_unreachable(); // no-warning
+  __builtin_assume(0); // no-warning
 }
 
 // Compile-time constant false positives
Index: lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
+++ lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
@@ -132,7 +132,8 @@
            ci != ce; ++ci) {
         if (Optional<CFGStmt> S = (*ci).getAs<CFGStmt>())
           if (const CallExpr *CE = dyn_cast<CallExpr>(S->getStmt())) {
-            if (CE->getBuiltinCallee() == Builtin::BI__builtin_unreachable) {
+            if (CE->getBuiltinCallee() == Builtin::BI__builtin_unreachable ||
+                CE->isBuiltinAssumeFalse(Eng.getContext())) {
               foundUnreachable = true;
               break;
             }
Index: lib/Analysis/ReachableCode.cpp
===================================================================
--- lib/Analysis/ReachableCode.cpp
+++ lib/Analysis/ReachableCode.cpp
@@ -66,6 +66,21 @@
   return false;
 }
 
+static bool isBuiltinAssumeFalse(const CFGBlock *B, const Stmt *S,
+                                 ASTContext &C) {
+  if (B->empty())  {
+    // Happens if S is B's terminator and B contains nothing else
+    // (e.g. a CFGBlock containing only a goto).
+    return false;
+  }
+  if (Optional<CFGStmt> CS = B->back().getAs<CFGStmt>()) {
+    if (const auto *CE = dyn_cast<CallExpr>(CS->getStmt())) {
+      return CE->getCallee()->IgnoreCasts() == S && CE->isBuiltinAssumeFalse(C);
+    }
+  }
+  return false;
+}
+
 static bool isDeadReturn(const CFGBlock *B, const Stmt *S) {
   // Look to see if the current control flow ends with a 'return', and see if
   // 'S' is a substatement. The 'return' may not be the last element in the
@@ -372,17 +387,18 @@
     llvm::BitVector &Reachable;
     SmallVector<const CFGBlock *, 10> WorkList;
     Preprocessor &PP;
+    ASTContext &C;
 
     typedef SmallVector<std::pair<const CFGBlock *, const Stmt *>, 12>
     DeferredLocsTy;
 
     DeferredLocsTy DeferredLocs;
 
   public:
-    DeadCodeScan(llvm::BitVector &reachable, Preprocessor &PP)
+    DeadCodeScan(llvm::BitVector &reachable, Preprocessor &PP, ASTContext &C)
     : Visited(reachable.size()),
       Reachable(reachable),
-      PP(PP) {}
+      PP(PP), C(C) {}
 
     void enqueue(const CFGBlock *block);
     unsigned scanBackwards(const CFGBlock *Start,
@@ -600,7 +616,8 @@
 
   if (isa<BreakStmt>(S)) {
     UK = reachable_code::UK_Break;
-  } else if (isTrivialDoWhile(B, S) || isBuiltinUnreachable(S)) {
+  } else if (isTrivialDoWhile(B, S) || isBuiltinUnreachable(S) ||
+             isBuiltinAssumeFalse(B, S, C)) {
     return;
   }
   else if (isDeadReturn(B, S)) {
@@ -693,7 +710,7 @@
     if (reachable[block->getBlockID()])
       continue;
     
-    DeadCodeScan DS(reachable, PP);
+    DeadCodeScan DS(reachable, PP, AC.getASTContext());
     numReachable += DS.scanBackwards(block, CB);
     
     if (numReachable == cfg->getNumBlockIDs())
Index: lib/Analysis/CFG.cpp
===================================================================
--- lib/Analysis/CFG.cpp
+++ lib/Analysis/CFG.cpp
@@ -2078,7 +2078,7 @@
   bool OmitArguments = false;
 
   if (FunctionDecl *FD = C->getDirectCallee()) {
-    if (FD->isNoReturn())
+    if (FD->isNoReturn() || C->isBuiltinAssumeFalse(*Context))
       NoReturn = true;
     if (FD->hasAttr<NoThrowAttr>())
       AddEHEdge = false;
Index: lib/AST/Expr.cpp
===================================================================
--- lib/AST/Expr.cpp
+++ lib/AST/Expr.cpp
@@ -2917,6 +2917,18 @@
   return false;
 }
 
+bool CallExpr::isBuiltinAssumeFalse(const ASTContext &Ctx) const {
+  const FunctionDecl* FD = getDirectCallee();
+  if (!FD || (FD->getBuiltinID() != Builtin::BI__assume &&
+              FD->getBuiltinID() != Builtin::BI__builtin_assume))
+    return false;
+  
+  const Expr* Arg = getArg(0);
+  bool ArgVal;
+  return !Arg->isValueDependent() &&
+         Arg->EvaluateAsBooleanCondition(ArgVal, Ctx) && !ArgVal;
+}
+
 namespace {
   /// \brief Look for any side effects within a Stmt.
   class SideEffectFinder : public ConstEvaluatedExprVisitor<SideEffectFinder> {
Index: include/clang/AST/Expr.h
===================================================================
--- include/clang/AST/Expr.h
+++ include/clang/AST/Expr.h
@@ -2357,6 +2357,10 @@
   SourceLocation getLocStart() const LLVM_READONLY;
   SourceLocation getLocEnd() const LLVM_READONLY;
 
+  /// Return true if this is a call to __assume() or __builtin_assume() with
+  /// a non-value-dependent constant parameter evaluating as false.
+  bool isBuiltinAssumeFalse(const ASTContext &Ctx) const;
+
   bool isCallToStdMove() const {
     const FunctionDecl* FD = getDirectCallee();
     return getNumArgs() == 1 && FD && FD->isInStdNamespace() &&
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to