diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/StaticAnalyzer/Core/Calls.cpp | 72 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp | 20 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ProgramState.cpp | 10 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/RegionStore.cpp | 88 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/Store.cpp | 35 |
5 files changed, 96 insertions, 129 deletions
diff --git a/lib/StaticAnalyzer/Core/Calls.cpp b/lib/StaticAnalyzer/Core/Calls.cpp index 8ea1336bb7..ced1154da7 100644 --- a/lib/StaticAnalyzer/Core/Calls.cpp +++ b/lib/StaticAnalyzer/Core/Calls.cpp @@ -219,20 +219,22 @@ bool CallEvent::mayBeInlined(const Stmt *S) { } -CallEvent::param_iterator AnyFunctionCall::param_begin() const { - const FunctionDecl *D = getDecl(); +CallEvent::param_iterator +AnyFunctionCall::param_begin(bool UseDefinitionParams) const { + const Decl *D = UseDefinitionParams ? getDefinition() : getDecl(); if (!D) return 0; - return D->param_begin(); + return cast<FunctionDecl>(D)->param_begin(); } -CallEvent::param_iterator AnyFunctionCall::param_end() const { - const FunctionDecl *D = getDecl(); +CallEvent::param_iterator +AnyFunctionCall::param_end(bool UseDefinitionParams) const { + const Decl *D = UseDefinitionParams ? getDefinition() : getDecl(); if (!D) return 0; - return D->param_end(); + return cast<FunctionDecl>(D)->param_end(); } QualType AnyFunctionCall::getDeclaredResultType() const { @@ -309,23 +311,31 @@ const FunctionDecl *SimpleCall::getDecl() const { } -void CXXMemberCall::addExtraInvalidatedRegions(RegionList &Regions) const { +SVal CXXMemberCall::getCXXThisVal() const { const Expr *Base = getOriginExpr()->getImplicitObjectArgument(); // FIXME: Will eventually need to cope with member pointers. This is // a limitation in getImplicitObjectArgument(). if (!Base) - return; - - if (const MemRegion *R = getSVal(Base).getAsRegion()) + return UnknownVal(); + + return getSVal(Base); +} + +void CXXMemberCall::addExtraInvalidatedRegions(RegionList &Regions) const { + if (const MemRegion *R = getCXXThisVal().getAsRegion()) Regions.push_back(R); } +SVal CXXMemberOperatorCall::getCXXThisVal() const { + const Expr *Base = getOriginExpr()->getArg(0); + return getSVal(Base); +} + void CXXMemberOperatorCall::addExtraInvalidatedRegions(RegionList &Regions) const { - const Expr *Base = getOriginExpr()->getArg(0); - if (const MemRegion *R = getSVal(Base).getAsRegion()) + if (const MemRegion *R = getCXXThisVal().getAsRegion()) Regions.push_back(R); } @@ -337,14 +347,22 @@ const BlockDataRegion *BlockCall::getBlockRegion() const { return dyn_cast_or_null<BlockDataRegion>(DataReg); } -CallEvent::param_iterator BlockCall::param_begin() const { +CallEvent::param_iterator +BlockCall::param_begin(bool UseDefinitionParams) const { + // Blocks don't have distinct declarations and definitions. + (void)UseDefinitionParams; + const BlockDecl *D = getBlockDecl(); if (!D) return 0; return D->param_begin(); } -CallEvent::param_iterator BlockCall::param_end() const { +CallEvent::param_iterator +BlockCall::param_end(bool UseDefinitionParams) const { + // Blocks don't have distinct declarations and definitions. + (void)UseDefinitionParams; + const BlockDecl *D = getBlockDecl(); if (!D) return 0; @@ -366,32 +384,46 @@ QualType BlockCall::getDeclaredResultType() const { } +SVal CXXConstructorCall::getCXXThisVal() const { + if (Target) + return loc::MemRegionVal(Target); + return UnknownVal(); +} + void CXXConstructorCall::addExtraInvalidatedRegions(RegionList &Regions) const { if (Target) Regions.push_back(Target); } +SVal CXXDestructorCall::getCXXThisVal() const { + if (Target) + return loc::MemRegionVal(Target); + return UnknownVal(); +} + void CXXDestructorCall::addExtraInvalidatedRegions(RegionList &Regions) const { if (Target) Regions.push_back(Target); } -CallEvent::param_iterator ObjCMethodCall::param_begin() const { - const ObjCMethodDecl *D = getDecl(); +CallEvent::param_iterator +ObjCMethodCall::param_begin(bool UseDefinitionParams) const { + const Decl *D = UseDefinitionParams ? getDefinition() : getDecl(); if (!D) return 0; - return D->param_begin(); + return cast<ObjCMethodDecl>(D)->param_begin(); } -CallEvent::param_iterator ObjCMethodCall::param_end() const { - const ObjCMethodDecl *D = getDecl(); +CallEvent::param_iterator +ObjCMethodCall::param_end(bool UseDefinitionParams) const { + const Decl *D = UseDefinitionParams ? getDefinition() : getDecl(); if (!D) return 0; - return D->param_end(); + return cast<ObjCMethodDecl>(D)->param_end(); } void diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index 92497dbb1e..2b47bc064d 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -55,11 +55,7 @@ void ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) { // Construct an edge representing the starting location in the callee. BlockEdge Loc(Entry, Succ, calleeCtx); - // Construct a new state which contains the mapping from actual to - // formal arguments. - const LocationContext *callerCtx = Pred->getLocationContext(); - ProgramStateRef state = Pred->getState()->enterStackFrame(callerCtx, - calleeCtx); + ProgramStateRef state = Pred->getState(); // Construct a new node and add it to the worklist. bool isNew; @@ -287,14 +283,9 @@ bool ExprEngine::inlineCall(ExplodedNodeSet &Dst, switch (Call.getKind()) { case CE_Function: case CE_CXXMember: + case CE_CXXMemberOperator: // These are always at least possible to inline. break; - case CE_CXXMemberOperator: - // FIXME: This should be possible to inline, but - // RegionStore::enterStackFrame isn't smart enough to handle the first - // argument being 'this'. The correct solution is to use CallEvent in - // enterStackFrame as well. - return false; case CE_CXXConstructor: case CE_CXXDestructor: // Do not inline constructors until we can really model destructors. @@ -337,8 +328,13 @@ bool ExprEngine::inlineCall(ExplodedNodeSet &Dst, currentStmtIdx); CallEnter Loc(CallE, CalleeSFC, Pred->getLocationContext()); + + // Construct a new state which contains the mapping from actual to + // formal arguments. + ProgramStateRef State = Pred->getState()->enterStackFrame(Call, CalleeSFC); + bool isNew; - if (ExplodedNode *N = G.getNode(Loc, Pred->getState(), false, &isNew)) { + if (ExplodedNode *N = G.getNode(Loc, State, false, &isNew)) { N->addPredecessor(Pred, G); if (isNew) Engine.getWorkList()->enqueue(N); diff --git a/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp index d7668dec1a..529be0a845 100644 --- a/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -203,11 +203,11 @@ ProgramStateRef ProgramState::unbindLoc(Loc LV) const { } ProgramStateRef -ProgramState::enterStackFrame(const LocationContext *callerCtx, - const StackFrameContext *calleeCtx) const { - const StoreRef &new_store = - getStateManager().StoreMgr->enterStackFrame(this, callerCtx, calleeCtx); - return makeWithStore(new_store); +ProgramState::enterStackFrame(const CallEvent &Call, + const StackFrameContext *CalleeCtx) const { + const StoreRef &NewStore = + getStateManager().StoreMgr->enterStackFrame(getStore(), Call, CalleeCtx); + return makeWithStore(NewStore); } SVal ProgramState::getSValAsScalarOrLoc(const MemRegion *R) const { diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp index fa26c13203..c084bd2ad0 100644 --- a/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -389,16 +389,6 @@ public: // Part of public interface to class. /// It returns a new Store with these values removed. StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx, SymbolReaper& SymReaper); - - StoreRef enterStackFrame(ProgramStateRef state, - const LocationContext *callerCtx, - const StackFrameContext *calleeCtx); - - StoreRef enterStackFrame(ProgramStateRef state, - const FunctionDecl *FD, - const LocationContext *callerCtx, - const StackFrameContext *calleeCtx); - //===------------------------------------------------------------------===// // Region "extents". @@ -2066,84 +2056,6 @@ StoreRef RegionStoreManager::removeDeadBindings(Store store, return StoreRef(B.getRootWithoutRetain(), *this); } -StoreRef RegionStoreManager::enterStackFrame(ProgramStateRef state, - const LocationContext *callerCtx, - const StackFrameContext *calleeCtx) -{ - const Decl *D = calleeCtx->getDecl(); - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) - return enterStackFrame(state, FD, callerCtx, calleeCtx); - - // FIXME: when we handle more cases, this will need to be expanded. - - const BlockDecl *BD = cast<BlockDecl>(D); - BlockDecl::param_const_iterator PI = BD->param_begin(), - PE = BD->param_end(); - StoreRef store = StoreRef(state->getStore(), *this); - const CallExpr *CE = cast<CallExpr>(calleeCtx->getCallSite()); - CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end(); - for (; AI != AE && PI != PE; ++AI, ++PI) { - SVal ArgVal = state->getSVal(*AI, callerCtx); - store = Bind(store.getStore(), - svalBuilder.makeLoc(MRMgr.getVarRegion(*PI, calleeCtx)), - ArgVal); - } - - return store; -} - -StoreRef RegionStoreManager::enterStackFrame(ProgramStateRef state, - const FunctionDecl *FD, - const LocationContext *callerCtx, - const StackFrameContext *calleeCtx) -{ - FunctionDecl::param_const_iterator PI = FD->param_begin(), - PE = FD->param_end(); - StoreRef store = StoreRef(state->getStore(), *this); - - if (CallExpr const *CE = dyn_cast<CallExpr>(calleeCtx->getCallSite())) { - CallExpr::const_arg_iterator AI = CE->arg_begin(), AE = CE->arg_end(); - - // Copy the arg expression value to the arg variables. We check that - // PI != PE because the actual number of arguments may be different than - // the function declaration. - for (; AI != AE && PI != PE; ++AI, ++PI) { - SVal ArgVal = state->getSVal(*AI, callerCtx); - store = Bind(store.getStore(), - svalBuilder.makeLoc(MRMgr.getVarRegion(*PI, calleeCtx)), - ArgVal); - } - - // For C++ method calls, also include the 'this' pointer. - if (const CXXMemberCallExpr *CME = dyn_cast<CXXMemberCallExpr>(CE)) { - loc::MemRegionVal This = - svalBuilder.getCXXThis(cast<CXXMethodDecl>(CME->getCalleeDecl()), - calleeCtx); - SVal CalledObj = state->getSVal(CME->getImplicitObjectArgument(), - callerCtx); - store = Bind(store.getStore(), This, CalledObj); - } - } - else if (const CXXConstructExpr *CE = - dyn_cast<CXXConstructExpr>(calleeCtx->getCallSite())) { - CXXConstructExpr::const_arg_iterator AI = CE->arg_begin(), - AE = CE->arg_end(); - - // Copy the arg expression value to the arg variables. - for (; AI != AE; ++AI, ++PI) { - SVal ArgVal = state->getSVal(*AI, callerCtx); - store = Bind(store.getStore(), - svalBuilder.makeLoc(MRMgr.getVarRegion(*PI, calleeCtx)), - ArgVal); - } - } - else { - assert(isa<CXXDestructorDecl>(calleeCtx->getDecl())); - } - - return store; -} - //===----------------------------------------------------------------------===// // Utility methods. //===----------------------------------------------------------------------===// diff --git a/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp index 11748ae54d..d5c88e8ad8 100644 --- a/lib/StaticAnalyzer/Core/Store.cpp +++ b/lib/StaticAnalyzer/Core/Store.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/AST/CharUnits.h" #include "clang/AST/DeclObjC.h" @@ -23,10 +24,36 @@ StoreManager::StoreManager(ProgramStateManager &stateMgr) : svalBuilder(stateMgr.getSValBuilder()), StateMgr(stateMgr), MRMgr(svalBuilder.getRegionManager()), Ctx(stateMgr.getContext()) {} -StoreRef StoreManager::enterStackFrame(ProgramStateRef state, - const LocationContext *callerCtx, - const StackFrameContext *calleeCtx) { - return StoreRef(state->getStore(), *this); +StoreRef StoreManager::enterStackFrame(Store OldStore, + const CallEvent &Call, + const StackFrameContext *LCtx) { + StoreRef Store = StoreRef(OldStore, *this); + + unsigned Idx = 0; + for (CallEvent::param_iterator I = Call.param_begin(/*UseDefinition=*/true), + E = Call.param_end(/*UseDefinition=*/true); + I != E; ++I, ++Idx) { + const ParmVarDecl *Decl = *I; + assert(Decl && "Formal parameter has no decl?"); + + SVal ArgVal = Call.getArgSVal(Idx); + if (!ArgVal.isUnknown()) { + Store = Bind(Store.getStore(), + svalBuilder.makeLoc(MRMgr.getVarRegion(Decl, LCtx)), + ArgVal); + } + } + + // FIXME: We will eventually want to generalize this to handle other non- + // parameter arguments besides 'this' (such as 'self' for ObjC methods). + SVal ThisVal = Call.getCXXThisVal(); + if (!ThisVal.isUndef()) { + const CXXMethodDecl *MD = cast<CXXMethodDecl>(Call.getDecl()); + loc::MemRegionVal ThisRegion = svalBuilder.getCXXThis(MD, LCtx); + Store = Bind(Store.getStore(), ThisRegion, ThisVal); + } + + return Store; } const MemRegion *StoreManager::MakeElementRegion(const MemRegion *Base, |