diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index 6f4bdd41fae7..02c92c9150f8 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -142,6 +142,9 @@ public: Eng.getBugReporter().EmitReport(R); } + /// \brief Get the declaration of the called function (path-sensitive). + const FunctionDecl *getCalleeDecl(const CallExpr *CE) const; + /// \brief Get the name of the called function (path-sensitive). StringRef getCalleeName(const CallExpr *CE) const; diff --git a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp index bc6e8f303fd9..1f627297ec89 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -249,11 +249,8 @@ static const char* GetCFNumberTypeStr(uint64_t i) { void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const { - const Expr *Callee = CE->getCallee(); const ProgramState *state = C.getState(); - SVal CallV = state->getSVal(Callee); - const FunctionDecl *FD = CallV.getAsFunctionDecl(); - + const FunctionDecl *FD = C.getCalleeDecl(CE); if (!FD) return; @@ -363,11 +360,8 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE, if (CE->getNumArgs() != 1) return; - // Get the function declaration of the callee. const ProgramState *state = C.getState(); - SVal X = state->getSVal(CE->getCallee()); - const FunctionDecl *FD = X.getAsFunctionDecl(); - + const FunctionDecl *FD = C.getCalleeDecl(CE); if (!FD) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp index 4ad7cc90312c..2cf1209f51d1 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -30,12 +30,9 @@ public: } bool BuiltinFunctionChecker::evalCall(const CallExpr *CE, - CheckerContext &C) const{ + CheckerContext &C) const { const ProgramState *state = C.getState(); - const Expr *Callee = CE->getCallee(); - SVal L = state->getSVal(Callee); - const FunctionDecl *FD = L.getAsFunctionDecl(); - + const FunctionDecl *FD = C.getCalleeDecl(CE); if (!FD) return false; diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 4299a12e387d..6ab98b41870a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -1664,20 +1664,9 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, //===----------------------------------------------------------------------===// bool CStringChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { - // Get the callee. All the functions we care about are C functions - // with simple identifiers. - const ProgramState *state = C.getState(); - const Expr *Callee = CE->getCallee(); - const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl(); - - if (!FD) + StringRef Name = C.getCalleeName(CE); + if (Name.empty()) return false; - - // Get the name of the callee. If it's a builtin, strip off the prefix. - IdentifierInfo *II = FD->getIdentifier(); - if (!II) // if no identifier, not a simple C function - return false; - StringRef Name = II->getName(); if (Name.startswith("__builtin_")) Name = Name.substr(10); diff --git a/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp index 2f3ff26de549..fa79f2186613 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp @@ -62,10 +62,7 @@ private: } // end anonymous namespace bool ChrootChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { - const ProgramState *state = C.getState(); - const Expr *Callee = CE->getCallee(); - SVal L = state->getSVal(Callee); - const FunctionDecl *FD = L.getAsFunctionDecl(); + const FunctionDecl *FD = C.getCalleeDecl(CE); if (!FD) return false; @@ -125,10 +122,7 @@ void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) const { // Check the jail state before any function call except chroot and chdir(). void ChrootChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const { - const ProgramState *state = C.getState(); - const Expr *Callee = CE->getCallee(); - SVal L = state->getSVal(Callee); - const FunctionDecl *FD = L.getAsFunctionDecl(); + const FunctionDecl *FD = C.getCalleeDecl(CE); if (!FD) return; @@ -143,7 +137,7 @@ void ChrootChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const { return; // If jail state is ROOT_CHANGED, generate BugReport. - void *const* k = state->FindGDM(ChrootChecker::getTag()); + void *const* k = C.getState()->FindGDM(ChrootChecker::getTag()); if (k) if (isRootChanged((intptr_t) *k)) if (ExplodedNode *N = C.addTransition()) { diff --git a/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp index c9de38c4a09b..b49684233a6c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp @@ -281,18 +281,12 @@ void MacOSKeychainAPIChecker:: void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const { - const ProgramState *State = C.getState(); - const Expr *Callee = CE->getCallee(); - SVal L = State->getSVal(Callee); unsigned idx = InvalidIdx; + const ProgramState *State = C.getState(); - const FunctionDecl *funDecl = L.getAsFunctionDecl(); - if (!funDecl) + StringRef funName = C.getCalleeName(CE); + if (funName.empty()) return; - IdentifierInfo *funI = funDecl->getIdentifier(); - if (!funI) - return; - StringRef funName = funI->getName(); // If it is a call to an allocator function, it could be a double allocation. idx = getTrackedFunctionIndex(funName, true); diff --git a/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp index 88d492e8d9a2..f8c01047c38c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp @@ -37,11 +37,11 @@ public: void checkPreStmt(const CallExpr *CE, CheckerContext &C) const; void CheckDispatchOnce(CheckerContext &C, const CallExpr *CE, - const IdentifierInfo *FI) const; + StringRef FName) const; typedef void (MacOSXAPIChecker::*SubChecker)(CheckerContext &, const CallExpr *, - const IdentifierInfo *) const; + StringRef FName) const; }; } //end anonymous namespace @@ -50,7 +50,7 @@ public: //===----------------------------------------------------------------------===// void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE, - const IdentifierInfo *FI) const { + StringRef FName) const { if (CE->getNumArgs() < 1) return; @@ -71,7 +71,7 @@ void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE, llvm::SmallString<256> S; llvm::raw_svector_ostream os(S); - os << "Call to '" << FI->getName() << "' uses"; + os << "Call to '" << FName << "' uses"; if (const VarRegion *VR = dyn_cast(R)) os << " the local variable '" << VR->getDecl()->getName() << '\''; else @@ -92,27 +92,18 @@ void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE, void MacOSXAPIChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const { - // FIXME: This sort of logic is common to several checkers, including - // UnixAPIChecker, PthreadLockChecker, and CStringChecker. Should refactor. - const ProgramState *state = C.getState(); - const Expr *Callee = CE->getCallee(); - const FunctionDecl *Fn = state->getSVal(Callee).getAsFunctionDecl(); - - if (!Fn) - return; - - const IdentifierInfo *FI = Fn->getIdentifier(); - if (!FI) + StringRef Name = C.getCalleeName(CE); + if (Name.empty()) return; SubChecker SC = - llvm::StringSwitch(FI->getName()) + llvm::StringSwitch(Name) .Cases("dispatch_once", "dispatch_once_f", &MacOSXAPIChecker::CheckDispatchOnce) .Default(NULL); if (SC) - (this->*SC)(C, CE, FI); + (this->*SC)(C, CE, Name); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index f217df9309d3..dd919e3a9b0a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -128,11 +128,7 @@ namespace ento { } bool MallocChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { - const ProgramState *state = C.getState(); - const Expr *Callee = CE->getCallee(); - SVal L = state->getSVal(Callee); - - const FunctionDecl *FD = L.getAsFunctionDecl(); + const FunctionDecl *FD = C.getCalleeDecl(CE); if (!FD) return false; diff --git a/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp index 7bdb871db92b..27d8fb5abbd1 100644 --- a/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp @@ -35,24 +35,27 @@ private: }; } +static StringRef getCalleeName(const ProgramState *State, + const CallExpr *CE) { + const Expr *Callee = CE->getCallee(); + SVal L = State->getSVal(Callee); + const FunctionDecl *funDecl = L.getAsFunctionDecl(); + if (!funDecl) + return StringRef(); + IdentifierInfo *funI = funDecl->getIdentifier(); + if (!funI) + return StringRef(); + return funI->getName(); +} + bool OSAtomicChecker::inlineCall(const CallExpr *CE, ExprEngine &Eng, ExplodedNode *Pred, ExplodedNodeSet &Dst) const { - const ProgramState *state = Pred->getState(); - const Expr *Callee = CE->getCallee(); - SVal L = state->getSVal(Callee); - - const FunctionDecl *FD = L.getAsFunctionDecl(); - if (!FD) + StringRef FName = getCalleeName(Pred->getState(), CE); + if (FName.empty()) return false; - const IdentifierInfo *II = FD->getIdentifier(); - if (!II) - return false; - - StringRef FName(II->getName()); - // Check for compare and swap. if (FName.startswith("OSAtomicCompareAndSwap") || FName.startswith("objc_atomicCompareAndSwap")) diff --git a/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp index c02b5b14ca64..45988f0a0973 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp @@ -57,18 +57,10 @@ template <> struct ProgramStateTrait : void PthreadLockChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const { const ProgramState *state = C.getState(); - const Expr *Callee = CE->getCallee(); - const FunctionDecl *FD = state->getSVal(Callee).getAsFunctionDecl(); - - if (!FD) + StringRef FName = C.getCalleeName(CE); + if (FName.empty()) return; - // Get the name of the callee. - IdentifierInfo *II = FD->getIdentifier(); - if (!II) // if no identifier, not a simple C function - return; - StringRef FName = II->getName(); - if (CE->getNumArgs() != 1) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 9537b31290b4..22cd050df31e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -2990,10 +2990,7 @@ void RetainCountChecker::processNonLeakError(const ProgramState *St, bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { // Get the callee. We're only interested in simple C functions. const ProgramState *state = C.getState(); - const Expr *Callee = CE->getCallee(); - SVal L = state->getSVal(Callee); - - const FunctionDecl *FD = L.getAsFunctionDecl(); + const FunctionDecl *FD = C.getCalleeDecl(CE); if (!FD) return false; @@ -3015,7 +3012,7 @@ bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { // See if it's one of the specific functions we know how to eval. bool canEval = false; - QualType ResultTy = FD->getResultType(); + QualType ResultTy = CE->getCallReturnType(); if (ResultTy->isObjCIdType()) { // Handle: id NSMakeCollectable(CFTypeRef) canEval = II->isStr("NSMakeCollectable"); diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index 94ff2663aa50..2f96bbfeac63 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -115,10 +115,7 @@ namespace ento { } bool StreamChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { - const ProgramState *state = C.getState(); - const Expr *Callee = CE->getCallee(); - SVal L = state->getSVal(Callee); - const FunctionDecl *FD = L.getAsFunctionDecl(); + const FunctionDecl *FD = C.getCalleeDecl(CE); if (!FD) return false; diff --git a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp index cec286d2f3e9..e955f9e90c7c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -224,21 +224,12 @@ void UnixAPIChecker::CheckMallocZero(CheckerContext &C, //===----------------------------------------------------------------------===// void UnixAPIChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const { - // Get the callee. All the functions we care about are C functions - // with simple identifiers. - const ProgramState *state = C.getState(); - const Expr *Callee = CE->getCallee(); - const FunctionDecl *Fn = state->getSVal(Callee).getAsFunctionDecl(); - - if (!Fn) - return; - - const IdentifierInfo *FI = Fn->getIdentifier(); - if (!FI) + StringRef FName = C.getCalleeName(CE); + if (FName.empty()) return; SubChecker SC = - llvm::StringSwitch(FI->getName()) + llvm::StringSwitch(FName) .Case("open", &UnixAPIChecker::CheckOpen) .Case("pthread_once", &UnixAPIChecker::CheckPthreadOnce) .Case("malloc", &UnixAPIChecker::CheckMallocZero) diff --git a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp index 75cb82a67c4f..5552a991d150 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp @@ -16,12 +16,15 @@ using namespace clang; using namespace ento; -StringRef CheckerContext::getCalleeName(const CallExpr *CE) const { +const FunctionDecl *CheckerContext::getCalleeDecl(const CallExpr *CE) const { const ProgramState *State = getState(); const Expr *Callee = CE->getCallee(); SVal L = State->getSVal(Callee); + return L.getAsFunctionDecl(); +} - const FunctionDecl *funDecl = L.getAsFunctionDecl(); +StringRef CheckerContext::getCalleeName(const CallExpr *CE) const { + const FunctionDecl *funDecl = getCalleeDecl(CE); if (!funDecl) return StringRef(); IdentifierInfo *funI = funDecl->getIdentifier();