[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