1*0b57cec5SDimitry Andric //= ProgramState.cpp - Path-Sensitive "State" for tracking values --*- C++ -*--=
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric //
9*0b57cec5SDimitry Andric //  This file implements ProgramState and ProgramStateManager.
10*0b57cec5SDimitry Andric //
11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
12*0b57cec5SDimitry Andric 
13*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
14*0b57cec5SDimitry Andric #include "clang/Analysis/CFG.h"
15*0b57cec5SDimitry Andric #include "clang/Basic/JsonSupport.h"
16*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
17*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
18a7dea167SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicType.h"
195ffd83dbSDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
20*0b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
21*0b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
22*0b57cec5SDimitry Andric 
23*0b57cec5SDimitry Andric using namespace clang;
24*0b57cec5SDimitry Andric using namespace ento;
25*0b57cec5SDimitry Andric 
26*0b57cec5SDimitry Andric namespace clang { namespace  ento {
27*0b57cec5SDimitry Andric /// Increments the number of times this state is referenced.
28*0b57cec5SDimitry Andric 
ProgramStateRetain(const ProgramState * state)29*0b57cec5SDimitry Andric void ProgramStateRetain(const ProgramState *state) {
30*0b57cec5SDimitry Andric   ++const_cast<ProgramState*>(state)->refCount;
31*0b57cec5SDimitry Andric }
32*0b57cec5SDimitry Andric 
33*0b57cec5SDimitry Andric /// Decrement the number of times this state is referenced.
ProgramStateRelease(const ProgramState * state)34*0b57cec5SDimitry Andric void ProgramStateRelease(const ProgramState *state) {
35*0b57cec5SDimitry Andric   assert(state->refCount > 0);
36*0b57cec5SDimitry Andric   ProgramState *s = const_cast<ProgramState*>(state);
37*0b57cec5SDimitry Andric   if (--s->refCount == 0) {
38*0b57cec5SDimitry Andric     ProgramStateManager &Mgr = s->getStateManager();
39*0b57cec5SDimitry Andric     Mgr.StateSet.RemoveNode(s);
40*0b57cec5SDimitry Andric     s->~ProgramState();
41*0b57cec5SDimitry Andric     Mgr.freeStates.push_back(s);
42*0b57cec5SDimitry Andric   }
43*0b57cec5SDimitry Andric }
44*0b57cec5SDimitry Andric }}
45*0b57cec5SDimitry Andric 
ProgramState(ProgramStateManager * mgr,const Environment & env,StoreRef st,GenericDataMap gdm)46*0b57cec5SDimitry Andric ProgramState::ProgramState(ProgramStateManager *mgr, const Environment& env,
47*0b57cec5SDimitry Andric                  StoreRef st, GenericDataMap gdm)
48*0b57cec5SDimitry Andric   : stateMgr(mgr),
49*0b57cec5SDimitry Andric     Env(env),
50*0b57cec5SDimitry Andric     store(st.getStore()),
51*0b57cec5SDimitry Andric     GDM(gdm),
52*0b57cec5SDimitry Andric     refCount(0) {
53*0b57cec5SDimitry Andric   stateMgr->getStoreManager().incrementReferenceCount(store);
54*0b57cec5SDimitry Andric }
55*0b57cec5SDimitry Andric 
ProgramState(const ProgramState & RHS)56*0b57cec5SDimitry Andric ProgramState::ProgramState(const ProgramState &RHS)
57*0b57cec5SDimitry Andric     : llvm::FoldingSetNode(),
58*0b57cec5SDimitry Andric       stateMgr(RHS.stateMgr),
59*0b57cec5SDimitry Andric       Env(RHS.Env),
60*0b57cec5SDimitry Andric       store(RHS.store),
61*0b57cec5SDimitry Andric       GDM(RHS.GDM),
62*0b57cec5SDimitry Andric       refCount(0) {
63*0b57cec5SDimitry Andric   stateMgr->getStoreManager().incrementReferenceCount(store);
64*0b57cec5SDimitry Andric }
65*0b57cec5SDimitry Andric 
~ProgramState()66*0b57cec5SDimitry Andric ProgramState::~ProgramState() {
67*0b57cec5SDimitry Andric   if (store)
68*0b57cec5SDimitry Andric     stateMgr->getStoreManager().decrementReferenceCount(store);
69*0b57cec5SDimitry Andric }
70*0b57cec5SDimitry Andric 
getID() const71*0b57cec5SDimitry Andric int64_t ProgramState::getID() const {
72*0b57cec5SDimitry Andric   return getStateManager().Alloc.identifyKnownAlignedObject<ProgramState>(this);
73*0b57cec5SDimitry Andric }
74*0b57cec5SDimitry Andric 
ProgramStateManager(ASTContext & Ctx,StoreManagerCreator CreateSMgr,ConstraintManagerCreator CreateCMgr,llvm::BumpPtrAllocator & alloc,ExprEngine * ExprEng)75*0b57cec5SDimitry Andric ProgramStateManager::ProgramStateManager(ASTContext &Ctx,
76*0b57cec5SDimitry Andric                                          StoreManagerCreator CreateSMgr,
77*0b57cec5SDimitry Andric                                          ConstraintManagerCreator CreateCMgr,
78*0b57cec5SDimitry Andric                                          llvm::BumpPtrAllocator &alloc,
795ffd83dbSDimitry Andric                                          ExprEngine *ExprEng)
805ffd83dbSDimitry Andric   : Eng(ExprEng), EnvMgr(alloc), GDMFactory(alloc),
81*0b57cec5SDimitry Andric     svalBuilder(createSimpleSValBuilder(alloc, Ctx, *this)),
82*0b57cec5SDimitry Andric     CallEventMgr(new CallEventManager(alloc)), Alloc(alloc) {
83*0b57cec5SDimitry Andric   StoreMgr = (*CreateSMgr)(*this);
845ffd83dbSDimitry Andric   ConstraintMgr = (*CreateCMgr)(*this, ExprEng);
85*0b57cec5SDimitry Andric }
86*0b57cec5SDimitry Andric 
87*0b57cec5SDimitry Andric 
~ProgramStateManager()88*0b57cec5SDimitry Andric ProgramStateManager::~ProgramStateManager() {
89*0b57cec5SDimitry Andric   for (GDMContextsTy::iterator I=GDMContexts.begin(), E=GDMContexts.end();
90*0b57cec5SDimitry Andric        I!=E; ++I)
91*0b57cec5SDimitry Andric     I->second.second(I->second.first);
92*0b57cec5SDimitry Andric }
93*0b57cec5SDimitry Andric 
removeDeadBindingsFromEnvironmentAndStore(ProgramStateRef state,const StackFrameContext * LCtx,SymbolReaper & SymReaper)94480093f4SDimitry Andric ProgramStateRef ProgramStateManager::removeDeadBindingsFromEnvironmentAndStore(
95480093f4SDimitry Andric     ProgramStateRef state, const StackFrameContext *LCtx,
96*0b57cec5SDimitry Andric     SymbolReaper &SymReaper) {
97*0b57cec5SDimitry Andric 
98*0b57cec5SDimitry Andric   // This code essentially performs a "mark-and-sweep" of the VariableBindings.
99*0b57cec5SDimitry Andric   // The roots are any Block-level exprs and Decls that our liveness algorithm
100*0b57cec5SDimitry Andric   // tells us are live.  We then see what Decls they may reference, and keep
101*0b57cec5SDimitry Andric   // those around.  This code more than likely can be made faster, and the
102*0b57cec5SDimitry Andric   // frequency of which this method is called should be experimented with
103*0b57cec5SDimitry Andric   // for optimum performance.
104*0b57cec5SDimitry Andric   ProgramState NewState = *state;
105*0b57cec5SDimitry Andric 
106*0b57cec5SDimitry Andric   NewState.Env = EnvMgr.removeDeadBindings(NewState.Env, SymReaper, state);
107*0b57cec5SDimitry Andric 
108*0b57cec5SDimitry Andric   // Clean up the store.
109*0b57cec5SDimitry Andric   StoreRef newStore = StoreMgr->removeDeadBindings(NewState.getStore(), LCtx,
110*0b57cec5SDimitry Andric                                                    SymReaper);
111*0b57cec5SDimitry Andric   NewState.setStore(newStore);
112*0b57cec5SDimitry Andric   SymReaper.setReapedStore(newStore);
113*0b57cec5SDimitry Andric 
114480093f4SDimitry Andric   return getPersistentState(NewState);
115*0b57cec5SDimitry Andric }
116*0b57cec5SDimitry Andric 
bindLoc(Loc LV,SVal V,const LocationContext * LCtx,bool notifyChanges) const117*0b57cec5SDimitry Andric ProgramStateRef ProgramState::bindLoc(Loc LV,
118*0b57cec5SDimitry Andric                                       SVal V,
119*0b57cec5SDimitry Andric                                       const LocationContext *LCtx,
120*0b57cec5SDimitry Andric                                       bool notifyChanges) const {
121*0b57cec5SDimitry Andric   ProgramStateManager &Mgr = getStateManager();
122*0b57cec5SDimitry Andric   ProgramStateRef newState = makeWithStore(Mgr.StoreMgr->Bind(getStore(),
123*0b57cec5SDimitry Andric                                                              LV, V));
124*0b57cec5SDimitry Andric   const MemRegion *MR = LV.getAsRegion();
125*0b57cec5SDimitry Andric   if (MR && notifyChanges)
126*0b57cec5SDimitry Andric     return Mgr.getOwningEngine().processRegionChange(newState, MR, LCtx);
127*0b57cec5SDimitry Andric 
128*0b57cec5SDimitry Andric   return newState;
129*0b57cec5SDimitry Andric }
130*0b57cec5SDimitry Andric 
131*0b57cec5SDimitry Andric ProgramStateRef
bindDefaultInitial(SVal loc,SVal V,const LocationContext * LCtx) const132*0b57cec5SDimitry Andric ProgramState::bindDefaultInitial(SVal loc, SVal V,
133*0b57cec5SDimitry Andric                                  const LocationContext *LCtx) const {
134*0b57cec5SDimitry Andric   ProgramStateManager &Mgr = getStateManager();
135*0b57cec5SDimitry Andric   const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
136*0b57cec5SDimitry Andric   const StoreRef &newStore = Mgr.StoreMgr->BindDefaultInitial(getStore(), R, V);
137*0b57cec5SDimitry Andric   ProgramStateRef new_state = makeWithStore(newStore);
138*0b57cec5SDimitry Andric   return Mgr.getOwningEngine().processRegionChange(new_state, R, LCtx);
139*0b57cec5SDimitry Andric }
140*0b57cec5SDimitry Andric 
141*0b57cec5SDimitry Andric ProgramStateRef
bindDefaultZero(SVal loc,const LocationContext * LCtx) const142*0b57cec5SDimitry Andric ProgramState::bindDefaultZero(SVal loc, const LocationContext *LCtx) const {
143*0b57cec5SDimitry Andric   ProgramStateManager &Mgr = getStateManager();
144*0b57cec5SDimitry Andric   const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
145*0b57cec5SDimitry Andric   const StoreRef &newStore = Mgr.StoreMgr->BindDefaultZero(getStore(), R);
146*0b57cec5SDimitry Andric   ProgramStateRef new_state = makeWithStore(newStore);
147*0b57cec5SDimitry Andric   return Mgr.getOwningEngine().processRegionChange(new_state, R, LCtx);
148*0b57cec5SDimitry Andric }
149*0b57cec5SDimitry Andric 
150*0b57cec5SDimitry Andric typedef ArrayRef<const MemRegion *> RegionList;
151*0b57cec5SDimitry Andric typedef ArrayRef<SVal> ValueList;
152*0b57cec5SDimitry Andric 
153*0b57cec5SDimitry Andric ProgramStateRef
invalidateRegions(RegionList Regions,const Expr * E,unsigned Count,const LocationContext * LCtx,bool CausedByPointerEscape,InvalidatedSymbols * IS,const CallEvent * Call,RegionAndSymbolInvalidationTraits * ITraits) const154*0b57cec5SDimitry Andric ProgramState::invalidateRegions(RegionList Regions,
155*0b57cec5SDimitry Andric                              const Expr *E, unsigned Count,
156*0b57cec5SDimitry Andric                              const LocationContext *LCtx,
157*0b57cec5SDimitry Andric                              bool CausedByPointerEscape,
158*0b57cec5SDimitry Andric                              InvalidatedSymbols *IS,
159*0b57cec5SDimitry Andric                              const CallEvent *Call,
160*0b57cec5SDimitry Andric                              RegionAndSymbolInvalidationTraits *ITraits) const {
161*0b57cec5SDimitry Andric   SmallVector<SVal, 8> Values;
162*0b57cec5SDimitry Andric   for (RegionList::const_iterator I = Regions.begin(),
163*0b57cec5SDimitry Andric                                   End = Regions.end(); I != End; ++I)
164*0b57cec5SDimitry Andric     Values.push_back(loc::MemRegionVal(*I));
165*0b57cec5SDimitry Andric 
166*0b57cec5SDimitry Andric   return invalidateRegionsImpl(Values, E, Count, LCtx, CausedByPointerEscape,
167*0b57cec5SDimitry Andric                                IS, ITraits, Call);
168*0b57cec5SDimitry Andric }
169*0b57cec5SDimitry Andric 
170*0b57cec5SDimitry Andric ProgramStateRef
invalidateRegions(ValueList Values,const Expr * E,unsigned Count,const LocationContext * LCtx,bool CausedByPointerEscape,InvalidatedSymbols * IS,const CallEvent * Call,RegionAndSymbolInvalidationTraits * ITraits) const171*0b57cec5SDimitry Andric ProgramState::invalidateRegions(ValueList Values,
172*0b57cec5SDimitry Andric                              const Expr *E, unsigned Count,
173*0b57cec5SDimitry Andric                              const LocationContext *LCtx,
174*0b57cec5SDimitry Andric                              bool CausedByPointerEscape,
175*0b57cec5SDimitry Andric                              InvalidatedSymbols *IS,
176*0b57cec5SDimitry Andric                              const CallEvent *Call,
177*0b57cec5SDimitry Andric                              RegionAndSymbolInvalidationTraits *ITraits) const {
178*0b57cec5SDimitry Andric 
179*0b57cec5SDimitry Andric   return invalidateRegionsImpl(Values, E, Count, LCtx, CausedByPointerEscape,
180*0b57cec5SDimitry Andric                                IS, ITraits, Call);
181*0b57cec5SDimitry Andric }
182*0b57cec5SDimitry Andric 
183*0b57cec5SDimitry Andric ProgramStateRef
invalidateRegionsImpl(ValueList Values,const Expr * E,unsigned Count,const LocationContext * LCtx,bool CausedByPointerEscape,InvalidatedSymbols * IS,RegionAndSymbolInvalidationTraits * ITraits,const CallEvent * Call) const184*0b57cec5SDimitry Andric ProgramState::invalidateRegionsImpl(ValueList Values,
185*0b57cec5SDimitry Andric                                     const Expr *E, unsigned Count,
186*0b57cec5SDimitry Andric                                     const LocationContext *LCtx,
187*0b57cec5SDimitry Andric                                     bool CausedByPointerEscape,
188*0b57cec5SDimitry Andric                                     InvalidatedSymbols *IS,
189*0b57cec5SDimitry Andric                                     RegionAndSymbolInvalidationTraits *ITraits,
190*0b57cec5SDimitry Andric                                     const CallEvent *Call) const {
191*0b57cec5SDimitry Andric   ProgramStateManager &Mgr = getStateManager();
1925ffd83dbSDimitry Andric   ExprEngine &Eng = Mgr.getOwningEngine();
193*0b57cec5SDimitry Andric 
194*0b57cec5SDimitry Andric   InvalidatedSymbols InvalidatedSyms;
195*0b57cec5SDimitry Andric   if (!IS)
196*0b57cec5SDimitry Andric     IS = &InvalidatedSyms;
197*0b57cec5SDimitry Andric 
198*0b57cec5SDimitry Andric   RegionAndSymbolInvalidationTraits ITraitsLocal;
199*0b57cec5SDimitry Andric   if (!ITraits)
200*0b57cec5SDimitry Andric     ITraits = &ITraitsLocal;
201*0b57cec5SDimitry Andric 
202*0b57cec5SDimitry Andric   StoreManager::InvalidatedRegions TopLevelInvalidated;
203*0b57cec5SDimitry Andric   StoreManager::InvalidatedRegions Invalidated;
204*0b57cec5SDimitry Andric   const StoreRef &newStore
205*0b57cec5SDimitry Andric   = Mgr.StoreMgr->invalidateRegions(getStore(), Values, E, Count, LCtx, Call,
206*0b57cec5SDimitry Andric                                     *IS, *ITraits, &TopLevelInvalidated,
207*0b57cec5SDimitry Andric                                     &Invalidated);
208*0b57cec5SDimitry Andric 
209*0b57cec5SDimitry Andric   ProgramStateRef newState = makeWithStore(newStore);
210*0b57cec5SDimitry Andric 
211*0b57cec5SDimitry Andric   if (CausedByPointerEscape) {
212*0b57cec5SDimitry Andric     newState = Eng.notifyCheckersOfPointerEscape(newState, IS,
213*0b57cec5SDimitry Andric                                                  TopLevelInvalidated,
214*0b57cec5SDimitry Andric                                                  Call,
215*0b57cec5SDimitry Andric                                                  *ITraits);
216*0b57cec5SDimitry Andric   }
217*0b57cec5SDimitry Andric 
218*0b57cec5SDimitry Andric   return Eng.processRegionChanges(newState, IS, TopLevelInvalidated,
219*0b57cec5SDimitry Andric                                   Invalidated, LCtx, Call);
220*0b57cec5SDimitry Andric }
221*0b57cec5SDimitry Andric 
killBinding(Loc LV) const222*0b57cec5SDimitry Andric ProgramStateRef ProgramState::killBinding(Loc LV) const {
223*0b57cec5SDimitry Andric   assert(!LV.getAs<loc::MemRegionVal>() && "Use invalidateRegion instead.");
224*0b57cec5SDimitry Andric 
225*0b57cec5SDimitry Andric   Store OldStore = getStore();
226*0b57cec5SDimitry Andric   const StoreRef &newStore =
227*0b57cec5SDimitry Andric     getStateManager().StoreMgr->killBinding(OldStore, LV);
228*0b57cec5SDimitry Andric 
229*0b57cec5SDimitry Andric   if (newStore.getStore() == OldStore)
230*0b57cec5SDimitry Andric     return this;
231*0b57cec5SDimitry Andric 
232*0b57cec5SDimitry Andric   return makeWithStore(newStore);
233*0b57cec5SDimitry Andric }
234*0b57cec5SDimitry Andric 
235*0b57cec5SDimitry Andric ProgramStateRef
enterStackFrame(const CallEvent & Call,const StackFrameContext * CalleeCtx) const236*0b57cec5SDimitry Andric ProgramState::enterStackFrame(const CallEvent &Call,
237*0b57cec5SDimitry Andric                               const StackFrameContext *CalleeCtx) const {
238*0b57cec5SDimitry Andric   const StoreRef &NewStore =
239*0b57cec5SDimitry Andric     getStateManager().StoreMgr->enterStackFrame(getStore(), Call, CalleeCtx);
240*0b57cec5SDimitry Andric   return makeWithStore(NewStore);
241*0b57cec5SDimitry Andric }
242*0b57cec5SDimitry Andric 
getSelfSVal(const LocationContext * LCtx) const2435ffd83dbSDimitry Andric SVal ProgramState::getSelfSVal(const LocationContext *LCtx) const {
2445ffd83dbSDimitry Andric   const ImplicitParamDecl *SelfDecl = LCtx->getSelfDecl();
2455ffd83dbSDimitry Andric   if (!SelfDecl)
2465ffd83dbSDimitry Andric     return SVal();
2475ffd83dbSDimitry Andric   return getSVal(getRegion(SelfDecl, LCtx));
2485ffd83dbSDimitry Andric }
2495ffd83dbSDimitry Andric 
getSValAsScalarOrLoc(const MemRegion * R) const250*0b57cec5SDimitry Andric SVal ProgramState::getSValAsScalarOrLoc(const MemRegion *R) const {
251*0b57cec5SDimitry Andric   // We only want to do fetches from regions that we can actually bind
252*0b57cec5SDimitry Andric   // values.  For example, SymbolicRegions of type 'id<...>' cannot
253*0b57cec5SDimitry Andric   // have direct bindings (but their can be bindings on their subregions).
254*0b57cec5SDimitry Andric   if (!R->isBoundable())
255*0b57cec5SDimitry Andric     return UnknownVal();
256*0b57cec5SDimitry Andric 
257*0b57cec5SDimitry Andric   if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
258*0b57cec5SDimitry Andric     QualType T = TR->getValueType();
259*0b57cec5SDimitry Andric     if (Loc::isLocType(T) || T->isIntegralOrEnumerationType())
260*0b57cec5SDimitry Andric       return getSVal(R);
261*0b57cec5SDimitry Andric   }
262*0b57cec5SDimitry Andric 
263*0b57cec5SDimitry Andric   return UnknownVal();
264*0b57cec5SDimitry Andric }
265*0b57cec5SDimitry Andric 
getSVal(Loc location,QualType T) const266*0b57cec5SDimitry Andric SVal ProgramState::getSVal(Loc location, QualType T) const {
267*0b57cec5SDimitry Andric   SVal V = getRawSVal(location, T);
268*0b57cec5SDimitry Andric 
269*0b57cec5SDimitry Andric   // If 'V' is a symbolic value that is *perfectly* constrained to
270*0b57cec5SDimitry Andric   // be a constant value, use that value instead to lessen the burden
271*0b57cec5SDimitry Andric   // on later analysis stages (so we have less symbolic values to reason
272*0b57cec5SDimitry Andric   // about).
273*0b57cec5SDimitry Andric   // We only go into this branch if we can convert the APSInt value we have
274*0b57cec5SDimitry Andric   // to the type of T, which is not always the case (e.g. for void).
275*0b57cec5SDimitry Andric   if (!T.isNull() && (T->isIntegralOrEnumerationType() || Loc::isLocType(T))) {
276*0b57cec5SDimitry Andric     if (SymbolRef sym = V.getAsSymbol()) {
277*0b57cec5SDimitry Andric       if (const llvm::APSInt *Int = getStateManager()
278*0b57cec5SDimitry Andric                                     .getConstraintManager()
279*0b57cec5SDimitry Andric                                     .getSymVal(this, sym)) {
280*0b57cec5SDimitry Andric         // FIXME: Because we don't correctly model (yet) sign-extension
281*0b57cec5SDimitry Andric         // and truncation of symbolic values, we need to convert
282*0b57cec5SDimitry Andric         // the integer value to the correct signedness and bitwidth.
283*0b57cec5SDimitry Andric         //
284*0b57cec5SDimitry Andric         // This shows up in the following:
285*0b57cec5SDimitry Andric         //
286*0b57cec5SDimitry Andric         //   char foo();
287*0b57cec5SDimitry Andric         //   unsigned x = foo();
288*0b57cec5SDimitry Andric         //   if (x == 54)
289*0b57cec5SDimitry Andric         //     ...
290*0b57cec5SDimitry Andric         //
291*0b57cec5SDimitry Andric         //  The symbolic value stored to 'x' is actually the conjured
292*0b57cec5SDimitry Andric         //  symbol for the call to foo(); the type of that symbol is 'char',
293*0b57cec5SDimitry Andric         //  not unsigned.
294*0b57cec5SDimitry Andric         const llvm::APSInt &NewV = getBasicVals().Convert(T, *Int);
295*0b57cec5SDimitry Andric 
296*0b57cec5SDimitry Andric         if (V.getAs<Loc>())
297*0b57cec5SDimitry Andric           return loc::ConcreteInt(NewV);
298*0b57cec5SDimitry Andric         else
299*0b57cec5SDimitry Andric           return nonloc::ConcreteInt(NewV);
300*0b57cec5SDimitry Andric       }
301*0b57cec5SDimitry Andric     }
302*0b57cec5SDimitry Andric   }
303*0b57cec5SDimitry Andric 
304*0b57cec5SDimitry Andric   return V;
305*0b57cec5SDimitry Andric }
306*0b57cec5SDimitry Andric 
BindExpr(const Stmt * S,const LocationContext * LCtx,SVal V,bool Invalidate) const307*0b57cec5SDimitry Andric ProgramStateRef ProgramState::BindExpr(const Stmt *S,
308*0b57cec5SDimitry Andric                                            const LocationContext *LCtx,
309*0b57cec5SDimitry Andric                                            SVal V, bool Invalidate) const{
310*0b57cec5SDimitry Andric   Environment NewEnv =
311*0b57cec5SDimitry Andric     getStateManager().EnvMgr.bindExpr(Env, EnvironmentEntry(S, LCtx), V,
312*0b57cec5SDimitry Andric                                       Invalidate);
313*0b57cec5SDimitry Andric   if (NewEnv == Env)
314*0b57cec5SDimitry Andric     return this;
315*0b57cec5SDimitry Andric 
316*0b57cec5SDimitry Andric   ProgramState NewSt = *this;
317*0b57cec5SDimitry Andric   NewSt.Env = NewEnv;
318*0b57cec5SDimitry Andric   return getStateManager().getPersistentState(NewSt);
319*0b57cec5SDimitry Andric }
320*0b57cec5SDimitry Andric 
assumeInBound(DefinedOrUnknownSVal Idx,DefinedOrUnknownSVal UpperBound,bool Assumption,QualType indexTy) const321*0b57cec5SDimitry Andric ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx,
322*0b57cec5SDimitry Andric                                       DefinedOrUnknownSVal UpperBound,
323*0b57cec5SDimitry Andric                                       bool Assumption,
324*0b57cec5SDimitry Andric                                       QualType indexTy) const {
325*0b57cec5SDimitry Andric   if (Idx.isUnknown() || UpperBound.isUnknown())
326*0b57cec5SDimitry Andric     return this;
327*0b57cec5SDimitry Andric 
328*0b57cec5SDimitry Andric   // Build an expression for 0 <= Idx < UpperBound.
329*0b57cec5SDimitry Andric   // This is the same as Idx + MIN < UpperBound + MIN, if overflow is allowed.
330*0b57cec5SDimitry Andric   // FIXME: This should probably be part of SValBuilder.
331*0b57cec5SDimitry Andric   ProgramStateManager &SM = getStateManager();
332*0b57cec5SDimitry Andric   SValBuilder &svalBuilder = SM.getSValBuilder();
333*0b57cec5SDimitry Andric   ASTContext &Ctx = svalBuilder.getContext();
334*0b57cec5SDimitry Andric 
335*0b57cec5SDimitry Andric   // Get the offset: the minimum value of the array index type.
336*0b57cec5SDimitry Andric   BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
337*0b57cec5SDimitry Andric   if (indexTy.isNull())
338*0b57cec5SDimitry Andric     indexTy = svalBuilder.getArrayIndexType();
339*0b57cec5SDimitry Andric   nonloc::ConcreteInt Min(BVF.getMinValue(indexTy));
340*0b57cec5SDimitry Andric 
341*0b57cec5SDimitry Andric   // Adjust the index.
342*0b57cec5SDimitry Andric   SVal newIdx = svalBuilder.evalBinOpNN(this, BO_Add,
343*0b57cec5SDimitry Andric                                         Idx.castAs<NonLoc>(), Min, indexTy);
344*0b57cec5SDimitry Andric   if (newIdx.isUnknownOrUndef())
345*0b57cec5SDimitry Andric     return this;
346*0b57cec5SDimitry Andric 
347*0b57cec5SDimitry Andric   // Adjust the upper bound.
348*0b57cec5SDimitry Andric   SVal newBound =
349*0b57cec5SDimitry Andric     svalBuilder.evalBinOpNN(this, BO_Add, UpperBound.castAs<NonLoc>(),
350*0b57cec5SDimitry Andric                             Min, indexTy);
351*0b57cec5SDimitry Andric 
352*0b57cec5SDimitry Andric   if (newBound.isUnknownOrUndef())
353*0b57cec5SDimitry Andric     return this;
354*0b57cec5SDimitry Andric 
355*0b57cec5SDimitry Andric   // Build the actual comparison.
356*0b57cec5SDimitry Andric   SVal inBound = svalBuilder.evalBinOpNN(this, BO_LT, newIdx.castAs<NonLoc>(),
357*0b57cec5SDimitry Andric                                          newBound.castAs<NonLoc>(), Ctx.IntTy);
358*0b57cec5SDimitry Andric   if (inBound.isUnknownOrUndef())
359*0b57cec5SDimitry Andric     return this;
360*0b57cec5SDimitry Andric 
361*0b57cec5SDimitry Andric   // Finally, let the constraint manager take care of it.
362*0b57cec5SDimitry Andric   ConstraintManager &CM = SM.getConstraintManager();
363*0b57cec5SDimitry Andric   return CM.assume(this, inBound.castAs<DefinedSVal>(), Assumption);
364*0b57cec5SDimitry Andric }
365*0b57cec5SDimitry Andric 
isNonNull(SVal V) const366*0b57cec5SDimitry Andric ConditionTruthVal ProgramState::isNonNull(SVal V) const {
367*0b57cec5SDimitry Andric   ConditionTruthVal IsNull = isNull(V);
368*0b57cec5SDimitry Andric   if (IsNull.isUnderconstrained())
369*0b57cec5SDimitry Andric     return IsNull;
370*0b57cec5SDimitry Andric   return ConditionTruthVal(!IsNull.getValue());
371*0b57cec5SDimitry Andric }
372*0b57cec5SDimitry Andric 
areEqual(SVal Lhs,SVal Rhs) const373*0b57cec5SDimitry Andric ConditionTruthVal ProgramState::areEqual(SVal Lhs, SVal Rhs) const {
374*0b57cec5SDimitry Andric   return stateMgr->getSValBuilder().areEqual(this, Lhs, Rhs);
375*0b57cec5SDimitry Andric }
376*0b57cec5SDimitry Andric 
isNull(SVal V) const377*0b57cec5SDimitry Andric ConditionTruthVal ProgramState::isNull(SVal V) const {
378*0b57cec5SDimitry Andric   if (V.isZeroConstant())
379*0b57cec5SDimitry Andric     return true;
380*0b57cec5SDimitry Andric 
381*0b57cec5SDimitry Andric   if (V.isConstant())
382*0b57cec5SDimitry Andric     return false;
383*0b57cec5SDimitry Andric 
384*0b57cec5SDimitry Andric   SymbolRef Sym = V.getAsSymbol(/* IncludeBaseRegion */ true);
385*0b57cec5SDimitry Andric   if (!Sym)
386*0b57cec5SDimitry Andric     return ConditionTruthVal();
387*0b57cec5SDimitry Andric 
388*0b57cec5SDimitry Andric   return getStateManager().ConstraintMgr->isNull(this, Sym);
389*0b57cec5SDimitry Andric }
390*0b57cec5SDimitry Andric 
getInitialState(const LocationContext * InitLoc)391*0b57cec5SDimitry Andric ProgramStateRef ProgramStateManager::getInitialState(const LocationContext *InitLoc) {
392*0b57cec5SDimitry Andric   ProgramState State(this,
393*0b57cec5SDimitry Andric                 EnvMgr.getInitialEnvironment(),
394*0b57cec5SDimitry Andric                 StoreMgr->getInitialStore(InitLoc),
395*0b57cec5SDimitry Andric                 GDMFactory.getEmptyMap());
396*0b57cec5SDimitry Andric 
397*0b57cec5SDimitry Andric   return getPersistentState(State);
398*0b57cec5SDimitry Andric }
399*0b57cec5SDimitry Andric 
getPersistentStateWithGDM(ProgramStateRef FromState,ProgramStateRef GDMState)400*0b57cec5SDimitry Andric ProgramStateRef ProgramStateManager::getPersistentStateWithGDM(
401*0b57cec5SDimitry Andric                                                      ProgramStateRef FromState,
402*0b57cec5SDimitry Andric                                                      ProgramStateRef GDMState) {
403*0b57cec5SDimitry Andric   ProgramState NewState(*FromState);
404*0b57cec5SDimitry Andric   NewState.GDM = GDMState->GDM;
405*0b57cec5SDimitry Andric   return getPersistentState(NewState);
406*0b57cec5SDimitry Andric }
407*0b57cec5SDimitry Andric 
getPersistentState(ProgramState & State)408*0b57cec5SDimitry Andric ProgramStateRef ProgramStateManager::getPersistentState(ProgramState &State) {
409*0b57cec5SDimitry Andric 
410*0b57cec5SDimitry Andric   llvm::FoldingSetNodeID ID;
411*0b57cec5SDimitry Andric   State.Profile(ID);
412*0b57cec5SDimitry Andric   void *InsertPos;
413*0b57cec5SDimitry Andric 
414*0b57cec5SDimitry Andric   if (ProgramState *I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
415*0b57cec5SDimitry Andric     return I;
416*0b57cec5SDimitry Andric 
417*0b57cec5SDimitry Andric   ProgramState *newState = nullptr;
418*0b57cec5SDimitry Andric   if (!freeStates.empty()) {
419*0b57cec5SDimitry Andric     newState = freeStates.back();
420*0b57cec5SDimitry Andric     freeStates.pop_back();
421*0b57cec5SDimitry Andric   }
422*0b57cec5SDimitry Andric   else {
423*0b57cec5SDimitry Andric     newState = (ProgramState*) Alloc.Allocate<ProgramState>();
424*0b57cec5SDimitry Andric   }
425*0b57cec5SDimitry Andric   new (newState) ProgramState(State);
426*0b57cec5SDimitry Andric   StateSet.InsertNode(newState, InsertPos);
427*0b57cec5SDimitry Andric   return newState;
428*0b57cec5SDimitry Andric }
429*0b57cec5SDimitry Andric 
makeWithStore(const StoreRef & store) const430*0b57cec5SDimitry Andric ProgramStateRef ProgramState::makeWithStore(const StoreRef &store) const {
431*0b57cec5SDimitry Andric   ProgramState NewSt(*this);
432*0b57cec5SDimitry Andric   NewSt.setStore(store);
433*0b57cec5SDimitry Andric   return getStateManager().getPersistentState(NewSt);
434*0b57cec5SDimitry Andric }
435*0b57cec5SDimitry Andric 
setStore(const StoreRef & newStore)436*0b57cec5SDimitry Andric void ProgramState::setStore(const StoreRef &newStore) {
437*0b57cec5SDimitry Andric   Store newStoreStore = newStore.getStore();
438*0b57cec5SDimitry Andric   if (newStoreStore)
439*0b57cec5SDimitry Andric     stateMgr->getStoreManager().incrementReferenceCount(newStoreStore);
440*0b57cec5SDimitry Andric   if (store)
441*0b57cec5SDimitry Andric     stateMgr->getStoreManager().decrementReferenceCount(store);
442*0b57cec5SDimitry Andric   store = newStoreStore;
443*0b57cec5SDimitry Andric }
444*0b57cec5SDimitry Andric 
445*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
446*0b57cec5SDimitry Andric //  State pretty-printing.
447*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
448*0b57cec5SDimitry Andric 
printJson(raw_ostream & Out,const LocationContext * LCtx,const char * NL,unsigned int Space,bool IsDot) const449*0b57cec5SDimitry Andric void ProgramState::printJson(raw_ostream &Out, const LocationContext *LCtx,
450*0b57cec5SDimitry Andric                              const char *NL, unsigned int Space,
451*0b57cec5SDimitry Andric                              bool IsDot) const {
452*0b57cec5SDimitry Andric   Indent(Out, Space, IsDot) << "\"program_state\": {" << NL;
453*0b57cec5SDimitry Andric   ++Space;
454*0b57cec5SDimitry Andric 
455*0b57cec5SDimitry Andric   ProgramStateManager &Mgr = getStateManager();
456*0b57cec5SDimitry Andric 
457*0b57cec5SDimitry Andric   // Print the store.
458*0b57cec5SDimitry Andric   Mgr.getStoreManager().printJson(Out, getStore(), NL, Space, IsDot);
459*0b57cec5SDimitry Andric 
460*0b57cec5SDimitry Andric   // Print out the environment.
461*0b57cec5SDimitry Andric   Env.printJson(Out, Mgr.getContext(), LCtx, NL, Space, IsDot);
462*0b57cec5SDimitry Andric 
463*0b57cec5SDimitry Andric   // Print out the constraints.
464*0b57cec5SDimitry Andric   Mgr.getConstraintManager().printJson(Out, this, NL, Space, IsDot);
465*0b57cec5SDimitry Andric 
466*0b57cec5SDimitry Andric   // Print out the tracked dynamic types.
467*0b57cec5SDimitry Andric   printDynamicTypeInfoJson(Out, this, NL, Space, IsDot);
468*0b57cec5SDimitry Andric 
469*0b57cec5SDimitry Andric   // Print checker-specific data.
470*0b57cec5SDimitry Andric   Mgr.getOwningEngine().printJson(Out, this, LCtx, NL, Space, IsDot);
471*0b57cec5SDimitry Andric 
472*0b57cec5SDimitry Andric   --Space;
473*0b57cec5SDimitry Andric   Indent(Out, Space, IsDot) << '}';
474*0b57cec5SDimitry Andric }
475*0b57cec5SDimitry Andric 
printDOT(raw_ostream & Out,const LocationContext * LCtx,unsigned int Space) const476*0b57cec5SDimitry Andric void ProgramState::printDOT(raw_ostream &Out, const LocationContext *LCtx,
477*0b57cec5SDimitry Andric                             unsigned int Space) const {
478*0b57cec5SDimitry Andric   printJson(Out, LCtx, /*NL=*/"\\l", Space, /*IsDot=*/true);
479*0b57cec5SDimitry Andric }
480*0b57cec5SDimitry Andric 
dump() const481*0b57cec5SDimitry Andric LLVM_DUMP_METHOD void ProgramState::dump() const {
482*0b57cec5SDimitry Andric   printJson(llvm::errs());
483*0b57cec5SDimitry Andric }
484*0b57cec5SDimitry Andric 
getAnalysisManager() const485*0b57cec5SDimitry Andric AnalysisManager& ProgramState::getAnalysisManager() const {
486*0b57cec5SDimitry Andric   return stateMgr->getOwningEngine().getAnalysisManager();
487*0b57cec5SDimitry Andric }
488*0b57cec5SDimitry Andric 
489*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
490*0b57cec5SDimitry Andric // Generic Data Map.
491*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
492*0b57cec5SDimitry Andric 
FindGDM(void * K) const493*0b57cec5SDimitry Andric void *const* ProgramState::FindGDM(void *K) const {
494*0b57cec5SDimitry Andric   return GDM.lookup(K);
495*0b57cec5SDimitry Andric }
496*0b57cec5SDimitry Andric 
497*0b57cec5SDimitry Andric void*
FindGDMContext(void * K,void * (* CreateContext)(llvm::BumpPtrAllocator &),void (* DeleteContext)(void *))498*0b57cec5SDimitry Andric ProgramStateManager::FindGDMContext(void *K,
499*0b57cec5SDimitry Andric                                void *(*CreateContext)(llvm::BumpPtrAllocator&),
500*0b57cec5SDimitry Andric                                void (*DeleteContext)(void*)) {
501*0b57cec5SDimitry Andric 
502*0b57cec5SDimitry Andric   std::pair<void*, void (*)(void*)>& p = GDMContexts[K];
503*0b57cec5SDimitry Andric   if (!p.first) {
504*0b57cec5SDimitry Andric     p.first = CreateContext(Alloc);
505*0b57cec5SDimitry Andric     p.second = DeleteContext;
506*0b57cec5SDimitry Andric   }
507*0b57cec5SDimitry Andric 
508*0b57cec5SDimitry Andric   return p.first;
509*0b57cec5SDimitry Andric }
510*0b57cec5SDimitry Andric 
addGDM(ProgramStateRef St,void * Key,void * Data)511*0b57cec5SDimitry Andric ProgramStateRef ProgramStateManager::addGDM(ProgramStateRef St, void *Key, void *Data){
512*0b57cec5SDimitry Andric   ProgramState::GenericDataMap M1 = St->getGDM();
513*0b57cec5SDimitry Andric   ProgramState::GenericDataMap M2 = GDMFactory.add(M1, Key, Data);
514*0b57cec5SDimitry Andric 
515*0b57cec5SDimitry Andric   if (M1 == M2)
516*0b57cec5SDimitry Andric     return St;
517*0b57cec5SDimitry Andric 
518*0b57cec5SDimitry Andric   ProgramState NewSt = *St;
519*0b57cec5SDimitry Andric   NewSt.GDM = M2;
520*0b57cec5SDimitry Andric   return getPersistentState(NewSt);
521*0b57cec5SDimitry Andric }
522*0b57cec5SDimitry Andric 
removeGDM(ProgramStateRef state,void * Key)523*0b57cec5SDimitry Andric ProgramStateRef ProgramStateManager::removeGDM(ProgramStateRef state, void *Key) {
524*0b57cec5SDimitry Andric   ProgramState::GenericDataMap OldM = state->getGDM();
525*0b57cec5SDimitry Andric   ProgramState::GenericDataMap NewM = GDMFactory.remove(OldM, Key);
526*0b57cec5SDimitry Andric 
527*0b57cec5SDimitry Andric   if (NewM == OldM)
528*0b57cec5SDimitry Andric     return state;
529*0b57cec5SDimitry Andric 
530*0b57cec5SDimitry Andric   ProgramState NewState = *state;
531*0b57cec5SDimitry Andric   NewState.GDM = NewM;
532*0b57cec5SDimitry Andric   return getPersistentState(NewState);
533*0b57cec5SDimitry Andric }
534*0b57cec5SDimitry Andric 
scan(nonloc::LazyCompoundVal val)535*0b57cec5SDimitry Andric bool ScanReachableSymbols::scan(nonloc::LazyCompoundVal val) {
536*0b57cec5SDimitry Andric   bool wasVisited = !visited.insert(val.getCVData()).second;
537*0b57cec5SDimitry Andric   if (wasVisited)
538*0b57cec5SDimitry Andric     return true;
539*0b57cec5SDimitry Andric 
540*0b57cec5SDimitry Andric   StoreManager &StoreMgr = state->getStateManager().getStoreManager();
541*0b57cec5SDimitry Andric   // FIXME: We don't really want to use getBaseRegion() here because pointer
542*0b57cec5SDimitry Andric   // arithmetic doesn't apply, but scanReachableSymbols only accepts base
543*0b57cec5SDimitry Andric   // regions right now.
544*0b57cec5SDimitry Andric   const MemRegion *R = val.getRegion()->getBaseRegion();
545*0b57cec5SDimitry Andric   return StoreMgr.scanReachableSymbols(val.getStore(), R, *this);
546*0b57cec5SDimitry Andric }
547*0b57cec5SDimitry Andric 
scan(nonloc::CompoundVal val)548*0b57cec5SDimitry Andric bool ScanReachableSymbols::scan(nonloc::CompoundVal val) {
549*0b57cec5SDimitry Andric   for (nonloc::CompoundVal::iterator I=val.begin(), E=val.end(); I!=E; ++I)
550*0b57cec5SDimitry Andric     if (!scan(*I))
551*0b57cec5SDimitry Andric       return false;
552*0b57cec5SDimitry Andric 
553*0b57cec5SDimitry Andric   return true;
554*0b57cec5SDimitry Andric }
555*0b57cec5SDimitry Andric 
scan(const SymExpr * sym)556*0b57cec5SDimitry Andric bool ScanReachableSymbols::scan(const SymExpr *sym) {
557*0b57cec5SDimitry Andric   for (SymExpr::symbol_iterator SI = sym->symbol_begin(),
558*0b57cec5SDimitry Andric                                 SE = sym->symbol_end();
559*0b57cec5SDimitry Andric        SI != SE; ++SI) {
560*0b57cec5SDimitry Andric     bool wasVisited = !visited.insert(*SI).second;
561*0b57cec5SDimitry Andric     if (wasVisited)
562*0b57cec5SDimitry Andric       continue;
563*0b57cec5SDimitry Andric 
564*0b57cec5SDimitry Andric     if (!visitor.VisitSymbol(*SI))
565*0b57cec5SDimitry Andric       return false;
566*0b57cec5SDimitry Andric   }
567*0b57cec5SDimitry Andric 
568*0b57cec5SDimitry Andric   return true;
569*0b57cec5SDimitry Andric }
570*0b57cec5SDimitry Andric 
scan(SVal val)571*0b57cec5SDimitry Andric bool ScanReachableSymbols::scan(SVal val) {
572*0b57cec5SDimitry Andric   if (Optional<loc::MemRegionVal> X = val.getAs<loc::MemRegionVal>())
573*0b57cec5SDimitry Andric     return scan(X->getRegion());
574*0b57cec5SDimitry Andric 
575*0b57cec5SDimitry Andric   if (Optional<nonloc::LazyCompoundVal> X =
576*0b57cec5SDimitry Andric           val.getAs<nonloc::LazyCompoundVal>())
577*0b57cec5SDimitry Andric     return scan(*X);
578*0b57cec5SDimitry Andric 
579*0b57cec5SDimitry Andric   if (Optional<nonloc::LocAsInteger> X = val.getAs<nonloc::LocAsInteger>())
580*0b57cec5SDimitry Andric     return scan(X->getLoc());
581*0b57cec5SDimitry Andric 
582*0b57cec5SDimitry Andric   if (SymbolRef Sym = val.getAsSymbol())
583*0b57cec5SDimitry Andric     return scan(Sym);
584*0b57cec5SDimitry Andric 
585*0b57cec5SDimitry Andric   if (Optional<nonloc::CompoundVal> X = val.getAs<nonloc::CompoundVal>())
586*0b57cec5SDimitry Andric     return scan(*X);
587*0b57cec5SDimitry Andric 
588*0b57cec5SDimitry Andric   return true;
589*0b57cec5SDimitry Andric }
590*0b57cec5SDimitry Andric 
scan(const MemRegion * R)591*0b57cec5SDimitry Andric bool ScanReachableSymbols::scan(const MemRegion *R) {
592*0b57cec5SDimitry Andric   if (isa<MemSpaceRegion>(R))
593*0b57cec5SDimitry Andric     return true;
594*0b57cec5SDimitry Andric 
595*0b57cec5SDimitry Andric   bool wasVisited = !visited.insert(R).second;
596*0b57cec5SDimitry Andric   if (wasVisited)
597*0b57cec5SDimitry Andric     return true;
598*0b57cec5SDimitry Andric 
599*0b57cec5SDimitry Andric   if (!visitor.VisitMemRegion(R))
600*0b57cec5SDimitry Andric     return false;
601*0b57cec5SDimitry Andric 
602*0b57cec5SDimitry Andric   // If this is a symbolic region, visit the symbol for the region.
603*0b57cec5SDimitry Andric   if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
604*0b57cec5SDimitry Andric     if (!visitor.VisitSymbol(SR->getSymbol()))
605*0b57cec5SDimitry Andric       return false;
606*0b57cec5SDimitry Andric 
607*0b57cec5SDimitry Andric   // If this is a subregion, also visit the parent regions.
608*0b57cec5SDimitry Andric   if (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
609*0b57cec5SDimitry Andric     const MemRegion *Super = SR->getSuperRegion();
610*0b57cec5SDimitry Andric     if (!scan(Super))
611*0b57cec5SDimitry Andric       return false;
612*0b57cec5SDimitry Andric 
613*0b57cec5SDimitry Andric     // When we reach the topmost region, scan all symbols in it.
614*0b57cec5SDimitry Andric     if (isa<MemSpaceRegion>(Super)) {
615*0b57cec5SDimitry Andric       StoreManager &StoreMgr = state->getStateManager().getStoreManager();
616*0b57cec5SDimitry Andric       if (!StoreMgr.scanReachableSymbols(state->getStore(), SR, *this))
617*0b57cec5SDimitry Andric         return false;
618*0b57cec5SDimitry Andric     }
619*0b57cec5SDimitry Andric   }
620*0b57cec5SDimitry Andric 
621*0b57cec5SDimitry Andric   // Regions captured by a block are also implicitly reachable.
622*0b57cec5SDimitry Andric   if (const BlockDataRegion *BDR = dyn_cast<BlockDataRegion>(R)) {
623*0b57cec5SDimitry Andric     BlockDataRegion::referenced_vars_iterator I = BDR->referenced_vars_begin(),
624*0b57cec5SDimitry Andric                                               E = BDR->referenced_vars_end();
625*0b57cec5SDimitry Andric     for ( ; I != E; ++I) {
626*0b57cec5SDimitry Andric       if (!scan(I.getCapturedRegion()))
627*0b57cec5SDimitry Andric         return false;
628*0b57cec5SDimitry Andric     }
629*0b57cec5SDimitry Andric   }
630*0b57cec5SDimitry Andric 
631*0b57cec5SDimitry Andric   return true;
632*0b57cec5SDimitry Andric }
633*0b57cec5SDimitry Andric 
scanReachableSymbols(SVal val,SymbolVisitor & visitor) const634*0b57cec5SDimitry Andric bool ProgramState::scanReachableSymbols(SVal val, SymbolVisitor& visitor) const {
635*0b57cec5SDimitry Andric   ScanReachableSymbols S(this, visitor);
636*0b57cec5SDimitry Andric   return S.scan(val);
637*0b57cec5SDimitry Andric }
638*0b57cec5SDimitry Andric 
scanReachableSymbols(llvm::iterator_range<region_iterator> Reachable,SymbolVisitor & visitor) const639*0b57cec5SDimitry Andric bool ProgramState::scanReachableSymbols(
640*0b57cec5SDimitry Andric     llvm::iterator_range<region_iterator> Reachable,
641*0b57cec5SDimitry Andric     SymbolVisitor &visitor) const {
642*0b57cec5SDimitry Andric   ScanReachableSymbols S(this, visitor);
643*0b57cec5SDimitry Andric   for (const MemRegion *R : Reachable) {
644*0b57cec5SDimitry Andric     if (!S.scan(R))
645*0b57cec5SDimitry Andric       return false;
646*0b57cec5SDimitry Andric   }
647*0b57cec5SDimitry Andric   return true;
648*0b57cec5SDimitry Andric }
649