]> granicus.if.org Git - clang/commitdiff
Add logic for invalidating array region to CFRefCount.cpp. When invalidating
authorZhongxing Xu <xuzhongxing@gmail.com>
Tue, 12 May 2009 10:10:00 +0000 (10:10 +0000)
committerZhongxing Xu <xuzhongxing@gmail.com>
Tue, 12 May 2009 10:10:00 +0000 (10:10 +0000)
array region, set its default value to conjured symbol. When retrieving its
element, create new region value symbol for the element.

Also fix some 80 columns violations.

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

include/clang/Analysis/PathSensitive/MemRegion.h
include/clang/Analysis/PathSensitive/SVals.h
include/clang/Analysis/PathSensitive/Store.h
lib/Analysis/CFRefCount.cpp
lib/Analysis/RegionStore.cpp
lib/Analysis/SVals.cpp
test/Analysis/array-struct.c

index 831da268b168425e3adc297597a39d3571e8bb49..0e8da2aee31826f0ebd13707517449b99c7745f9 100644 (file)
@@ -217,6 +217,7 @@ public:
   }
 
   bool isDeclared() const { return codekind == Declared; }
+  bool isSymbolic() const { return codekind == Symbolic; }
 
   const FunctionDecl* getDecl() const {
     assert(codekind == Declared);
index 70c0d09a0347a2d0bf1a358c2f544803e2fa0624..ee6d4dcf1f376be206c66354efb74ab73c405a52 100644 (file)
@@ -90,6 +90,9 @@ public:
   
   bool isZeroConstant() const;
 
+  /// hasConjuredSymbol - If this SVal wraps a conjured symbol, return true;
+  bool hasConjuredSymbol() const;
+
   /// getAsFunctionDecl - If this SVal is a MemRegionVal and wraps a
   /// CodeTextRegion wrapping a FunctionDecl, return that FunctionDecl. 
   /// Otherwise return 0.
index 5c1422549e2dc48ec4ddaad4d5e5ff5afcb2625e..adcb2f76e0f36c4a93fb72aa16ea66d4a97e847d 100644 (file)
@@ -161,6 +161,11 @@ public:
     return St;
   }
 
+  virtual const GRState* setDefaultValue(const GRState* St,
+                                         const MemRegion* R, SVal V) {
+    return St;
+  }
+
   virtual void print(Store store, std::ostream& Out,
                      const char* nl, const char *sep) = 0;
       
index 5120d4f0fc508ddb08828048d0ca65bbeab50b5b..dc9602a7b2805489257dda6591d194298ef6e19d 100644 (file)
@@ -1721,7 +1721,7 @@ private:
 
   void ProcessNonLeakError(ExplodedNodeSet<GRState>& Dst,
                            GRStmtNodeBuilder<GRState>& Builder,
-                           Expr* NodeExpr, Expr* ErrorExpr,                        
+                           Expr* NodeExpr, Expr* ErrorExpr,
                            ExplodedNode<GRState>* Pred,
                            const GRState* St,
                            RefVal::Kind hasErr, SymbolRef Sym);
@@ -1767,7 +1767,7 @@ public:
                    Expr* Ex,
                    Expr* Receiver,
                    const RetainSummary& Summ,
-                   ExprIterator arg_beg, ExprIterator arg_end,                             
+                   ExprIterator arg_beg, ExprIterator arg_end,
                    ExplodedNode<GRState>* Pred);
     
   virtual void EvalCall(ExplodedNodeSet<GRState>& Dst,
@@ -1995,7 +1995,7 @@ namespace {
 
     CFRefReport(CFRefBug& D, const CFRefCount &tf,
                 ExplodedNode<GRState> *n, SymbolRef sym, const char* endText)
-      : RangedBugReport(D, D.getDescription(), endText, n), Sym(sym), TF(tf) {}    
+      : RangedBugReport(D, D.getDescription(), endText, n), Sym(sym), TF(tf) {}
     
     virtual ~CFRefReport() {}
     
@@ -2302,7 +2302,7 @@ PathDiagnosticPiece* CFRefReport::VisitNode(const ExplodedNode<GRState>* N,
             if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
               return 0;
             
-            assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());            
+            assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
             os << "Object sent -autorelease message";
             break;
           }
@@ -2623,8 +2623,10 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
                              ExplodedNode<GRState>* Pred) {
   
   // Get the state.
-  GRStateRef state(Builder.GetState(Pred), Eng.getStateManager());
-  ASTContext& Ctx = Eng.getStateManager().getContext();
+  GRStateManager& StateMgr = Eng.getStateManager();
+  GRStateRef state(Builder.GetState(Pred), StateMgr);
+  ASTContext& Ctx = StateMgr.getContext();
+  ValueManager &ValMgr = Eng.getValueManager();
 
   // Evaluate the effect of the arguments.
   RefVal::Kind hasErr = (RefVal::Kind) 0;
@@ -2680,7 +2682,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
             // with an interface to StoreManager so that this logic can be
             // approriately delegated to the respective StoreManagers while
             // still allowing us to do checker-specific logic (e.g.,
-            // invalidating reference counts), probably via callbacks.            
+            // invalidating reference counts), probably via callbacks.
             if (ER->getElementType()->isIntegralType()) {
               const MemRegion *superReg = ER->getSuperRegion();
               if (isa<VarRegion>(superReg) || isa<FieldRegion>(superReg) ||
@@ -2730,15 +2732,21 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
                 QualType FT = FD->getType();
                 
                 if (Loc::IsLocType(FT) || 
-                    (FT->isIntegerType() && FT->isScalarType())) {                  
+                    (FT->isIntegerType() && FT->isScalarType())) {
                   const FieldRegion* FR = MRMgr.getFieldRegion(FD, R);
-                  ValueManager &ValMgr = Eng.getValueManager();
+
                   SVal V = ValMgr.getConjuredSymbolVal(*I, FT, Count);
                   state = state.BindLoc(Loc::MakeVal(FR), V);
                 }                
               }
-            }
-            else {
+            } else if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
+              // Set the default value of the array to conjured symbol.
+              StoreManager& StoreMgr = Eng.getStateManager().getStoreManager();
+              SVal V = ValMgr.getConjuredSymbolVal(*I, AT->getElementType(),
+                                                   Count);
+              state = GRStateRef(StoreMgr.setDefaultValue(state, R, V), 
+                                 StateMgr);
+            } else {
               // Just blast away other values.
               state = state.BindLoc(*MR, UnknownVal());
             }
index 9d29a90b3e768524ab6ab73edd80c91b06419181..440080db7e0c1db2129e3edda89875fad526b5ce 100644 (file)
@@ -276,7 +276,7 @@ public:
   void iterBindings(Store store, BindingsHandler& f) {
     // FIXME: Implement.
   }
-
+  const GRState* setDefaultValue(const GRState* St, const MemRegion* R, SVal V);
 private:
   const GRState* BindArray(const GRState* St, const TypedRegion* R, SVal V);
 
@@ -759,8 +759,13 @@ SVal RegionStoreManager::Retrieve(const GRState* St, Loc L, QualType T) {
     const MemRegion* SuperR = cast<SubRegion>(R)->getSuperRegion();
     GRStateTrait<RegionDefaultValue>::lookup_type D = 
       state.get<RegionDefaultValue>(SuperR);
-    if (D)
-      return *D;
+    if (D) {
+      // If the default value is symbolic, we need to create a new symbol.
+      if (D->hasConjuredSymbol())
+        return ValMgr.getRegionValueSymbolVal(R);
+      else
+        return *D;
+    }
   }
   
   if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) {
@@ -1274,3 +1279,9 @@ const GRState* RegionStoreManager::setCastType(const GRState* St,
   GRStateRef state(St, StateMgr);
   return state.set<RegionCasts>(R, T);
 }
+
+const GRState* RegionStoreManager::setDefaultValue(const GRState* St,
+                                                   const MemRegion* R, SVal V) {
+  GRStateRef state(St, StateMgr);
+  return state.set<RegionDefaultValue>(R, V);
+}
index e10ea8952aa2714cd4520f3f4e89e6019d5383bb..e19b16867b39256144358b1b63dddde2fd3e0382 100644 (file)
@@ -30,6 +30,31 @@ using llvm::APSInt;
 // Utility methods.
 //===----------------------------------------------------------------------===//
 
+bool SVal::hasConjuredSymbol() const {
+  if (const nonloc::SymbolVal* SV = dyn_cast<nonloc::SymbolVal>(this)) {
+    SymbolRef sym = SV->getSymbol();
+    if (isa<SymbolConjured>(sym))
+      return true;
+  }
+
+  if (const loc::MemRegionVal *RV = dyn_cast<loc::MemRegionVal>(this)) {
+    const MemRegion *R = RV->getRegion();
+    if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
+      SymbolRef sym = SR->getSymbol();
+      if (isa<SymbolConjured>(sym))
+        return true;
+    } else if (const CodeTextRegion *CTR = dyn_cast<CodeTextRegion>(R)) {
+      if (CTR->isSymbolic()) {
+        SymbolRef sym = CTR->getSymbol();
+        if (isa<SymbolConjured>(sym))
+          return true;
+      }
+    }
+  }
+
+  return false;
+}
+
 const FunctionDecl* SVal::getAsFunctionDecl() const {
   if (const loc::MemRegionVal* X = dyn_cast<loc::MemRegionVal>(this)) {
     const MemRegion* R = X->getRegion();
index 2b1aea75db0a858ffd65c89d103afd2a66710bc1..318f92f907ee7eecb007ebcaa6caa38a0cd09e3e 100644 (file)
@@ -132,3 +132,13 @@ static struct s3 opt;
 void f14() {
   struct s3 my_opt = opt;
 }
+
+void bar(int*);
+
+// Test if the array is correctly invalidated.
+void f15() {
+  int a[10];
+  bar(a);
+  if (a[1]) // no-warning
+    1;
+}