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