xref: /freebsd-src/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/ProgramState.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
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.
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 
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 
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 
630b57cec5SDimitry Andric ProgramState::~ProgramState() {
640b57cec5SDimitry Andric   if (store)
650b57cec5SDimitry Andric     stateMgr->getStoreManager().decrementReferenceCount(store);
660b57cec5SDimitry Andric }
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric int64_t ProgramState::getID() const {
690b57cec5SDimitry Andric   return getStateManager().Alloc.identifyKnownAlignedObject<ProgramState>(this);
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric 
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 
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 
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 
1140b57cec5SDimitry 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
1290b57cec5SDimitry 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
1390b57cec5SDimitry 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
1510b57cec5SDimitry 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;
15906c3fb27SDimitry Andric   for (const MemRegion *Reg : Regions)
16006c3fb27SDimitry 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
1670b57cec5SDimitry 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
1800b57cec5SDimitry 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 
2180b57cec5SDimitry 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 
229*0fca6ea1SDimitry Andric /// SymbolicRegions are expected to be wrapped by an ElementRegion as a
230*0fca6ea1SDimitry Andric /// canonical representation. As a canonical representation, SymbolicRegions
231*0fca6ea1SDimitry Andric /// should be wrapped by ElementRegions before getting a FieldRegion.
232*0fca6ea1SDimitry Andric /// See f8643a9b31c4029942f67d4534c9139b45173504 why.
233*0fca6ea1SDimitry Andric SVal ProgramState::wrapSymbolicRegion(SVal Val) const {
234*0fca6ea1SDimitry Andric   const auto *BaseReg = dyn_cast_or_null<SymbolicRegion>(Val.getAsRegion());
235*0fca6ea1SDimitry Andric   if (!BaseReg)
236*0fca6ea1SDimitry Andric     return Val;
237*0fca6ea1SDimitry Andric 
238*0fca6ea1SDimitry Andric   StoreManager &SM = getStateManager().getStoreManager();
239*0fca6ea1SDimitry Andric   QualType ElemTy = BaseReg->getPointeeStaticType();
240*0fca6ea1SDimitry Andric   return loc::MemRegionVal{SM.GetElementZeroRegion(BaseReg, ElemTy)};
241*0fca6ea1SDimitry Andric }
242*0fca6ea1SDimitry Andric 
2430b57cec5SDimitry Andric ProgramStateRef
2440b57cec5SDimitry Andric ProgramState::enterStackFrame(const CallEvent &Call,
2450b57cec5SDimitry Andric                               const StackFrameContext *CalleeCtx) const {
2460b57cec5SDimitry Andric   const StoreRef &NewStore =
2470b57cec5SDimitry Andric     getStateManager().StoreMgr->enterStackFrame(getStore(), Call, CalleeCtx);
2480b57cec5SDimitry Andric   return makeWithStore(NewStore);
2490b57cec5SDimitry Andric }
2500b57cec5SDimitry Andric 
2515ffd83dbSDimitry Andric SVal ProgramState::getSelfSVal(const LocationContext *LCtx) const {
2525ffd83dbSDimitry Andric   const ImplicitParamDecl *SelfDecl = LCtx->getSelfDecl();
2535ffd83dbSDimitry Andric   if (!SelfDecl)
2545ffd83dbSDimitry Andric     return SVal();
2555ffd83dbSDimitry Andric   return getSVal(getRegion(SelfDecl, LCtx));
2565ffd83dbSDimitry Andric }
2575ffd83dbSDimitry Andric 
2580b57cec5SDimitry Andric SVal ProgramState::getSValAsScalarOrLoc(const MemRegion *R) const {
2590b57cec5SDimitry Andric   // We only want to do fetches from regions that we can actually bind
2600b57cec5SDimitry Andric   // values.  For example, SymbolicRegions of type 'id<...>' cannot
2610b57cec5SDimitry Andric   // have direct bindings (but their can be bindings on their subregions).
2620b57cec5SDimitry Andric   if (!R->isBoundable())
2630b57cec5SDimitry Andric     return UnknownVal();
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric   if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) {
2660b57cec5SDimitry Andric     QualType T = TR->getValueType();
2670b57cec5SDimitry Andric     if (Loc::isLocType(T) || T->isIntegralOrEnumerationType())
2680b57cec5SDimitry Andric       return getSVal(R);
2690b57cec5SDimitry Andric   }
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric   return UnknownVal();
2720b57cec5SDimitry Andric }
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric SVal ProgramState::getSVal(Loc location, QualType T) const {
2750b57cec5SDimitry Andric   SVal V = getRawSVal(location, T);
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric   // If 'V' is a symbolic value that is *perfectly* constrained to
2780b57cec5SDimitry Andric   // be a constant value, use that value instead to lessen the burden
2790b57cec5SDimitry Andric   // on later analysis stages (so we have less symbolic values to reason
2800b57cec5SDimitry Andric   // about).
2810b57cec5SDimitry Andric   // We only go into this branch if we can convert the APSInt value we have
2820b57cec5SDimitry Andric   // to the type of T, which is not always the case (e.g. for void).
2830b57cec5SDimitry Andric   if (!T.isNull() && (T->isIntegralOrEnumerationType() || Loc::isLocType(T))) {
2840b57cec5SDimitry Andric     if (SymbolRef sym = V.getAsSymbol()) {
2850b57cec5SDimitry Andric       if (const llvm::APSInt *Int = getStateManager()
2860b57cec5SDimitry Andric                                     .getConstraintManager()
2870b57cec5SDimitry Andric                                     .getSymVal(this, sym)) {
2880b57cec5SDimitry Andric         // FIXME: Because we don't correctly model (yet) sign-extension
2890b57cec5SDimitry Andric         // and truncation of symbolic values, we need to convert
2900b57cec5SDimitry Andric         // the integer value to the correct signedness and bitwidth.
2910b57cec5SDimitry Andric         //
2920b57cec5SDimitry Andric         // This shows up in the following:
2930b57cec5SDimitry Andric         //
2940b57cec5SDimitry Andric         //   char foo();
2950b57cec5SDimitry Andric         //   unsigned x = foo();
2960b57cec5SDimitry Andric         //   if (x == 54)
2970b57cec5SDimitry Andric         //     ...
2980b57cec5SDimitry Andric         //
2990b57cec5SDimitry Andric         //  The symbolic value stored to 'x' is actually the conjured
3000b57cec5SDimitry Andric         //  symbol for the call to foo(); the type of that symbol is 'char',
3010b57cec5SDimitry Andric         //  not unsigned.
3020b57cec5SDimitry Andric         const llvm::APSInt &NewV = getBasicVals().Convert(T, *Int);
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric         if (V.getAs<Loc>())
3050b57cec5SDimitry Andric           return loc::ConcreteInt(NewV);
3060b57cec5SDimitry Andric         else
3070b57cec5SDimitry Andric           return nonloc::ConcreteInt(NewV);
3080b57cec5SDimitry Andric       }
3090b57cec5SDimitry Andric     }
3100b57cec5SDimitry Andric   }
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric   return V;
3130b57cec5SDimitry Andric }
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric ProgramStateRef ProgramState::BindExpr(const Stmt *S,
3160b57cec5SDimitry Andric                                            const LocationContext *LCtx,
3170b57cec5SDimitry Andric                                            SVal V, bool Invalidate) const{
3180b57cec5SDimitry Andric   Environment NewEnv =
3190b57cec5SDimitry Andric     getStateManager().EnvMgr.bindExpr(Env, EnvironmentEntry(S, LCtx), V,
3200b57cec5SDimitry Andric                                       Invalidate);
3210b57cec5SDimitry Andric   if (NewEnv == Env)
3220b57cec5SDimitry Andric     return this;
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   ProgramState NewSt = *this;
3250b57cec5SDimitry Andric   NewSt.Env = NewEnv;
3260b57cec5SDimitry Andric   return getStateManager().getPersistentState(NewSt);
3270b57cec5SDimitry Andric }
3280b57cec5SDimitry Andric 
329bdd1243dSDimitry Andric [[nodiscard]] std::pair<ProgramStateRef, ProgramStateRef>
33081ad6265SDimitry Andric ProgramState::assumeInBoundDual(DefinedOrUnknownSVal Idx,
3310b57cec5SDimitry Andric                                 DefinedOrUnknownSVal UpperBound,
3320b57cec5SDimitry Andric                                 QualType indexTy) const {
3330b57cec5SDimitry Andric   if (Idx.isUnknown() || UpperBound.isUnknown())
33481ad6265SDimitry Andric     return {this, this};
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric   // Build an expression for 0 <= Idx < UpperBound.
3370b57cec5SDimitry Andric   // This is the same as Idx + MIN < UpperBound + MIN, if overflow is allowed.
3380b57cec5SDimitry Andric   // FIXME: This should probably be part of SValBuilder.
3390b57cec5SDimitry Andric   ProgramStateManager &SM = getStateManager();
3400b57cec5SDimitry Andric   SValBuilder &svalBuilder = SM.getSValBuilder();
3410b57cec5SDimitry Andric   ASTContext &Ctx = svalBuilder.getContext();
3420b57cec5SDimitry Andric 
3430b57cec5SDimitry Andric   // Get the offset: the minimum value of the array index type.
3440b57cec5SDimitry Andric   BasicValueFactory &BVF = svalBuilder.getBasicValueFactory();
3450b57cec5SDimitry Andric   if (indexTy.isNull())
3460b57cec5SDimitry Andric     indexTy = svalBuilder.getArrayIndexType();
3470b57cec5SDimitry Andric   nonloc::ConcreteInt Min(BVF.getMinValue(indexTy));
3480b57cec5SDimitry Andric 
3490b57cec5SDimitry Andric   // Adjust the index.
3500b57cec5SDimitry Andric   SVal newIdx = svalBuilder.evalBinOpNN(this, BO_Add,
3510b57cec5SDimitry Andric                                         Idx.castAs<NonLoc>(), Min, indexTy);
3520b57cec5SDimitry Andric   if (newIdx.isUnknownOrUndef())
35381ad6265SDimitry Andric     return {this, this};
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric   // Adjust the upper bound.
3560b57cec5SDimitry Andric   SVal newBound =
3570b57cec5SDimitry Andric     svalBuilder.evalBinOpNN(this, BO_Add, UpperBound.castAs<NonLoc>(),
3580b57cec5SDimitry Andric                             Min, indexTy);
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric   if (newBound.isUnknownOrUndef())
36181ad6265SDimitry Andric     return {this, this};
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric   // Build the actual comparison.
3640b57cec5SDimitry Andric   SVal inBound = svalBuilder.evalBinOpNN(this, BO_LT, newIdx.castAs<NonLoc>(),
3650b57cec5SDimitry Andric                                          newBound.castAs<NonLoc>(), Ctx.IntTy);
3660b57cec5SDimitry Andric   if (inBound.isUnknownOrUndef())
36781ad6265SDimitry Andric     return {this, this};
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric   // Finally, let the constraint manager take care of it.
3700b57cec5SDimitry Andric   ConstraintManager &CM = SM.getConstraintManager();
37181ad6265SDimitry Andric   return CM.assumeDual(this, inBound.castAs<DefinedSVal>());
37281ad6265SDimitry Andric }
37381ad6265SDimitry Andric 
37481ad6265SDimitry Andric ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx,
37581ad6265SDimitry Andric                                             DefinedOrUnknownSVal UpperBound,
37681ad6265SDimitry Andric                                             bool Assumption,
37781ad6265SDimitry Andric                                             QualType indexTy) const {
37881ad6265SDimitry Andric   std::pair<ProgramStateRef, ProgramStateRef> R =
37981ad6265SDimitry Andric       assumeInBoundDual(Idx, UpperBound, indexTy);
38081ad6265SDimitry Andric   return Assumption ? R.first : R.second;
3810b57cec5SDimitry Andric }
3820b57cec5SDimitry Andric 
3830b57cec5SDimitry Andric ConditionTruthVal ProgramState::isNonNull(SVal V) const {
3840b57cec5SDimitry Andric   ConditionTruthVal IsNull = isNull(V);
3850b57cec5SDimitry Andric   if (IsNull.isUnderconstrained())
3860b57cec5SDimitry Andric     return IsNull;
3870b57cec5SDimitry Andric   return ConditionTruthVal(!IsNull.getValue());
3880b57cec5SDimitry Andric }
3890b57cec5SDimitry Andric 
3900b57cec5SDimitry Andric ConditionTruthVal ProgramState::areEqual(SVal Lhs, SVal Rhs) const {
3910b57cec5SDimitry Andric   return stateMgr->getSValBuilder().areEqual(this, Lhs, Rhs);
3920b57cec5SDimitry Andric }
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric ConditionTruthVal ProgramState::isNull(SVal V) const {
3950b57cec5SDimitry Andric   if (V.isZeroConstant())
3960b57cec5SDimitry Andric     return true;
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   if (V.isConstant())
3990b57cec5SDimitry Andric     return false;
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric   SymbolRef Sym = V.getAsSymbol(/* IncludeBaseRegion */ true);
4020b57cec5SDimitry Andric   if (!Sym)
4030b57cec5SDimitry Andric     return ConditionTruthVal();
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric   return getStateManager().ConstraintMgr->isNull(this, Sym);
4060b57cec5SDimitry Andric }
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric ProgramStateRef ProgramStateManager::getInitialState(const LocationContext *InitLoc) {
4090b57cec5SDimitry Andric   ProgramState State(this,
4100b57cec5SDimitry Andric                 EnvMgr.getInitialEnvironment(),
4110b57cec5SDimitry Andric                 StoreMgr->getInitialStore(InitLoc),
4120b57cec5SDimitry Andric                 GDMFactory.getEmptyMap());
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric   return getPersistentState(State);
4150b57cec5SDimitry Andric }
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric ProgramStateRef ProgramStateManager::getPersistentStateWithGDM(
4180b57cec5SDimitry Andric                                                      ProgramStateRef FromState,
4190b57cec5SDimitry Andric                                                      ProgramStateRef GDMState) {
4200b57cec5SDimitry Andric   ProgramState NewState(*FromState);
4210b57cec5SDimitry Andric   NewState.GDM = GDMState->GDM;
4220b57cec5SDimitry Andric   return getPersistentState(NewState);
4230b57cec5SDimitry Andric }
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric ProgramStateRef ProgramStateManager::getPersistentState(ProgramState &State) {
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric   llvm::FoldingSetNodeID ID;
4280b57cec5SDimitry Andric   State.Profile(ID);
4290b57cec5SDimitry Andric   void *InsertPos;
4300b57cec5SDimitry Andric 
4310b57cec5SDimitry Andric   if (ProgramState *I = StateSet.FindNodeOrInsertPos(ID, InsertPos))
4320b57cec5SDimitry Andric     return I;
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric   ProgramState *newState = nullptr;
4350b57cec5SDimitry Andric   if (!freeStates.empty()) {
4360b57cec5SDimitry Andric     newState = freeStates.back();
4370b57cec5SDimitry Andric     freeStates.pop_back();
4380b57cec5SDimitry Andric   }
4390b57cec5SDimitry Andric   else {
44006c3fb27SDimitry Andric     newState = Alloc.Allocate<ProgramState>();
4410b57cec5SDimitry Andric   }
4420b57cec5SDimitry Andric   new (newState) ProgramState(State);
4430b57cec5SDimitry Andric   StateSet.InsertNode(newState, InsertPos);
4440b57cec5SDimitry Andric   return newState;
4450b57cec5SDimitry Andric }
4460b57cec5SDimitry Andric 
4470b57cec5SDimitry Andric ProgramStateRef ProgramState::makeWithStore(const StoreRef &store) const {
4480b57cec5SDimitry Andric   ProgramState NewSt(*this);
4490b57cec5SDimitry Andric   NewSt.setStore(store);
4500b57cec5SDimitry Andric   return getStateManager().getPersistentState(NewSt);
4510b57cec5SDimitry Andric }
4520b57cec5SDimitry Andric 
45381ad6265SDimitry Andric ProgramStateRef ProgramState::cloneAsPosteriorlyOverconstrained() const {
45481ad6265SDimitry Andric   ProgramState NewSt(*this);
45581ad6265SDimitry Andric   NewSt.PosteriorlyOverconstrained = true;
45681ad6265SDimitry Andric   return getStateManager().getPersistentState(NewSt);
45781ad6265SDimitry Andric }
45881ad6265SDimitry Andric 
4590b57cec5SDimitry Andric void ProgramState::setStore(const StoreRef &newStore) {
4600b57cec5SDimitry Andric   Store newStoreStore = newStore.getStore();
4610b57cec5SDimitry Andric   if (newStoreStore)
4620b57cec5SDimitry Andric     stateMgr->getStoreManager().incrementReferenceCount(newStoreStore);
4630b57cec5SDimitry Andric   if (store)
4640b57cec5SDimitry Andric     stateMgr->getStoreManager().decrementReferenceCount(store);
4650b57cec5SDimitry Andric   store = newStoreStore;
4660b57cec5SDimitry Andric }
4670b57cec5SDimitry Andric 
468*0fca6ea1SDimitry Andric SVal ProgramState::getLValue(const FieldDecl *D, SVal Base) const {
469*0fca6ea1SDimitry Andric   Base = wrapSymbolicRegion(Base);
470*0fca6ea1SDimitry Andric   return getStateManager().StoreMgr->getLValueField(D, Base);
471*0fca6ea1SDimitry Andric }
472*0fca6ea1SDimitry Andric 
473*0fca6ea1SDimitry Andric SVal ProgramState::getLValue(const IndirectFieldDecl *D, SVal Base) const {
474*0fca6ea1SDimitry Andric   StoreManager &SM = *getStateManager().StoreMgr;
475*0fca6ea1SDimitry Andric   Base = wrapSymbolicRegion(Base);
476*0fca6ea1SDimitry Andric 
477*0fca6ea1SDimitry Andric   // FIXME: This should work with `SM.getLValueField(D->getAnonField(), Base)`,
478*0fca6ea1SDimitry Andric   // but that would break some tests. There is probably a bug somewhere that it
479*0fca6ea1SDimitry Andric   // would expose.
480*0fca6ea1SDimitry Andric   for (const auto *I : D->chain()) {
481*0fca6ea1SDimitry Andric     Base = SM.getLValueField(cast<FieldDecl>(I), Base);
482*0fca6ea1SDimitry Andric   }
483*0fca6ea1SDimitry Andric   return Base;
484*0fca6ea1SDimitry Andric }
485*0fca6ea1SDimitry Andric 
4860b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4870b57cec5SDimitry Andric //  State pretty-printing.
4880b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric void ProgramState::printJson(raw_ostream &Out, const LocationContext *LCtx,
4910b57cec5SDimitry Andric                              const char *NL, unsigned int Space,
4920b57cec5SDimitry Andric                              bool IsDot) const {
4930b57cec5SDimitry Andric   Indent(Out, Space, IsDot) << "\"program_state\": {" << NL;
4940b57cec5SDimitry Andric   ++Space;
4950b57cec5SDimitry Andric 
4960b57cec5SDimitry Andric   ProgramStateManager &Mgr = getStateManager();
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric   // Print the store.
4990b57cec5SDimitry Andric   Mgr.getStoreManager().printJson(Out, getStore(), NL, Space, IsDot);
5000b57cec5SDimitry Andric 
5010b57cec5SDimitry Andric   // Print out the environment.
5020b57cec5SDimitry Andric   Env.printJson(Out, Mgr.getContext(), LCtx, NL, Space, IsDot);
5030b57cec5SDimitry Andric 
5040b57cec5SDimitry Andric   // Print out the constraints.
5050b57cec5SDimitry Andric   Mgr.getConstraintManager().printJson(Out, this, NL, Space, IsDot);
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric   // Print out the tracked dynamic types.
5080b57cec5SDimitry Andric   printDynamicTypeInfoJson(Out, this, NL, Space, IsDot);
5090b57cec5SDimitry Andric 
5100b57cec5SDimitry Andric   // Print checker-specific data.
5110b57cec5SDimitry Andric   Mgr.getOwningEngine().printJson(Out, this, LCtx, NL, Space, IsDot);
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric   --Space;
5140b57cec5SDimitry Andric   Indent(Out, Space, IsDot) << '}';
5150b57cec5SDimitry Andric }
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric void ProgramState::printDOT(raw_ostream &Out, const LocationContext *LCtx,
5180b57cec5SDimitry Andric                             unsigned int Space) const {
5190b57cec5SDimitry Andric   printJson(Out, LCtx, /*NL=*/"\\l", Space, /*IsDot=*/true);
5200b57cec5SDimitry Andric }
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric LLVM_DUMP_METHOD void ProgramState::dump() const {
5230b57cec5SDimitry Andric   printJson(llvm::errs());
5240b57cec5SDimitry Andric }
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric AnalysisManager& ProgramState::getAnalysisManager() const {
5270b57cec5SDimitry Andric   return stateMgr->getOwningEngine().getAnalysisManager();
5280b57cec5SDimitry Andric }
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
5310b57cec5SDimitry Andric // Generic Data Map.
5320b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
5330b57cec5SDimitry Andric 
5340b57cec5SDimitry Andric void *const* ProgramState::FindGDM(void *K) const {
5350b57cec5SDimitry Andric   return GDM.lookup(K);
5360b57cec5SDimitry Andric }
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric void*
5390b57cec5SDimitry Andric ProgramStateManager::FindGDMContext(void *K,
5400b57cec5SDimitry Andric                                void *(*CreateContext)(llvm::BumpPtrAllocator&),
5410b57cec5SDimitry Andric                                void (*DeleteContext)(void*)) {
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric   std::pair<void*, void (*)(void*)>& p = GDMContexts[K];
5440b57cec5SDimitry Andric   if (!p.first) {
5450b57cec5SDimitry Andric     p.first = CreateContext(Alloc);
5460b57cec5SDimitry Andric     p.second = DeleteContext;
5470b57cec5SDimitry Andric   }
5480b57cec5SDimitry Andric 
5490b57cec5SDimitry Andric   return p.first;
5500b57cec5SDimitry Andric }
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric ProgramStateRef ProgramStateManager::addGDM(ProgramStateRef St, void *Key, void *Data){
5530b57cec5SDimitry Andric   ProgramState::GenericDataMap M1 = St->getGDM();
5540b57cec5SDimitry Andric   ProgramState::GenericDataMap M2 = GDMFactory.add(M1, Key, Data);
5550b57cec5SDimitry Andric 
5560b57cec5SDimitry Andric   if (M1 == M2)
5570b57cec5SDimitry Andric     return St;
5580b57cec5SDimitry Andric 
5590b57cec5SDimitry Andric   ProgramState NewSt = *St;
5600b57cec5SDimitry Andric   NewSt.GDM = M2;
5610b57cec5SDimitry Andric   return getPersistentState(NewSt);
5620b57cec5SDimitry Andric }
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric ProgramStateRef ProgramStateManager::removeGDM(ProgramStateRef state, void *Key) {
5650b57cec5SDimitry Andric   ProgramState::GenericDataMap OldM = state->getGDM();
5660b57cec5SDimitry Andric   ProgramState::GenericDataMap NewM = GDMFactory.remove(OldM, Key);
5670b57cec5SDimitry Andric 
5680b57cec5SDimitry Andric   if (NewM == OldM)
5690b57cec5SDimitry Andric     return state;
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric   ProgramState NewState = *state;
5720b57cec5SDimitry Andric   NewState.GDM = NewM;
5730b57cec5SDimitry Andric   return getPersistentState(NewState);
5740b57cec5SDimitry Andric }
5750b57cec5SDimitry Andric 
5760b57cec5SDimitry Andric bool ScanReachableSymbols::scan(nonloc::LazyCompoundVal val) {
5770b57cec5SDimitry Andric   bool wasVisited = !visited.insert(val.getCVData()).second;
5780b57cec5SDimitry Andric   if (wasVisited)
5790b57cec5SDimitry Andric     return true;
5800b57cec5SDimitry Andric 
5810b57cec5SDimitry Andric   StoreManager &StoreMgr = state->getStateManager().getStoreManager();
5820b57cec5SDimitry Andric   // FIXME: We don't really want to use getBaseRegion() here because pointer
5830b57cec5SDimitry Andric   // arithmetic doesn't apply, but scanReachableSymbols only accepts base
5840b57cec5SDimitry Andric   // regions right now.
5850b57cec5SDimitry Andric   const MemRegion *R = val.getRegion()->getBaseRegion();
5860b57cec5SDimitry Andric   return StoreMgr.scanReachableSymbols(val.getStore(), R, *this);
5870b57cec5SDimitry Andric }
5880b57cec5SDimitry Andric 
5890b57cec5SDimitry Andric bool ScanReachableSymbols::scan(nonloc::CompoundVal val) {
59006c3fb27SDimitry Andric   for (SVal V : val)
59106c3fb27SDimitry Andric     if (!scan(V))
5920b57cec5SDimitry Andric       return false;
5930b57cec5SDimitry Andric 
5940b57cec5SDimitry Andric   return true;
5950b57cec5SDimitry Andric }
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric bool ScanReachableSymbols::scan(const SymExpr *sym) {
59806c3fb27SDimitry Andric   for (SymbolRef SubSym : sym->symbols()) {
59906c3fb27SDimitry Andric     bool wasVisited = !visited.insert(SubSym).second;
6000b57cec5SDimitry Andric     if (wasVisited)
6010b57cec5SDimitry Andric       continue;
6020b57cec5SDimitry Andric 
60306c3fb27SDimitry Andric     if (!visitor.VisitSymbol(SubSym))
6040b57cec5SDimitry Andric       return false;
6050b57cec5SDimitry Andric   }
6060b57cec5SDimitry Andric 
6070b57cec5SDimitry Andric   return true;
6080b57cec5SDimitry Andric }
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric bool ScanReachableSymbols::scan(SVal val) {
611bdd1243dSDimitry Andric   if (std::optional<loc::MemRegionVal> X = val.getAs<loc::MemRegionVal>())
6120b57cec5SDimitry Andric     return scan(X->getRegion());
6130b57cec5SDimitry Andric 
614bdd1243dSDimitry Andric   if (std::optional<nonloc::LazyCompoundVal> X =
6150b57cec5SDimitry Andric           val.getAs<nonloc::LazyCompoundVal>())
6160b57cec5SDimitry Andric     return scan(*X);
6170b57cec5SDimitry Andric 
618bdd1243dSDimitry Andric   if (std::optional<nonloc::LocAsInteger> X = val.getAs<nonloc::LocAsInteger>())
6190b57cec5SDimitry Andric     return scan(X->getLoc());
6200b57cec5SDimitry Andric 
6210b57cec5SDimitry Andric   if (SymbolRef Sym = val.getAsSymbol())
6220b57cec5SDimitry Andric     return scan(Sym);
6230b57cec5SDimitry Andric 
624bdd1243dSDimitry Andric   if (std::optional<nonloc::CompoundVal> X = val.getAs<nonloc::CompoundVal>())
6250b57cec5SDimitry Andric     return scan(*X);
6260b57cec5SDimitry Andric 
6270b57cec5SDimitry Andric   return true;
6280b57cec5SDimitry Andric }
6290b57cec5SDimitry Andric 
6300b57cec5SDimitry Andric bool ScanReachableSymbols::scan(const MemRegion *R) {
6310b57cec5SDimitry Andric   if (isa<MemSpaceRegion>(R))
6320b57cec5SDimitry Andric     return true;
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric   bool wasVisited = !visited.insert(R).second;
6350b57cec5SDimitry Andric   if (wasVisited)
6360b57cec5SDimitry Andric     return true;
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric   if (!visitor.VisitMemRegion(R))
6390b57cec5SDimitry Andric     return false;
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric   // If this is a symbolic region, visit the symbol for the region.
6420b57cec5SDimitry Andric   if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
6430b57cec5SDimitry Andric     if (!visitor.VisitSymbol(SR->getSymbol()))
6440b57cec5SDimitry Andric       return false;
6450b57cec5SDimitry Andric 
6460b57cec5SDimitry Andric   // If this is a subregion, also visit the parent regions.
6470b57cec5SDimitry Andric   if (const SubRegion *SR = dyn_cast<SubRegion>(R)) {
6480b57cec5SDimitry Andric     const MemRegion *Super = SR->getSuperRegion();
6490b57cec5SDimitry Andric     if (!scan(Super))
6500b57cec5SDimitry Andric       return false;
6510b57cec5SDimitry Andric 
6520b57cec5SDimitry Andric     // When we reach the topmost region, scan all symbols in it.
6530b57cec5SDimitry Andric     if (isa<MemSpaceRegion>(Super)) {
6540b57cec5SDimitry Andric       StoreManager &StoreMgr = state->getStateManager().getStoreManager();
6550b57cec5SDimitry Andric       if (!StoreMgr.scanReachableSymbols(state->getStore(), SR, *this))
6560b57cec5SDimitry Andric         return false;
6570b57cec5SDimitry Andric     }
6580b57cec5SDimitry Andric   }
6590b57cec5SDimitry Andric 
6600b57cec5SDimitry Andric   // Regions captured by a block are also implicitly reachable.
6610b57cec5SDimitry Andric   if (const BlockDataRegion *BDR = dyn_cast<BlockDataRegion>(R)) {
66206c3fb27SDimitry Andric     for (auto Var : BDR->referenced_vars()) {
66306c3fb27SDimitry Andric       if (!scan(Var.getCapturedRegion()))
6640b57cec5SDimitry Andric         return false;
6650b57cec5SDimitry Andric     }
6660b57cec5SDimitry Andric   }
6670b57cec5SDimitry Andric 
6680b57cec5SDimitry Andric   return true;
6690b57cec5SDimitry Andric }
6700b57cec5SDimitry Andric 
6710b57cec5SDimitry Andric bool ProgramState::scanReachableSymbols(SVal val, SymbolVisitor& visitor) const {
6720b57cec5SDimitry Andric   ScanReachableSymbols S(this, visitor);
6730b57cec5SDimitry Andric   return S.scan(val);
6740b57cec5SDimitry Andric }
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric bool ProgramState::scanReachableSymbols(
6770b57cec5SDimitry Andric     llvm::iterator_range<region_iterator> Reachable,
6780b57cec5SDimitry Andric     SymbolVisitor &visitor) const {
6790b57cec5SDimitry Andric   ScanReachableSymbols S(this, visitor);
6800b57cec5SDimitry Andric   for (const MemRegion *R : Reachable) {
6810b57cec5SDimitry Andric     if (!S.scan(R))
6820b57cec5SDimitry Andric       return false;
6830b57cec5SDimitry Andric   }
6840b57cec5SDimitry Andric   return true;
6850b57cec5SDimitry Andric }
686