diff options
Diffstat (limited to 'lib/StaticAnalyzer')
-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; } |