diff options
author | Jordan Rose <jordan_rose@apple.com> | 2012-07-31 01:07:55 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2012-07-31 01:07:55 +0000 |
commit | ef15831780b705475e7b237ac16418e9b53cb7a6 (patch) | |
tree | f8c07cce224c57117e2945eef1ff165f09104941 /lib | |
parent | 2f71622dc8888e6da7ce786e42e8e9fbab075de6 (diff) |
[analyzer] Let CallEvent decide what goes in an inital stack frame.
This removes explicit checks for 'this' and 'self' from
Store::enterStackFrame. It also removes getCXXThisRegion() as a virtual
method on all CallEvents; it's now only implemented in the parts of the
hierarchy where it is relevant. Finally, it removes the option to ask
for the ParmVarDecls attached to the definition of an inlined function,
saving a recomputation of the result of getRuntimeDefinition().
No visible functionality change!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161017 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/StaticAnalyzer/Core/CallEvent.cpp | 146 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp | 36 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/Store.cpp | 34 |
3 files changed, 149 insertions, 67 deletions
diff --git a/lib/StaticAnalyzer/Core/CallEvent.cpp b/lib/StaticAnalyzer/Core/CallEvent.cpp index bfc00ed2e0..b28c01d035 100644 --- a/lib/StaticAnalyzer/Core/CallEvent.cpp +++ b/lib/StaticAnalyzer/Core/CallEvent.cpp @@ -232,25 +232,53 @@ bool CallEvent::mayBeInlined(const Stmt *S) { || isa<CXXConstructExpr>(S); } +static void addParameterValuesToBindings(const StackFrameContext *CalleeCtx, + CallEvent::BindingsTy &Bindings, + SValBuilder &SVB, + const CallEvent &Call, + CallEvent::param_iterator I, + CallEvent::param_iterator E) { + MemRegionManager &MRMgr = SVB.getRegionManager(); -CallEvent::param_iterator -AnyFunctionCall::param_begin(bool UseDefinitionParams) const { - const Decl *D = UseDefinitionParams ? getRuntimeDefinition() - : getDecl(); + unsigned Idx = 0; + for (; I != E; ++I, ++Idx) { + const ParmVarDecl *ParamDecl = *I; + assert(ParamDecl && "Formal parameter has no decl?"); + + SVal ArgVal = Call.getArgSVal(Idx); + if (!ArgVal.isUnknown()) { + Loc ParamLoc = SVB.makeLoc(MRMgr.getVarRegion(ParamDecl, CalleeCtx)); + Bindings.push_back(std::make_pair(ParamLoc, ArgVal)); + } + } + + // FIXME: Variadic arguments are not handled at all right now. +} + + +CallEvent::param_iterator AnyFunctionCall::param_begin() const { + const FunctionDecl *D = getDecl(); if (!D) return 0; - return cast<FunctionDecl>(D)->param_begin(); + return D->param_begin(); } -CallEvent::param_iterator -AnyFunctionCall::param_end(bool UseDefinitionParams) const { - const Decl *D = UseDefinitionParams ? getRuntimeDefinition() - : getDecl(); +CallEvent::param_iterator AnyFunctionCall::param_end() const { + const FunctionDecl *D = getDecl(); if (!D) return 0; - return cast<FunctionDecl>(D)->param_end(); + return D->param_end(); +} + +void AnyFunctionCall::getInitialStackFrameContents( + const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const { + const FunctionDecl *D = cast<FunctionDecl>(CalleeCtx->getDecl()); + SValBuilder &SVB = getState()->getStateManager().getSValBuilder(); + addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this, + D->param_begin(), D->param_end()); } QualType AnyFunctionCall::getDeclaredResultType() const { @@ -371,6 +399,21 @@ const Decl *CXXInstanceCall::getRuntimeDefinition() const { return 0; } +void CXXInstanceCall::getInitialStackFrameContents( + const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const { + AnyFunctionCall::getInitialStackFrameContents(CalleeCtx, Bindings); + + SVal ThisVal = getCXXThisVal(); + if (!ThisVal.isUnknown()) { + SValBuilder &SVB = getState()->getStateManager().getSValBuilder(); + const CXXMethodDecl *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl()); + Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx); + Bindings.push_back(std::make_pair(ThisLoc, ThisVal)); + } +} + + SVal CXXMemberCall::getCXXThisVal() const { const Expr *Base = getOriginExpr()->getImplicitObjectArgument(); @@ -397,22 +440,14 @@ const BlockDataRegion *BlockCall::getBlockRegion() const { return dyn_cast_or_null<BlockDataRegion>(DataReg); } -CallEvent::param_iterator -BlockCall::param_begin(bool UseDefinitionParams) const { - // Blocks don't have distinct declarations and definitions. - (void)UseDefinitionParams; - +CallEvent::param_iterator BlockCall::param_begin() const { const BlockDecl *D = getBlockDecl(); if (!D) return 0; return D->param_begin(); } -CallEvent::param_iterator -BlockCall::param_end(bool UseDefinitionParams) const { - // Blocks don't have distinct declarations and definitions. - (void)UseDefinitionParams; - +CallEvent::param_iterator BlockCall::param_end() const { const BlockDecl *D = getBlockDecl(); if (!D) return 0; @@ -425,6 +460,15 @@ void BlockCall::getExtraInvalidatedRegions(RegionList &Regions) const { Regions.push_back(R); } +void BlockCall::getInitialStackFrameContents(const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const { + const BlockDecl *D = cast<BlockDecl>(CalleeCtx->getDecl()); + SValBuilder &SVB = getState()->getStateManager().getSValBuilder(); + addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this, + D->param_begin(), D->param_end()); +} + + QualType BlockCall::getDeclaredResultType() const { const BlockDataRegion *BR = getBlockRegion(); if (!BR) @@ -445,6 +489,21 @@ void CXXConstructorCall::getExtraInvalidatedRegions(RegionList &Regions) const { Regions.push_back(static_cast<const MemRegion *>(Data)); } +void CXXConstructorCall::getInitialStackFrameContents( + const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const { + AnyFunctionCall::getInitialStackFrameContents(CalleeCtx, Bindings); + + SVal ThisVal = getCXXThisVal(); + if (!ThisVal.isUnknown()) { + SValBuilder &SVB = getState()->getStateManager().getSValBuilder(); + const CXXMethodDecl *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl()); + Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx); + Bindings.push_back(std::make_pair(ThisLoc, ThisVal)); + } +} + + SVal CXXDestructorCall::getCXXThisVal() const { if (Data) @@ -474,25 +533,35 @@ const Decl *CXXDestructorCall::getRuntimeDefinition() const { return 0; } +void CXXDestructorCall::getInitialStackFrameContents( + const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const { + AnyFunctionCall::getInitialStackFrameContents(CalleeCtx, Bindings); -CallEvent::param_iterator -ObjCMethodCall::param_begin(bool UseDefinitionParams) const { - const Decl *D = UseDefinitionParams ? getRuntimeDefinition() - : getDecl(); + SVal ThisVal = getCXXThisVal(); + if (!ThisVal.isUnknown()) { + SValBuilder &SVB = getState()->getStateManager().getSValBuilder(); + const CXXMethodDecl *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl()); + Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx); + Bindings.push_back(std::make_pair(ThisLoc, ThisVal)); + } +} + + +CallEvent::param_iterator ObjCMethodCall::param_begin() const { + const ObjCMethodDecl *D = getDecl(); if (!D) return 0; - return cast<ObjCMethodDecl>(D)->param_begin(); + return D->param_begin(); } -CallEvent::param_iterator -ObjCMethodCall::param_end(bool UseDefinitionParams) const { - const Decl *D = UseDefinitionParams ? getRuntimeDefinition() - : getDecl(); +CallEvent::param_iterator ObjCMethodCall::param_end() const { + const ObjCMethodDecl *D = getDecl(); if (!D) return 0; - return cast<ObjCMethodDecl>(D)->param_end(); + return D->param_end(); } void @@ -626,6 +695,23 @@ const Decl *ObjCMethodCall::getRuntimeDefinition() const { return 0; } +void ObjCMethodCall::getInitialStackFrameContents( + const StackFrameContext *CalleeCtx, + BindingsTy &Bindings) const { + const ObjCMethodDecl *D = cast<ObjCMethodDecl>(CalleeCtx->getDecl()); + SValBuilder &SVB = getState()->getStateManager().getSValBuilder(); + addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this, + D->param_begin(), D->param_end()); + + SVal SelfVal = getReceiverSVal(); + if (!SelfVal.isUnknown()) { + const VarDecl *SelfD = CalleeCtx->getAnalysisDeclContext()->getSelfDecl(); + MemRegionManager &MRMgr = SVB.getRegionManager(); + Loc SelfLoc = SVB.makeLoc(MRMgr.getVarRegion(SelfD, CalleeCtx)); + Bindings.push_back(std::make_pair(SelfLoc, SelfVal)); + } +} + CallEventRef<SimpleCall> CallEventManager::getSimpleCall(const CallExpr *CE, ProgramStateRef State, diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index 47d732e515..00ea6daf4f 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -284,14 +284,14 @@ bool ExprEngine::inlineCall(const CallEvent &Call, const StackFrameContext *CallerSFC = CurLC->getCurrentStackFrame(); const LocationContext *ParentOfCallee = 0; + // FIXME: Refactor this check into a hypothetical CallEvent::canInline. switch (Call.getKind()) { case CE_Function: case CE_CXXMember: case CE_CXXMemberOperator: // These are always at least possible to inline. break; - case CE_CXXConstructor: - case CE_CXXDestructor: { + case CE_CXXConstructor: { // Only inline constructors and destructors if we built the CFGs for them // properly. const AnalysisDeclContext *ADC = CallerSFC->getAnalysisDeclContext(); @@ -299,19 +299,37 @@ bool ExprEngine::inlineCall(const CallEvent &Call, !ADC->getCFGBuildOptions().AddInitializers) return false; + const CXXConstructorCall &Ctor = cast<CXXConstructorCall>(Call); + // FIXME: We don't handle constructors or destructors for arrays properly. - const MemRegion *Target = Call.getCXXThisVal().getAsRegion(); + const MemRegion *Target = Ctor.getCXXThisVal().getAsRegion(); if (Target && isa<ElementRegion>(Target)) return false; // FIXME: This is a hack. We don't handle temporary destructors // right now, so we shouldn't inline their constructors. - if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) { - const CXXConstructExpr *CtorExpr = Ctor->getOriginExpr(); - if (CtorExpr->getConstructionKind() == CXXConstructExpr::CK_Complete) - if (!Target || !isa<DeclRegion>(Target)) - return false; - } + const CXXConstructExpr *CtorExpr = Ctor.getOriginExpr(); + if (CtorExpr->getConstructionKind() == CXXConstructExpr::CK_Complete) + if (!Target || !isa<DeclRegion>(Target)) + return false; + + break; + } + case CE_CXXDestructor: { + // Only inline constructors and destructors if we built the CFGs for them + // properly. + const AnalysisDeclContext *ADC = CallerSFC->getAnalysisDeclContext(); + if (!ADC->getCFGBuildOptions().AddImplicitDtors || + !ADC->getCFGBuildOptions().AddInitializers) + return false; + + const CXXDestructorCall &Dtor = cast<CXXDestructorCall>(Call); + + // FIXME: We don't handle constructors or destructors for arrays properly. + const MemRegion *Target = Dtor.getCXXThisVal().getAsRegion(); + if (Target && isa<ElementRegion>(Target)) + return false; + break; } case CE_CXXAllocator: diff --git a/lib/StaticAnalyzer/Core/Store.cpp b/lib/StaticAnalyzer/Core/Store.cpp index ed221c5419..63a5e382c9 100644 --- a/lib/StaticAnalyzer/Core/Store.cpp +++ b/lib/StaticAnalyzer/Core/Store.cpp @@ -29,37 +29,15 @@ StoreRef StoreManager::enterStackFrame(Store OldStore, 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); - } - } + SmallVector<CallEvent::FrameBindingTy, 16> InitialBindings; + Call.getInitialStackFrameContents(LCtx, InitialBindings); - // 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 (isa<DefinedSVal>(ThisVal)) { - const CXXMethodDecl *MD = cast<CXXMethodDecl>(Call.getDecl()); - loc::MemRegionVal ThisRegion = svalBuilder.getCXXThis(MD, LCtx); - Store = Bind(Store.getStore(), ThisRegion, ThisVal); + for (CallEvent::BindingsTy::iterator I = InitialBindings.begin(), + E = InitialBindings.end(); + I != E; ++I) { + Store = Bind(Store.getStore(), I->first, I->second); } - if (const ObjCMethodCall *MCall = dyn_cast<ObjCMethodCall>(&Call)) { - SVal SelfVal = MCall->getReceiverSVal(); - const VarDecl *SelfDecl = LCtx->getAnalysisDeclContext()->getSelfDecl(); - Store = Bind(Store.getStore(), - svalBuilder.makeLoc(MRMgr.getVarRegion(SelfDecl, LCtx)), - SelfVal); - } return Store; } |