aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/StaticAnalyzer/Core/Calls.cpp72
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp20
-rw-r--r--lib/StaticAnalyzer/Core/ProgramState.cpp10
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp88
-rw-r--r--lib/StaticAnalyzer/Core/Store.cpp35
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,