aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core')
-rw-r--r--lib/StaticAnalyzer/Core/CallEvent.cpp146
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp36
-rw-r--r--lib/StaticAnalyzer/Core/Store.cpp34
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;
}