Skip to content

Commit

Permalink
[analyzer] Refactor checkers to use helper function for getting calle…
Browse files Browse the repository at this point in the history
…e 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
  • Loading branch information
AnnaZaks committed Dec 1, 2011
1 parent a078ecf commit b805c8f
Show file tree
Hide file tree
Showing 14 changed files with 52 additions and 111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ class CheckerContext {
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;

Expand Down
10 changes: 2 additions & 8 deletions lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;

Expand Down
7 changes: 2 additions & 5 deletions lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,9 @@ class BuiltinFunctionChecker : public Checker<eval::Call> {
}

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;

Expand Down
15 changes: 2 additions & 13 deletions lib/StaticAnalyzer/Checkers/CStringChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
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
StringRef Name = C.getCalleeName(CE);
if (Name.empty())
return false;
StringRef Name = II->getName();
if (Name.startswith("__builtin_"))
Name = Name.substr(10);

Expand Down
12 changes: 3 additions & 9 deletions lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,7 @@ class ChrootChecker : public Checker<eval::Call, check::PreStmt<CallExpr> > {
} // 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;

Expand Down Expand Up @@ -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;

Expand All @@ -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()) {
Expand Down
12 changes: 3 additions & 9 deletions lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
return;
IdentifierInfo *funI = funDecl->getIdentifier();
if (!funI)
StringRef funName = C.getCalleeName(CE);
if (funName.empty())
return;
StringRef funName = funI->getName();

// If it is a call to an allocator function, it could be a double allocation.
idx = getTrackedFunctionIndex(funName, true);
Expand Down
25 changes: 8 additions & 17 deletions lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ class MacOSXAPIChecker : public Checker< check::PreStmt<CallExpr> > {
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

Expand All @@ -50,7 +50,7 @@ class MacOSXAPIChecker : public Checker< check::PreStmt<CallExpr> > {
//===----------------------------------------------------------------------===//

void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE,
const IdentifierInfo *FI) const {
StringRef FName) const {
if (CE->getNumArgs() < 1)
return;

Expand All @@ -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<VarRegion>(R))
os << " the local variable '" << VR->getDecl()->getName() << '\'';
else
Expand All @@ -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<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);
}

//===----------------------------------------------------------------------===//
Expand Down
6 changes: 1 addition & 5 deletions lib/StaticAnalyzer/Checkers/MallocChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
27 changes: 15 additions & 12 deletions lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,26 @@ class OSAtomicChecker : public Checker<eval::InlineCall> {
};
}

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)
return false;

const IdentifierInfo *II = FD->getIdentifier();
if (!II)
StringRef FName = getCalleeName(Pred->getState(), CE);
if (FName.empty())
return false;

StringRef FName(II->getName());

// Check for compare and swap.
if (FName.startswith("OSAtomicCompareAndSwap") ||
Expand Down
12 changes: 2 additions & 10 deletions lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,9 @@ template <> struct ProgramStateTrait<LockSet> :
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)
return;

// Get the name of the callee.
IdentifierInfo *II = FD->getIdentifier();
if (!II) // if no identifier, not a simple C function
StringRef FName = C.getCalleeName(CE);
if (FName.empty())
return;
StringRef FName = II->getName();

if (CE->getNumArgs() != 1)
return;
Expand Down
7 changes: 2 additions & 5 deletions lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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");
Expand Down
5 changes: 1 addition & 4 deletions lib/StaticAnalyzer/Checkers/StreamChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
15 changes: 3 additions & 12 deletions lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<SubChecker>(FI->getName())
llvm::StringSwitch<SubChecker>(FName)
.Case("open", &UnixAPIChecker::CheckOpen)
.Case("pthread_once", &UnixAPIChecker::CheckPthreadOnce)
.Case("malloc", &UnixAPIChecker::CheckMallocZero)
Expand Down
7 changes: 5 additions & 2 deletions lib/StaticAnalyzer/Core/CheckerContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit b805c8f

Please sign in to comment.