diff options
author | Ted Kremenek <kremenek@apple.com> | 2009-09-09 20:36:12 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2009-09-09 20:36:12 +0000 |
commit | cfcd7fd0de701c5ce05e96de1ed2d0bf8c7035d9 (patch) | |
tree | 09d076f2264ed225907c005b2b0d0b4bb47dfaab | |
parent | 0d36aa8c23776cde8819ff4d65b1f87507182a9f (diff) |
Implement: <rdar://problem/7185647> [RegionStore] 'self' cannot be NULL upon entry to a method
Here we implement this as a precondition within GRExprEngine, even though it is
related to how BasicStoreManager and RegionStoreManager model 'self'
differently. Putting this as a high-level precondition is more general, which is
why it isn't in RegionStore.cpp.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81378 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 26 | ||||
-rw-r--r-- | test/Analysis/misc-ps.m | 13 |
2 files changed, 35 insertions, 4 deletions
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index b4b69cdcd6..ff9554c836 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -198,11 +198,15 @@ void GRExprEngine::AddCheck(GRSimpleAPICheck *A) { const GRState* GRExprEngine::getInitialState(const LocationContext *InitLoc) { const GRState *state = StateMgr.getInitialState(InitLoc); - // Precondition: the first argument of 'main' is an integer guaranteed - // to be > 0. + // Preconditions. + // FIXME: It would be nice if we had a more general mechanism to add // such preconditions. Some day. - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(InitLoc->getDecl())) + const Decl *D = InitLoc->getDecl(); + + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + // Precondition: the first argument of 'main' is an integer guaranteed + // to be > 0. if (strcmp(FD->getIdentifier()->getName(), "main") == 0 && FD->getNumParams() > 0) { const ParmVarDecl *PD = FD->getParamDecl(0); @@ -218,7 +222,21 @@ const GRState* GRExprEngine::getInitialState(const LocationContext *InitLoc) { state = newState; } } - + } + else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { + // Precondition: 'self' is always non-null upon entry to an Objective-C + // method. + const ImplicitParamDecl *SelfD = MD->getSelfDecl(); + const MemRegion *R = state->getRegion(SelfD, InitLoc); + SVal V = state->getSVal(loc::MemRegionVal(R)); + + if (const Loc *LV = dyn_cast<Loc>(&V)) { + // Assume that the pointer value in 'self' is non-null. + state = state->assume(*LV, true); + assert(state && "'self' cannot be null"); + } + } + return state; } diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m index cbfb5b1d46..34a09536db 100644 --- a/test/Analysis/misc-ps.m +++ b/test/Analysis/misc-ps.m @@ -554,3 +554,16 @@ void pr4781(unsigned long *raw1) { } } +// <rdar://problem/7185647> - 'self' should be treated as being non-null +// upon entry to an objective-c method. +@interface RDar7185647 +- (id)foo; +@end +@implementation RDar7185647 +- (id) foo { + if (self) + return self; + *((int *) 0x0) = 0xDEADBEEF; // no-warning + return self; +} +@end |