diff options
author | Zhongxing Xu <xuzhongxing@gmail.com> | 2009-12-07 09:17:35 +0000 |
---|---|---|
committer | Zhongxing Xu <xuzhongxing@gmail.com> | 2009-12-07 09:17:35 +0000 |
commit | 175447f743490a34d3dcfe6ad630a38fceaa8c4d (patch) | |
tree | 2991ec7a6f025669f4c89d4735b0adabccac141b /clang/lib/Analysis/NoReturnFunctionChecker.cpp | |
parent | 7bc9bb355551cd7e03d46229b13289855e87df60 (diff) | |
download | bcm5719-llvm-175447f743490a34d3dcfe6ad630a38fceaa8c4d.tar.gz bcm5719-llvm-175447f743490a34d3dcfe6ad630a38fceaa8c4d.zip |
Add EvalCallExpr interface to checker, and migrate the no-return function
handler to this interface.
GRExprEngine::CheckerEvalCall() will return true if one of the checkers has
processed the node. In the future this might return void when we have some
default checker.
llvm-svn: 90755
Diffstat (limited to 'clang/lib/Analysis/NoReturnFunctionChecker.cpp')
-rw-r--r-- | clang/lib/Analysis/NoReturnFunctionChecker.cpp | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/clang/lib/Analysis/NoReturnFunctionChecker.cpp b/clang/lib/Analysis/NoReturnFunctionChecker.cpp new file mode 100644 index 00000000000..6806273d4b4 --- /dev/null +++ b/clang/lib/Analysis/NoReturnFunctionChecker.cpp @@ -0,0 +1,80 @@ +//=== NoReturnFunctionChecker.cpp -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines NoReturnFunctionChecker, which evaluates functions that do not +// return to the caller. +// +//===----------------------------------------------------------------------===// + +#include "GRExprEngineInternalChecks.h" +#include "clang/Analysis/PathSensitive/Checker.h" +#include "llvm/ADT/StringSwitch.h" + +using namespace clang; + +namespace { + +class NoReturnFunctionChecker : public Checker { +public: + static void *getTag() { static int tag = 0; return &tag; } + virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE); +}; + +} + +void clang::RegisterNoReturnFunctionChecker(GRExprEngine &Eng) { + Eng.registerCheck(new NoReturnFunctionChecker()); +} + +bool NoReturnFunctionChecker::EvalCallExpr(CheckerContext &C, + const CallExpr *CE) { + const GRState *state = C.getState(); + const Expr *Callee = CE->getCallee(); + SVal L = state->getSVal(Callee); + const FunctionDecl *FD = L.getAsFunctionDecl(); + if (!FD) + return false; + + bool BuildSinks = false; + + if (FD->getAttr<NoReturnAttr>() || FD->getAttr<AnalyzerNoReturnAttr>()) + 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. + using llvm::StringRef; + BuildSinks + = llvm::StringSwitch<bool>(StringRef(FD->getIdentifier()->getName())) + .Case("exit", true) + .Case("panic", true) + .Case("error", true) + .Case("Assert", true) + // FIXME: This is just a wrapper around throwing an exception. + // Eventually inter-procedural analysis should handle this easily. + .Case("ziperr", true) + .Case("assfail", true) + .Case("db_error", true) + .Case("__assert", true) + .Case("__assert_rtn", true) + .Case("__assert_fail", true) + .Case("dtrace_assfail", true) + .Case("yy_fatal_error", true) + .Case("_XCAssertionFailureHandler", true) + .Case("_DTAssertionFailureHandler", true) + .Case("_TSAssertionFailureHandler", true) + .Default(false); + } + + if (!BuildSinks) + return false; + + C.GenerateSink(CE); + return true; +} |