CheckerContext.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. //== CheckerContext.cpp - Context info for path-sensitive checkers-----------=//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file defines CheckerContext that provides contextual info for
  10. // path-sensitive checkers.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
  14. #include "clang/Basic/Builtins.h"
  15. #include "clang/Lex/Lexer.h"
  16. using namespace clang;
  17. using namespace ento;
  18. const FunctionDecl *CheckerContext::getCalleeDecl(const CallExpr *CE) const {
  19. const Expr *Callee = CE->getCallee();
  20. SVal L = Pred->getSVal(Callee);
  21. return L.getAsFunctionDecl();
  22. }
  23. StringRef CheckerContext::getCalleeName(const FunctionDecl *FunDecl) const {
  24. if (!FunDecl)
  25. return StringRef();
  26. IdentifierInfo *funI = FunDecl->getIdentifier();
  27. if (!funI)
  28. return StringRef();
  29. return funI->getName();
  30. }
  31. StringRef CheckerContext::getDeclDescription(const Decl *D) {
  32. if (isa<ObjCMethodDecl>(D) || isa<CXXMethodDecl>(D))
  33. return "method";
  34. if (isa<BlockDecl>(D))
  35. return "anonymous block";
  36. return "function";
  37. }
  38. bool CheckerContext::isCLibraryFunction(const FunctionDecl *FD,
  39. StringRef Name) {
  40. // To avoid false positives (Ex: finding user defined functions with
  41. // similar names), only perform fuzzy name matching when it's a builtin.
  42. // Using a string compare is slow, we might want to switch on BuiltinID here.
  43. unsigned BId = FD->getBuiltinID();
  44. if (BId != 0) {
  45. if (Name.empty())
  46. return true;
  47. StringRef BName = FD->getASTContext().BuiltinInfo.getName(BId);
  48. if (BName.find(Name) != StringRef::npos)
  49. return true;
  50. }
  51. const IdentifierInfo *II = FD->getIdentifier();
  52. // If this is a special C++ name without IdentifierInfo, it can't be a
  53. // C library function.
  54. if (!II)
  55. return false;
  56. // Look through 'extern "C"' and anything similar invented in the future.
  57. // If this function is not in TU directly, it is not a C library function.
  58. if (!FD->getDeclContext()->getRedeclContext()->isTranslationUnit())
  59. return false;
  60. // If this function is not externally visible, it is not a C library function.
  61. // Note that we make an exception for inline functions, which may be
  62. // declared in header files without external linkage.
  63. if (!FD->isInlined() && !FD->isExternallyVisible())
  64. return false;
  65. if (Name.empty())
  66. return true;
  67. StringRef FName = II->getName();
  68. if (FName.equals(Name))
  69. return true;
  70. if (FName.startswith("__inline") && (FName.find(Name) != StringRef::npos))
  71. return true;
  72. if (FName.startswith("__") && FName.endswith("_chk") &&
  73. FName.find(Name) != StringRef::npos)
  74. return true;
  75. return false;
  76. }
  77. StringRef CheckerContext::getMacroNameOrSpelling(SourceLocation &Loc) {
  78. if (Loc.isMacroID())
  79. return Lexer::getImmediateMacroName(Loc, getSourceManager(),
  80. getLangOpts());
  81. SmallVector<char, 16> buf;
  82. return Lexer::getSpelling(Loc, buf, getSourceManager(), getLangOpts());
  83. }
  84. /// Evaluate comparison and return true if it's known that condition is true
  85. static bool evalComparison(SVal LHSVal, BinaryOperatorKind ComparisonOp,
  86. SVal RHSVal, ProgramStateRef State) {
  87. if (LHSVal.isUnknownOrUndef())
  88. return false;
  89. ProgramStateManager &Mgr = State->getStateManager();
  90. if (!LHSVal.getAs<NonLoc>()) {
  91. LHSVal = Mgr.getStoreManager().getBinding(State->getStore(),
  92. LHSVal.castAs<Loc>());
  93. if (LHSVal.isUnknownOrUndef() || !LHSVal.getAs<NonLoc>())
  94. return false;
  95. }
  96. SValBuilder &Bldr = Mgr.getSValBuilder();
  97. SVal Eval = Bldr.evalBinOp(State, ComparisonOp, LHSVal, RHSVal,
  98. Bldr.getConditionType());
  99. if (Eval.isUnknownOrUndef())
  100. return false;
  101. ProgramStateRef StTrue, StFalse;
  102. std::tie(StTrue, StFalse) = State->assume(Eval.castAs<DefinedSVal>());
  103. return StTrue && !StFalse;
  104. }
  105. bool CheckerContext::isGreaterOrEqual(const Expr *E, unsigned long long Val) {
  106. DefinedSVal V = getSValBuilder().makeIntVal(Val, getASTContext().LongLongTy);
  107. return evalComparison(getSVal(E), BO_GE, V, getState());
  108. }
  109. bool CheckerContext::isNegative(const Expr *E) {
  110. DefinedSVal V = getSValBuilder().makeIntVal(0, false);
  111. return evalComparison(getSVal(E), BO_LT, V, getState());
  112. }