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