]> granicus.if.org Git - clang/commitdiff
[analyzer] Refactor checkers to use helper function for getting callee Decl and name.
authorAnna Zaks <ganna@apple.com>
Thu, 1 Dec 2011 05:57:37 +0000 (05:57 +0000)
committerAnna Zaks <ganna@apple.com>
Thu, 1 Dec 2011 05:57:37 +0000 (05:57 +0000)
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

14 files changed:
include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h
lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp
lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
lib/StaticAnalyzer/Checkers/CStringChecker.cpp
lib/StaticAnalyzer/Checkers/ChrootChecker.cpp
lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
lib/StaticAnalyzer/Checkers/MallocChecker.cpp
lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp
lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp
lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
lib/StaticAnalyzer/Checkers/StreamChecker.cpp
lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
lib/StaticAnalyzer/Core/CheckerContext.cpp

index 6f4bdd41fae7f722731c296f9863067fc4188f05..02c92c9150f8cdf4d4a908f0f7b2ab4205acff85 100644 (file)
@@ -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;
 
index bc6e8f303fd9628d291fffe9eaa34f9c2d45e3c3..1f627297ec895b2a83bb896a2c495b0fbb5243e0 100644 (file)
@@ -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;
   
index 4ad7cc90312c10464edf29a05afa1f6dc5349903..2cf1209f51d14f4fbedd58e56db2df4f4d4d2d2b 100644 (file)
@@ -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;
 
index 4299a12e387d8963b49cf26aa2b4148103c93320..6ab98b41870ad9a233531e5dbb52a92f68f753ad 100644 (file)
@@ -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);
 
index 2f3ff26de5499b978a49b297167fafdb97f969e2..fa79f2186613f11dbe214bf49c335eee66edeb46 100644 (file)
@@ -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()) {
index c9de38c4a09be493d04ef045eddbfd8e936337aa..b49684233a6c3fea9b84e4ac022a242b90cc3444 100644 (file)
@@ -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);
index 88d492e8d9a2e1cc3ba0284572c3d1bb342ccc59..f8c01047c38c84e8e6a9dd0da4fa590a7a227b4c 100644 (file)
@@ -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<VarRegion>(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<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);
 }
 
 //===----------------------------------------------------------------------===//
index f217df9309d3d2d268d72c6f4f7fa64f17222c21..dd919e3a9b0ab4ea0aebbae9b440f96c7e8964ba 100644 (file)
@@ -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;
 
index 7bdb871db92b477d78bf3ee7379324e5e8d37b4a..27d8fb5abbd1443a3c98c39621febd77cb575d19 100644 (file)
@@ -35,23 +35,26 @@ 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)
-    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") ||
index c02b5b14ca641e85354efe51e3acef02afb327af..45988f0a097339f4ee27f431e05f5eb7784d6f6d 100644 (file)
@@ -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;
index 9537b31290b49bc7f6ed80397c3eb952e8f51b53..22cd050df31e9da11da3fc2cfd69eb4ac4ab1445 100644 (file)
@@ -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");
index 94ff2663aa509458ee5730453800231a39136ac2..2f96bbfeac63c20b611d33a9c08ba3081195c03d 100644 (file)
@@ -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;
 
index cec286d2f3e97d2a75baa7a1b1f69a5b036232f9..e955f9e90c7c432206329a78a4113e2bd4874cef 100644 (file)
@@ -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)
index 75cb82a67c4fbd4429acc3b60c74ab725736d27f..5552a991d150dfb3e59f14f29915bdcd06146f89 100644 (file)
 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();