[analyzer] Refactor checkers to use helper function for getting callee Decl and name.
We are getting name of the called function or it's declaration in a few checkers. Refactor them to use the helper function in the CheckerContext.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145576 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
index 6f4bdd4..02c92c9 100644
--- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
+++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
@@ -142,6 +142,9 @@
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/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
index bc6e8f3..1f62729 100644
--- a/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
+++ b/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
@@ -249,11 +249,8 @@
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 @@
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/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
index 4ad7cc9..2cf1209 100644
--- a/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
@@ -30,12 +30,9 @@
}
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/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 4299a12..6ab98b4 100644
--- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -1664,20 +1664,9 @@
//===----------------------------------------------------------------------===//
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/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
index 2f3ff26..fa79f21 100644
--- a/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
@@ -62,10 +62,7 @@
} // 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 @@
// 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 @@
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/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
index c9de38c..b496842 100644
--- a/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
@@ -281,18 +281,12 @@
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/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
index 88d492e..f8c0104 100644
--- a/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
@@ -37,11 +37,11 @@
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 @@
//===----------------------------------------------------------------------===//
void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE,
- const IdentifierInfo *FI) const {
+ StringRef FName) const {
if (CE->getNumArgs() < 1)
return;
@@ -71,7 +71,7 @@
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<VarRegion>(R))
os << " the local variable '" << VR->getDecl()->getName() << '\'';
else
@@ -92,27 +92,18 @@
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<SubChecker>(FI->getName())
+ llvm::StringSwitch<SubChecker>(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/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index f217df9..dd919e3 100644
--- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -128,11 +128,7 @@
}
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/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp b/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
index 7bdb871..27d8fb5 100644
--- a/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
@@ -35,24 +35,27 @@
};
}
+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/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
index c02b5b1..45988f0 100644
--- a/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
@@ -57,18 +57,10 @@
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/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
index 9537b31..22cd050 100644
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -2990,10 +2990,7 @@
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 @@
// 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/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
index 94ff266..2f96bbf 100644
--- a/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/StreamChecker.cpp
@@ -115,10 +115,7 @@
}
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/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
index cec286d..e955f9e 100644
--- a/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -224,21 +224,12 @@
//===----------------------------------------------------------------------===//
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<SubChecker>(FI->getName())
+ llvm::StringSwitch<SubChecker>(FName)
.Case("open", &UnixAPIChecker::CheckOpen)
.Case("pthread_once", &UnixAPIChecker::CheckPthreadOnce)
.Case("malloc", &UnixAPIChecker::CheckMallocZero)
diff --git a/lib/StaticAnalyzer/Core/CheckerContext.cpp b/lib/StaticAnalyzer/Core/CheckerContext.cpp
index 75cb82a..5552a99 100644
--- a/lib/StaticAnalyzer/Core/CheckerContext.cpp
+++ b/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();