Extract mark-no-return-function code into a function.
llvm-svn: 80979
This commit is contained in:
parent
1eaa90b901
commit
1748d8a43d
|
|
@ -1417,6 +1417,88 @@ static bool EvalOSAtomic(ExplodedNodeSet& Dst,
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Transfer function: Function calls.
|
// Transfer function: Function calls.
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
static void MarkNoReturnFunction(const FunctionDecl *FD, CallExpr *CE,
|
||||||
|
const GRState *state,
|
||||||
|
GRStmtNodeBuilder *Builder) {
|
||||||
|
if (FD->getAttr<NoReturnAttr>() ||
|
||||||
|
FD->getAttr<AnalyzerNoReturnAttr>())
|
||||||
|
Builder->BuildSinks = true;
|
||||||
|
else {
|
||||||
|
// HACK: Some functions are not marked noreturn, and don't return.
|
||||||
|
// Here are a few hardwired ones. If this takes too long, we can
|
||||||
|
// potentially cache these results.
|
||||||
|
const char* s = FD->getIdentifier()->getName();
|
||||||
|
unsigned n = strlen(s);
|
||||||
|
|
||||||
|
switch (n) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
if (!memcmp(s, "exit", 4)) Builder->BuildSinks = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 5:
|
||||||
|
if (!memcmp(s, "panic", 5)) Builder->BuildSinks = true;
|
||||||
|
else if (!memcmp(s, "error", 5)) {
|
||||||
|
if (CE->getNumArgs() > 0) {
|
||||||
|
SVal X = state->getSVal(*CE->arg_begin());
|
||||||
|
// FIXME: use Assume to inspect the possible symbolic value of
|
||||||
|
// X. Also check the specific signature of error().
|
||||||
|
nonloc::ConcreteInt* CI = dyn_cast<nonloc::ConcreteInt>(&X);
|
||||||
|
if (CI && CI->getValue() != 0)
|
||||||
|
Builder->BuildSinks = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 6:
|
||||||
|
if (!memcmp(s, "Assert", 6)) {
|
||||||
|
Builder->BuildSinks = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: This is just a wrapper around throwing an exception.
|
||||||
|
// Eventually inter-procedural analysis should handle this easily.
|
||||||
|
if (!memcmp(s, "ziperr", 6)) Builder->BuildSinks = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 7:
|
||||||
|
if (!memcmp(s, "assfail", 7)) Builder->BuildSinks = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
if (!memcmp(s ,"db_error", 8) ||
|
||||||
|
!memcmp(s, "__assert", 8))
|
||||||
|
Builder->BuildSinks = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 12:
|
||||||
|
if (!memcmp(s, "__assert_rtn", 12)) Builder->BuildSinks = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 13:
|
||||||
|
if (!memcmp(s, "__assert_fail", 13)) Builder->BuildSinks = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 14:
|
||||||
|
if (!memcmp(s, "dtrace_assfail", 14) ||
|
||||||
|
!memcmp(s, "yy_fatal_error", 14))
|
||||||
|
Builder->BuildSinks = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 26:
|
||||||
|
if (!memcmp(s, "_XCAssertionFailureHandler", 26) ||
|
||||||
|
!memcmp(s, "_DTAssertionFailureHandler", 26) ||
|
||||||
|
!memcmp(s, "_TSAssertionFailureHandler", 26))
|
||||||
|
Builder->BuildSinks = true;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GRExprEngine::EvalCall(ExplodedNodeSet& Dst, CallExpr* CE, SVal L,
|
void GRExprEngine::EvalCall(ExplodedNodeSet& Dst, CallExpr* CE, SVal L,
|
||||||
ExplodedNode* Pred) {
|
ExplodedNode* Pred) {
|
||||||
|
|
@ -1498,86 +1580,8 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, ExplodedNode* Pred,
|
||||||
|
|
||||||
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
|
SaveAndRestore<bool> OldSink(Builder->BuildSinks);
|
||||||
const FunctionDecl* FD = L.getAsFunctionDecl();
|
const FunctionDecl* FD = L.getAsFunctionDecl();
|
||||||
if (FD) {
|
if (FD)
|
||||||
if (FD->getAttr<NoReturnAttr>() ||
|
MarkNoReturnFunction(FD, CE, state, Builder);
|
||||||
FD->getAttr<AnalyzerNoReturnAttr>())
|
|
||||||
Builder->BuildSinks = true;
|
|
||||||
else {
|
|
||||||
// HACK: Some functions are not marked noreturn, and don't return.
|
|
||||||
// Here are a few hardwired ones. If this takes too long, we can
|
|
||||||
// potentially cache these results.
|
|
||||||
const char* s = FD->getIdentifier()->getName();
|
|
||||||
unsigned n = strlen(s);
|
|
||||||
|
|
||||||
switch (n) {
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 4:
|
|
||||||
if (!memcmp(s, "exit", 4)) Builder->BuildSinks = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 5:
|
|
||||||
if (!memcmp(s, "panic", 5)) Builder->BuildSinks = true;
|
|
||||||
else if (!memcmp(s, "error", 5)) {
|
|
||||||
if (CE->getNumArgs() > 0) {
|
|
||||||
SVal X = state->getSVal(*CE->arg_begin());
|
|
||||||
// FIXME: use Assume to inspect the possible symbolic value of
|
|
||||||
// X. Also check the specific signature of error().
|
|
||||||
nonloc::ConcreteInt* CI = dyn_cast<nonloc::ConcreteInt>(&X);
|
|
||||||
if (CI && CI->getValue() != 0)
|
|
||||||
Builder->BuildSinks = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 6:
|
|
||||||
if (!memcmp(s, "Assert", 6)) {
|
|
||||||
Builder->BuildSinks = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: This is just a wrapper around throwing an exception.
|
|
||||||
// Eventually inter-procedural analysis should handle this easily.
|
|
||||||
if (!memcmp(s, "ziperr", 6)) Builder->BuildSinks = true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 7:
|
|
||||||
if (!memcmp(s, "assfail", 7)) Builder->BuildSinks = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 8:
|
|
||||||
if (!memcmp(s ,"db_error", 8) ||
|
|
||||||
!memcmp(s, "__assert", 8))
|
|
||||||
Builder->BuildSinks = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 12:
|
|
||||||
if (!memcmp(s, "__assert_rtn", 12)) Builder->BuildSinks = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 13:
|
|
||||||
if (!memcmp(s, "__assert_fail", 13)) Builder->BuildSinks = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 14:
|
|
||||||
if (!memcmp(s, "dtrace_assfail", 14) ||
|
|
||||||
!memcmp(s, "yy_fatal_error", 14))
|
|
||||||
Builder->BuildSinks = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 26:
|
|
||||||
if (!memcmp(s, "_XCAssertionFailureHandler", 26) ||
|
|
||||||
!memcmp(s, "_DTAssertionFailureHandler", 26) ||
|
|
||||||
!memcmp(s, "_TSAssertionFailureHandler", 26))
|
|
||||||
Builder->BuildSinks = true;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Evaluate the call.
|
// Evaluate the call.
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue