]> granicus.if.org Git - clang/commitdiff
Added preliminary support for CompoundLiterals in the static analyzer:
authorTed Kremenek <kremenek@apple.com>
Mon, 27 Oct 2008 21:54:31 +0000 (21:54 +0000)
committerTed Kremenek <kremenek@apple.com>
Mon, 27 Oct 2008 21:54:31 +0000 (21:54 +0000)
- GRExprEngine::VisitCompoundLiteral...
   (1) visits the initializer list (generating ExplodedNodes)
   (2) creates a CompoundMemRegion for the literal
   (3) creates a new state with the bound literal values using
       GRStateManager::BindCompoundLiteral

- GRStateManager::BindCompoundLiteral simply calls
  StoreManager::BindCompoundLiteral to get a new store and returns a persistent
  GRState with that store.

- BasicStore::BindCompoundLiteral simply returns the same store, as it
  doesn't handle field sensitivity

- RegionStore::BindCompoundLiteral currently fires an assert (pending discussion
  of how to best implement mappings for CompoundLiteralRegion).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58277 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/PathSensitive/GRExprEngine.h
include/clang/Analysis/PathSensitive/GRState.h
include/clang/Analysis/PathSensitive/Store.h
lib/Analysis/BasicStore.cpp
lib/Analysis/GRExprEngine.cpp
lib/Analysis/GRState.cpp
lib/Analysis/RegionStore.cpp

index 8c5e6ed4034d73b9bca16bf1eb5f5398e410de5b..22454810bef8f869df422ebca114e4643c43b1ba 100644 (file)
@@ -499,6 +499,10 @@ protected:
   /// VisitCast - Transfer function logic for all casts (implicit and explicit).
   void VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst);
   
+  /// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
+  void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, NodeTy* Pred,
+                                NodeSet& Dst);
+  
   /// VisitDeclRefExpr - Transfer function logic for DeclRefExprs.
   void VisitDeclRefExpr(DeclRefExpr* DR, NodeTy* Pred, NodeSet& Dst,
                         bool asLValue); 
index d9b058ce842e36e3754c1feafc86990d4749aa3c..265d028e8acaa2c73d76a18523da9e257705706b 100644 (file)
@@ -329,6 +329,14 @@ public:
 
   const GRState* AddDecl(const GRState* St, const VarDecl* VD, Expr* Ex, 
                          unsigned Count);
+  
+  /// BindCompoundLiteral - Return the state that has the bindings currently
+  ///  in 'state' plus the bindings for the CompoundLiteral.  'R' is the region
+  ///  for the compound literal and 'BegInit' and 'EndInit' represent an
+  ///  array of initializer values.
+  const GRState* BindCompoundLiteral(const GRState* state,
+                                     const CompoundLiteralRegion* R,
+                                     const SVal* BegInit, const SVal* EndInit);
 
   const GRState* RemoveDeadBindings(const GRState* St, Stmt* Loc, 
                                        const LiveVariables& Liveness,
index 7610c54e1b7d7d84bbe21f934d7033d6ceba82c8..41464c176fe781a7336f30ac84d81e3d9fbeff8c 100644 (file)
@@ -47,6 +47,15 @@ public:
   
   virtual Store Bind(Store St, Loc LV, SVal V) = 0;
   virtual Store Remove(Store St, Loc LV) = 0;
+  
+  /// BindCompoundLiteral - Return the store that has the bindings currently
+  ///  in 'store' plus the bindings for the CompoundLiteral.  'R' is the region
+  ///  for the compound literal and 'BegInit' and 'EndInit' represent an
+  ///  array of initializer values.
+  virtual Store BindCompoundLiteral(Store store, const CompoundLiteralRegion* R,
+                                    const SVal* BegInit,
+                                    const SVal* EndInit) = 0;
+  
   virtual Store getInitialStore() = 0;
   virtual MemRegionManager& getRegionManager() = 0;
 
index 88959545028b45f7a65d3229cd2bf6f34b27d511..05c8523d2dc2c7581e77e2eddda95c557daaa2da 100644 (file)
@@ -46,6 +46,11 @@ public:
     return loc::MemRegionVal(MRMgr.getVarRegion(VD));
   }
   
+  Store BindCompoundLiteral(Store store, const CompoundLiteralRegion* R,
+                            const SVal* BegInit, const SVal* EndInit) {
+    return store;
+  }
+  
   SVal getLValueVar(const GRState* St, const VarDecl* VD);
   SVal getLValueString(const GRState* St, const StringLiteral* S);
   SVal getLValueIvar(const GRState* St, const ObjCIvarDecl* D, SVal Base);
index 282a08c21a5c8e2e269378f2a72d2d376c2b24a2..67dd79a193e4603e1725f9be791035fb3b8c2b3b 100644 (file)
@@ -430,6 +430,10 @@ void GRExprEngine::VisitLValue(Expr* Ex, NodeTy* Pred, NodeSet& Dst) {
       VisitMemberExpr(cast<MemberExpr>(Ex), Pred, Dst, true);
       return;
       
+    case Stmt::CompoundLiteralExprClass:
+      VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(Ex), Pred, Dst);
+      return;
+      
     case Stmt::ObjCPropertyRefExprClass:
       // FIXME: Property assignments are lvalues, but not really "locations".
       //  e.g.:  self.x = something;
@@ -1530,6 +1534,35 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
   }
 }
 
+void GRExprEngine::VisitCompoundLiteralExpr(CompoundLiteralExpr* CL,
+                                            NodeTy* Pred, NodeSet& Dst) {
+
+  // FIXME: Can getInitializer() be NULL?
+  InitListExpr* ILE = cast<InitListExpr>(CL->getInitializer()->IgnoreParens());
+  NodeSet Tmp;
+  Visit(ILE, Pred, Tmp);
+  
+  for (NodeSet::iterator I = Tmp.begin(), EI = Tmp.end(); I!=EI; ++I) {
+    // Retrieve the initializer values from the environment and store them
+    // into a vector that will then be handed off to the Store.    
+    const GRState* St = GetState(*I);    
+    llvm::SmallVector<SVal, 10> IVals;
+    IVals.reserve(ILE->getNumInits());
+    
+    for (Stmt::child_iterator J=ILE->child_begin(), EJ=ILE->child_end();
+          J!=EJ; ++J)
+      IVals.push_back(GetSVal(St, cast<Expr>(*J)));
+
+    const CompoundLiteralRegion* R = 
+      StateMgr.getRegionManager().getCompoundLiteralRegion(CL);
+    
+    assert (!IVals.empty() && "Initializer cannot be empty.");
+
+    St = StateMgr.BindCompoundLiteral(St, R, &IVals[0], &IVals[0]+IVals.size());
+    MakeNode(Dst, CL, *I, SetSVal(St, CL, loc::MemRegionVal(R)));
+  }
+}
+
 void GRExprEngine::VisitDeclStmt(DeclStmt* DS, NodeTy* Pred, NodeSet& Dst) {  
 
   // The CFG has one DeclStmt per Decl.  
index 828be2229ff56ca091b4ab54c9642c7faf6060cf..03b724779e9d201b3186f14be3a95d1d73bbdcb8 100644 (file)
@@ -92,6 +92,26 @@ const GRState* GRStateManager::AddDecl(const GRState* St, const VarDecl* VD,
   return getPersistentState(NewSt);
 }
 
+/// BindCompoundLiteral - Return the store that has the bindings currently
+///  in 'store' plus the bindings for the CompoundLiteral.  'R' is the region
+///  for the compound literal and 'BegInit' and 'EndInit' represent an
+///  array of initializer values.
+const GRState*
+GRStateManager::BindCompoundLiteral(const GRState* state,
+                                    const CompoundLiteralRegion* R,                                    
+                                    const SVal* BegInit, const SVal* EndInit) {
+
+  Store oldStore = state->getStore();
+  Store newStore = StoreMgr->BindCompoundLiteral(oldStore, R, BegInit, EndInit);
+  
+  if (newStore == oldStore)
+    return state;
+  
+  GRState newState = *state;
+  newState.St = newStore;
+  return getPersistentState(newState);
+}
+
 const GRState* GRStateManager::Unbind(const GRState* St, Loc LV) {
   Store OldStore = St->getStore();
   Store NewStore = StoreMgr->Remove(OldStore, LV);
index 6a65919b1ee5a287d8a0d4a6a237bdc62bcfcb6a..1c73ceae202cc66648280f8655ae36daca59c360 100644 (file)
@@ -45,6 +45,15 @@ public:
   SVal GetRegionSVal(Store St, const MemRegion* R) {
     return Retrieve(St, loc::MemRegionVal(R));
   }
+  
+  Store BindCompoundLiteral(Store store, const CompoundLiteralRegion* R,
+                            const SVal* BegInit, const SVal* EndInit) {
+    
+    // FIXME: Let's discuss how we want to do the mapping in RegionStore
+    //  from CompoundLiteralRegion to values.
+    assert (false && "Not yet implemented.");
+    return store;
+  }
 
   SVal getLValueString(const GRState* St, const StringLiteral* S);