diff options
author | Zhongxing Xu <xuzhongxing@gmail.com> | 2009-09-04 02:13:36 +0000 |
---|---|---|
committer | Zhongxing Xu <xuzhongxing@gmail.com> | 2009-09-04 02:13:36 +0000 |
commit | 326d6176ae9c7fc69be31b842476f71ffce0e000 (patch) | |
tree | 7821f31794e7ab793ffd4b0735095705360cf01c /lib/Analysis/GRExprEngine.cpp | |
parent | f1bbbb49f06a7462476cd88166fccda5feb15cab (diff) |
Extract mark-no-return-function code into a function.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80979 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/GRExprEngine.cpp')
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 164 |
1 files changed, 84 insertions, 80 deletions
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 006af8c9ce..ba17d21a6c 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -1417,6 +1417,88 @@ static bool EvalOSAtomic(ExplodedNodeSet& Dst, //===----------------------------------------------------------------------===// // 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, ExplodedNode* Pred) { @@ -1498,86 +1580,8 @@ void GRExprEngine::VisitCallRec(CallExpr* CE, ExplodedNode* Pred, SaveAndRestore<bool> OldSink(Builder->BuildSinks); const FunctionDecl* FD = L.getAsFunctionDecl(); - if (FD) { - 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; - } - - } - } + if (FD) + MarkNoReturnFunction(FD, CE, state, Builder); // Evaluate the call. |