136981b17SDimitry Andric //= ProgramState.cpp - Path-Sensitive "State" for tracking values --*- C++ -*--=
2ec2b103cSEd Schouten //
322989816SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422989816SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
522989816SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ec2b103cSEd Schouten //
7ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
8ec2b103cSEd Schouten //
936981b17SDimitry Andric // This file implements ProgramState and ProgramStateManager.
10ec2b103cSEd Schouten //
11ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
12ec2b103cSEd Schouten
13809500fcSDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
1411d2b2d2SRoman Divacky #include "clang/Analysis/CFG.h"
1522989816SDimitry Andric #include "clang/Basic/JsonSupport.h"
1622989816SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
1756d91b49SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
18519fc96cSDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h"
19cfca06d7SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
2036981b17SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
21ec2b103cSEd Schouten #include "llvm/Support/raw_ostream.h"
22e3b55780SDimitry Andric #include <optional>
23ec2b103cSEd Schouten
24ec2b103cSEd Schouten using namespace clang;
25bca07a45SDimitry Andric using namespace ento;
26ec2b103cSEd Schouten
27dbe13110SDimitry Andric namespace clang { namespace ento {
28dbe13110SDimitry Andric /// Increments the number of times this state is referenced.
29dbe13110SDimitry Andric
ProgramStateRetain(const ProgramState * state)30dbe13110SDimitry Andric void ProgramStateRetain(const ProgramState *state) {
31dbe13110SDimitry Andric ++const_cast<ProgramState*>(state)->refCount;
32dbe13110SDimitry Andric }
33dbe13110SDimitry Andric
34dbe13110SDimitry Andric /// Decrement the number of times this state is referenced.
ProgramStateRelease(const ProgramState * state)35dbe13110SDimitry Andric void ProgramStateRelease(const ProgramState *state) {
36dbe13110SDimitry Andric assert(state->refCount > 0);
37dbe13110SDimitry Andric ProgramState *s = const_cast<ProgramState*>(state);
38dbe13110SDimitry Andric if (--s->refCount == 0) {
39dbe13110SDimitry Andric ProgramStateManager &Mgr = s->getStateManager();
40dbe13110SDimitry Andric Mgr.StateSet.RemoveNode(s);
41dbe13110SDimitry Andric s->~ProgramState();
42dbe13110SDimitry Andric Mgr.freeStates.push_back(s);
43dbe13110SDimitry Andric }
44dbe13110SDimitry Andric }
45dbe13110SDimitry Andric }}
46dbe13110SDimitry Andric
ProgramState(ProgramStateManager * mgr,const Environment & env,StoreRef st,GenericDataMap gdm)4736981b17SDimitry Andric ProgramState::ProgramState(ProgramStateManager *mgr, const Environment& env,
48bca07a45SDimitry Andric StoreRef st, GenericDataMap gdm)
49bca07a45SDimitry Andric : stateMgr(mgr),
50bca07a45SDimitry Andric Env(env),
51bca07a45SDimitry Andric store(st.getStore()),
52bca07a45SDimitry Andric GDM(gdm),
53bca07a45SDimitry Andric refCount(0) {
54bca07a45SDimitry Andric stateMgr->getStoreManager().incrementReferenceCount(store);
55bca07a45SDimitry Andric }
56bca07a45SDimitry Andric
ProgramState(const ProgramState & RHS)5736981b17SDimitry Andric ProgramState::ProgramState(const ProgramState &RHS)
586f8fc217SDimitry Andric : stateMgr(RHS.stateMgr), Env(RHS.Env), store(RHS.store), GDM(RHS.GDM),
59145449b1SDimitry Andric PosteriorlyOverconstrained(RHS.PosteriorlyOverconstrained), refCount(0) {
60bca07a45SDimitry Andric stateMgr->getStoreManager().incrementReferenceCount(store);
61bca07a45SDimitry Andric }
62bca07a45SDimitry Andric
~ProgramState()6336981b17SDimitry Andric ProgramState::~ProgramState() {
64bca07a45SDimitry Andric if (store)
65bca07a45SDimitry Andric stateMgr->getStoreManager().decrementReferenceCount(store);
66bca07a45SDimitry Andric }
67bca07a45SDimitry Andric
getID() const68676fbe81SDimitry Andric int64_t ProgramState::getID() const {
69676fbe81SDimitry Andric return getStateManager().Alloc.identifyKnownAlignedObject<ProgramState>(this);
70676fbe81SDimitry Andric }
71676fbe81SDimitry Andric
ProgramStateManager(ASTContext & Ctx,StoreManagerCreator CreateSMgr,ConstraintManagerCreator CreateCMgr,llvm::BumpPtrAllocator & alloc,ExprEngine * ExprEng)7256d91b49SDimitry Andric ProgramStateManager::ProgramStateManager(ASTContext &Ctx,
7356d91b49SDimitry Andric StoreManagerCreator CreateSMgr,
7456d91b49SDimitry Andric ConstraintManagerCreator CreateCMgr,
7556d91b49SDimitry Andric llvm::BumpPtrAllocator &alloc,
76cfca06d7SDimitry Andric ExprEngine *ExprEng)
77cfca06d7SDimitry Andric : Eng(ExprEng), EnvMgr(alloc), GDMFactory(alloc),
7856d91b49SDimitry Andric svalBuilder(createSimpleSValBuilder(alloc, Ctx, *this)),
7956d91b49SDimitry Andric CallEventMgr(new CallEventManager(alloc)), Alloc(alloc) {
8006d4ba38SDimitry Andric StoreMgr = (*CreateSMgr)(*this);
81cfca06d7SDimitry Andric ConstraintMgr = (*CreateCMgr)(*this, ExprEng);
8256d91b49SDimitry Andric }
8356d91b49SDimitry Andric
8456d91b49SDimitry Andric
~ProgramStateManager()8536981b17SDimitry Andric ProgramStateManager::~ProgramStateManager() {
86ec2b103cSEd Schouten for (GDMContextsTy::iterator I=GDMContexts.begin(), E=GDMContexts.end();
87ec2b103cSEd Schouten I!=E; ++I)
88ec2b103cSEd Schouten I->second.second(I->second.first);
89ec2b103cSEd Schouten }
90ec2b103cSEd Schouten
removeDeadBindingsFromEnvironmentAndStore(ProgramStateRef state,const StackFrameContext * LCtx,SymbolReaper & SymReaper)91706b4fc4SDimitry Andric ProgramStateRef ProgramStateManager::removeDeadBindingsFromEnvironmentAndStore(
92706b4fc4SDimitry Andric ProgramStateRef state, const StackFrameContext *LCtx,
93ec2b103cSEd Schouten SymbolReaper &SymReaper) {
94ec2b103cSEd Schouten
95ec2b103cSEd Schouten // This code essentially performs a "mark-and-sweep" of the VariableBindings.
96ec2b103cSEd Schouten // The roots are any Block-level exprs and Decls that our liveness algorithm
97ec2b103cSEd Schouten // tells us are live. We then see what Decls they may reference, and keep
98ec2b103cSEd Schouten // those around. This code more than likely can be made faster, and the
99ec2b103cSEd Schouten // frequency of which this method is called should be experimented with
100ec2b103cSEd Schouten // for optimum performance.
10136981b17SDimitry Andric ProgramState NewState = *state;
102ec2b103cSEd Schouten
10336981b17SDimitry Andric NewState.Env = EnvMgr.removeDeadBindings(NewState.Env, SymReaper, state);
104ec2b103cSEd Schouten
105ec2b103cSEd Schouten // Clean up the store.
10636981b17SDimitry Andric StoreRef newStore = StoreMgr->removeDeadBindings(NewState.getStore(), LCtx,
10736981b17SDimitry Andric SymReaper);
10836981b17SDimitry Andric NewState.setStore(newStore);
10936981b17SDimitry Andric SymReaper.setReapedStore(newStore);
11036981b17SDimitry Andric
111706b4fc4SDimitry Andric return getPersistentState(NewState);
1123d1dcd9bSDimitry Andric }
1133d1dcd9bSDimitry Andric
bindLoc(Loc LV,SVal V,const LocationContext * LCtx,bool notifyChanges) const1147442d6faSDimitry Andric ProgramStateRef ProgramState::bindLoc(Loc LV,
1157442d6faSDimitry Andric SVal V,
1167442d6faSDimitry Andric const LocationContext *LCtx,
1177442d6faSDimitry Andric bool notifyChanges) const {
11836981b17SDimitry Andric ProgramStateManager &Mgr = getStateManager();
119dbe13110SDimitry Andric ProgramStateRef newState = makeWithStore(Mgr.StoreMgr->Bind(getStore(),
120bca07a45SDimitry Andric LV, V));
1213d1dcd9bSDimitry Andric const MemRegion *MR = LV.getAsRegion();
122676fbe81SDimitry Andric if (MR && notifyChanges)
123676fbe81SDimitry Andric return Mgr.getOwningEngine().processRegionChange(newState, MR, LCtx);
1243d1dcd9bSDimitry Andric
125bca07a45SDimitry Andric return newState;
1263d1dcd9bSDimitry Andric }
1273d1dcd9bSDimitry Andric
12848675466SDimitry Andric ProgramStateRef
bindDefaultInitial(SVal loc,SVal V,const LocationContext * LCtx) const12948675466SDimitry Andric ProgramState::bindDefaultInitial(SVal loc, SVal V,
1307442d6faSDimitry Andric const LocationContext *LCtx) const {
13136981b17SDimitry Andric ProgramStateManager &Mgr = getStateManager();
132809500fcSDimitry Andric const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
13348675466SDimitry Andric const StoreRef &newStore = Mgr.StoreMgr->BindDefaultInitial(getStore(), R, V);
134dbe13110SDimitry Andric ProgramStateRef new_state = makeWithStore(newStore);
135676fbe81SDimitry Andric return Mgr.getOwningEngine().processRegionChange(new_state, R, LCtx);
13648675466SDimitry Andric }
13748675466SDimitry Andric
13848675466SDimitry Andric ProgramStateRef
bindDefaultZero(SVal loc,const LocationContext * LCtx) const13948675466SDimitry Andric ProgramState::bindDefaultZero(SVal loc, const LocationContext *LCtx) const {
14048675466SDimitry Andric ProgramStateManager &Mgr = getStateManager();
14148675466SDimitry Andric const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
14248675466SDimitry Andric const StoreRef &newStore = Mgr.StoreMgr->BindDefaultZero(getStore(), R);
14348675466SDimitry Andric ProgramStateRef new_state = makeWithStore(newStore);
144676fbe81SDimitry Andric return Mgr.getOwningEngine().processRegionChange(new_state, R, LCtx);
1453d1dcd9bSDimitry Andric }
1463d1dcd9bSDimitry Andric
147809500fcSDimitry Andric typedef ArrayRef<const MemRegion *> RegionList;
148809500fcSDimitry Andric typedef ArrayRef<SVal> ValueList;
149809500fcSDimitry Andric
150dbe13110SDimitry Andric ProgramStateRef
invalidateRegions(RegionList Regions,const Expr * E,unsigned Count,const LocationContext * LCtx,bool CausedByPointerEscape,InvalidatedSymbols * IS,const CallEvent * Call,RegionAndSymbolInvalidationTraits * ITraits) const151809500fcSDimitry Andric ProgramState::invalidateRegions(RegionList Regions,
1523d1dcd9bSDimitry Andric const Expr *E, unsigned Count,
153dbe13110SDimitry Andric const LocationContext *LCtx,
154809500fcSDimitry Andric bool CausedByPointerEscape,
155809500fcSDimitry Andric InvalidatedSymbols *IS,
156809500fcSDimitry Andric const CallEvent *Call,
157bfef3995SDimitry Andric RegionAndSymbolInvalidationTraits *ITraits) const {
158809500fcSDimitry Andric SmallVector<SVal, 8> Values;
1597fa27ce4SDimitry Andric for (const MemRegion *Reg : Regions)
1607fa27ce4SDimitry Andric Values.push_back(loc::MemRegionVal(Reg));
161809500fcSDimitry Andric
162809500fcSDimitry Andric return invalidateRegionsImpl(Values, E, Count, LCtx, CausedByPointerEscape,
163bfef3995SDimitry Andric IS, ITraits, Call);
16429cafa66SDimitry Andric }
16529cafa66SDimitry Andric
166dbe13110SDimitry Andric ProgramStateRef
invalidateRegions(ValueList Values,const Expr * E,unsigned Count,const LocationContext * LCtx,bool CausedByPointerEscape,InvalidatedSymbols * IS,const CallEvent * Call,RegionAndSymbolInvalidationTraits * ITraits) const167809500fcSDimitry Andric ProgramState::invalidateRegions(ValueList Values,
16829cafa66SDimitry Andric const Expr *E, unsigned Count,
169dbe13110SDimitry Andric const LocationContext *LCtx,
170809500fcSDimitry Andric bool CausedByPointerEscape,
171809500fcSDimitry Andric InvalidatedSymbols *IS,
172809500fcSDimitry Andric const CallEvent *Call,
173bfef3995SDimitry Andric RegionAndSymbolInvalidationTraits *ITraits) const {
174bfef3995SDimitry Andric
175809500fcSDimitry Andric return invalidateRegionsImpl(Values, E, Count, LCtx, CausedByPointerEscape,
176bfef3995SDimitry Andric IS, ITraits, Call);
177809500fcSDimitry Andric }
178809500fcSDimitry Andric
179809500fcSDimitry Andric ProgramStateRef
invalidateRegionsImpl(ValueList Values,const Expr * E,unsigned Count,const LocationContext * LCtx,bool CausedByPointerEscape,InvalidatedSymbols * IS,RegionAndSymbolInvalidationTraits * ITraits,const CallEvent * Call) const180809500fcSDimitry Andric ProgramState::invalidateRegionsImpl(ValueList Values,
181809500fcSDimitry Andric const Expr *E, unsigned Count,
182809500fcSDimitry Andric const LocationContext *LCtx,
183809500fcSDimitry Andric bool CausedByPointerEscape,
184bfef3995SDimitry Andric InvalidatedSymbols *IS,
185bfef3995SDimitry Andric RegionAndSymbolInvalidationTraits *ITraits,
186bfef3995SDimitry Andric const CallEvent *Call) const {
18736981b17SDimitry Andric ProgramStateManager &Mgr = getStateManager();
188cfca06d7SDimitry Andric ExprEngine &Eng = Mgr.getOwningEngine();
1893d1dcd9bSDimitry Andric
190676fbe81SDimitry Andric InvalidatedSymbols InvalidatedSyms;
191bfef3995SDimitry Andric if (!IS)
192676fbe81SDimitry Andric IS = &InvalidatedSyms;
193bfef3995SDimitry Andric
194bfef3995SDimitry Andric RegionAndSymbolInvalidationTraits ITraitsLocal;
195bfef3995SDimitry Andric if (!ITraits)
196bfef3995SDimitry Andric ITraits = &ITraitsLocal;
197bfef3995SDimitry Andric
198809500fcSDimitry Andric StoreManager::InvalidatedRegions TopLevelInvalidated;
19936981b17SDimitry Andric StoreManager::InvalidatedRegions Invalidated;
200bca07a45SDimitry Andric const StoreRef &newStore
201bfef3995SDimitry Andric = Mgr.StoreMgr->invalidateRegions(getStore(), Values, E, Count, LCtx, Call,
202bfef3995SDimitry Andric *IS, *ITraits, &TopLevelInvalidated,
203809500fcSDimitry Andric &Invalidated);
204809500fcSDimitry Andric
205dbe13110SDimitry Andric ProgramStateRef newState = makeWithStore(newStore);
206809500fcSDimitry Andric
207809500fcSDimitry Andric if (CausedByPointerEscape) {
208676fbe81SDimitry Andric newState = Eng.notifyCheckersOfPointerEscape(newState, IS,
209809500fcSDimitry Andric TopLevelInvalidated,
210676fbe81SDimitry Andric Call,
211bfef3995SDimitry Andric *ITraits);
212809500fcSDimitry Andric }
213809500fcSDimitry Andric
214676fbe81SDimitry Andric return Eng.processRegionChanges(newState, IS, TopLevelInvalidated,
2157442d6faSDimitry Andric Invalidated, LCtx, Call);
2163d1dcd9bSDimitry Andric }
2173d1dcd9bSDimitry Andric
killBinding(Loc LV) const21813cc256eSDimitry Andric ProgramStateRef ProgramState::killBinding(Loc LV) const {
2194ebdf5c4SEd Schouten Store OldStore = getStore();
22013cc256eSDimitry Andric const StoreRef &newStore =
22113cc256eSDimitry Andric getStateManager().StoreMgr->killBinding(OldStore, LV);
222ec2b103cSEd Schouten
223bca07a45SDimitry Andric if (newStore.getStore() == OldStore)
2244ebdf5c4SEd Schouten return this;
225ec2b103cSEd Schouten
226bca07a45SDimitry Andric return makeWithStore(newStore);
2273d1dcd9bSDimitry Andric }
2283d1dcd9bSDimitry Andric
229ac9a064cSDimitry Andric /// SymbolicRegions are expected to be wrapped by an ElementRegion as a
230ac9a064cSDimitry Andric /// canonical representation. As a canonical representation, SymbolicRegions
231ac9a064cSDimitry Andric /// should be wrapped by ElementRegions before getting a FieldRegion.
232ac9a064cSDimitry Andric /// See f8643a9b31c4029942f67d4534c9139b45173504 why.
wrapSymbolicRegion(SVal Val) const233ac9a064cSDimitry Andric SVal ProgramState::wrapSymbolicRegion(SVal Val) const {
234ac9a064cSDimitry Andric const auto *BaseReg = dyn_cast_or_null<SymbolicRegion>(Val.getAsRegion());
235ac9a064cSDimitry Andric if (!BaseReg)
236ac9a064cSDimitry Andric return Val;
237ac9a064cSDimitry Andric
238ac9a064cSDimitry Andric StoreManager &SM = getStateManager().getStoreManager();
239ac9a064cSDimitry Andric QualType ElemTy = BaseReg->getPointeeStaticType();
240ac9a064cSDimitry Andric return loc::MemRegionVal{SM.GetElementZeroRegion(BaseReg, ElemTy)};
241ac9a064cSDimitry Andric }
242ac9a064cSDimitry Andric
243dbe13110SDimitry Andric ProgramStateRef
enterStackFrame(const CallEvent & Call,const StackFrameContext * CalleeCtx) const24456d91b49SDimitry Andric ProgramState::enterStackFrame(const CallEvent &Call,
24556d91b49SDimitry Andric const StackFrameContext *CalleeCtx) const {
24656d91b49SDimitry Andric const StoreRef &NewStore =
24756d91b49SDimitry Andric getStateManager().StoreMgr->enterStackFrame(getStore(), Call, CalleeCtx);
24856d91b49SDimitry Andric return makeWithStore(NewStore);
2494ebdf5c4SEd Schouten }
2504ebdf5c4SEd Schouten
getSelfSVal(const LocationContext * LCtx) const251cfca06d7SDimitry Andric SVal ProgramState::getSelfSVal(const LocationContext *LCtx) const {
252cfca06d7SDimitry Andric const ImplicitParamDecl *SelfDecl = LCtx->getSelfDecl();
253cfca06d7SDimitry Andric if (!SelfDecl)
254cfca06d7SDimitry Andric return SVal();
255cfca06d7SDimitry Andric return getSVal(getRegion(SelfDecl, LCtx));
256cfca06d7SDimitry Andric }
257cfca06d7SDimitry Andric
getSValAsScalarOrLoc(const MemRegion * R) const25836981b17SDimitry Andric SVal ProgramState::getSValAsScalarOrLoc(const MemRegion *R) const {
2594ebdf5c4SEd Schouten // We only want to do fetches from regions that we can actually bind
2604ebdf5c4SEd Schouten // values. For example, SymbolicRegions of type 'id<...>' cannot
2614ebdf5c4SEd Schouten // have direct bindings (but their can be bindings on their subregions).
2624ebdf5c4SEd Schouten if (!R->isBoundable())
2634ebdf5c4SEd Schouten return UnknownVal();
2644ebdf5c4SEd Schouten
26536981b17SDimitry Andric if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
2663d1dcd9bSDimitry Andric QualType T = TR->getValueType();
2676a037251SDimitry Andric if (Loc::isLocType(T) || T->isIntegralOrEnumerationType())
2684ebdf5c4SEd Schouten return getSVal(R);
2694ebdf5c4SEd Schouten }
2704ebdf5c4SEd Schouten
2714ebdf5c4SEd Schouten return UnknownVal();
2724ebdf5c4SEd Schouten }
2734ebdf5c4SEd Schouten
getSVal(Loc location,QualType T) const27436981b17SDimitry Andric SVal ProgramState::getSVal(Loc location, QualType T) const {
27548675466SDimitry Andric SVal V = getRawSVal(location, T);
2764ebdf5c4SEd Schouten
2773d1dcd9bSDimitry Andric // If 'V' is a symbolic value that is *perfectly* constrained to
2783d1dcd9bSDimitry Andric // be a constant value, use that value instead to lessen the burden
2793d1dcd9bSDimitry Andric // on later analysis stages (so we have less symbolic values to reason
2803d1dcd9bSDimitry Andric // about).
281461a67faSDimitry Andric // We only go into this branch if we can convert the APSInt value we have
282461a67faSDimitry Andric // to the type of T, which is not always the case (e.g. for void).
283461a67faSDimitry Andric if (!T.isNull() && (T->isIntegralOrEnumerationType() || Loc::isLocType(T))) {
2843d1dcd9bSDimitry Andric if (SymbolRef sym = V.getAsSymbol()) {
28513cc256eSDimitry Andric if (const llvm::APSInt *Int = getStateManager()
28613cc256eSDimitry Andric .getConstraintManager()
28713cc256eSDimitry Andric .getSymVal(this, sym)) {
2883d1dcd9bSDimitry Andric // FIXME: Because we don't correctly model (yet) sign-extension
2893d1dcd9bSDimitry Andric // and truncation of symbolic values, we need to convert
2903d1dcd9bSDimitry Andric // the integer value to the correct signedness and bitwidth.
2913d1dcd9bSDimitry Andric //
2923d1dcd9bSDimitry Andric // This shows up in the following:
2933d1dcd9bSDimitry Andric //
2943d1dcd9bSDimitry Andric // char foo();
2953d1dcd9bSDimitry Andric // unsigned x = foo();
2963d1dcd9bSDimitry Andric // if (x == 54)
2973d1dcd9bSDimitry Andric // ...
2983d1dcd9bSDimitry Andric //
2993d1dcd9bSDimitry Andric // The symbolic value stored to 'x' is actually the conjured
3003d1dcd9bSDimitry Andric // symbol for the call to foo(); the type of that symbol is 'char',
3013d1dcd9bSDimitry Andric // not unsigned.
3023d1dcd9bSDimitry Andric const llvm::APSInt &NewV = getBasicVals().Convert(T, *Int);
3033d1dcd9bSDimitry Andric
304809500fcSDimitry Andric if (V.getAs<Loc>())
3053d1dcd9bSDimitry Andric return loc::ConcreteInt(NewV);
3063d1dcd9bSDimitry Andric else
3073d1dcd9bSDimitry Andric return nonloc::ConcreteInt(NewV);
3083d1dcd9bSDimitry Andric }
3093d1dcd9bSDimitry Andric }
3103d1dcd9bSDimitry Andric }
3113d1dcd9bSDimitry Andric
3123d1dcd9bSDimitry Andric return V;
3133d1dcd9bSDimitry Andric }
3143d1dcd9bSDimitry Andric
BindExpr(const Stmt * S,const LocationContext * LCtx,SVal V,bool Invalidate) const315dbe13110SDimitry Andric ProgramStateRef ProgramState::BindExpr(const Stmt *S,
316dbe13110SDimitry Andric const LocationContext *LCtx,
317dbe13110SDimitry Andric SVal V, bool Invalidate) const{
318dbe13110SDimitry Andric Environment NewEnv =
319dbe13110SDimitry Andric getStateManager().EnvMgr.bindExpr(Env, EnvironmentEntry(S, LCtx), V,
3204c8b2481SRoman Divacky Invalidate);
3214ebdf5c4SEd Schouten if (NewEnv == Env)
3224ebdf5c4SEd Schouten return this;
3234ebdf5c4SEd Schouten
32436981b17SDimitry Andric ProgramState NewSt = *this;
3254ebdf5c4SEd Schouten NewSt.Env = NewEnv;
3264c8b2481SRoman Divacky return getStateManager().getPersistentState(NewSt);
3274ebdf5c4SEd Schouten }
3284ebdf5c4SEd Schouten
329e3b55780SDimitry Andric [[nodiscard]] std::pair<ProgramStateRef, ProgramStateRef>
assumeInBoundDual(DefinedOrUnknownSVal Idx,DefinedOrUnknownSVal UpperBound,QualType indexTy) const330145449b1SDimitry Andric ProgramState::assumeInBoundDual(DefinedOrUnknownSVal Idx,
3313d1dcd9bSDimitry Andric DefinedOrUnknownSVal UpperBound,
332dbe13110SDimitry Andric QualType indexTy) const {
3333d1dcd9bSDimitry Andric if (Idx.isUnknown() || UpperBound.isUnknown())
334145449b1SDimitry Andric return {this, this};
3353d1dcd9bSDimitry Andric
3363d1dcd9bSDimitry Andric // Build an expression for 0 <= Idx < UpperBound.
3373d1dcd9bSDimitry Andric // This is the same as Idx + MIN < UpperBound + MIN, if overflow is allowed.
338bca07a45SDimitry Andric // FIXME: This should probably be part of SValBuilder.
33936981b17SDimitry Andric ProgramStateManager &SM = getStateManager();
340bca07a45SDimitry Andric SValBuilder &svalBuilder = SM.getSValBuilder();
341bca07a45SDimitry Andric ASTContext &Ctx = svalBuilder.getContext();
3423d1dcd9bSDimitry Andric
3433d1dcd9bSDimitry Andric // Get the offset: the minimum value of the array index type.
344bca07a45SDimitry Andric BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
345dbe13110SDimitry Andric if (indexTy.isNull())
34648675466SDimitry Andric indexTy = svalBuilder.getArrayIndexType();
347bca07a45SDimitry Andric nonloc::ConcreteInt Min(BVF.getMinValue(indexTy));
3483d1dcd9bSDimitry Andric
3493d1dcd9bSDimitry Andric // Adjust the index.
350bca07a45SDimitry Andric SVal newIdx = svalBuilder.evalBinOpNN(this, BO_Add,
351809500fcSDimitry Andric Idx.castAs<NonLoc>(), Min, indexTy);
352bca07a45SDimitry Andric if (newIdx.isUnknownOrUndef())
353145449b1SDimitry Andric return {this, this};
3543d1dcd9bSDimitry Andric
3553d1dcd9bSDimitry Andric // Adjust the upper bound.
356bca07a45SDimitry Andric SVal newBound =
357809500fcSDimitry Andric svalBuilder.evalBinOpNN(this, BO_Add, UpperBound.castAs<NonLoc>(),
358bca07a45SDimitry Andric Min, indexTy);
359bca07a45SDimitry Andric
360bca07a45SDimitry Andric if (newBound.isUnknownOrUndef())
361145449b1SDimitry Andric return {this, this};
3623d1dcd9bSDimitry Andric
3633d1dcd9bSDimitry Andric // Build the actual comparison.
364809500fcSDimitry Andric SVal inBound = svalBuilder.evalBinOpNN(this, BO_LT, newIdx.castAs<NonLoc>(),
365809500fcSDimitry Andric newBound.castAs<NonLoc>(), Ctx.IntTy);
366bca07a45SDimitry Andric if (inBound.isUnknownOrUndef())
367145449b1SDimitry Andric return {this, this};
3683d1dcd9bSDimitry Andric
3693d1dcd9bSDimitry Andric // Finally, let the constraint manager take care of it.
3703d1dcd9bSDimitry Andric ConstraintManager &CM = SM.getConstraintManager();
371145449b1SDimitry Andric return CM.assumeDual(this, inBound.castAs<DefinedSVal>());
372145449b1SDimitry Andric }
373145449b1SDimitry Andric
assumeInBound(DefinedOrUnknownSVal Idx,DefinedOrUnknownSVal UpperBound,bool Assumption,QualType indexTy) const374145449b1SDimitry Andric ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx,
375145449b1SDimitry Andric DefinedOrUnknownSVal UpperBound,
376145449b1SDimitry Andric bool Assumption,
377145449b1SDimitry Andric QualType indexTy) const {
378145449b1SDimitry Andric std::pair<ProgramStateRef, ProgramStateRef> R =
379145449b1SDimitry Andric assumeInBoundDual(Idx, UpperBound, indexTy);
380145449b1SDimitry Andric return Assumption ? R.first : R.second;
381809500fcSDimitry Andric }
382809500fcSDimitry Andric
isNonNull(SVal V) const38348675466SDimitry Andric ConditionTruthVal ProgramState::isNonNull(SVal V) const {
38448675466SDimitry Andric ConditionTruthVal IsNull = isNull(V);
38548675466SDimitry Andric if (IsNull.isUnderconstrained())
38648675466SDimitry Andric return IsNull;
38748675466SDimitry Andric return ConditionTruthVal(!IsNull.getValue());
38848675466SDimitry Andric }
38948675466SDimitry Andric
areEqual(SVal Lhs,SVal Rhs) const39048675466SDimitry Andric ConditionTruthVal ProgramState::areEqual(SVal Lhs, SVal Rhs) const {
39148675466SDimitry Andric return stateMgr->getSValBuilder().areEqual(this, Lhs, Rhs);
39248675466SDimitry Andric }
39348675466SDimitry Andric
isNull(SVal V) const394809500fcSDimitry Andric ConditionTruthVal ProgramState::isNull(SVal V) const {
395809500fcSDimitry Andric if (V.isZeroConstant())
396809500fcSDimitry Andric return true;
397809500fcSDimitry Andric
398809500fcSDimitry Andric if (V.isConstant())
399809500fcSDimitry Andric return false;
400809500fcSDimitry Andric
4016a037251SDimitry Andric SymbolRef Sym = V.getAsSymbol(/* IncludeBaseRegion */ true);
402809500fcSDimitry Andric if (!Sym)
403809500fcSDimitry Andric return ConditionTruthVal();
404809500fcSDimitry Andric
405809500fcSDimitry Andric return getStateManager().ConstraintMgr->isNull(this, Sym);
4063d1dcd9bSDimitry Andric }
4073d1dcd9bSDimitry Andric
getInitialState(const LocationContext * InitLoc)408dbe13110SDimitry Andric ProgramStateRef ProgramStateManager::getInitialState(const LocationContext *InitLoc) {
40936981b17SDimitry Andric ProgramState State(this,
410dd5132ceSRoman Divacky EnvMgr.getInitialEnvironment(),
4114c8b2481SRoman Divacky StoreMgr->getInitialStore(InitLoc),
412bca07a45SDimitry Andric GDMFactory.getEmptyMap());
413ec2b103cSEd Schouten
4144c8b2481SRoman Divacky return getPersistentState(State);
415ec2b103cSEd Schouten }
416ec2b103cSEd Schouten
getPersistentStateWithGDM(ProgramStateRef FromState,ProgramStateRef GDMState)417dbe13110SDimitry Andric ProgramStateRef ProgramStateManager::getPersistentStateWithGDM(
418dbe13110SDimitry Andric ProgramStateRef FromState,
419dbe13110SDimitry Andric ProgramStateRef GDMState) {
420dbe13110SDimitry Andric ProgramState NewState(*FromState);
42136981b17SDimitry Andric NewState.GDM = GDMState->GDM;
42236981b17SDimitry Andric return getPersistentState(NewState);
42336981b17SDimitry Andric }
42436981b17SDimitry Andric
getPersistentState(ProgramState & State)425dbe13110SDimitry Andric ProgramStateRef ProgramStateManager::getPersistentState(ProgramState &State) {
426ec2b103cSEd Schouten
427ec2b103cSEd Schouten llvm::FoldingSetNodeID ID;
428ec2b103cSEd Schouten State.Profile(ID);
429ec2b103cSEd Schouten void *InsertPos;
430ec2b103cSEd Schouten
43136981b17SDimitry Andric if (ProgramState *I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
432ec2b103cSEd Schouten return I;
433ec2b103cSEd Schouten
4349f4dbff6SDimitry Andric ProgramState *newState = nullptr;
435bca07a45SDimitry Andric if (!freeStates.empty()) {
436bca07a45SDimitry Andric newState = freeStates.back();
437bca07a45SDimitry Andric freeStates.pop_back();
438bca07a45SDimitry Andric }
439bca07a45SDimitry Andric else {
4407fa27ce4SDimitry Andric newState = Alloc.Allocate<ProgramState>();
441bca07a45SDimitry Andric }
44236981b17SDimitry Andric new (newState) ProgramState(State);
443bca07a45SDimitry Andric StateSet.InsertNode(newState, InsertPos);
444bca07a45SDimitry Andric return newState;
445ec2b103cSEd Schouten }
446ec2b103cSEd Schouten
makeWithStore(const StoreRef & store) const447dbe13110SDimitry Andric ProgramStateRef ProgramState::makeWithStore(const StoreRef &store) const {
448dbe13110SDimitry Andric ProgramState NewSt(*this);
449bca07a45SDimitry Andric NewSt.setStore(store);
4504c8b2481SRoman Divacky return getStateManager().getPersistentState(NewSt);
451ec2b103cSEd Schouten }
452ec2b103cSEd Schouten
cloneAsPosteriorlyOverconstrained() const453145449b1SDimitry Andric ProgramStateRef ProgramState::cloneAsPosteriorlyOverconstrained() const {
454145449b1SDimitry Andric ProgramState NewSt(*this);
455145449b1SDimitry Andric NewSt.PosteriorlyOverconstrained = true;
456145449b1SDimitry Andric return getStateManager().getPersistentState(NewSt);
457145449b1SDimitry Andric }
458145449b1SDimitry Andric
setStore(const StoreRef & newStore)45936981b17SDimitry Andric void ProgramState::setStore(const StoreRef &newStore) {
460bca07a45SDimitry Andric Store newStoreStore = newStore.getStore();
461bca07a45SDimitry Andric if (newStoreStore)
462bca07a45SDimitry Andric stateMgr->getStoreManager().incrementReferenceCount(newStoreStore);
463bca07a45SDimitry Andric if (store)
464bca07a45SDimitry Andric stateMgr->getStoreManager().decrementReferenceCount(store);
465bca07a45SDimitry Andric store = newStoreStore;
466bca07a45SDimitry Andric }
467bca07a45SDimitry Andric
getLValue(const FieldDecl * D,SVal Base) const468ac9a064cSDimitry Andric SVal ProgramState::getLValue(const FieldDecl *D, SVal Base) const {
469ac9a064cSDimitry Andric Base = wrapSymbolicRegion(Base);
470ac9a064cSDimitry Andric return getStateManager().StoreMgr->getLValueField(D, Base);
471ac9a064cSDimitry Andric }
472ac9a064cSDimitry Andric
getLValue(const IndirectFieldDecl * D,SVal Base) const473ac9a064cSDimitry Andric SVal ProgramState::getLValue(const IndirectFieldDecl *D, SVal Base) const {
474ac9a064cSDimitry Andric StoreManager &SM = *getStateManager().StoreMgr;
475ac9a064cSDimitry Andric Base = wrapSymbolicRegion(Base);
476ac9a064cSDimitry Andric
477ac9a064cSDimitry Andric // FIXME: This should work with `SM.getLValueField(D->getAnonField(), Base)`,
478ac9a064cSDimitry Andric // but that would break some tests. There is probably a bug somewhere that it
479ac9a064cSDimitry Andric // would expose.
480ac9a064cSDimitry Andric for (const auto *I : D->chain()) {
481ac9a064cSDimitry Andric Base = SM.getLValueField(cast<FieldDecl>(I), Base);
482ac9a064cSDimitry Andric }
483ac9a064cSDimitry Andric return Base;
484ac9a064cSDimitry Andric }
485ac9a064cSDimitry Andric
486ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
487ec2b103cSEd Schouten // State pretty-printing.
488ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
489ec2b103cSEd Schouten
printJson(raw_ostream & Out,const LocationContext * LCtx,const char * NL,unsigned int Space,bool IsDot) const49022989816SDimitry Andric void ProgramState::printJson(raw_ostream &Out, const LocationContext *LCtx,
49122989816SDimitry Andric const char *NL, unsigned int Space,
49222989816SDimitry Andric bool IsDot) const {
49322989816SDimitry Andric Indent(Out, Space, IsDot) << "\"program_state\": {" << NL;
49422989816SDimitry Andric ++Space;
49522989816SDimitry Andric
49636981b17SDimitry Andric ProgramStateManager &Mgr = getStateManager();
49722989816SDimitry Andric
49822989816SDimitry Andric // Print the store.
49922989816SDimitry Andric Mgr.getStoreManager().printJson(Out, getStore(), NL, Space, IsDot);
5004c8b2481SRoman Divacky
501dbe13110SDimitry Andric // Print out the environment.
50222989816SDimitry Andric Env.printJson(Out, Mgr.getContext(), LCtx, NL, Space, IsDot);
503ec2b103cSEd Schouten
504dbe13110SDimitry Andric // Print out the constraints.
50522989816SDimitry Andric Mgr.getConstraintManager().printJson(Out, this, NL, Space, IsDot);
506ec2b103cSEd Schouten
50748675466SDimitry Andric // Print out the tracked dynamic types.
50822989816SDimitry Andric printDynamicTypeInfoJson(Out, this, NL, Space, IsDot);
50948675466SDimitry Andric
510ec2b103cSEd Schouten // Print checker-specific data.
51122989816SDimitry Andric Mgr.getOwningEngine().printJson(Out, this, LCtx, NL, Space, IsDot);
51222989816SDimitry Andric
51322989816SDimitry Andric --Space;
51422989816SDimitry Andric Indent(Out, Space, IsDot) << '}';
515ec2b103cSEd Schouten }
516ec2b103cSEd Schouten
printDOT(raw_ostream & Out,const LocationContext * LCtx,unsigned int Space) const51722989816SDimitry Andric void ProgramState::printDOT(raw_ostream &Out, const LocationContext *LCtx,
51822989816SDimitry Andric unsigned int Space) const {
51922989816SDimitry Andric printJson(Out, LCtx, /*NL=*/"\\l", Space, /*IsDot=*/true);
520ec2b103cSEd Schouten }
521ec2b103cSEd Schouten
dump() const5222b6b257fSDimitry Andric LLVM_DUMP_METHOD void ProgramState::dump() const {
52322989816SDimitry Andric printJson(llvm::errs());
524ec2b103cSEd Schouten }
525ec2b103cSEd Schouten
getAnalysisManager() const526c7e70c43SDimitry Andric AnalysisManager& ProgramState::getAnalysisManager() const {
527676fbe81SDimitry Andric return stateMgr->getOwningEngine().getAnalysisManager();
528c7e70c43SDimitry Andric }
529c7e70c43SDimitry Andric
530ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
531ec2b103cSEd Schouten // Generic Data Map.
532ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
533ec2b103cSEd Schouten
FindGDM(void * K) const53436981b17SDimitry Andric void *const* ProgramState::FindGDM(void *K) const {
535ec2b103cSEd Schouten return GDM.lookup(K);
536ec2b103cSEd Schouten }
537ec2b103cSEd Schouten
538ec2b103cSEd Schouten void*
FindGDMContext(void * K,void * (* CreateContext)(llvm::BumpPtrAllocator &),void (* DeleteContext)(void *))53936981b17SDimitry Andric ProgramStateManager::FindGDMContext(void *K,
540ec2b103cSEd Schouten void *(*CreateContext)(llvm::BumpPtrAllocator&),
541ec2b103cSEd Schouten void (*DeleteContext)(void*)) {
542ec2b103cSEd Schouten
543ec2b103cSEd Schouten std::pair<void*, void (*)(void*)>& p = GDMContexts[K];
544ec2b103cSEd Schouten if (!p.first) {
545ec2b103cSEd Schouten p.first = CreateContext(Alloc);
546ec2b103cSEd Schouten p.second = DeleteContext;
547ec2b103cSEd Schouten }
548ec2b103cSEd Schouten
549ec2b103cSEd Schouten return p.first;
550ec2b103cSEd Schouten }
551ec2b103cSEd Schouten
addGDM(ProgramStateRef St,void * Key,void * Data)552dbe13110SDimitry Andric ProgramStateRef ProgramStateManager::addGDM(ProgramStateRef St, void *Key, void *Data){
55336981b17SDimitry Andric ProgramState::GenericDataMap M1 = St->getGDM();
55436981b17SDimitry Andric ProgramState::GenericDataMap M2 = GDMFactory.add(M1, Key, Data);
555ec2b103cSEd Schouten
556ec2b103cSEd Schouten if (M1 == M2)
557ec2b103cSEd Schouten return St;
558ec2b103cSEd Schouten
55936981b17SDimitry Andric ProgramState NewSt = *St;
560ec2b103cSEd Schouten NewSt.GDM = M2;
561ec2b103cSEd Schouten return getPersistentState(NewSt);
562ec2b103cSEd Schouten }
563ec2b103cSEd Schouten
removeGDM(ProgramStateRef state,void * Key)564dbe13110SDimitry Andric ProgramStateRef ProgramStateManager::removeGDM(ProgramStateRef state, void *Key) {
56536981b17SDimitry Andric ProgramState::GenericDataMap OldM = state->getGDM();
56636981b17SDimitry Andric ProgramState::GenericDataMap NewM = GDMFactory.remove(OldM, Key);
56711d2b2d2SRoman Divacky
56811d2b2d2SRoman Divacky if (NewM == OldM)
56911d2b2d2SRoman Divacky return state;
57011d2b2d2SRoman Divacky
57136981b17SDimitry Andric ProgramState NewState = *state;
57211d2b2d2SRoman Divacky NewState.GDM = NewM;
57311d2b2d2SRoman Divacky return getPersistentState(NewState);
57411d2b2d2SRoman Divacky }
57511d2b2d2SRoman Divacky
scan(nonloc::LazyCompoundVal val)576bfef3995SDimitry Andric bool ScanReachableSymbols::scan(nonloc::LazyCompoundVal val) {
577bfef3995SDimitry Andric bool wasVisited = !visited.insert(val.getCVData()).second;
578bfef3995SDimitry Andric if (wasVisited)
579bfef3995SDimitry Andric return true;
580bfef3995SDimitry Andric
581bfef3995SDimitry Andric StoreManager &StoreMgr = state->getStateManager().getStoreManager();
582bfef3995SDimitry Andric // FIXME: We don't really want to use getBaseRegion() here because pointer
583bfef3995SDimitry Andric // arithmetic doesn't apply, but scanReachableSymbols only accepts base
584bfef3995SDimitry Andric // regions right now.
585bfef3995SDimitry Andric const MemRegion *R = val.getRegion()->getBaseRegion();
586bfef3995SDimitry Andric return StoreMgr.scanReachableSymbols(val.getStore(), R, *this);
587bfef3995SDimitry Andric }
588bfef3995SDimitry Andric
scan(nonloc::CompoundVal val)589ec2b103cSEd Schouten bool ScanReachableSymbols::scan(nonloc::CompoundVal val) {
5907fa27ce4SDimitry Andric for (SVal V : val)
5917fa27ce4SDimitry Andric if (!scan(V))
592ec2b103cSEd Schouten return false;
593ec2b103cSEd Schouten
594ec2b103cSEd Schouten return true;
595ec2b103cSEd Schouten }
596ec2b103cSEd Schouten
scan(const SymExpr * sym)59736981b17SDimitry Andric bool ScanReachableSymbols::scan(const SymExpr *sym) {
5987fa27ce4SDimitry Andric for (SymbolRef SubSym : sym->symbols()) {
5997fa27ce4SDimitry Andric bool wasVisited = !visited.insert(SubSym).second;
600bfef3995SDimitry Andric if (wasVisited)
601bab175ecSDimitry Andric continue;
60236981b17SDimitry Andric
6037fa27ce4SDimitry Andric if (!visitor.VisitSymbol(SubSym))
60436981b17SDimitry Andric return false;
605bab175ecSDimitry Andric }
60636981b17SDimitry Andric
60736981b17SDimitry Andric return true;
60836981b17SDimitry Andric }
60936981b17SDimitry Andric
scan(SVal val)610ec2b103cSEd Schouten bool ScanReachableSymbols::scan(SVal val) {
611e3b55780SDimitry Andric if (std::optional<loc::MemRegionVal> X = val.getAs<loc::MemRegionVal>())
612ec2b103cSEd Schouten return scan(X->getRegion());
613ec2b103cSEd Schouten
614e3b55780SDimitry Andric if (std::optional<nonloc::LazyCompoundVal> X =
615bfef3995SDimitry Andric val.getAs<nonloc::LazyCompoundVal>())
616bfef3995SDimitry Andric return scan(*X);
61756d91b49SDimitry Andric
618e3b55780SDimitry Andric if (std::optional<nonloc::LocAsInteger> X = val.getAs<nonloc::LocAsInteger>())
619ee791ddeSRoman Divacky return scan(X->getLoc());
620ee791ddeSRoman Divacky
621ec2b103cSEd Schouten if (SymbolRef Sym = val.getAsSymbol())
62236981b17SDimitry Andric return scan(Sym);
62336981b17SDimitry Andric
624e3b55780SDimitry Andric if (std::optional<nonloc::CompoundVal> X = val.getAs<nonloc::CompoundVal>())
625ec2b103cSEd Schouten return scan(*X);
626ec2b103cSEd Schouten
627ec2b103cSEd Schouten return true;
628ec2b103cSEd Schouten }
629ec2b103cSEd Schouten
scan(const MemRegion * R)630ec2b103cSEd Schouten bool ScanReachableSymbols::scan(const MemRegion *R) {
63136981b17SDimitry Andric if (isa<MemSpaceRegion>(R))
632ec2b103cSEd Schouten return true;
633ec2b103cSEd Schouten
634bfef3995SDimitry Andric bool wasVisited = !visited.insert(R).second;
635bfef3995SDimitry Andric if (wasVisited)
63636981b17SDimitry Andric return true;
637dbe13110SDimitry Andric
638dbe13110SDimitry Andric if (!visitor.VisitMemRegion(R))
639dbe13110SDimitry Andric return false;
640dbe13110SDimitry Andric
641ec2b103cSEd Schouten // If this is a symbolic region, visit the symbol for the region.
642ec2b103cSEd Schouten if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
643ec2b103cSEd Schouten if (!visitor.VisitSymbol(SR->getSymbol()))
644ec2b103cSEd Schouten return false;
645ec2b103cSEd Schouten
646ec2b103cSEd Schouten // If this is a subregion, also visit the parent regions.
64756d91b49SDimitry Andric if (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
64856d91b49SDimitry Andric const MemRegion *Super = SR->getSuperRegion();
64956d91b49SDimitry Andric if (!scan(Super))
650ec2b103cSEd Schouten return false;
651ec2b103cSEd Schouten
65256d91b49SDimitry Andric // When we reach the topmost region, scan all symbols in it.
65356d91b49SDimitry Andric if (isa<MemSpaceRegion>(Super)) {
65456d91b49SDimitry Andric StoreManager &StoreMgr = state->getStateManager().getStoreManager();
65556d91b49SDimitry Andric if (!StoreMgr.scanReachableSymbols(state->getStore(), SR, *this))
656ec2b103cSEd Schouten return false;
65756d91b49SDimitry Andric }
65856d91b49SDimitry Andric }
659ec2b103cSEd Schouten
66056d91b49SDimitry Andric // Regions captured by a block are also implicitly reachable.
66156d91b49SDimitry Andric if (const BlockDataRegion *BDR = dyn_cast<BlockDataRegion>(R)) {
6627fa27ce4SDimitry Andric for (auto Var : BDR->referenced_vars()) {
6637fa27ce4SDimitry Andric if (!scan(Var.getCapturedRegion()))
66456d91b49SDimitry Andric return false;
66556d91b49SDimitry Andric }
66656d91b49SDimitry Andric }
667ec2b103cSEd Schouten
66856d91b49SDimitry Andric return true;
669ec2b103cSEd Schouten }
670ec2b103cSEd Schouten
scanReachableSymbols(SVal val,SymbolVisitor & visitor) const67136981b17SDimitry Andric bool ProgramState::scanReachableSymbols(SVal val, SymbolVisitor& visitor) const {
672b897c866SEd Schouten ScanReachableSymbols S(this, visitor);
673ec2b103cSEd Schouten return S.scan(val);
674ec2b103cSEd Schouten }
675ec2b103cSEd Schouten
scanReachableSymbols(llvm::iterator_range<region_iterator> Reachable,SymbolVisitor & visitor) const676676fbe81SDimitry Andric bool ProgramState::scanReachableSymbols(
677676fbe81SDimitry Andric llvm::iterator_range<region_iterator> Reachable,
6781569ce68SRoman Divacky SymbolVisitor &visitor) const {
6791569ce68SRoman Divacky ScanReachableSymbols S(this, visitor);
680676fbe81SDimitry Andric for (const MemRegion *R : Reachable) {
681676fbe81SDimitry Andric if (!S.scan(R))
6821569ce68SRoman Divacky return false;
6831569ce68SRoman Divacky }
68434d02d0bSRoman Divacky return true;
68534d02d0bSRoman Divacky }
686