forked from OSchip/llvm-project
Teach Wreturn-type, Wunreachable-code, and alpha.deadcode.UnreachableCode to treat __assume(0) like __builtin_unreachable.
Fixes PR29134. https://reviews.llvm.org/D43221 llvm-svn: 325052
This commit is contained in:
parent
fdb3b036cc
commit
758fbacea5
|
@ -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() &&
|
||||
|
|
|
@ -2917,6 +2917,18 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef,
|
|||
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> {
|
||||
|
|
|
@ -2134,7 +2134,7 @@ CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
|
|||
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;
|
||||
|
|
|
@ -66,6 +66,21 @@ static bool isBuiltinUnreachable(const Stmt *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 CFGBlock *B,
|
|||
|
||||
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(AnalysisDeclContext &AC, Preprocessor &PP,
|
|||
if (reachable[block->getBlockID()])
|
||||
continue;
|
||||
|
||||
DeadCodeScan DS(reachable, PP);
|
||||
DeadCodeScan DS(reachable, PP, AC.getASTContext());
|
||||
numReachable += DS.scanBackwards(block, CB);
|
||||
|
||||
if (numReachable == cfg->getNumBlockIDs())
|
||||
|
|
|
@ -132,7 +132,8 @@ void UnreachableCodeChecker::checkEndAnalysis(ExplodedGraph &G,
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {\
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue