Index: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h =================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -769,6 +769,9 @@ assert(s->getType()->isAnyPointerType() || s->getType()->isReferenceType() || s->getType()->isBlockPointerType()); + + // populateWorklistFromSymbol() relies on this assertion, and needs to be + // updated if more cases are introduced. assert(isa(sreg) || isa(sreg)); } Index: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h =================================================================== --- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -130,6 +130,8 @@ /// used to query and manipulate MemRegion objects. MemRegionManager& getRegionManager() { return MRMgr; } + SValBuilder& getSValBuilder() { return svalBuilder; } + virtual Loc getLValueVar(const VarDecl *VD, const LocationContext *LC) { return svalBuilder.makeLoc(MRMgr.getVarRegion(VD, LC)); } Index: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -2394,7 +2394,10 @@ namespace { class RemoveDeadBindingsWorker : public ClusterAnalysis { - SmallVector Postponed; + using ChildrenListTy = SmallVector; + using MapParentsToDerivedTy = llvm::DenseMap; + + MapParentsToDerivedTy ParentsToDerived; SymbolReaper &SymReaper; const StackFrameContext *CurrentLCtx; @@ -2415,8 +2418,10 @@ bool AddToWorkList(const MemRegion *R); - bool UpdatePostponed(); void VisitBinding(SVal V); + +private: + void populateWorklistFromSymbol(SymbolRef s); }; } @@ -2436,10 +2441,11 @@ } if (const SymbolicRegion *SR = dyn_cast(baseR)) { - if (SymReaper.isLive(SR->getSymbol())) + if (SymReaper.isLive(SR->getSymbol())) { AddToWorkList(SR, &C); - else - Postponed.push_back(SR); + } else if (const auto *SD = dyn_cast(SR->getSymbol())) { + ParentsToDerived[SD->getParentSymbol()].push_back(SD); + } return; } @@ -2451,7 +2457,7 @@ // CXXThisRegion in the current or parent location context is live. if (const CXXThisRegion *TR = dyn_cast(baseR)) { - const StackArgumentsSpaceRegion *StackReg = + const auto *StackReg = cast(TR->getSuperRegion()); const StackFrameContext *RegCtx = StackReg->getStackFrame(); if (CurrentLCtx && @@ -2496,6 +2502,15 @@ // If V is a region, then add it to the worklist. if (const MemRegion *R = V.getAsRegion()) { AddToWorkList(R); + + if (const auto *TVR = dyn_cast(R)) { + DefinedOrUnknownSVal RVS = + RM.getSValBuilder().getRegionValueSymbolVal(TVR); + if (const MemRegion *SR = RVS.getAsRegion()) { + AddToWorkList(SR); + } + } + SymReaper.markLive(R); // All regions captured by a block are also live. @@ -2509,27 +2524,30 @@ // Update the set of live symbols. - for (SymExpr::symbol_iterator SI = V.symbol_begin(), SE = V.symbol_end(); - SI!=SE; ++SI) + for (auto SI = V.symbol_begin(), SE = V.symbol_end(); SI != SE; ++SI) { + populateWorklistFromSymbol(*SI); + + for (const auto *SD : ParentsToDerived[*SI]) + populateWorklistFromSymbol(SD); + SymReaper.markLive(*SI); + } } -bool RemoveDeadBindingsWorker::UpdatePostponed() { - // See if any postponed SymbolicRegions are actually live now, after - // having done a scan. - bool changed = false; - - for (SmallVectorImpl::iterator - I = Postponed.begin(), E = Postponed.end() ; I != E ; ++I) { - if (const SymbolicRegion *SR = *I) { - if (SymReaper.isLive(SR->getSymbol())) { - changed |= AddToWorkList(SR); - *I = nullptr; - } +void RemoveDeadBindingsWorker::populateWorklistFromSymbol(SymbolRef S) { + if (const auto *SD = dyn_cast(S)) { + if (Loc::isLocType(SD->getType()) && !SymReaper.isLive(SD)) { + const SymbolicRegion *SR = RM.getRegionManager().getSymbolicRegion(SD); + + if (B.contains(SR)) + AddToWorkList(SR); + + const SymbolicRegion *SHR = + RM.getRegionManager().getSymbolicHeapRegion(SD); + if (B.contains(SHR)) + AddToWorkList(SHR); } } - - return changed; } StoreRef RegionStoreManager::removeDeadBindings(Store store, @@ -2545,7 +2563,7 @@ W.AddToWorkList(*I); } - do W.RunWorkList(); while (W.UpdatePostponed()); + W.RunWorkList(); // We have now scanned the store, marking reachable regions and symbols // as live. We now remove all the regions that are dead from the store