10b57cec5SDimitry Andric //= ProgramState.cpp - Path-Sensitive "State" for tracking values --*- C++ -*--=
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric //  This file implements ProgramState and ProgramStateManager.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
140b57cec5SDimitry Andric #include "clang/Analysis/CFG.h"
150b57cec5SDimitry Andric #include "clang/Basic/JsonSupport.h"
160b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
170b57cec5SDimitry 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"
200b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
210b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
22bdd1243dSDimitry Andric #include <optional>
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric using namespace clang;
250b57cec5SDimitry Andric using namespace ento;
260b57cec5SDimitry Andric 
270b57cec5SDimitry Andric namespace clang { namespace  ento {
280b57cec5SDimitry Andric /// Increments the number of times this state is referenced.
290b57cec5SDimitry Andric 
ProgramStateRetain(const ProgramState * state)300b57cec5SDimitry Andric void ProgramStateRetain(const ProgramState *state) {
310b57cec5SDimitry Andric   ++const_cast<ProgramState*>(state)->refCount;
320b57cec5SDimitry Andric }
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric /// Decrement the number of times this state is referenced.
ProgramStateRelease(const ProgramState * state)350b57cec5SDimitry Andric void ProgramStateRelease(const ProgramState *state) {
360b57cec5SDimitry Andric   assert(state->refCount > 0);
370b57cec5SDimitry Andric   ProgramState *s = const_cast<ProgramState*>(state);
380b57cec5SDimitry Andric   if (--s->refCount == 0) {
390b57cec5SDimitry Andric     ProgramStateManager &Mgr = s->getStateManager();
400b57cec5SDimitry Andric     Mgr.StateSet.RemoveNode(s);
410b57cec5SDimitry Andric     s->~ProgramState();
420b57cec5SDimitry Andric     Mgr.freeStates.push_back(s);
430b57cec5SDimitry Andric   }
440b57cec5SDimitry Andric }
450b57cec5SDimitry Andric }}
460b57cec5SDimitry Andric 
ProgramState(ProgramStateManager * mgr,const Environment & env,StoreRef st,GenericDataMap gdm)470b57cec5SDimitry Andric ProgramState::ProgramState(ProgramStateManager *mgr, const Environment& env,
480b57cec5SDimitry Andric                  StoreRef st, GenericDataMap gdm)
490b57cec5SDimitry Andric   : stateMgr(mgr),
500b57cec5SDimitry Andric     Env(env),
510b57cec5SDimitry Andric     store(st.getStore()),
520b57cec5SDimitry Andric     GDM(gdm),
530b57cec5SDimitry Andric     refCount(0) {
540b57cec5SDimitry Andric   stateMgr->getStoreManager().incrementReferenceCount(store);
550b57cec5SDimitry Andric }
560b57cec5SDimitry Andric 
ProgramState(const ProgramState & RHS)570b57cec5SDimitry Andric ProgramState::ProgramState(const ProgramState &RHS)
5804eeddc0SDimitry Andric     : stateMgr(RHS.stateMgr), Env(RHS.Env), store(RHS.store), GDM(RHS.GDM),
5981ad6265SDimitry Andric       PosteriorlyOverconstrained(RHS.PosteriorlyOverconstrained), refCount(0) {
600b57cec5SDimitry Andric   stateMgr->getStoreManager().incrementReferenceCount(store);
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric 
~ProgramState()630b57cec5SDimitry Andric ProgramState::~ProgramState() {
640b57cec5SDimitry Andric   if (store)
650b57cec5SDimitry Andric     stateMgr->getStoreManager().decrementReferenceCount(store);
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric 
getID() const680b57cec5SDimitry Andric int64_t ProgramState::getID() const {
690b57cec5SDimitry Andric   return getStateManager().Alloc.identifyKnownAlignedObject<ProgramState>(this);
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric 
ProgramStateManager(ASTContext & Ctx,StoreManagerCreator CreateSMgr,ConstraintManagerCreator CreateCMgr,llvm::BumpPtrAllocator & alloc,ExprEngine * ExprEng)720b57cec5SDimitry Andric ProgramStateManager::ProgramStateManager(ASTContext &Ctx,
730b57cec5SDimitry Andric                                          StoreManagerCreator CreateSMgr,
740b57cec5SDimitry Andric                                          ConstraintManagerCreator CreateCMgr,
750b57cec5SDimitry Andric                                          llvm::BumpPtrAllocator &alloc,
765ffd83dbSDimitry Andric                                          ExprEngine *ExprEng)
775ffd83dbSDimitry Andric   : Eng(ExprEng), EnvMgr(alloc), GDMFactory(alloc),
780b57cec5SDimitry Andric     svalBuilder(createSimpleSValBuilder(alloc, Ctx, *this)),
790b57cec5SDimitry Andric     CallEventMgr(new CallEventManager(alloc)), Alloc(alloc) {
800b57cec5SDimitry Andric   StoreMgr = (*CreateSMgr)(*this);
815ffd83dbSDimitry Andric   ConstraintMgr = (*CreateCMgr)(*this, ExprEng);
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric 
~ProgramStateManager()850b57cec5SDimitry Andric ProgramStateManager::~ProgramStateManager() {
860b57cec5SDimitry Andric   for (GDMContextsTy::iterator I=GDMContexts.begin(), E=GDMContexts.end();
870b57cec5SDimitry Andric        I!=E; ++I)
880b57cec5SDimitry Andric     I->second.second(I->second.first);
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric 
removeDeadBindingsFromEnvironmentAndStore(ProgramStateRef state,const StackFrameContext * LCtx,SymbolReaper & SymReaper)91480093f4SDimitry Andric ProgramStateRef ProgramStateManager::removeDeadBindingsFromEnvironmentAndStore(
92480093f4SDimitry Andric     ProgramStateRef state, const StackFrameContext *LCtx,
930b57cec5SDimitry Andric     SymbolReaper &SymReaper) {
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   // This code essentially performs a "mark-and-sweep" of the VariableBindings.
960b57cec5SDimitry Andric   // The roots are any Block-level exprs and Decls that our liveness algorithm
970b57cec5SDimitry Andric   // tells us are live.  We then see what Decls they may reference, and keep
980b57cec5SDimitry Andric   // those around.  This code more than likely can be made faster, and the
990b57cec5SDimitry Andric   // frequency of which this method is called should be experimented with
1000b57cec5SDimitry Andric   // for optimum performance.
1010b57cec5SDimitry Andric   ProgramState NewState = *state;
1020b57cec5SDimitry Andric 
1030b57cec5SDimitry Andric   NewState.Env = EnvMgr.removeDeadBindings(NewState.Env, SymReaper, state);
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric   // Clean up the store.
1060b57cec5SDimitry Andric   StoreRef newStore = StoreMgr->removeDeadBindings(NewState.getStore(), LCtx,
1070b57cec5SDimitry Andric                                                    SymReaper);
1080b57cec5SDimitry Andric   NewState.setStore(newStore);
1090b57cec5SDimitry Andric   SymReaper.setReapedStore(newStore);
1100b57cec5SDimitry Andric 
111480093f4SDimitry Andric   return getPersistentState(NewState);
1120b57cec5SDimitry Andric }
1130b57cec5SDimitry Andric 
bindLoc(Loc LV,SVal V,const LocationContext * LCtx,bool notifyChanges) const1140b57cec5SDimitry Andric ProgramStateRef ProgramState::bindLoc(Loc LV,
1150b57cec5SDimitry Andric                                       SVal V,
1160b57cec5SDimitry Andric                                       const LocationContext *LCtx,
1170b57cec5SDimitry Andric                                       bool notifyChanges) const {
1180b57cec5SDimitry Andric   ProgramStateManager &Mgr = getStateManager();
1190b57cec5SDimitry Andric   ProgramStateRef newState = makeWithStore(Mgr.StoreMgr->Bind(getStore(),
1200b57cec5SDimitry Andric                                                              LV, V));
1210b57cec5SDimitry Andric   const MemRegion *MR = LV.getAsRegion();
1220b57cec5SDimitry Andric   if (MR && notifyChanges)
1230b57cec5SDimitry Andric     return Mgr.getOwningEngine().processRegionChange(newState, MR, LCtx);
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   return newState;
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric ProgramStateRef
bindDefaultInitial(SVal loc,SVal V,const LocationContext * LCtx) const1290b57cec5SDimitry Andric ProgramState::bindDefaultInitial(SVal loc, SVal V,
1300b57cec5SDimitry Andric                                  const LocationContext *LCtx) const {
1310b57cec5SDimitry Andric   ProgramStateManager &Mgr = getStateManager();
1320b57cec5SDimitry Andric   const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
1330b57cec5SDimitry Andric   const StoreRef &newStore = Mgr.StoreMgr->BindDefaultInitial(getStore(), R, V);
1340b57cec5SDimitry Andric   ProgramStateRef new_state = makeWithStore(newStore);
1350b57cec5SDimitry Andric   return Mgr.getOwningEngine().processRegionChange(new_state, R, LCtx);
1360b57cec5SDimitry Andric }
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric ProgramStateRef
bindDefaultZero(SVal loc,const LocationContext * LCtx) const1390b57cec5SDimitry Andric ProgramState::bindDefaultZero(SVal loc, const LocationContext *LCtx) const {
1400b57cec5SDimitry Andric   ProgramStateManager &Mgr = getStateManager();
1410b57cec5SDimitry Andric   const MemRegion *R = loc.castAs<loc::MemRegionVal>().getRegion();
1420b57cec5SDimitry Andric   const StoreRef &newStore = Mgr.StoreMgr->BindDefaultZero(getStore(), R);
1430b57cec5SDimitry Andric   ProgramStateRef new_state = makeWithStore(newStore);
1440b57cec5SDimitry Andric   return Mgr.getOwningEngine().processRegionChange(new_state, R, LCtx);
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric typedef ArrayRef<const MemRegion *> RegionList;
1480b57cec5SDimitry Andric typedef ArrayRef<SVal> ValueList;
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric ProgramStateRef
invalidateRegions(RegionList Regions,const Expr * E,unsigned Count,const LocationContext * LCtx,bool CausedByPointerEscape,InvalidatedSymbols * IS,const CallEvent * Call,RegionAndSymbolInvalidationTraits * ITraits) const1510b57cec5SDimitry Andric ProgramState::invalidateRegions(RegionList Regions,
1520b57cec5SDimitry Andric                              const Expr *E, unsigned Count,
1530b57cec5SDimitry Andric                              const LocationContext *LCtx,
1540b57cec5SDimitry Andric                              bool CausedByPointerEscape,
1550b57cec5SDimitry Andric                              InvalidatedSymbols *IS,
1560b57cec5SDimitry Andric                              const CallEvent *Call,
1570b57cec5SDimitry Andric                              RegionAndSymbolInvalidationTraits *ITraits) const {
1580b57cec5SDimitry Andric   SmallVector<SVal, 8> Values;
159*fe013be4SDimitry Andric   for (const MemRegion *Reg : Regions)
160*fe013be4SDimitry Andric     Values.push_back(loc::MemRegionVal(Reg));
1610b57cec5SDimitry Andric 
1620b57cec5SDimitry Andric   return invalidateRegionsImpl(Values, E, Count, LCtx, CausedByPointerEscape,
1630b57cec5SDimitry Andric                                IS, ITraits, Call);
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric 
1660b57cec5SDimitry Andric ProgramStateRef
invalidateRegions(ValueList Values,const Expr * E,unsigned Count,const LocationContext * LCtx,bool CausedByPointerEscape,InvalidatedSymbols * IS,const CallEvent * Call,RegionAndSymbolInvalidationTraits * ITraits) const1670b57cec5SDimitry Andric ProgramState::invalidateRegions(ValueList Values,
1680b57cec5SDimitry Andric                              const Expr *E, unsigned Count,
1690b57cec5SDimitry Andric                              const LocationContext *LCtx,
1700b57cec5SDimitry Andric                              bool CausedByPointerEscape,
1710b57cec5SDimitry Andric                              InvalidatedSymbols *IS,
1720b57cec5SDimitry Andric                              const CallEvent *Call,
1730b57cec5SDimitry Andric                              RegionAndSymbolInvalidationTraits *ITraits) const {
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   return invalidateRegionsImpl(Values, E, Count, LCtx, CausedByPointerEscape,
1760b57cec5SDimitry Andric                                IS, ITraits, Call);
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric ProgramStateRef
invalidateRegionsImpl(ValueList Values,const Expr * E,unsigned Count,const LocationContext * LCtx,bool CausedByPointerEscape,InvalidatedSymbols * IS,RegionAndSymbolInvalidationTraits * ITraits,const CallEvent * Call) const1800b57cec5SDimitry Andric ProgramState::invalidateRegionsImpl(ValueList Values,
1810b57cec5SDimitry Andric                                     const Expr *E, unsigned Count,
1820b57cec5SDimitry Andric                                     const LocationContext *LCtx,
1830b57cec5SDimitry Andric                                     bool CausedByPointerEscape,
1840b57cec5SDimitry Andric                                     InvalidatedSymbols *IS,
1850b57cec5SDimitry Andric                                     RegionAndSymbolInvalidationTraits *ITraits,
1860b57cec5SDimitry Andric                                     const CallEvent *Call) const {
1870b57cec5SDimitry Andric   ProgramStateManager &Mgr = getStateManager();
1885ffd83dbSDimitry Andric   ExprEngine &Eng = Mgr.getOwningEngine();
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   InvalidatedSymbols InvalidatedSyms;
1910b57cec5SDimitry Andric   if (!IS)
1920b57cec5SDimitry Andric     IS = &InvalidatedSyms;
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   RegionAndSymbolInvalidationTraits ITraitsLocal;
1950b57cec5SDimitry Andric   if (!ITraits)
1960b57cec5SDimitry Andric     ITraits = &ITraitsLocal;
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   StoreManager::InvalidatedRegions TopLevelInvalidated;
1990b57cec5SDimitry Andric   StoreManager::InvalidatedRegions Invalidated;
2000b57cec5SDimitry Andric   const StoreRef &newStore
2010b57cec5SDimitry Andric   = Mgr.StoreMgr->invalidateRegions(getStore(), Values, E, Count, LCtx, Call,
2020b57cec5SDimitry Andric                                     *IS, *ITraits, &TopLevelInvalidated,
2030b57cec5SDimitry Andric                                     &Invalidated);
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric   ProgramStateRef newState = makeWithStore(newStore);
2060b57cec5SDimitry Andric 
2070b57cec5SDimitry Andric   if (CausedByPointerEscape) {
2080b57cec5SDimitry Andric     newState = Eng.notifyCheckersOfPointerEscape(newState, IS,
2090b57cec5SDimitry Andric                                                  TopLevelInvalidated,
2100b57cec5SDimitry Andric                                                  Call,
2110b57cec5SDimitry Andric                                                  *ITraits);
2120b57cec5SDimitry Andric   }
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   return Eng.processRegionChanges(newState, IS, TopLevelInvalidated,
2150b57cec5SDimitry Andric                                   Invalidated, LCtx, Call);
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric 
killBinding(Loc LV) const2180b57cec5SDimitry Andric ProgramStateRef ProgramState::killBinding(Loc LV) const {
2190b57cec5SDimitry Andric   Store OldStore = getStore();
2200b57cec5SDimitry Andric   const StoreRef &newStore =
2210b57cec5SDimitry Andric     getStateManager().StoreMgr->killBinding(OldStore, LV);
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric   if (newStore.getStore() == OldStore)
2240b57cec5SDimitry Andric     return this;
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   return makeWithStore(newStore);
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric ProgramStateRef
enterStackFrame(const CallEvent & Call,const StackFrameContext * CalleeCtx) const2300b57cec5SDimitry Andric ProgramState::enterStackFrame(const CallEvent &Call,
2310b57cec5SDimitry Andric                               const StackFrameContext *CalleeCtx) const {
2320b57cec5SDimitry Andric   const StoreRef &NewStore =
2330b57cec5SDimitry Andric     getStateManager().StoreMgr->enterStackFrame(getStore(), Call, CalleeCtx);
2340b57cec5SDimitry Andric   return makeWithStore(NewStore);
2350b57cec5SDimitry Andric }
2360b57cec5SDimitry Andric 
getSelfSVal(const LocationContext * LCtx) const2375ffd83dbSDimitry Andric SVal ProgramState::getSelfSVal(const LocationContext *LCtx) const {
2385ffd83dbSDimitry Andric   const ImplicitParamDecl *SelfDecl = LCtx->getSelfDecl();
2395ffd83dbSDimitry Andric   if (!SelfDecl)
2405ffd83dbSDimitry Andric     return SVal();
2415ffd83dbSDimitry Andric   return getSVal(getRegion(SelfDecl, LCtx));
2425ffd83dbSDimitry Andric }
2435ffd83dbSDimitry Andric 
getSValAsScalarOrLoc(const MemRegion * R) const2440b57cec5SDimitry Andric SVal ProgramState::getSValAsScalarOrLoc(const MemRegion *R) const {
2450b57cec5SDimitry Andric   // We only want to do fetches from regions that we can actually bind
2460b57cec5SDimitry Andric   // values.  For example, SymbolicRegions of type 'id<...>' cannot
2470b57cec5SDimitry Andric   // have direct bindings (but their can be bindings on their subregions).
2480b57cec5SDimitry Andric   if (!R->isBoundable())
2490b57cec5SDimitry Andric     return UnknownVal();
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric   if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
2520b57cec5SDimitry Andric     QualType T = TR->getValueType();
2530b57cec5SDimitry Andric     if (Loc::isLocType(T) || T->isIntegralOrEnumerationType())
2540b57cec5SDimitry Andric       return getSVal(R);
2550b57cec5SDimitry Andric   }
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric   return UnknownVal();
2580b57cec5SDimitry Andric }
2590b57cec5SDimitry Andric 
getSVal(Loc location,QualType T) const2600b57cec5SDimitry Andric SVal ProgramState::getSVal(Loc location, QualType T) const {
2610b57cec5SDimitry Andric   SVal V = getRawSVal(location, T);
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric   // If 'V' is a symbolic value that is *perfectly* constrained to
2640b57cec5SDimitry Andric   // be a constant value, use that value instead to lessen the burden
2650b57cec5SDimitry Andric   // on later analysis stages (so we have less symbolic values to reason
2660b57cec5SDimitry Andric   // about).
2670b57cec5SDimitry Andric   // We only go into this branch if we can convert the APSInt value we have
2680b57cec5SDimitry Andric   // to the type of T, which is not always the case (e.g. for void).
2690b57cec5SDimitry Andric   if (!T.isNull() && (T->isIntegralOrEnumerationType() || Loc::isLocType(T))) {
2700b57cec5SDimitry Andric     if (SymbolRef sym = V.getAsSymbol()) {
2710b57cec5SDimitry Andric       if (const llvm::APSInt *Int = getStateManager()
2720b57cec5SDimitry Andric                                     .getConstraintManager()
2730b57cec5SDimitry Andric                                     .getSymVal(this, sym)) {
2740b57cec5SDimitry Andric         // FIXME: Because we don't correctly model (yet) sign-extension
2750b57cec5SDimitry Andric         // and truncation of symbolic values, we need to convert
2760b57cec5SDimitry Andric         // the integer value to the correct signedness and bitwidth.
2770b57cec5SDimitry Andric         //
2780b57cec5SDimitry Andric         // This shows up in the following:
2790b57cec5SDimitry Andric         //
2800b57cec5SDimitry Andric         //   char foo();
2810b57cec5SDimitry Andric         //   unsigned x = foo();
2820b57cec5SDimitry Andric         //   if (x == 54)
2830b57cec5SDimitry Andric         //     ...
2840b57cec5SDimitry Andric         //
2850b57cec5SDimitry Andric         //  The symbolic value stored to 'x' is actually the conjured
2860b57cec5SDimitry Andric         //  symbol for the call to foo(); the type of that symbol is 'char',
2870b57cec5SDimitry Andric         //  not unsigned.
2880b57cec5SDimitry Andric         const llvm::APSInt &NewV = getBasicVals().Convert(T, *Int);
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric         if (V.getAs<Loc>())
2910b57cec5SDimitry Andric           return loc::ConcreteInt(NewV);
2920b57cec5SDimitry Andric         else
2930b57cec5SDimitry Andric           return nonloc::ConcreteInt(NewV);
2940b57cec5SDimitry Andric       }
2950b57cec5SDimitry Andric     }
2960b57cec5SDimitry Andric   }
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric   return V;
2990b57cec5SDimitry Andric }
3000b57cec5SDimitry Andric 
BindExpr(const Stmt * S,const LocationContext * LCtx,SVal V,bool Invalidate) const3010b57cec5SDimitry Andric ProgramStateRef ProgramState::BindExpr(const Stmt *S,
3020b57cec5SDimitry Andric                                            const LocationContext *LCtx,
3030b57cec5SDimitry Andric                                            SVal V, bool Invalidate) const{
3040b57cec5SDimitry Andric   Environment NewEnv =
3050b57cec5SDimitry Andric     getStateManager().EnvMgr.bindExpr(Env, EnvironmentEntry(S, LCtx), V,
3060b57cec5SDimitry Andric                                       Invalidate);
3070b57cec5SDimitry Andric   if (NewEnv == Env)
3080b57cec5SDimitry Andric     return this;
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric   ProgramState NewSt = *this;
3110b57cec5SDimitry Andric   NewSt.Env = NewEnv;
3120b57cec5SDimitry Andric   return getStateManager().getPersistentState(NewSt);
3130b57cec5SDimitry Andric }
3140b57cec5SDimitry Andric 
315bdd1243dSDimitry Andric [[nodiscard]] std::pair<ProgramStateRef, ProgramStateRef>
assumeInBoundDual(DefinedOrUnknownSVal Idx,DefinedOrUnknownSVal UpperBound,QualType indexTy) const31681ad6265SDimitry Andric ProgramState::assumeInBoundDual(DefinedOrUnknownSVal Idx,
3170b57cec5SDimitry Andric                                 DefinedOrUnknownSVal UpperBound,
3180b57cec5SDimitry Andric                                 QualType indexTy) const {
3190b57cec5SDimitry Andric   if (Idx.isUnknown() || UpperBound.isUnknown())
32081ad6265SDimitry Andric     return {this, this};
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric   // Build an expression for 0 <= Idx < UpperBound.
3230b57cec5SDimitry Andric   // This is the same as Idx + MIN < UpperBound + MIN, if overflow is allowed.
3240b57cec5SDimitry Andric   // FIXME: This should probably be part of SValBuilder.
3250b57cec5SDimitry Andric   ProgramStateManager &SM = getStateManager();
3260b57cec5SDimitry Andric   SValBuilder &svalBuilder = SM.getSValBuilder();
3270b57cec5SDimitry Andric   ASTContext &Ctx = svalBuilder.getContext();
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric   // Get the offset: the minimum value of the array index type.
3300b57cec5SDimitry Andric   BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
3310b57cec5SDimitry Andric   if (indexTy.isNull())
3320b57cec5SDimitry Andric     indexTy = svalBuilder.getArrayIndexType();
3330b57cec5SDimitry Andric   nonloc::ConcreteInt Min(BVF.getMinValue(indexTy));
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric   // Adjust the index.
3360b57cec5SDimitry Andric   SVal newIdx = svalBuilder.evalBinOpNN(this, BO_Add,
3370b57cec5SDimitry Andric                                         Idx.castAs<NonLoc>(), Min, indexTy);
3380b57cec5SDimitry Andric   if (newIdx.isUnknownOrUndef())
33981ad6265SDimitry Andric     return {this, this};
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric   // Adjust the upper bound.
3420b57cec5SDimitry Andric   SVal newBound =
3430b57cec5SDimitry Andric     svalBuilder.evalBinOpNN(this, BO_Add, UpperBound.castAs<NonLoc>(),
3440b57cec5SDimitry Andric                             Min, indexTy);
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric   if (newBound.isUnknownOrUndef())
34781ad6265SDimitry Andric     return {this, this};
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   // Build the actual comparison.
3500b57cec5SDimitry Andric   SVal inBound = svalBuilder.evalBinOpNN(this, BO_LT, newIdx.castAs<NonLoc>(),
3510b57cec5SDimitry Andric                                          newBound.castAs<NonLoc>(), Ctx.IntTy);
3520b57cec5SDimitry Andric   if (inBound.isUnknownOrUndef())
35381ad6265SDimitry Andric     return {this, this};
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric   // Finally, let the constraint manager take care of it.
3560b57cec5SDimitry Andric   ConstraintManager &CM = SM.getConstraintManager();
35781ad6265SDimitry Andric   return CM.assumeDual(this, inBound.castAs<DefinedSVal>());
35881ad6265SDimitry Andric }
35981ad6265SDimitry Andric 
assumeInBound(DefinedOrUnknownSVal Idx,DefinedOrUnknownSVal UpperBound,bool Assumption,QualType indexTy) const36081ad6265SDimitry Andric ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx,
36181ad6265SDimitry Andric                                             DefinedOrUnknownSVal UpperBound,
36281ad6265SDimitry Andric                                             bool Assumption,
36381ad6265SDimitry Andric                                             QualType indexTy) const {
36481ad6265SDimitry Andric   std::pair<ProgramStateRef, ProgramStateRef> R =
36581ad6265SDimitry Andric       assumeInBoundDual(Idx, UpperBound, indexTy);
36681ad6265SDimitry Andric   return Assumption ? R.first : R.second;
3670b57cec5SDimitry Andric }
3680b57cec5SDimitry Andric 
isNonNull(SVal V) const3690b57cec5SDimitry Andric ConditionTruthVal ProgramState::isNonNull(SVal V) const {
3700b57cec5SDimitry Andric   ConditionTruthVal IsNull = isNull(V);
3710b57cec5SDimitry Andric   if (IsNull.isUnderconstrained())
3720b57cec5SDimitry Andric     return IsNull;
3730b57cec5SDimitry Andric   return ConditionTruthVal(!IsNull.getValue());
3740b57cec5SDimitry Andric }
3750b57cec5SDimitry Andric 
areEqual(SVal Lhs,SVal Rhs) const3760b57cec5SDimitry Andric ConditionTruthVal ProgramState::areEqual(SVal Lhs, SVal Rhs) const {
3770b57cec5SDimitry Andric   return stateMgr->getSValBuilder().areEqual(this, Lhs, Rhs);
3780b57cec5SDimitry Andric }
3790b57cec5SDimitry Andric 
isNull(SVal V) const3800b57cec5SDimitry Andric ConditionTruthVal ProgramState::isNull(SVal V) const {
3810b57cec5SDimitry Andric   if (V.isZeroConstant())
3820b57cec5SDimitry Andric     return true;
3830b57cec5SDimitry Andric 
3840b57cec5SDimitry Andric   if (V.isConstant())
3850b57cec5SDimitry Andric     return false;
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   SymbolRef Sym = V.getAsSymbol(/* IncludeBaseRegion */ true);
3880b57cec5SDimitry Andric   if (!Sym)
3890b57cec5SDimitry Andric     return ConditionTruthVal();
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric   return getStateManager().ConstraintMgr->isNull(this, Sym);
3920b57cec5SDimitry Andric }
3930b57cec5SDimitry Andric 
getInitialState(const LocationContext * InitLoc)3940b57cec5SDimitry Andric ProgramStateRef ProgramStateManager::getInitialState(const LocationContext *InitLoc) {
3950b57cec5SDimitry Andric   ProgramState State(this,
3960b57cec5SDimitry Andric                 EnvMgr.getInitialEnvironment(),
3970b57cec5SDimitry Andric                 StoreMgr->getInitialStore(InitLoc),
3980b57cec5SDimitry Andric                 GDMFactory.getEmptyMap());
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric   return getPersistentState(State);
4010b57cec5SDimitry Andric }
4020b57cec5SDimitry Andric 
getPersistentStateWithGDM(ProgramStateRef FromState,ProgramStateRef GDMState)4030b57cec5SDimitry Andric ProgramStateRef ProgramStateManager::getPersistentStateWithGDM(
4040b57cec5SDimitry Andric                                                      ProgramStateRef FromState,
4050b57cec5SDimitry Andric                                                      ProgramStateRef GDMState) {
4060b57cec5SDimitry Andric   ProgramState NewState(*FromState);
4070b57cec5SDimitry Andric   NewState.GDM = GDMState->GDM;
4080b57cec5SDimitry Andric   return getPersistentState(NewState);
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric 
getPersistentState(ProgramState & State)4110b57cec5SDimitry Andric ProgramStateRef ProgramStateManager::getPersistentState(ProgramState &State) {
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric   llvm::FoldingSetNodeID ID;
4140b57cec5SDimitry Andric   State.Profile(ID);
4150b57cec5SDimitry Andric   void *InsertPos;
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric   if (ProgramState *I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
4180b57cec5SDimitry Andric     return I;
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric   ProgramState *newState = nullptr;
4210b57cec5SDimitry Andric   if (!freeStates.empty()) {
4220b57cec5SDimitry Andric     newState = freeStates.back();
4230b57cec5SDimitry Andric     freeStates.pop_back();
4240b57cec5SDimitry Andric   }
4250b57cec5SDimitry Andric   else {
426*fe013be4SDimitry Andric     newState = Alloc.Allocate<ProgramState>();
4270b57cec5SDimitry Andric   }
4280b57cec5SDimitry Andric   new (newState) ProgramState(State);
4290b57cec5SDimitry Andric   StateSet.InsertNode(newState, InsertPos);
4300b57cec5SDimitry Andric   return newState;
4310b57cec5SDimitry Andric }
4320b57cec5SDimitry Andric 
makeWithStore(const StoreRef & store) const4330b57cec5SDimitry Andric ProgramStateRef ProgramState::makeWithStore(const StoreRef &store) const {
4340b57cec5SDimitry Andric   ProgramState NewSt(*this);
4350b57cec5SDimitry Andric   NewSt.setStore(store);
4360b57cec5SDimitry Andric   return getStateManager().getPersistentState(NewSt);
4370b57cec5SDimitry Andric }
4380b57cec5SDimitry Andric 
cloneAsPosteriorlyOverconstrained() const43981ad6265SDimitry Andric ProgramStateRef ProgramState::cloneAsPosteriorlyOverconstrained() const {
44081ad6265SDimitry Andric   ProgramState NewSt(*this);
44181ad6265SDimitry Andric   NewSt.PosteriorlyOverconstrained = true;
44281ad6265SDimitry Andric   return getStateManager().getPersistentState(NewSt);
44381ad6265SDimitry Andric }
44481ad6265SDimitry Andric 
setStore(const StoreRef & newStore)4450b57cec5SDimitry Andric void ProgramState::setStore(const StoreRef &newStore) {
4460b57cec5SDimitry Andric   Store newStoreStore = newStore.getStore();
4470b57cec5SDimitry Andric   if (newStoreStore)
4480b57cec5SDimitry Andric     stateMgr->getStoreManager().incrementReferenceCount(newStoreStore);
4490b57cec5SDimitry Andric   if (store)
4500b57cec5SDimitry Andric     stateMgr->getStoreManager().decrementReferenceCount(store);
4510b57cec5SDimitry Andric   store = newStoreStore;
4520b57cec5SDimitry Andric }
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4550b57cec5SDimitry Andric //  State pretty-printing.
4560b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4570b57cec5SDimitry Andric 
printJson(raw_ostream & Out,const LocationContext * LCtx,const char * NL,unsigned int Space,bool IsDot) const4580b57cec5SDimitry Andric void ProgramState::printJson(raw_ostream &Out, const LocationContext *LCtx,
4590b57cec5SDimitry Andric                              const char *NL, unsigned int Space,
4600b57cec5SDimitry Andric                              bool IsDot) const {
4610b57cec5SDimitry Andric   Indent(Out, Space, IsDot) << "\"program_state\": {" << NL;
4620b57cec5SDimitry Andric   ++Space;
4630b57cec5SDimitry Andric 
4640b57cec5SDimitry Andric   ProgramStateManager &Mgr = getStateManager();
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric   // Print the store.
4670b57cec5SDimitry Andric   Mgr.getStoreManager().printJson(Out, getStore(), NL, Space, IsDot);
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric   // Print out the environment.
4700b57cec5SDimitry Andric   Env.printJson(Out, Mgr.getContext(), LCtx, NL, Space, IsDot);
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric   // Print out the constraints.
4730b57cec5SDimitry Andric   Mgr.getConstraintManager().printJson(Out, this, NL, Space, IsDot);
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric   // Print out the tracked dynamic types.
4760b57cec5SDimitry Andric   printDynamicTypeInfoJson(Out, this, NL, Space, IsDot);
4770b57cec5SDimitry Andric 
4780b57cec5SDimitry Andric   // Print checker-specific data.
4790b57cec5SDimitry Andric   Mgr.getOwningEngine().printJson(Out, this, LCtx, NL, Space, IsDot);
4800b57cec5SDimitry Andric 
4810b57cec5SDimitry Andric   --Space;
4820b57cec5SDimitry Andric   Indent(Out, Space, IsDot) << '}';
4830b57cec5SDimitry Andric }
4840b57cec5SDimitry Andric 
printDOT(raw_ostream & Out,const LocationContext * LCtx,unsigned int Space) const4850b57cec5SDimitry Andric void ProgramState::printDOT(raw_ostream &Out, const LocationContext *LCtx,
4860b57cec5SDimitry Andric                             unsigned int Space) const {
4870b57cec5SDimitry Andric   printJson(Out, LCtx, /*NL=*/"\\l", Space, /*IsDot=*/true);
4880b57cec5SDimitry Andric }
4890b57cec5SDimitry Andric 
dump() const4900b57cec5SDimitry Andric LLVM_DUMP_METHOD void ProgramState::dump() const {
4910b57cec5SDimitry Andric   printJson(llvm::errs());
4920b57cec5SDimitry Andric }
4930b57cec5SDimitry Andric 
getAnalysisManager() const4940b57cec5SDimitry Andric AnalysisManager& ProgramState::getAnalysisManager() const {
4950b57cec5SDimitry Andric   return stateMgr->getOwningEngine().getAnalysisManager();
4960b57cec5SDimitry Andric }
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4990b57cec5SDimitry Andric // Generic Data Map.
5000b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
5010b57cec5SDimitry Andric 
FindGDM(void * K) const5020b57cec5SDimitry Andric void *const* ProgramState::FindGDM(void *K) const {
5030b57cec5SDimitry Andric   return GDM.lookup(K);
5040b57cec5SDimitry Andric }
5050b57cec5SDimitry Andric 
5060b57cec5SDimitry Andric void*
FindGDMContext(void * K,void * (* CreateContext)(llvm::BumpPtrAllocator &),void (* DeleteContext)(void *))5070b57cec5SDimitry Andric ProgramStateManager::FindGDMContext(void *K,
5080b57cec5SDimitry Andric                                void *(*CreateContext)(llvm::BumpPtrAllocator&),
5090b57cec5SDimitry Andric                                void (*DeleteContext)(void*)) {
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric   std::pair<void*, void (*)(void*)>& p = GDMContexts[K];
5120b57cec5SDimitry Andric   if (!p.first) {
5130b57cec5SDimitry Andric     p.first = CreateContext(Alloc);
5140b57cec5SDimitry Andric     p.second = DeleteContext;
5150b57cec5SDimitry Andric   }
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric   return p.first;
5180b57cec5SDimitry Andric }
5190b57cec5SDimitry Andric 
addGDM(ProgramStateRef St,void * Key,void * Data)5200b57cec5SDimitry Andric ProgramStateRef ProgramStateManager::addGDM(ProgramStateRef St, void *Key, void *Data){
5210b57cec5SDimitry Andric   ProgramState::GenericDataMap M1 = St->getGDM();
5220b57cec5SDimitry Andric   ProgramState::GenericDataMap M2 = GDMFactory.add(M1, Key, Data);
5230b57cec5SDimitry Andric 
5240b57cec5SDimitry Andric   if (M1 == M2)
5250b57cec5SDimitry Andric     return St;
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric   ProgramState NewSt = *St;
5280b57cec5SDimitry Andric   NewSt.GDM = M2;
5290b57cec5SDimitry Andric   return getPersistentState(NewSt);
5300b57cec5SDimitry Andric }
5310b57cec5SDimitry Andric 
removeGDM(ProgramStateRef state,void * Key)5320b57cec5SDimitry Andric ProgramStateRef ProgramStateManager::removeGDM(ProgramStateRef state, void *Key) {
5330b57cec5SDimitry Andric   ProgramState::GenericDataMap OldM = state->getGDM();
5340b57cec5SDimitry Andric   ProgramState::GenericDataMap NewM = GDMFactory.remove(OldM, Key);
5350b57cec5SDimitry Andric 
5360b57cec5SDimitry Andric   if (NewM == OldM)
5370b57cec5SDimitry Andric     return state;
5380b57cec5SDimitry Andric 
5390b57cec5SDimitry Andric   ProgramState NewState = *state;
5400b57cec5SDimitry Andric   NewState.GDM = NewM;
5410b57cec5SDimitry Andric   return getPersistentState(NewState);
5420b57cec5SDimitry Andric }
5430b57cec5SDimitry Andric 
scan(nonloc::LazyCompoundVal val)5440b57cec5SDimitry Andric bool ScanReachableSymbols::scan(nonloc::LazyCompoundVal val) {
5450b57cec5SDimitry Andric   bool wasVisited = !visited.insert(val.getCVData()).second;
5460b57cec5SDimitry Andric   if (wasVisited)
5470b57cec5SDimitry Andric     return true;
5480b57cec5SDimitry Andric 
5490b57cec5SDimitry Andric   StoreManager &StoreMgr = state->getStateManager().getStoreManager();
5500b57cec5SDimitry Andric   // FIXME: We don't really want to use getBaseRegion() here because pointer
5510b57cec5SDimitry Andric   // arithmetic doesn't apply, but scanReachableSymbols only accepts base
5520b57cec5SDimitry Andric   // regions right now.
5530b57cec5SDimitry Andric   const MemRegion *R = val.getRegion()->getBaseRegion();
5540b57cec5SDimitry Andric   return StoreMgr.scanReachableSymbols(val.getStore(), R, *this);
5550b57cec5SDimitry Andric }
5560b57cec5SDimitry Andric 
scan(nonloc::CompoundVal val)5570b57cec5SDimitry Andric bool ScanReachableSymbols::scan(nonloc::CompoundVal val) {
558*fe013be4SDimitry Andric   for (SVal V : val)
559*fe013be4SDimitry Andric     if (!scan(V))
5600b57cec5SDimitry Andric       return false;
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric   return true;
5630b57cec5SDimitry Andric }
5640b57cec5SDimitry Andric 
scan(const SymExpr * sym)5650b57cec5SDimitry Andric bool ScanReachableSymbols::scan(const SymExpr *sym) {
566*fe013be4SDimitry Andric   for (SymbolRef SubSym : sym->symbols()) {
567*fe013be4SDimitry Andric     bool wasVisited = !visited.insert(SubSym).second;
5680b57cec5SDimitry Andric     if (wasVisited)
5690b57cec5SDimitry Andric       continue;
5700b57cec5SDimitry Andric 
571*fe013be4SDimitry Andric     if (!visitor.VisitSymbol(SubSym))
5720b57cec5SDimitry Andric       return false;
5730b57cec5SDimitry Andric   }
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric   return true;
5760b57cec5SDimitry Andric }
5770b57cec5SDimitry Andric 
scan(SVal val)5780b57cec5SDimitry Andric bool ScanReachableSymbols::scan(SVal val) {
579bdd1243dSDimitry Andric   if (std::optional<loc::MemRegionVal> X = val.getAs<loc::MemRegionVal>())
5800b57cec5SDimitry Andric     return scan(X->getRegion());
5810b57cec5SDimitry Andric 
582bdd1243dSDimitry Andric   if (std::optional<nonloc::LazyCompoundVal> X =
5830b57cec5SDimitry Andric           val.getAs<nonloc::LazyCompoundVal>())
5840b57cec5SDimitry Andric     return scan(*X);
5850b57cec5SDimitry Andric 
586bdd1243dSDimitry Andric   if (std::optional<nonloc::LocAsInteger> X = val.getAs<nonloc::LocAsInteger>())
5870b57cec5SDimitry Andric     return scan(X->getLoc());
5880b57cec5SDimitry Andric 
5890b57cec5SDimitry Andric   if (SymbolRef Sym = val.getAsSymbol())
5900b57cec5SDimitry Andric     return scan(Sym);
5910b57cec5SDimitry Andric 
592bdd1243dSDimitry Andric   if (std::optional<nonloc::CompoundVal> X = val.getAs<nonloc::CompoundVal>())
5930b57cec5SDimitry Andric     return scan(*X);
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   return true;
5960b57cec5SDimitry Andric }
5970b57cec5SDimitry Andric 
scan(const MemRegion * R)5980b57cec5SDimitry Andric bool ScanReachableSymbols::scan(const MemRegion *R) {
5990b57cec5SDimitry Andric   if (isa<MemSpaceRegion>(R))
6000b57cec5SDimitry Andric     return true;
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric   bool wasVisited = !visited.insert(R).second;
6030b57cec5SDimitry Andric   if (wasVisited)
6040b57cec5SDimitry Andric     return true;
6050b57cec5SDimitry Andric 
6060b57cec5SDimitry Andric   if (!visitor.VisitMemRegion(R))
6070b57cec5SDimitry Andric     return false;
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric   // If this is a symbolic region, visit the symbol for the region.
6100b57cec5SDimitry Andric   if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
6110b57cec5SDimitry Andric     if (!visitor.VisitSymbol(SR->getSymbol()))
6120b57cec5SDimitry Andric       return false;
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric   // If this is a subregion, also visit the parent regions.
6150b57cec5SDimitry Andric   if (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
6160b57cec5SDimitry Andric     const MemRegion *Super = SR->getSuperRegion();
6170b57cec5SDimitry Andric     if (!scan(Super))
6180b57cec5SDimitry Andric       return false;
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric     // When we reach the topmost region, scan all symbols in it.
6210b57cec5SDimitry Andric     if (isa<MemSpaceRegion>(Super)) {
6220b57cec5SDimitry Andric       StoreManager &StoreMgr = state->getStateManager().getStoreManager();
6230b57cec5SDimitry Andric       if (!StoreMgr.scanReachableSymbols(state->getStore(), SR, *this))
6240b57cec5SDimitry Andric         return false;
6250b57cec5SDimitry Andric     }
6260b57cec5SDimitry Andric   }
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric   // Regions captured by a block are also implicitly reachable.
6290b57cec5SDimitry Andric   if (const BlockDataRegion *BDR = dyn_cast<BlockDataRegion>(R)) {
630*fe013be4SDimitry Andric     for (auto Var : BDR->referenced_vars()) {
631*fe013be4SDimitry Andric       if (!scan(Var.getCapturedRegion()))
6320b57cec5SDimitry Andric         return false;
6330b57cec5SDimitry Andric     }
6340b57cec5SDimitry Andric   }
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric   return true;
6370b57cec5SDimitry Andric }
6380b57cec5SDimitry Andric 
scanReachableSymbols(SVal val,SymbolVisitor & visitor) const6390b57cec5SDimitry Andric bool ProgramState::scanReachableSymbols(SVal val, SymbolVisitor& visitor) const {
6400b57cec5SDimitry Andric   ScanReachableSymbols S(this, visitor);
6410b57cec5SDimitry Andric   return S.scan(val);
6420b57cec5SDimitry Andric }
6430b57cec5SDimitry Andric 
scanReachableSymbols(llvm::iterator_range<region_iterator> Reachable,SymbolVisitor & visitor) const6440b57cec5SDimitry Andric bool ProgramState::scanReachableSymbols(
6450b57cec5SDimitry Andric     llvm::iterator_range<region_iterator> Reachable,
6460b57cec5SDimitry Andric     SymbolVisitor &visitor) const {
6470b57cec5SDimitry Andric   ScanReachableSymbols S(this, visitor);
6480b57cec5SDimitry Andric   for (const MemRegion *R : Reachable) {
6490b57cec5SDimitry Andric     if (!S.scan(R))
6500b57cec5SDimitry Andric       return false;
6510b57cec5SDimitry Andric   }
6520b57cec5SDimitry Andric   return true;
6530b57cec5SDimitry Andric }
654