aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/CFRefCount.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core/CFRefCount.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/CFRefCount.cpp77
1 files changed, 37 insertions, 40 deletions
diff --git a/lib/StaticAnalyzer/Core/CFRefCount.cpp b/lib/StaticAnalyzer/Core/CFRefCount.cpp
index 07487f14e1..5991e5325f 100644
--- a/lib/StaticAnalyzer/Core/CFRefCount.cpp
+++ b/lib/StaticAnalyzer/Core/CFRefCount.cpp
@@ -2439,23 +2439,6 @@ 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::evalCallOrMessage(ExplodedNodeSet &Dst, ExprEngine &Eng,
StmtNodeBuilder &Builder,
const CallOrObjCMessage &callOrMsg,
@@ -2465,18 +2448,11 @@ void CFRefCount::evalCallOrMessage(ExplodedNodeSet &Dst, ExprEngine &Eng,
const ProgramState *state) {
SmallVector<const MemRegion*, 10> RegionsToInvalidate;
-
- // 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.
if (Receiver) {
SVal V = Receiver.getSValAsScalarOrLoc(state);
- if (SymbolRef Sym = V.getAsLocSymbol()) {
- if (state->get<RefBindings>(Sym))
- WhitelistedSymbols.insert(Sym);
- }
if (const MemRegion *region = V.getAsRegion())
RegionsToInvalidate.push_back(region);
}
@@ -2490,7 +2466,7 @@ void CFRefCount::evalCallOrMessage(ExplodedNodeSet &Dst, ExprEngine &Eng,
}
for (unsigned idx = 0, e = callOrMsg.getNumArgs(); idx != e; ++idx) {
- SVal V = callOrMsg.getArgSValAsScalarOrLoc(idx);
+ SVal V = callOrMsg.getArgSVal(idx);
// If we are passing a location wrapped as an integer, unwrap it and
// invalidate the values referred by the location.
@@ -2499,10 +2475,6 @@ void CFRefCount::evalCallOrMessage(ExplodedNodeSet &Dst, ExprEngine &Eng,
else if (!isa<Loc>(V))
continue;
- if (SymbolRef Sym = V.getAsLocSymbol())
- if (state->get<RefBindings>(Sym))
- WhitelistedSymbols.insert(Sym);
-
if (const MemRegion *R = V.getAsRegion()) {
// Invalidate the value of the variable passed by reference.
@@ -2562,9 +2534,7 @@ void CFRefCount::evalCallOrMessage(ExplodedNodeSet &Dst, ExprEngine &Eng,
// global variables.
// NOTE: RetainReleaseChecker handles the actual invalidation of symbols.
state =
- state->invalidateRegions(RegionsToInvalidate.data(),
- RegionsToInvalidate.data() +
- RegionsToInvalidate.size(),
+ state->invalidateRegions(RegionsToInvalidate,
Ex, Count, &IS,
/* invalidateGlobals = */
Eng.doesInvalidateGlobals(callOrMsg));
@@ -2611,6 +2581,7 @@ class RetainReleaseChecker
check::PostStmt<BlockExpr>,
check::PostStmt<CastExpr>,
check::PostStmt<CallExpr>,
+ check::PostStmt<CXXConstructExpr>,
check::PostObjCMessage,
check::PreStmt<ReturnStmt>,
check::RegionChanges,
@@ -2770,6 +2741,7 @@ public:
void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
void checkPostStmt(const CallExpr *CE, CheckerContext &C) const;
+ void checkPostStmt(const CXXConstructExpr *CE, CheckerContext &C) const;
void checkPostObjCMessage(const ObjCMessage &Msg, CheckerContext &C) const;
void checkSummary(const RetainSummary &Summ, const CallOrObjCMessage &Call,
InstanceReceiver Receiver, CheckerContext &C) const;
@@ -2779,10 +2751,11 @@ public:
const ProgramState *evalAssume(const ProgramState *state, SVal Cond,
bool Assumption) const;
- const ProgramState *checkRegionChanges(const ProgramState *state,
- const StoreManager::InvalidatedSymbols *invalidated,
- const MemRegion * const *begin,
- const MemRegion * const *end) const;
+ const ProgramState *
+ checkRegionChanges(const ProgramState *state,
+ const StoreManager::InvalidatedSymbols *invalidated,
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions) const;
bool wantsRegionChangeUpdate(const ProgramState *state) const {
return true;
@@ -2912,11 +2885,18 @@ const ProgramState *RetainReleaseChecker::evalAssume(const ProgramState *state,
const ProgramState *
RetainReleaseChecker::checkRegionChanges(const ProgramState *state,
const StoreManager::InvalidatedSymbols *invalidated,
- const MemRegion * const *begin,
- const MemRegion * const *end) const {
+ ArrayRef<const MemRegion *> ExplicitRegions,
+ ArrayRef<const MemRegion *> Regions) const {
if (!invalidated)
return state;
+ llvm::SmallPtrSet<SymbolRef, 8> WhitelistedSymbols;
+ for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
+ E = ExplicitRegions.end(); I != E; ++I) {
+ if (const SymbolicRegion *SR = (*I)->StripCasts()->getAs<SymbolicRegion>())
+ WhitelistedSymbols.insert(SR->getSymbol());
+ }
+
for (StoreManager::InvalidatedSymbols::const_iterator I=invalidated->begin(),
E = invalidated->end(); I!=E; ++I) {
SymbolRef sym = *I;
@@ -3036,6 +3016,23 @@ void RetainReleaseChecker::checkPostStmt(const CallExpr *CE,
checkSummary(*Summ, CallOrObjCMessage(CE, state), InstanceReceiver(), C);
}
+void RetainReleaseChecker::checkPostStmt(const CXXConstructExpr *CE,
+ CheckerContext &C) const {
+ const CXXConstructorDecl *Ctor = CE->getConstructor();
+ if (!Ctor)
+ return;
+
+ RetainSummaryManager &Summaries = getSummaryManager(C.getASTContext());
+ RetainSummary *Summ = Summaries.getSummary(Ctor);
+
+ // If we didn't get a summary, this constructor doesn't affect retain counts.
+ if (!Summ)
+ return;
+
+ const ProgramState *state = C.getState();
+ checkSummary(*Summ, CallOrObjCMessage(CE, state), InstanceReceiver(), C);
+}
+
void RetainReleaseChecker::checkPostObjCMessage(const ObjCMessage &Msg,
CheckerContext &C) const {
const ProgramState *state = C.getState();
@@ -3071,7 +3068,7 @@ void RetainReleaseChecker::checkSummary(const RetainSummary &Summ,
SymbolRef ErrorSym = 0;
for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
- SVal V = CallOrMsg.getArgSValAsScalarOrLoc(idx);
+ SVal V = CallOrMsg.getArgSVal(idx);
if (SymbolRef Sym = V.getAsLocSymbol()) {
if (RefBindings::data_type *T = state->get<RefBindings>(Sym)) {
@@ -3434,7 +3431,7 @@ bool RetainReleaseChecker::evalCall(const CallExpr *CE,
// Invalidate the argument region.
unsigned Count = C.getNodeBuilder().getCurrentBlockCount();
- state = state->invalidateRegion(ArgRegion, CE, Count);
+ state = state->invalidateRegions(ArgRegion, CE, Count);
// Restore the refcount status of the argument.
if (Binding)