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, 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.contains(Name)) 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.contains(Name)) 87 return true; 88 89 if (FName.startswith("__") && FName.endswith("_chk") && FName.contains(Name)) 90 return true; 91 92 return false; 93 } 94 95 StringRef CheckerContext::getMacroNameOrSpelling(SourceLocation &Loc) { 96 if (Loc.isMacroID()) 97 return Lexer::getImmediateMacroName(Loc, getSourceManager(), 98 getLangOpts()); 99 SmallString<16> buf; 100 return Lexer::getSpelling(Loc, buf, getSourceManager(), getLangOpts()); 101 } 102 103 /// Evaluate comparison and return true if it's known that condition is true 104 static bool evalComparison(SVal LHSVal, BinaryOperatorKind ComparisonOp, 105 SVal RHSVal, ProgramStateRef State) { 106 if (LHSVal.isUnknownOrUndef()) 107 return false; 108 ProgramStateManager &Mgr = State->getStateManager(); 109 if (!LHSVal.getAs<NonLoc>()) { 110 LHSVal = Mgr.getStoreManager().getBinding(State->getStore(), 111 LHSVal.castAs<Loc>()); 112 if (LHSVal.isUnknownOrUndef() || !LHSVal.getAs<NonLoc>()) 113 return false; 114 } 115 116 SValBuilder &Bldr = Mgr.getSValBuilder(); 117 SVal Eval = Bldr.evalBinOp(State, ComparisonOp, LHSVal, RHSVal, 118 Bldr.getConditionType()); 119 if (Eval.isUnknownOrUndef()) 120 return false; 121 ProgramStateRef StTrue, StFalse; 122 std::tie(StTrue, StFalse) = State->assume(Eval.castAs<DefinedSVal>()); 123 return StTrue && !StFalse; 124 } 125 126 bool CheckerContext::isGreaterOrEqual(const Expr *E, unsigned long long Val) { 127 DefinedSVal V = getSValBuilder().makeIntVal(Val, getASTContext().LongLongTy); 128 return evalComparison(getSVal(E), BO_GE, V, getState()); 129 } 130 131 bool CheckerContext::isNegative(const Expr *E) { 132 DefinedSVal V = getSValBuilder().makeIntVal(0, false); 133 return evalComparison(getSVal(E), BO_LT, V, getState()); 134 } 135