]> granicus.if.org Git - clang/commitdiff
For GRExprEngine::EvalBind() (and called visitors), unifiy StoreE and AssignE. Now...
authorTed Kremenek <kremenek@apple.com>
Thu, 2 Sep 2010 00:56:20 +0000 (00:56 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 2 Sep 2010 00:56:20 +0000 (00:56 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112789 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Checker/PathSensitive/Checker.h
include/clang/Checker/PathSensitive/GRExprEngine.h
lib/Checker/GRExprEngine.cpp
lib/Checker/MallocChecker.cpp
lib/Checker/UndefinedAssignmentChecker.cpp
test/Analysis/plist-output.m

index af28fc3ca7fe0cc387e6d195ab74a5bac85d8798..136a29da5f2a7d097be7f0d31e83783aaa1bc953 100644 (file)
@@ -226,7 +226,6 @@ private:
   // FIXME: Remove the 'tag' option.
   void GR_VisitBind(ExplodedNodeSet &Dst,
                     GRStmtNodeBuilder &Builder, GRExprEngine &Eng,
-                    const Stmt *AssignE,
                     const Stmt *StoreE, ExplodedNode *Pred, void *tag, 
                     SVal location, SVal val,
                     bool isPrevisit) {
@@ -234,7 +233,7 @@ private:
                      isPrevisit ? ProgramPoint::PreStmtKind :
                      ProgramPoint::PostStmtKind, 0, StoreE);
     assert(isPrevisit && "Only previsit supported for now.");
-    PreVisitBind(C, AssignE, StoreE, location, val);
+    PreVisitBind(C, StoreE, location, val);
   }
   
   // FIXME: Remove the 'tag' option.
@@ -264,8 +263,8 @@ public:
   virtual void _PreVisit(CheckerContext &C, const Stmt *S) {}
   virtual void _PostVisit(CheckerContext &C, const Stmt *S) {}
   virtual void VisitLocation(CheckerContext &C, const Stmt *S, SVal location) {}
-  virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE,
-                            const Stmt *StoreE, SVal location, SVal val) {}
+  virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
+                            SVal location, SVal val) {}
   virtual void EvalDeadSymbols(CheckerContext &C, SymbolReaper &SymReaper) {}
   virtual void EvalEndPath(GREndPathNodeBuilder &B, void *tag,
                            GRExprEngine &Eng) {}
index 55dab2a8a3270632926e4755788208e2ee424eaf..5ba0b36b315dbc27a43695e1414e1a4cd481ca85 100644 (file)
@@ -295,10 +295,9 @@ public:
                               const GRState *state,
                               ExplodedNode *Pred);
   
-  void CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
-                        ExplodedNodeSet &Dst, ExplodedNodeSet &Src, 
-                        SVal location, SVal val, bool isPrevisit);
-
+  void CheckerVisitBind(const Stmt *StoreE, ExplodedNodeSet &Dst,
+                        ExplodedNodeSet &Src,  SVal location, SVal val,
+                        bool isPrevisit);
 
   /// Visit - Transfer function logic for all statements.  Dispatches to
   ///  other functions that handle specific kinds of statements.
@@ -494,8 +493,7 @@ protected:
 
   /// EvalBind - Handle the semantics of binding a value to a specific location.
   ///  This method is used by EvalStore, VisitDeclStmt, and others.
-  void EvalBind(ExplodedNodeSet& Dst, const Stmt *AssignE,
-                const Stmt* StoreE, ExplodedNode* Pred,
+  void EvalBind(ExplodedNodeSet& Dst, const Stmt* StoreE, ExplodedNode* Pred,
                 const GRState* St, SVal location, SVal Val,
                 bool atDeclInit = false);
 
index c9173aa92afe5780a25bcd61e5eb2dfa3880351c..12974e999e6eda8fc9ff13dd85907cb275bd1544 100644 (file)
@@ -306,10 +306,9 @@ bool GRExprEngine::CheckerEvalCall(const CallExpr *CE,
 
 // FIXME: This is largely copy-paste from CheckerVisit().  Need to
 // unify.
-void GRExprEngine::CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
-                                    ExplodedNodeSet &Dst,
-                                    ExplodedNodeSet &Src,
-                                    SVal location, SVal val, bool isPrevisit) {
+void GRExprEngine::CheckerVisitBind(const Stmt *StoreE, ExplodedNodeSet &Dst,
+                                    ExplodedNodeSet &Src, SVal location,
+                                    SVal val, bool isPrevisit) {
 
   if (Checkers.empty()) {
     Dst.insert(Src);
@@ -334,7 +333,7 @@ void GRExprEngine::CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
 
     for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
          NI != NE; ++NI)
-      checker->GR_VisitBind(*CurrSet, *Builder, *this, AssignE, StoreE,
+      checker->GR_VisitBind(*CurrSet, *Builder, *this, StoreE,
                             *NI, tag, location, val, isPrevisit);
 
     // Update which NodeSet is the current one.
@@ -1816,16 +1815,15 @@ void GRExprEngine::VisitMemberExpr(const MemberExpr* M, ExplodedNode* Pred,
 
 /// EvalBind - Handle the semantics of binding a value to a specific location.
 ///  This method is used by EvalStore and (soon) VisitDeclStmt, and others.
-void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, const Stmt *AssignE,
-                            const Stmt* StoreE, ExplodedNode* Pred,
-                            const GRState* state, SVal location, SVal Val,
-                            bool atDeclInit) {
+void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, const Stmt* StoreE,
+                            ExplodedNode* Pred, const GRState* state,
+                            SVal location, SVal Val, bool atDeclInit) {
 
 
   // Do a previsit of the bind.
   ExplodedNodeSet CheckedSet, Src;
   Src.Add(Pred);
-  CheckerVisitBind(AssignE, StoreE, CheckedSet, Src, location, Val, true);
+  CheckerVisitBind(StoreE, CheckedSet, Src, location, Val, true);
 
   for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
        I!=E; ++I) {
@@ -1858,6 +1856,10 @@ void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, const Stmt *AssignE,
     // The next thing to do is check if the GRTransferFuncs object wants to
     // update the state based on the new binding.  If the GRTransferFunc object
     // doesn't do anything, just auto-propagate the current state.
+    
+    // NOTE: We use 'AssignE' for the location of the PostStore if 'AssignE'
+    // is non-NULL.  Checkers typically care about 
+    
     GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, newState, StoreE,
                                     newState != state);
 
@@ -1872,7 +1874,7 @@ void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, const Stmt *AssignE,
 ///  @param location The location to store the value
 ///  @param Val The value to be stored
 void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, const Expr *AssignE,
-                             const Expr* StoreE,
+                             const Expr* LocationE,
                              ExplodedNode* Pred,
                              const GRState* state, SVal location, SVal Val,
                              const void *tag) {
@@ -1881,7 +1883,7 @@ void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, const Expr *AssignE,
 
   // Evaluate the location (checks for bad dereferences).
   ExplodedNodeSet Tmp;
-  EvalLocation(Tmp, StoreE, Pred, state, location, tag, false);
+  EvalLocation(Tmp, LocationE, Pred, state, location, tag, false);
 
   if (Tmp.empty())
     return;
@@ -1892,9 +1894,12 @@ void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, const Expr *AssignE,
                                                    ProgramPoint::PostStoreKind);
   SaveAndRestore<const void*> OldTag(Builder->Tag, tag);
 
-  // Proceed with the store.
+  // Proceed with the store.  We use AssignE as the anchor for the PostStore
+  // ProgramPoint if it is non-NULL, and LocationE otherwise.
+  const Expr *StoreE = AssignE ? AssignE : LocationE;
+
   for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
-    EvalBind(Dst, AssignE, StoreE, *NI, GetState(*NI), location, Val);
+    EvalBind(Dst, StoreE, *NI, GetState(*NI), location, Val);
 }
 
 void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, const Expr *Ex, 
@@ -2701,7 +2706,7 @@ void GRExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
                                                Builder->getCurrentBlockCount());
       }
 
-      EvalBind(Dst, DS, DS, *I, state,
+      EvalBind(Dst, DS, *I, state,
                loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
     }
     else {
@@ -2733,7 +2738,7 @@ void GRExprEngine::VisitCondInit(const VarDecl *VD, const Stmt *S,
                                             Builder->getCurrentBlockCount());
     }
 
-    EvalBind(Dst, S, S, N, state,
+    EvalBind(Dst, S, N, state,
              loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
   }
 }
index 3224f7bb2e814ed6e8067f2d61d9a8bff24bf62e..ac98c89a8d9ee3dc42eba1c3ff01328311cc2e48 100644 (file)
@@ -82,9 +82,8 @@ public:
   const GRState *EvalAssume(const GRState *state, SVal Cond, bool Assumption,
                             bool *respondsToCallback);
   void VisitLocation(CheckerContext &C, const Stmt *S, SVal l);
-  virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE,
-                            const Stmt *StoreE, SVal location,
-                            SVal val);
+  virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
+                            SVal location, SVal val);
 
 private:
   void MallocMem(CheckerContext &C, const CallExpr *CE);
@@ -676,7 +675,6 @@ void MallocChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l) {
 }
 
 void MallocChecker::PreVisitBind(CheckerContext &C,
-                                 const Stmt *AssignE,
                                  const Stmt *StoreE,
                                  SVal location,
                                  SVal val) {
index 6cef60eaee298dcac8f982c8528b41c76f8273db..ccc97489e6312b6209024da9fc3c5e48182738ff 100644 (file)
@@ -25,9 +25,8 @@ class UndefinedAssignmentChecker
 public:
   UndefinedAssignmentChecker() : BT(0) {}
   static void *getTag();
-  virtual void PreVisitBind(CheckerContext &C, const Stmt *AssignE,
-                            const Stmt *StoreE, SVal location,
-                            SVal val);
+  virtual void PreVisitBind(CheckerContext &C, const Stmt *StoreE,
+                            SVal location, SVal val);
 };
 }
 
@@ -41,7 +40,6 @@ void *UndefinedAssignmentChecker::getTag() {
 }
 
 void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
-                                              const Stmt *AssignE,
                                               const Stmt *StoreE,
                                               SVal location,
                                               SVal val) {
@@ -61,8 +59,8 @@ void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
   // Generate a report for this bug.
   const Expr *ex = 0;
 
-  while (AssignE) {
-    if (const BinaryOperator *B = dyn_cast<BinaryOperator>(AssignE)) {
+  while (StoreE) {
+    if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) {
       if (B->isCompoundAssignmentOp()) {
         const GRState *state = C.getState();
         if (state->getSVal(B->getLHS()).isUndef()) {
@@ -77,7 +75,7 @@ void UndefinedAssignmentChecker::PreVisitBind(CheckerContext &C,
       break;
     }
 
-    if (const DeclStmt *DS = dyn_cast<DeclStmt>(AssignE)) {
+    if (const DeclStmt *DS = dyn_cast<DeclStmt>(StoreE)) {
       const VarDecl* VD = dyn_cast<VarDecl>(DS->getSingleDecl());
       ex = VD->getInit();
     }
index aa866de03c1faef8361da01b34e6a894d5a4a1f8..95faa06a06334a96baceb65520e79d2aee484633 100644 (file)
@@ -205,7 +205,7 @@ void test_null_field(void) {
 // CHECK:         </dict>
 // CHECK:         <dict>
 // CHECK:          <key>line</key><integer>10</integer>
-// CHECK:          <key>col</key><integer>3</integer>
+// CHECK:          <key>col</key><integer>7</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:        </array>