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