[cfe-commits] r59313 - in /cfe/trunk: include/clang/Analysis/PathSensitive/GRExprEngine.h lib/Analysis/GRExprEngine.cpp

Ted Kremenek kremenek at apple.com
Fri Nov 14 11:47:18 PST 2008


Author: kremenek
Date: Fri Nov 14 13:47:18 2008
New Revision: 59313

URL: http://llvm.org/viewvc/llvm-project?rev=59313&view=rev
Log:
Second attempt at implementation transfer function support for ObjCForCollectionStmt.  We now assume that the 'element' expression can be any lvalue.

Modified:
    cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
    cfe/trunk/lib/Analysis/GRExprEngine.cpp

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h?rev=59313&r1=59312&r2=59313&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Fri Nov 14 13:47:18 2008
@@ -543,6 +543,9 @@
   void VisitObjCForCollectionStmt(ObjCForCollectionStmt* S, NodeTy* Pred,
                                   NodeSet& Dst);
   
+  void VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S, NodeTy* Pred,
+                                     NodeSet& Dst, SVal ElementV);
+  
   /// VisitObjCMessageExpr - Transfer function for ObjC message expressions.
   void VisitObjCMessageExpr(ObjCMessageExpr* ME, NodeTy* Pred, NodeSet& Dst);
   
@@ -656,7 +659,7 @@
   void EvalLoad(NodeSet& Dst, Expr* Ex, NodeTy* Pred,
                 const GRState* St, SVal location, bool CheckOnly = false);
   
-  const GRState* EvalLocation(Expr* Ex, NodeTy* Pred,
+  const GRState* EvalLocation(Stmt* Ex, NodeTy* Pred,
                               const GRState* St, SVal location,
                               bool isLoad = false);
   

Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=59313&r1=59312&r2=59313&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Fri Nov 14 13:47:18 2008
@@ -306,18 +306,18 @@
         MakeNode(Dst, B, Pred, BindExpr(St, B, GetSVal(St, B->getRHS())));
         break;
       }
-      
+
       VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst);
       break;
     }
-      
+
     case Stmt::CallExprClass:
     case Stmt::CXXOperatorCallExprClass: {
       CallExpr* C = cast<CallExpr>(S);
       VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst);
-      break;      
+      break;
     }
-      
+
       // FIXME: ChooseExpr is really a constant.  We need to fix
       //        the CFG do not model them as explicit control-flow.
       
@@ -1010,7 +1010,7 @@
     MakeNode(Dst, Ex, *I, (*I)->getState());
 }
 
-const GRState* GRExprEngine::EvalLocation(Expr* Ex, NodeTy* Pred,
+const GRState* GRExprEngine::EvalLocation(Stmt* Ex, NodeTy* Pred,
                                           const GRState* St,
                                           SVal location, bool isLoad) {
   
@@ -1382,50 +1382,67 @@
   //    container is empty.  Thus this transfer function will by default
   //    result in state splitting.
   
-  Stmt* elem = S->getElement();  
-  VarDecl* ElemD;
-  bool newDecl = false;
+  Stmt* elem = S->getElement();
+  SVal ElementV;
     
   if (DeclStmt* DS = dyn_cast<DeclStmt>(elem)) {
-    ElemD = cast<VarDecl>(DS->getSolitaryDecl());
+    VarDecl* ElemD = cast<VarDecl>(DS->getSolitaryDecl());
     assert (ElemD->getInit() == 0);
-    newDecl = true;
+    ElementV = getStateManager().GetLValue(GetState(Pred), ElemD);
+    VisitObjCForCollectionStmtAux(S, Pred, Dst, ElementV);
+    return;
   }
-  else
-    ElemD = cast<VarDecl>(cast<DeclRefExpr>(elem)->getDecl());
+
+  NodeSet Tmp;
+  VisitLValue(cast<Expr>(elem), Pred, Tmp);
   
+  for (NodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
+    const GRState* state = GetState(*I);
+    VisitObjCForCollectionStmtAux(S, *I, Dst, GetSVal(state, elem));
+  }
+}
+
+void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
+                                                 NodeTy* Pred, NodeSet& Dst,
+                                                 SVal ElementV) {
+    
+
   
-  // Get the current state, as well as the QualType for 'int' and the
-  // type of the element.
-  GRStateRef state = GRStateRef(GetState(Pred), getStateManager());
-  QualType IntTy = getContext().IntTy;
-  QualType ElemTy = ElemD->getType();
+  // Get the current state.  Use 'EvalLocation' to determine if it is a null
+  // pointer, etc.
+  Stmt* elem = S->getElement();
+  GRStateRef state = GRStateRef(EvalLocation(elem, Pred, GetState(Pred),
+                                             ElementV, false),
+                                getStateManager());
   
+  if (!state)
+    return;
+
   // Handle the case where the container still has elements.
+  QualType IntTy = getContext().IntTy;
   SVal TrueV = NonLoc::MakeVal(getBasicVals(), 1, IntTy);
   GRStateRef hasElems = state.BindExpr(S, TrueV);
   
-  assert (Loc::IsLocType(ElemTy));
-  unsigned Count = Builder->getCurrentBlockCount();
-  loc::SymbolVal SymV(SymMgr.getConjuredSymbol(elem, ElemTy, Count));
-  
-  if (newDecl)
-    hasElems = hasElems.BindDecl(ElemD, &SymV, Count);
-  else
-    hasElems = hasElems.BindLoc(hasElems.GetLValue(ElemD), SymV);
-  
   // Handle the case where the container has no elements.
   SVal FalseV = NonLoc::MakeVal(getBasicVals(), 0, IntTy);
   GRStateRef noElems = state.BindExpr(S, FalseV);
-
-  if (!newDecl) {
-    // We only need to bind nil to an existing variable, since out of the
-    // loop the VarDecl won't exist and there will be no chance to get it's
-    // address via the '&' operator.
-    SVal nilV = loc::ConcreteInt(getBasicVals().getValue(0, ElemTy));
-    noElems.BindLoc(noElems.GetLValue(ElemD), nilV);
-  }
-
+  
+  if (loc::MemRegionVal* MV = dyn_cast<loc::MemRegionVal>(&ElementV))
+    if (const TypedRegion* R = dyn_cast<TypedRegion>(MV->getRegion())) {
+      // FIXME: The proper thing to do is to really iterate over the
+      //  container.  We will do this with dispatch logic to the store.
+      //  For now, just 'conjure' up a symbolic value.
+      QualType T = R->getType(getContext());
+      assert (Loc::IsLocType(T));
+      unsigned Count = Builder->getCurrentBlockCount();
+      loc::SymbolVal SymV(SymMgr.getConjuredSymbol(elem, T, Count));
+      hasElems = hasElems.BindLoc(ElementV, SymV);
+
+      // Bind the location to 'nil' on the false branch.
+      SVal nilV = loc::ConcreteInt(getBasicVals().getValue(0, T));      
+      noElems = noElems.BindLoc(ElementV, nilV);      
+    }
+  
   // Create the new nodes.
   MakeNode(Dst, S, Pred, hasElems);
   MakeNode(Dst, S, Pred, noElems);





More information about the cfe-commits mailing list