xref: /src/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ProgramState.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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