blob: 6806273d4b4b9db6ae99831a7eb41e7129d9d155 [file] [log] [blame]
Zhongxing Xu935ef902009-12-07 09:17:35 +00001//=== NoReturnFunctionChecker.cpp -------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This defines NoReturnFunctionChecker, which evaluates functions that do not
11// return to the caller.
12//
13//===----------------------------------------------------------------------===//
14
15#include "GRExprEngineInternalChecks.h"
16#include "clang/Analysis/PathSensitive/Checker.h"
17#include "llvm/ADT/StringSwitch.h"
18
19using namespace clang;
20
21namespace {
22
23class NoReturnFunctionChecker : public Checker {
24public:
25 static void *getTag() { static int tag = 0; return &tag; }
26 virtual bool EvalCallExpr(CheckerContext &C, const CallExpr *CE);
27};
28
29}
30
31void clang::RegisterNoReturnFunctionChecker(GRExprEngine &Eng) {
32 Eng.registerCheck(new NoReturnFunctionChecker());
33}
34
35bool NoReturnFunctionChecker::EvalCallExpr(CheckerContext &C,
36 const CallExpr *CE) {
37 const GRState *state = C.getState();
38 const Expr *Callee = CE->getCallee();
39 SVal L = state->getSVal(Callee);
40 const FunctionDecl *FD = L.getAsFunctionDecl();
41 if (!FD)
42 return false;
43
44 bool BuildSinks = false;
45
46 if (FD->getAttr<NoReturnAttr>() || FD->getAttr<AnalyzerNoReturnAttr>())
47 BuildSinks = true;
48 else {
49 // HACK: Some functions are not marked noreturn, and don't return.
50 // Here are a few hardwired ones. If this takes too long, we can
51 // potentially cache these results.
52 using llvm::StringRef;
53 BuildSinks
54 = llvm::StringSwitch<bool>(StringRef(FD->getIdentifier()->getName()))
55 .Case("exit", true)
56 .Case("panic", true)
57 .Case("error", true)
58 .Case("Assert", true)
59 // FIXME: This is just a wrapper around throwing an exception.
60 // Eventually inter-procedural analysis should handle this easily.
61 .Case("ziperr", true)
62 .Case("assfail", true)
63 .Case("db_error", true)
64 .Case("__assert", true)
65 .Case("__assert_rtn", true)
66 .Case("__assert_fail", true)
67 .Case("dtrace_assfail", true)
68 .Case("yy_fatal_error", true)
69 .Case("_XCAssertionFailureHandler", true)
70 .Case("_DTAssertionFailureHandler", true)
71 .Case("_TSAssertionFailureHandler", true)
72 .Default(false);
73 }
74
75 if (!BuildSinks)
76 return false;
77
78 C.GenerateSink(CE);
79 return true;
80}