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