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