diff options
author | Ted Kremenek <kremenek@apple.com> | 2011-12-01 05:29:42 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2011-12-01 05:29:42 +0000 |
commit | a078ecf3484d62b01d9f8c01e0fecffd65c583e1 (patch) | |
tree | c3b2f812fa390aa92899ca275a95620248fa0b53 | |
parent | 3ed7903d27f0e7e0cd3a61c165d39eca70f3cff5 (diff) |
When analyzing a C++ method (without a specific caller), assume 'this' is non-null. Fixes <rdar://problem/10508787>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@145575 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 51 | ||||
-rw-r--r-- | test/Analysis/misc-ps-region-store.cpp | 14 |
2 files changed, 48 insertions, 17 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index a3fd4f80dc..f5d26c9645 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -83,13 +83,13 @@ ExprEngine::~ExprEngine() { const ProgramState *ExprEngine::getInitialState(const LocationContext *InitLoc) { const ProgramState *state = StateMgr.getInitialState(InitLoc); + const Decl *D = InitLoc->getDecl(); // Preconditions. - // FIXME: It would be nice if we had a more general mechanism to add // such preconditions. Some day. do { - 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. @@ -119,25 +119,42 @@ const ProgramState *ExprEngine::getInitialState(const LocationContext *InitLoc) if (const ProgramState *newState = state->assume(*Constraint, true)) state = newState; - - break; } + break; + } + while (0); + + 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"); + } + } - 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"); + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { + if (!MD->isStatic()) { + // Precondition: 'this' is always non-null upon entry to the + // top-level function. This is our starting assumption for + // analyzing an "open" program. + const StackFrameContext *SFC = InitLoc->getCurrentStackFrame(); + if (SFC->getParent() == 0) { + loc::MemRegionVal L(getCXXThisRegion(MD, SFC)); + SVal V = state->getSVal(L); + if (const Loc *LV = dyn_cast<Loc>(&V)) { + state = state->assume(*LV, true); + assert(state && "'this' cannot be null"); + } } } - } while (0); - + } + return state; } diff --git a/test/Analysis/misc-ps-region-store.cpp b/test/Analysis/misc-ps-region-store.cpp index df90a7562d..111f829cd0 100644 --- a/test/Analysis/misc-ps-region-store.cpp +++ b/test/Analysis/misc-ps-region-store.cpp @@ -492,3 +492,17 @@ double PR11450() { return NaN; } +// Test that 'this' is assumed null upon analyzing the entry to a "top-level" +// function (i.e., when not analyzing from a specific caller). +struct TestNullThis { + int field; + void test(); +}; + +void TestNullThis::test() { + int *p = &field; + if (p) + return; + field = 2; // no-warning +} + |