/// Scan all symbols referenced by the constraints. If the symbol is not alive /// as marked in LSymbols, mark it as dead in DSymbols. ProgramStateRef BasicConstraintManager::removeDeadBindings(ProgramStateRef state, SymbolReaper& SymReaper) { ConstEqTy CE = state->get<ConstEq>(); ConstEqTy::Factory& CEFactory = state->get_context<ConstEq>(); for (ConstEqTy::iterator I = CE.begin(), E = CE.end(); I!=E; ++I) { SymbolRef sym = I.getKey(); if (SymReaper.maybeDead(sym)) CE = CEFactory.remove(CE, sym); } state = state->set<ConstEq>(CE); ConstNotEqTy CNE = state->get<ConstNotEq>(); ConstNotEqTy::Factory& CNEFactory = state->get_context<ConstNotEq>(); for (ConstNotEqTy::iterator I = CNE.begin(), E = CNE.end(); I != E; ++I) { SymbolRef sym = I.getKey(); if (SymReaper.maybeDead(sym)) CNE = CNEFactory.remove(CNE, sym); } return state->set<ConstNotEq>(CNE); }
/// Scan all symbols referenced by the constraints. If the symbol is not alive /// as marked in LSymbols, mark it as dead in DSymbols. ProgramStateRef RangeConstraintManager::removeDeadBindings(ProgramStateRef state, SymbolReaper& SymReaper) { ConstraintRangeTy CR = state->get<ConstraintRange>(); ConstraintRangeTy::Factory& CRFactory = state->get_context<ConstraintRange>(); for (ConstraintRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) { SymbolRef sym = I.getKey(); if (SymReaper.maybeDead(sym)) CR = CRFactory.remove(CR, sym); } return state->set<ConstraintRange>(CR); }
/// Scan all symbols referenced by the constraints. If the symbol is not alive /// as marked in LSymbols, mark it as dead in DSymbols. ProgramStateRef RangeConstraintManager::removeDeadBindings(ProgramStateRef State, SymbolReaper &SymReaper) { bool Changed = false; ConstraintRangeTy CR = State->get<ConstraintRange>(); ConstraintRangeTy::Factory &CRFactory = State->get_context<ConstraintRange>(); for (ConstraintRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) { SymbolRef Sym = I.getKey(); if (SymReaper.maybeDead(Sym)) { Changed = true; CR = CRFactory.remove(CR, Sym); } } return Changed ? State->set<ConstraintRange>(CR) : State; }
// removeDeadBindings: // - Remove subexpression bindings. // - Remove dead block expression bindings. // - Keep live block expression bindings: // - Mark their reachable symbols live in SymbolReaper, // see ScanReachableSymbols. // - Mark the region in DRoots if the binding is a loc::MemRegionVal. Environment EnvironmentManager::removeDeadBindings(Environment Env, SymbolReaper &SymReaper, ProgramStateRef ST) { // We construct a new Environment object entirely, as this is cheaper than // individually removing all the subexpression bindings (which will greatly // outnumber block-level expression bindings). Environment NewEnv = getInitialEnvironment(); MarkLiveCallback CB(SymReaper); ScanReachableSymbols RSScaner(ST, CB); llvm::ImmutableMapRef<EnvironmentEntry,SVal> EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(), F.getTreeFactory()); // Iterate over the block-expr bindings. for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { const EnvironmentEntry &BlkExpr = I.getKey(); const SVal &X = I.getData(); if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) { // Copy the binding to the new map. EBMapRef = EBMapRef.add(BlkExpr, X); // If the block expr's value is a memory region, then mark that region. if (Optional<loc::MemRegionVal> R = X.getAs<loc::MemRegionVal>()) SymReaper.markLive(R->getRegion()); // Mark all symbols in the block expr's value live. RSScaner.scan(X); continue; } else { SymExpr::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end(); for (; SI != SE; ++SI) SymReaper.maybeDead(*SI); } } NewEnv.ExprBindings = EBMapRef.asImmutableMap(); return NewEnv; }
Store BasicStoreManager::RemoveDeadBindings(Store store, Stmt* Loc, SymbolReaper& SymReaper, llvm::SmallVectorImpl<const MemRegion*>& RegionRoots) { BindingsTy B = GetBindings(store); typedef SVal::symbol_iterator symbol_iterator; // Iterate over the variable bindings. for (BindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I) { if (const VarRegion *VR = dyn_cast<VarRegion>(I.getKey())) { if (SymReaper.isLive(Loc, VR)) RegionRoots.push_back(VR); else continue; } else if (isa<ObjCIvarRegion>(I.getKey())) { RegionRoots.push_back(I.getKey()); } else continue; // Mark the bindings in the data as live. SVal X = I.getData(); for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI) SymReaper.markLive(*SI); } // Scan for live variables and live symbols. llvm::SmallPtrSet<const MemRegion*, 10> Marked; while (!RegionRoots.empty()) { const MemRegion* MR = RegionRoots.back(); RegionRoots.pop_back(); while (MR) { if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(MR)) { SymReaper.markLive(SymR->getSymbol()); break; } else if (isa<VarRegion>(MR) || isa<ObjCIvarRegion>(MR)) { if (Marked.count(MR)) break; Marked.insert(MR); SVal X = Retrieve(store, loc::MemRegionVal(MR)); // FIXME: We need to handle symbols nested in region definitions. for (symbol_iterator SI=X.symbol_begin(),SE=X.symbol_end(); SI!=SE; ++SI) SymReaper.markLive(*SI); if (!isa<loc::MemRegionVal>(X)) break; const loc::MemRegionVal& LVD = cast<loc::MemRegionVal>(X); RegionRoots.push_back(LVD.getRegion()); break; } else if (const SubRegion* R = dyn_cast<SubRegion>(MR)) MR = R->getSuperRegion(); else break; } } // Remove dead variable bindings. for (BindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I) { const MemRegion* R = I.getKey(); if (!Marked.count(R)) { store = Remove(store, ValMgr.makeLoc(R)); SVal X = I.getData(); for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI) SymReaper.maybeDead(*SI); } } return store; }