Author: nico
Date: Tue Feb 13 13:31:47 2018
New Revision: 325052

URL: http://llvm.org/viewvc/llvm-project?rev=325052&view=rev
Log:
Teach Wreturn-type, Wunreachable-code, and alpha.deadcode.UnreachableCode to 
treat __assume(0) like __builtin_unreachable.

Fixes PR29134.
https://reviews.llvm.org/D43221

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

Modified: cfe/trunk/include/clang/AST/Expr.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=325052&r1=325051&r2=325052&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Tue Feb 13 13:31:47 2018
@@ -2357,6 +2357,10 @@ public:
   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() &&

Modified: cfe/trunk/lib/AST/Expr.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=325052&r1=325051&r2=325052&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Tue Feb 13 13:31:47 2018
@@ -2917,6 +2917,18 @@ bool Expr::isConstantInitializer(ASTCont
   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> {

Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=325052&r1=325051&r2=325052&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Tue Feb 13 13:31:47 2018
@@ -2134,7 +2134,7 @@ CFGBlock *CFGBuilder::VisitCallExpr(Call
   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;

Modified: cfe/trunk/lib/Analysis/ReachableCode.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ReachableCode.cpp?rev=325052&r1=325051&r2=325052&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ReachableCode.cpp (original)
+++ cfe/trunk/lib/Analysis/ReachableCode.cpp Tue Feb 13 13:31:47 2018
@@ -66,6 +66,21 @@ static bool isBuiltinUnreachable(const S
   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,6 +387,7 @@ namespace {
     llvm::BitVector &Reachable;
     SmallVector<const CFGBlock *, 10> WorkList;
     Preprocessor &PP;
+    ASTContext &C;
 
     typedef SmallVector<std::pair<const CFGBlock *, const Stmt *>, 12>
     DeferredLocsTy;
@@ -379,10 +395,10 @@ namespace {
     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 @@ void DeadCodeScan::reportDeadCode(const
 
   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 @@ void FindUnreachableCode(AnalysisDeclCon
     if (reachable[block->getBlockID()])
       continue;
     
-    DeadCodeScan DS(reachable, PP);
+    DeadCodeScan DS(reachable, PP, AC.getASTContext());
     numReachable += DS.scanBackwards(block, CB);
     
     if (numReachable == cfg->getNumBlockIDs())

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp?rev=325052&r1=325051&r2=325052&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/UnreachableCodeChecker.cpp Tue Feb 13 
13:31:47 2018
@@ -132,7 +132,8 @@ void UnreachableCodeChecker::checkEndAna
            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;
             }

Modified: cfe/trunk/test/Analysis/unreachable-code-path.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/unreachable-code-path.c?rev=325052&r1=325051&r2=325052&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/unreachable-code-path.c (original)
+++ cfe/trunk/test/Analysis/unreachable-code-path.c Tue Feb 13 13:31:47 2018
@@ -63,6 +63,7 @@ void test6(const char *c) {
   if (c) return;
   if (!c) return;
   __builtin_unreachable(); // no-warning
+  __builtin_assume(0); // no-warning
 }
 
 // Compile-time constant false positives

Modified: cfe/trunk/test/Sema/return.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/return.c?rev=325052&r1=325051&r2=325052&view=diff
==============================================================================
--- cfe/trunk/test/Sema/return.c (original)
+++ cfe/trunk/test/Sema/return.c Tue Feb 13 13:31:47 2018
@@ -283,6 +283,18 @@ lbl:
     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 {\

Modified: cfe/trunk/test/Sema/warn-unreachable.c
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-unreachable.c?rev=325052&r1=325051&r2=325052&view=diff
==============================================================================
--- cfe/trunk/test/Sema/warn-unreachable.c (original)
+++ cfe/trunk/test/Sema/warn-unreachable.c Tue Feb 13 13:31:47 2018
@@ -468,6 +468,7 @@ int pr13910_foo(int x) {
   else
     return x;
   __builtin_unreachable(); // expected no warning
+  __builtin_assume(0); // expected no warning
 }
 
 int pr13910_bar(int x) {
@@ -485,16 +486,19 @@ int pr13910_bar2(int x) {
     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
 }


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to