NoReturnFunctionChecker.cpp 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. //=== 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. #include "InternalChecks.h"
  15. #include "clang/StaticAnalyzer/PathSensitive/CheckerVisitor.h"
  16. #include "llvm/ADT/StringSwitch.h"
  17. using namespace clang;
  18. using namespace ento;
  19. namespace {
  20. class NoReturnFunctionChecker : public CheckerVisitor<NoReturnFunctionChecker> {
  21. public:
  22. static void *getTag() { static int tag = 0; return &tag; }
  23. void PostVisitCallExpr(CheckerContext &C, const CallExpr *CE);
  24. };
  25. }
  26. void ento::RegisterNoReturnFunctionChecker(ExprEngine &Eng) {
  27. Eng.registerCheck(new NoReturnFunctionChecker());
  28. }
  29. void NoReturnFunctionChecker::PostVisitCallExpr(CheckerContext &C,
  30. const CallExpr *CE) {
  31. const GRState *state = C.getState();
  32. const Expr *Callee = CE->getCallee();
  33. bool BuildSinks = getFunctionExtInfo(Callee->getType()).getNoReturn();
  34. if (!BuildSinks) {
  35. SVal L = state->getSVal(Callee);
  36. const FunctionDecl *FD = L.getAsFunctionDecl();
  37. if (!FD)
  38. return;
  39. if (FD->getAttr<AnalyzerNoReturnAttr>())
  40. BuildSinks = true;
  41. else if (const IdentifierInfo *II = FD->getIdentifier()) {
  42. // HACK: Some functions are not marked noreturn, and don't return.
  43. // Here are a few hardwired ones. If this takes too long, we can
  44. // potentially cache these results.
  45. BuildSinks
  46. = llvm::StringSwitch<bool>(llvm::StringRef(II->getName()))
  47. .Case("exit", true)
  48. .Case("panic", true)
  49. .Case("error", true)
  50. .Case("Assert", true)
  51. // FIXME: This is just a wrapper around throwing an exception.
  52. // Eventually inter-procedural analysis should handle this easily.
  53. .Case("ziperr", true)
  54. .Case("assfail", true)
  55. .Case("db_error", true)
  56. .Case("__assert", true)
  57. .Case("__assert_rtn", true)
  58. .Case("__assert_fail", true)
  59. .Case("dtrace_assfail", true)
  60. .Case("yy_fatal_error", true)
  61. .Case("_XCAssertionFailureHandler", true)
  62. .Case("_DTAssertionFailureHandler", true)
  63. .Case("_TSAssertionFailureHandler", true)
  64. .Default(false);
  65. }
  66. }
  67. if (BuildSinks)
  68. C.generateSink(CE);
  69. }