diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core/CFRefCount.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/CFRefCount.cpp | 77 |
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) |