void BasicStoreManager::iterBindings(Store store, BindingsHandler& f) { BindingsTy B = GetBindings(store); for (BindingsTy::iterator I=B.begin(), E=B.end(); I != E; ++I) f.HandleBinding(*this, store, I.getKey(), I.getData()); }
void CXXInstanceCall::getInitialStackFrameContents( const StackFrameContext *CalleeCtx, BindingsTy &Bindings) const { AnyFunctionCall::getInitialStackFrameContents(CalleeCtx, Bindings); // Handle the binding of 'this' in the new stack frame. SVal ThisVal = getCXXThisVal(); if (!ThisVal.isUnknown()) { ProgramStateManager &StateMgr = getState()->getStateManager(); SValBuilder &SVB = StateMgr.getSValBuilder(); const CXXMethodDecl *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl()); Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx); // If we devirtualized to a different member function, we need to make sure // we have the proper layering of CXXBaseObjectRegions. if (MD->getCanonicalDecl() != getDecl()->getCanonicalDecl()) { ASTContext &Ctx = SVB.getContext(); const CXXRecordDecl *Class = MD->getParent(); QualType Ty = Ctx.getPointerType(Ctx.getRecordType(Class)); // FIXME: CallEvent maybe shouldn't be directly accessing StoreManager. bool Failed; ThisVal = StateMgr.getStoreManager().evalDynamicCast(ThisVal, Ty, Failed); assert(!Failed && "Calling an incorrectly devirtualized method"); } if (!ThisVal.isUnknown()) Bindings.push_back(std::make_pair(ThisLoc, ThisVal)); } }
void BasicStoreManager::print(Store store, llvm::raw_ostream& Out, const char* nl, const char *sep) { BindingsTy B = GetBindings(store); Out << "Variables:" << nl; bool isFirst = true; for (BindingsTy::iterator I=B.begin(), E=B.end(); I != E; ++I) { if (isFirst) isFirst = false; else Out << nl; Out << ' ' << I.getKey() << " : " << I.getData(); } }
void CXXConstructorCall::getInitialStackFrameContents( const StackFrameContext *CalleeCtx, BindingsTy &Bindings) const { AnyFunctionCall::getInitialStackFrameContents(CalleeCtx, Bindings); SVal ThisVal = getCXXThisVal(); if (!ThisVal.isUnknown()) { SValBuilder &SVB = getState()->getStateManager().getSValBuilder(); const CXXMethodDecl *MD = cast<CXXMethodDecl>(CalleeCtx->getDecl()); Loc ThisLoc = SVB.getCXXThis(MD, CalleeCtx); Bindings.push_back(std::make_pair(ThisLoc, ThisVal)); } }
Store BasicStoreManager::InvalidateRegion(Store store, const MemRegion *R, const Expr *E, unsigned Count, InvalidatedSymbols *IS) { R = R->StripCasts(); if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R))) return store; if (IS) { 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(R->getContext()); SVal V = ValMgr.getConjuredSymbolVal(R, E, T, Count); return Bind(store, loc::MemRegionVal(R), V); }
SVal BasicStoreManager::Retrieve(Store store, Loc loc, QualType T) { if (isa<UnknownVal>(loc)) return UnknownVal(); assert(!isa<UndefinedVal>(loc)); switch (loc.getSubKind()) { case loc::MemRegionKind: { const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion(); if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R))) return UnknownVal(); BindingsTy B = GetBindings(store); BindingsTy::data_type *Val = B.lookup(R); const TypedRegion *TR = cast<TypedRegion>(R); if (Val) return CastRetrievedVal(*Val, TR, T); SVal V = LazyRetrieve(store, TR); return V.isUnknownOrUndef() ? V : CastRetrievedVal(V, TR, T); } case loc::ConcreteIntKind: // Some clients may call GetSVal with such an option simply because // they are doing a quick scan through their Locs (potentially to // invalidate their bindings). Just return Undefined. return UndefinedVal(); default: assert (false && "Invalid Loc."); break; } return UnknownVal(); }
void ObjCMethodCall::getInitialStackFrameContents( const StackFrameContext *CalleeCtx, BindingsTy &Bindings) const { const ObjCMethodDecl *D = cast<ObjCMethodDecl>(CalleeCtx->getDecl()); SValBuilder &SVB = getState()->getStateManager().getSValBuilder(); addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this, D->param_begin(), D->param_end()); SVal SelfVal = getReceiverSVal(); if (!SelfVal.isUnknown()) { const VarDecl *SelfD = CalleeCtx->getAnalysisDeclContext()->getSelfDecl(); MemRegionManager &MRMgr = SVB.getRegionManager(); Loc SelfLoc = SVB.makeLoc(MRMgr.getVarRegion(SelfD, CalleeCtx)); Bindings.push_back(std::make_pair(SelfLoc, SelfVal)); } }
void BlockCall::getInitialStackFrameContents(const StackFrameContext *CalleeCtx, BindingsTy &Bindings) const { SValBuilder &SVB = getState()->getStateManager().getSValBuilder(); ArrayRef<ParmVarDecl*> Params; if (isConversionFromLambda()) { auto *LambdaOperatorDecl = cast<CXXMethodDecl>(CalleeCtx->getDecl()); Params = LambdaOperatorDecl->parameters(); // For blocks converted from a C++ lambda, the callee declaration is the // operator() method on the lambda so we bind "this" to // the lambda captured by the block. const VarRegion *CapturedLambdaRegion = getRegionStoringCapturedLambda(); SVal ThisVal = loc::MemRegionVal(CapturedLambdaRegion); Loc ThisLoc = SVB.getCXXThis(LambdaOperatorDecl, CalleeCtx); Bindings.push_back(std::make_pair(ThisLoc, ThisVal)); } else { Params = cast<BlockDecl>(CalleeCtx->getDecl())->parameters(); } addParameterValuesToBindings(CalleeCtx, Bindings, SVB, *this, Params); }
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; }