NoReturnFunctionChecker.cpp revision 218887
121308Sache//=== NoReturnFunctionChecker.cpp -------------------------------*- C++ -*-===// 221308Sache// 321308Sache// The LLVM Compiler Infrastructure 421308Sache// 521308Sache// This file is distributed under the University of Illinois Open Source 621308Sache// License. See LICENSE.TXT for details. 721308Sache// 821308Sache//===----------------------------------------------------------------------===// 921308Sache// 1058310Sache// This defines NoReturnFunctionChecker, which evaluates functions that do not 1121308Sache// return to the caller. 1221308Sache// 1321308Sache//===----------------------------------------------------------------------===// 1421308Sache 1521308Sache#include "InternalChecks.h" 1621308Sache#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerVisitor.h" 1721308Sache#include "llvm/ADT/StringSwitch.h" 1821308Sache 1921308Sacheusing namespace clang; 2058310Sacheusing namespace ento; 2158310Sache 2221308Sachenamespace { 2321308Sache 2421308Sacheclass NoReturnFunctionChecker : public CheckerVisitor<NoReturnFunctionChecker> { 2521308Sachepublic: 2621308Sache static void *getTag() { static int tag = 0; return &tag; } 2721308Sache void PostVisitCallExpr(CheckerContext &C, const CallExpr *CE); 2821308Sache}; 2921308Sache 3021308Sache} 3121308Sache 3221308Sachevoid ento::RegisterNoReturnFunctionChecker(ExprEngine &Eng) { 3321308Sache Eng.registerCheck(new NoReturnFunctionChecker()); 3421308Sache} 3558310Sache 3621308Sachevoid NoReturnFunctionChecker::PostVisitCallExpr(CheckerContext &C, 3721308Sache const CallExpr *CE) { 3821308Sache const GRState *state = C.getState(); 3921308Sache const Expr *Callee = CE->getCallee(); 4021308Sache 4121308Sache bool BuildSinks = getFunctionExtInfo(Callee->getType()).getNoReturn(); 4221308Sache 4358310Sache if (!BuildSinks) { 4458310Sache SVal L = state->getSVal(Callee); 4558310Sache const FunctionDecl *FD = L.getAsFunctionDecl(); 4658310Sache if (!FD) 4758310Sache return; 4858310Sache 4958310Sache if (FD->getAttr<AnalyzerNoReturnAttr>()) 5058310Sache BuildSinks = true; 5121308Sache else if (const IdentifierInfo *II = FD->getIdentifier()) { 5221308Sache // HACK: Some functions are not marked noreturn, and don't return. 5321308Sache // Here are a few hardwired ones. If this takes too long, we can 54119610Sache // potentially cache these results. 5521308Sache BuildSinks 56119610Sache = llvm::StringSwitch<bool>(llvm::StringRef(II->getName())) 5721308Sache .Case("exit", true) 58119610Sache .Case("panic", true) 5921308Sache .Case("error", true) 60119610Sache .Case("Assert", true) 6121308Sache // FIXME: This is just a wrapper around throwing an exception. 6221308Sache // Eventually inter-procedural analysis should handle this easily. 6321308Sache .Case("ziperr", true) 6421308Sache .Case("assfail", true) 6521308Sache .Case("db_error", true) 66119610Sache .Case("__assert", true) 6721308Sache .Case("__assert_rtn", true) 6858310Sache .Case("__assert_fail", true) 69119610Sache .Case("dtrace_assfail", true) 7021308Sache .Case("yy_fatal_error", true) 71119610Sache .Case("_XCAssertionFailureHandler", true) 7221308Sache .Case("_DTAssertionFailureHandler", true) 73119610Sache .Case("_TSAssertionFailureHandler", true) 7421308Sache .Default(false); 7521308Sache } 7621308Sache } 7721308Sache 7821308Sache if (BuildSinks) 7921308Sache C.generateSink(CE); 8021308Sache} 8121308Sache