aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer')
-rw-r--r--lib/StaticAnalyzer/Checkers/CStringChecker.cpp2
-rw-r--r--lib/StaticAnalyzer/Core/BasicStore.cpp18
-rw-r--r--lib/StaticAnalyzer/Core/CFRefCount.cpp69
-rw-r--r--lib/StaticAnalyzer/Core/CheckerManager.cpp3
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp8
-rw-r--r--lib/StaticAnalyzer/Core/FlatStore.cpp4
-rw-r--r--lib/StaticAnalyzer/Core/GRState.cpp16
-rw-r--r--lib/StaticAnalyzer/Core/RegionStore.cpp21
8 files changed, 96 insertions, 45 deletions
diff --git a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index 4f9c641edf..f4b9a3e90c 100644
--- a/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -42,6 +42,7 @@ public:
bool wantsRegionChangeUpdate(const GRState *state) const;
const GRState *checkRegionChanges(const GRState *state,
+ const StoreManager::InvalidatedSymbols *,
const MemRegion * const *Begin,
const MemRegion * const *End) const;
@@ -1305,6 +1306,7 @@ bool CStringChecker::wantsRegionChangeUpdate(const GRState *state) const {
const GRState *
CStringChecker::checkRegionChanges(const GRState *state,
+ const StoreManager::InvalidatedSymbols *,
const MemRegion * const *Begin,
const MemRegion * const *End) const {
CStringLength::EntryMap Entries = state->get<CStringLength>();
diff --git a/lib/StaticAnalyzer/Core/BasicStore.cpp b/lib/StaticAnalyzer/Core/BasicStore.cpp
index 4faa84ca26..7c9f45a474 100644
--- a/lib/StaticAnalyzer/Core/BasicStore.cpp
+++ b/lib/StaticAnalyzer/Core/BasicStore.cpp
@@ -49,11 +49,11 @@ public:
SVal Retrieve(Store store, Loc loc, QualType T = QualType());
StoreRef invalidateRegion(Store store, const MemRegion *R, const Expr *E,
- unsigned Count, InvalidatedSymbols *IS);
+ unsigned Count, InvalidatedSymbols &IS);
StoreRef invalidateRegions(Store store, const MemRegion * const *Begin,
const MemRegion * const *End, const Expr *E,
- unsigned Count, InvalidatedSymbols *IS,
+ unsigned Count, InvalidatedSymbols &IS,
bool invalidateGlobals,
InvalidatedRegions *Regions);
@@ -538,7 +538,7 @@ StoreRef BasicStoreManager::invalidateRegions(Store store,
const MemRegion * const *I,
const MemRegion * const *End,
const Expr *E, unsigned Count,
- InvalidatedSymbols *IS,
+ InvalidatedSymbols &IS,
bool invalidateGlobals,
InvalidatedRegions *Regions) {
StoreRef newStore(store, *this);
@@ -587,18 +587,16 @@ StoreRef BasicStoreManager::invalidateRegion(Store store,
const MemRegion *R,
const Expr *E,
unsigned Count,
- InvalidatedSymbols *IS) {
+ InvalidatedSymbols &IS) {
R = R->StripCasts();
if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R)))
return StoreRef(store, *this);
- if (IS) {
- BindingsTy B = GetBindings(store);
- if (BindingsTy::data_type *Val = B.lookup(R)) {
- if (SymbolRef Sym = Val->getAsSymbol())
- IS->insert(Sym);
- }
+ BindingsTy B = GetBindings(store);
+ if (BindingsTy::data_type *Val = B.lookup(R)) {
+ if (SymbolRef Sym = Val->getAsSymbol())
+ IS.insert(Sym);
}
QualType T = cast<TypedRegion>(R)->getValueType();
diff --git a/lib/StaticAnalyzer/Core/CFRefCount.cpp b/lib/StaticAnalyzer/Core/CFRefCount.cpp
index d9b1ce825c..9fd7fc7d4c 100644
--- a/lib/StaticAnalyzer/Core/CFRefCount.cpp
+++ b/lib/StaticAnalyzer/Core/CFRefCount.cpp
@@ -2494,6 +2494,23 @@ static QualType GetReturnType(const Expr* RetE, ASTContext& Ctx) {
return RetTy;
}
+
+// HACK: Symbols that have ref-count state that are referenced directly
+// (not as structure or array elements, or via bindings) by an argument
+// should not have their ref-count state stripped after we have
+// done an invalidation pass.
+//
+// FIXME: This is a global to currently share between CFRefCount and
+// RetainReleaseChecker. Eventually all functionality in CFRefCount should
+// be migrated to RetainReleaseChecker, and we can make this a non-global.
+llvm::DenseSet<SymbolRef> WhitelistedSymbols;
+namespace {
+struct ResetWhiteList {
+ ResetWhiteList() {}
+ ~ResetWhiteList() { WhitelistedSymbols.clear(); }
+};
+}
+
void CFRefCount::evalSummary(ExplodedNodeSet& Dst,
ExprEngine& Eng,
StmtNodeBuilder& Builder,
@@ -2510,12 +2527,9 @@ void CFRefCount::evalSummary(ExplodedNodeSet& Dst,
SymbolRef ErrorSym = 0;
llvm::SmallVector<const MemRegion*, 10> RegionsToInvalidate;
-
- // HACK: Symbols that have ref-count state that are referenced directly
- // (not as structure or array elements, or via bindings) by an argument
- // should not have their ref-count state stripped after we have
- // done an invalidation pass.
- llvm::DenseSet<SymbolRef> WhitelistedSymbols;
+
+ // Use RAII to make sure the whitelist is properly cleared.
+ ResetWhiteList resetWhiteList;
// Invalidate all instance variables of the receiver of a message.
// FIXME: We should be able to do better with inter-procedural analysis.
@@ -2624,21 +2638,13 @@ void CFRefCount::evalSummary(ExplodedNodeSet& Dst,
// NOTE: Even if RegionsToInvalidate is empty, we must still invalidate
// global variables.
+ // NOTE: RetainReleaseChecker handles the actual invalidation of symbols.
state = state->invalidateRegions(RegionsToInvalidate.data(),
RegionsToInvalidate.data() +
RegionsToInvalidate.size(),
Ex, Count, &IS,
/* invalidateGlobals = */ true);
- for (StoreManager::InvalidatedSymbols::iterator I = IS.begin(),
- E = IS.end(); I!=E; ++I) {
- SymbolRef sym = *I;
- if (WhitelistedSymbols.count(sym))
- continue;
- // Remove any existing reference-count binding.
- state = state->remove<RefBindings>(*I);
- }
-
// Evaluate the effect on the message receiver.
if (!ErrorRange.isValid() && Receiver) {
SymbolRef Sym = Receiver.getSValAsScalarOrLoc(state).getAsLocSymbol();
@@ -3418,12 +3424,43 @@ void CFRefCount::ProcessNonLeakError(ExplodedNodeSet& Dst,
namespace {
class RetainReleaseChecker
- : public Checker< check::PostStmt<BlockExpr> > {
+ : public Checker< check::PostStmt<BlockExpr>, check::RegionChanges > {
public:
+ bool wantsRegionUpdate;
+
+ RetainReleaseChecker() : wantsRegionUpdate(true) {}
+
+
void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
+ const GRState *checkRegionChanges(const GRState *state,
+ const StoreManager::InvalidatedSymbols *invalidated,
+ const MemRegion * const *begin,
+ const MemRegion * const *end) const;
+
+ bool wantsRegionChangeUpdate(const GRState *state) const {
+ return wantsRegionUpdate;
+ }
};
} // end anonymous namespace
+const GRState *
+RetainReleaseChecker::checkRegionChanges(const GRState *state,
+ const StoreManager::InvalidatedSymbols *invalidated,
+ const MemRegion * const *begin,
+ const MemRegion * const *end) const {
+ if (!invalidated)
+ return state;
+
+ for (StoreManager::InvalidatedSymbols::const_iterator I=invalidated->begin(),
+ E = invalidated->end(); I!=E; ++I) {
+ SymbolRef sym = *I;
+ if (WhitelistedSymbols.count(sym))
+ continue;
+ // Remove any existing reference-count binding.
+ state = state->remove<RefBindings>(sym);
+ }
+ return state;
+}
void RetainReleaseChecker::checkPostStmt(const BlockExpr *BE,
CheckerContext &C) const {
diff --git a/lib/StaticAnalyzer/Core/CheckerManager.cpp b/lib/StaticAnalyzer/Core/CheckerManager.cpp
index 4a2549091c..78c8b8bda2 100644
--- a/lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ b/lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -345,6 +345,7 @@ bool CheckerManager::wantsRegionChangeUpdate(const GRState *state) {
/// \brief Run checkers for region changes.
const GRState *
CheckerManager::runCheckersForRegionChanges(const GRState *state,
+ const StoreManager::InvalidatedSymbols *invalidated,
const MemRegion * const *Begin,
const MemRegion * const *End) {
for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) {
@@ -352,7 +353,7 @@ CheckerManager::runCheckersForRegionChanges(const GRState *state,
// bail out.
if (!state)
return NULL;
- state = RegionChangesCheckers[i].CheckFn(state, Begin, End);
+ state = RegionChangesCheckers[i].CheckFn(state, invalidated, Begin, End);
}
return state;
}
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 657420d06f..69ef4cfc4c 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -179,9 +179,11 @@ bool ExprEngine::wantsRegionChangeUpdate(const GRState* state) {
const GRState *
ExprEngine::processRegionChanges(const GRState *state,
- const MemRegion * const *Begin,
- const MemRegion * const *End) {
- return getCheckerManager().runCheckersForRegionChanges(state, Begin, End);
+ const StoreManager::InvalidatedSymbols *invalidated,
+ const MemRegion * const *Begin,
+ const MemRegion * const *End) {
+ return getCheckerManager().runCheckersForRegionChanges(state, invalidated,
+ Begin, End);
}
void ExprEngine::processEndWorklist(bool hasWorkRemaining) {
diff --git a/lib/StaticAnalyzer/Core/FlatStore.cpp b/lib/StaticAnalyzer/Core/FlatStore.cpp
index 7bdca6b7f1..ca867aebde 100644
--- a/lib/StaticAnalyzer/Core/FlatStore.cpp
+++ b/lib/StaticAnalyzer/Core/FlatStore.cpp
@@ -59,7 +59,7 @@ public:
StoreRef invalidateRegions(Store store, const MemRegion * const *I,
const MemRegion * const *E, const Expr *Ex,
- unsigned Count, InvalidatedSymbols *IS,
+ unsigned Count, InvalidatedSymbols &IS,
bool invalidateGlobals,
InvalidatedRegions *Regions);
@@ -175,7 +175,7 @@ StoreRef FlatStoreManager::invalidateRegions(Store store,
const MemRegion * const *I,
const MemRegion * const *E,
const Expr *Ex, unsigned Count,
- InvalidatedSymbols *IS,
+ InvalidatedSymbols &IS,
bool invalidateGlobals,
InvalidatedRegions *Regions) {
assert(false && "Not implemented");
diff --git a/lib/StaticAnalyzer/Core/GRState.cpp b/lib/StaticAnalyzer/Core/GRState.cpp
index 7b216775b8..0f6ff1ef58 100644
--- a/lib/StaticAnalyzer/Core/GRState.cpp
+++ b/lib/StaticAnalyzer/Core/GRState.cpp
@@ -141,6 +141,20 @@ const GRState *GRState::invalidateRegions(const MemRegion * const *Begin,
const Expr *E, unsigned Count,
StoreManager::InvalidatedSymbols *IS,
bool invalidateGlobals) const {
+ if (!IS) {
+ StoreManager::InvalidatedSymbols invalidated;
+ return invalidateRegionsImpl(Begin, End, E, Count,
+ invalidated, invalidateGlobals);
+ }
+ return invalidateRegionsImpl(Begin, End, E, Count, *IS, invalidateGlobals);
+}
+
+const GRState *
+GRState::invalidateRegionsImpl(const MemRegion * const *Begin,
+ const MemRegion * const *End,
+ const Expr *E, unsigned Count,
+ StoreManager::InvalidatedSymbols &IS,
+ bool invalidateGlobals) const {
GRStateManager &Mgr = getStateManager();
SubEngine* Eng = Mgr.getOwningEngine();
@@ -150,7 +164,7 @@ const GRState *GRState::invalidateRegions(const MemRegion * const *Begin,
= Mgr.StoreMgr->invalidateRegions(getStore(), Begin, End, E, Count, IS,
invalidateGlobals, &Regions);
const GRState *newState = makeWithStore(newStore);
- return Eng->processRegionChanges(newState,
+ return Eng->processRegionChanges(newState, &IS,
&Regions.front(),
&Regions.back()+1);
}
diff --git a/lib/StaticAnalyzer/Core/RegionStore.cpp b/lib/StaticAnalyzer/Core/RegionStore.cpp
index 4522f976e6..fe17773fc7 100644
--- a/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ b/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -240,7 +240,7 @@ public:
const MemRegion * const *Begin,
const MemRegion * const *End,
const Expr *E, unsigned Count,
- InvalidatedSymbols *IS,
+ InvalidatedSymbols &IS,
bool invalidateGlobals,
InvalidatedRegions *Regions);
@@ -586,14 +586,14 @@ class invalidateRegionsWorker : public ClusterAnalysis<invalidateRegionsWorker>
{
const Expr *Ex;
unsigned Count;
- StoreManager::InvalidatedSymbols *IS;
+ StoreManager::InvalidatedSymbols &IS;
StoreManager::InvalidatedRegions *Regions;
public:
invalidateRegionsWorker(RegionStoreManager &rm,
GRStateManager &stateMgr,
RegionBindings b,
const Expr *ex, unsigned count,
- StoreManager::InvalidatedSymbols *is,
+ StoreManager::InvalidatedSymbols &is,
StoreManager::InvalidatedRegions *r,
bool includeGlobals)
: ClusterAnalysis<invalidateRegionsWorker>(rm, stateMgr, b, includeGlobals),
@@ -609,9 +609,8 @@ private:
void invalidateRegionsWorker::VisitBinding(SVal V) {
// A symbol? Mark it touched by the invalidation.
- if (IS)
- if (SymbolRef Sym = V.getAsSymbol())
- IS->insert(Sym);
+ if (SymbolRef Sym = V.getAsSymbol())
+ IS.insert(Sym);
if (const MemRegion *R = V.getAsRegion()) {
AddToWorkList(R);
@@ -648,11 +647,9 @@ void invalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
}
void invalidateRegionsWorker::VisitBaseRegion(const MemRegion *baseR) {
- if (IS) {
- // Symbolic region? Mark that symbol touched by the invalidation.
- if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR))
- IS->insert(SR->getSymbol());
- }
+ // Symbolic region? Mark that symbol touched by the invalidation.
+ if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR))
+ IS.insert(SR->getSymbol());
// BlockDataRegion? If so, invalidate captured variables that are passed
// by reference.
@@ -724,7 +721,7 @@ StoreRef RegionStoreManager::invalidateRegions(Store store,
const MemRegion * const *I,
const MemRegion * const *E,
const Expr *Ex, unsigned Count,
- InvalidatedSymbols *IS,
+ InvalidatedSymbols &IS,
bool invalidateGlobals,
InvalidatedRegions *Regions) {
invalidateRegionsWorker W(*this, StateMgr,