[cfe-commits] r66166 - in /cfe/trunk: lib/Analysis/BasicStore.cpp test/Analysis/misc-ps-region-store.m test/Analysis/misc-ps.m

Ted Kremenek kremenek at apple.com
Thu Mar 5 10:08:28 PST 2009


Author: kremenek
Date: Thu Mar  5 12:08:28 2009
New Revision: 66166

URL: http://llvm.org/viewvc/llvm-project?rev=66166&view=rev
Log:
Retrofit some basic tracking of ivars (for the current object) into BasicStore.

Modified:
    cfe/trunk/lib/Analysis/BasicStore.cpp
    cfe/trunk/test/Analysis/misc-ps-region-store.m
    cfe/trunk/test/Analysis/misc-ps.m

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

==============================================================================
--- cfe/trunk/lib/Analysis/BasicStore.cpp (original)
+++ cfe/trunk/lib/Analysis/BasicStore.cpp Thu Mar  5 12:08:28 2009
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "clang/AST/ExprObjC.h"
 #include "clang/Analysis/Analyses/LiveVariables.h"
 #include "clang/Analysis/PathSensitive/GRState.h"
 #include "llvm/ADT/ImmutableMap.h"
@@ -57,6 +58,8 @@
     return StateMgr.MakeStateWithStore(St, store);
   }
 
+  Store scanForIvars(Stmt *B, const Decl* SelfDecl, Store St);
+  
   Store BindInternal(Store St, Loc loc, SVal V);  
   Store Remove(Store St, Loc loc);
   Store getInitialStore();
@@ -147,6 +150,19 @@
 
 SVal BasicStoreManager::getLValueIvar(const GRState* St, const ObjCIvarDecl* D,
                                       SVal Base) {
+  
+  if (Base.isUnknownOrUndef())
+    return Base;
+
+  Loc BaseL = cast<Loc>(Base);
+
+  if (isa<loc::MemRegionVal>(BaseL)) {
+    const MemRegion *BaseR = cast<loc::MemRegionVal>(BaseL).getRegion();
+
+    if (BaseR == SelfRegion)
+      return loc::MemRegionVal(MRMgr.getObjCIvarRegion(D, BaseR));
+  }
+  
   return UnknownVal();
 }
   
@@ -293,14 +309,12 @@
   switch (loc.getSubKind()) {
 
     case loc::MemRegionKind: {
-      const VarRegion* R =
-        dyn_cast<VarRegion>(cast<loc::MemRegionVal>(loc).getRegion());
+      const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion();
       
-      if (!R)
+      if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R)))
         return UnknownVal();
       
-      Store store = state->getStore();
-      BindingsTy B = GetBindings(store);
+      BindingsTy B = GetBindings(state->getStore());
       BindingsTy::data_type* T = B.lookup(R);
       return T ? *T : UnknownVal();
     }
@@ -327,12 +341,16 @@
 Store BasicStoreManager::BindInternal(Store store, Loc loc, SVal V) {    
   switch (loc.getSubKind()) {      
     case loc::MemRegionKind: {
-      const VarRegion* R =
-        dyn_cast<VarRegion>(cast<loc::MemRegionVal>(loc).getRegion());
+      const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion();
       
-      if (!R)
+      if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R)))
         return store;
       
+      // We only track bindings to self.ivar.
+      if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R))
+        if (IVR->getSuperRegion() != SelfRegion)
+          return store;
+
       BindingsTy B = GetBindings(store);
       return V.isUnknown()
         ? VBFactory.Remove(B, R).getRoot()
@@ -347,14 +365,12 @@
 Store BasicStoreManager::Remove(Store store, Loc loc) {
   switch (loc.getSubKind()) {
     case loc::MemRegionKind: {
-      const VarRegion* R =
-        dyn_cast<VarRegion>(cast<loc::MemRegionVal>(loc).getRegion());
+      const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion();
       
-      if (!R)
+      if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R)))
         return store;
       
-      BindingsTy B = GetBindings(store);
-      return VBFactory.Remove(B, R).getRoot();
+      return VBFactory.Remove(GetBindings(store), R).getRoot();
     }
     default:
       assert ("Remove for given Loc type not yet implemented.");
@@ -374,18 +390,26 @@
   
   // Iterate over the variable bindings.
   for (BindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I) {
-    const VarRegion *VR = cast<VarRegion>(I.getKey());
-    if (SymReaper.isLive(Loc, VR->getDecl())) {
-      RegionRoots.push_back(VR);      
-      SVal X = I.getData();
-      
-      for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
-        SymReaper.markLive(*SI);
+    if (const VarRegion *VR = dyn_cast<VarRegion>(I.getKey())) {
+      if (SymReaper.isLive(Loc, VR->getDecl()))
+        RegionRoots.push_back(VR);
+      else
+        continue;
+    }
+    else if (isa<ObjCIvarRegion>(I.getKey())) {
+      RegionRoots.push_back(I.getKey());
     }
+    else
+      continue;
+    
+    // Mark the bindings in the data as live.
+    SVal X = I.getData();
+    for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
+      SymReaper.markLive(*SI);
   }
   
   // Scan for live variables and live symbols.
-  llvm::SmallPtrSet<const VarRegion*, 10> Marked;
+  llvm::SmallPtrSet<const MemRegion*, 10> Marked;
   
   while (!RegionRoots.empty()) {
     const MemRegion* MR = RegionRoots.back();
@@ -396,12 +420,12 @@
         SymReaper.markLive(SymR->getSymbol());
         break;
       }
-      else if (const VarRegion* R = dyn_cast<VarRegion>(MR)) {
-        if (Marked.count(R))
+      else if (isa<VarRegion>(MR) || isa<ObjCIvarRegion>(MR)) {
+        if (Marked.count(MR))
           break;
         
-        Marked.insert(R);
-        SVal X = Retrieve(state, loc::MemRegionVal(R));
+        Marked.insert(MR);
+        SVal X = Retrieve(state, loc::MemRegionVal(MR));
     
         // FIXME: We need to handle symbols nested in region definitions.
         for (symbol_iterator SI=X.symbol_begin(),SE=X.symbol_end();SI!=SE;++SI)
@@ -423,7 +447,7 @@
   
   // Remove dead variable bindings.  
   for (BindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I) {
-    const VarRegion* R = cast<VarRegion>(I.getKey());
+    const MemRegion* R = I.getKey();
     
     if (!Marked.count(R)) {
       store = Remove(store, Loc::MakeVal(R));
@@ -433,19 +457,46 @@
         SymReaper.maybeDead(*SI);
     }
   }
-  
+
   return store;
 }
 
-Store BasicStoreManager::getInitialStore() {
+Store BasicStoreManager::scanForIvars(Stmt *B, const Decl* SelfDecl, Store St) {
+  for (Stmt::child_iterator CI=B->child_begin(), CE=B->child_end();
+       CI != CE; ++CI) {
+    
+    if (!*CI)
+      continue;
+    
+    // Check if the statement is an ivar reference.  We only
+    // care about self.ivar.
+    if (ObjCIvarRefExpr *IV = dyn_cast<ObjCIvarRefExpr>(*CI)) {
+      const Expr *Base = IV->getBase()->IgnoreParenCasts();
+      if (const DeclRefExpr *DR = dyn_cast<DeclRefExpr>(Base)) {
+        if (DR->getDecl() == SelfDecl) {
+          const MemRegion *IVR = MRMgr.getObjCIvarRegion(IV->getDecl(),
+                                                         SelfRegion);
+          
+          SVal X = SVal::GetRValueSymbolVal(StateMgr.getSymbolManager(),
+                                            IVR);
+          
+          St = BindInternal(St, Loc::MakeVal(IVR), X);
+        }
+      }
+    }
+    else
+      St = scanForIvars(*CI, SelfDecl, St);
+  }
   
+  return St;
+}
+
+Store BasicStoreManager::getInitialStore() {  
   // The LiveVariables information already has a compilation of all VarDecls
   // used in the function.  Iterate through this set, and "symbolicate"
   // any VarDecl whose value originally comes from outside the function.
-
   typedef LiveVariables::AnalysisDataTy LVDataTy;
   LVDataTy& D = StateMgr.getLiveVariables().getAnalysisData();
-
   Store St = VBFactory.GetEmptyMap().getRoot();
 
   for (LVDataTy::decl_iterator I=D.begin_decl(), E=D.end_decl(); I != E; ++I) {
@@ -463,6 +514,10 @@
           
           St = BindInternal(St, Loc::MakeVal(MRMgr.getVarRegion(PD)),
                             Loc::MakeVal(SelfRegion));
+          
+          // Scan the method for ivar references.  While this requires an
+          // entire AST scan, the cost should not be high in practice.
+          St = scanForIvars(MD->getBody(), PD, St);
         }
       }
     }

Modified: cfe/trunk/test/Analysis/misc-ps-region-store.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps-region-store.m?rev=66166&r1=66165&r2=66166&view=diff

==============================================================================
--- cfe/trunk/test/Analysis/misc-ps-region-store.m (original)
+++ cfe/trunk/test/Analysis/misc-ps-region-store.m Thu Mar  5 12:08:28 2009
@@ -68,23 +68,3 @@
   return 'a';
 }
 
-///
- at interface Test3 : NSObject {
-  int flag;
-}
-- (void)test_self_tracking;
- at end
-
- at implementation Test3
-- (void)test_self_tracking {
-  char *p = 0;
-  char c;
-
-  if (flag)
-    p = "hello";
-
-  if (flag)
-    c = *p; // no-warning
-}
- at end
-

Modified: cfe/trunk/test/Analysis/misc-ps.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps.m?rev=66166&r1=66165&r2=66166&view=diff

==============================================================================
--- cfe/trunk/test/Analysis/misc-ps.m (original)
+++ cfe/trunk/test/Analysis/misc-ps.m Thu Mar  5 12:08:28 2009
@@ -3,9 +3,29 @@
 // RUN: clang -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=basic --verify -fblocks %s &&
 // RUN: clang -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=range --verify -fblocks %s
 
+typedef struct objc_selector *SEL;
+typedef signed char BOOL;
+typedef int NSInteger;
+typedef unsigned int NSUInteger;
+typedef struct _NSZone NSZone;
+ at class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
+ at protocol NSObject  - (BOOL)isEqual:(id)object; @end
+ at protocol NSCopying  - (id)copyWithZone:(NSZone *)zone; @end
+ at protocol NSMutableCopying  - (id)mutableCopyWithZone:(NSZone *)zone; @end
+ at protocol NSCoding  - (void)encodeWithCoder:(NSCoder *)aCoder; @end
+ at interface NSObject <NSObject> {} - (id)init; @end
+extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);
+ at interface NSString : NSObject <NSCopying, NSMutableCopying, NSCoding>
+- (NSUInteger)length;
++ (id)stringWithUTF8String:(const char *)nullTerminatedCString;
+ at end extern NSString * const NSBundleDidLoadNotification;
+ at interface NSAssertionHandler : NSObject {}
++ (NSAssertionHandler *)currentHandler;
+- (void)handleFailureInMethod:(SEL)selector object:(id)object file:(NSString *)fileName lineNumber:(NSInteger)line description:(NSString *)format,...;
+ at end
+extern NSString * const NSConnectionReplyMode;
 
 // Reduced test case from crash in <rdar://problem/6253157>
- at class NSObject;
 @interface A @end
 @implementation A
 - (void)foo:(void (^)(NSObject *x))block {
@@ -125,4 +145,23 @@
   return (__a64vector)a[0];
 }
 
+// Test basic tracking of ivars associated with 'self'.
+ at interface SelfIvarTest : NSObject {
+  int flag;
+}
+- (void)test_self_tracking;
+ at end
+
+ at implementation SelfIvarTest
+- (void)test_self_tracking {
+  char *p = 0;
+  char c;
+
+  if (flag)
+    p = "hello";
+
+  if (flag)
+    c = *p; // no-warning
+}
+ at end
 





More information about the cfe-commits mailing list