blob: 12527e076221ce3ffb29a9e98b09bfd35cc53baf [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"
Ted Kremenekcfd8ea92010-03-26 22:57:13 +000016#include "clang/Checker/PathSensitive/CheckerVisitor.h"
Zhongxing Xu935ef902009-12-07 09:17:35 +000017#include "llvm/ADT/StringSwitch.h"
18
19using namespace clang;
20
21namespace {
22
Ted Kremenekcfd8ea92010-03-26 22:57:13 +000023class NoReturnFunctionChecker : public CheckerVisitor<NoReturnFunctionChecker> {
Zhongxing Xu935ef902009-12-07 09:17:35 +000024public:
25 static void *getTag() { static int tag = 0; return &tag; }
Ted Kremenekcfd8ea92010-03-26 22:57:13 +000026 void PostVisitCallExpr(CheckerContext &C, const CallExpr *CE);
Zhongxing Xu935ef902009-12-07 09:17:35 +000027};
28
29}
30
31void clang::RegisterNoReturnFunctionChecker(GRExprEngine &Eng) {
32 Eng.registerCheck(new NoReturnFunctionChecker());
33}
34
Ted Kremenekcfd8ea92010-03-26 22:57:13 +000035void NoReturnFunctionChecker::PostVisitCallExpr(CheckerContext &C,
36 const CallExpr *CE) {
Zhongxing Xu935ef902009-12-07 09:17:35 +000037 const GRState *state = C.getState();
38 const Expr *Callee = CE->getCallee();
Zhongxing Xu935ef902009-12-07 09:17:35 +000039
Rafael Espindola264ba482010-03-30 20:24:48 +000040 bool BuildSinks = getFunctionExtInfo(Callee->getType()).getNoReturn();
Zhongxing Xu935ef902009-12-07 09:17:35 +000041
Ted Kremenekcfd8ea92010-03-26 22:57:13 +000042 if (!BuildSinks) {
43 SVal L = state->getSVal(Callee);
44 const FunctionDecl *FD = L.getAsFunctionDecl();
45 if (!FD)
46 return;
47
48 if (FD->getAttr<AnalyzerNoReturnAttr>())
49 BuildSinks = true;
50 else if (const IdentifierInfo *II = FD->getIdentifier()) {
51 // HACK: Some functions are not marked noreturn, and don't return.
52 // Here are a few hardwired ones. If this takes too long, we can
53 // potentially cache these results.
54 BuildSinks
55 = llvm::StringSwitch<bool>(llvm::StringRef(II->getName()))
56 .Case("exit", true)
57 .Case("panic", true)
58 .Case("error", true)
59 .Case("Assert", true)
60 // FIXME: This is just a wrapper around throwing an exception.
61 // Eventually inter-procedural analysis should handle this easily.
62 .Case("ziperr", true)
63 .Case("assfail", true)
64 .Case("db_error", true)
65 .Case("__assert", true)
66 .Case("__assert_rtn", true)
67 .Case("__assert_fail", true)
68 .Case("dtrace_assfail", true)
69 .Case("yy_fatal_error", true)
70 .Case("_XCAssertionFailureHandler", true)
71 .Case("_DTAssertionFailureHandler", true)
72 .Case("_TSAssertionFailureHandler", true)
73 .Default(false);
74 }
Zhongxing Xu935ef902009-12-07 09:17:35 +000075 }
Zhongxing Xu935ef902009-12-07 09:17:35 +000076
Ted Kremenekcfd8ea92010-03-26 22:57:13 +000077 if (BuildSinks)
78 C.GenerateSink(CE);
Zhongxing Xu935ef902009-12-07 09:17:35 +000079}