clang API Documentation
00001 //= GRState.cpp - Path-Sensitive "State" for tracking values -----*- C++ -*--=// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements GRState and GRStateManager. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "clang/Analysis/CFG.h" 00015 #include "clang/StaticAnalyzer/Core/PathSensitive/GRStateTrait.h" 00016 #include "clang/StaticAnalyzer/Core/PathSensitive/GRState.h" 00017 #include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h" 00018 #include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h" 00019 #include "llvm/Support/raw_ostream.h" 00020 00021 using namespace clang; 00022 using namespace ento; 00023 00024 // Give the vtable for ConstraintManager somewhere to live. 00025 // FIXME: Move this elsewhere. 00026 ConstraintManager::~ConstraintManager() {} 00027 00028 GRState::GRState(GRStateManager *mgr, const Environment& env, 00029 StoreRef st, GenericDataMap gdm) 00030 : stateMgr(mgr), 00031 Env(env), 00032 store(st.getStore()), 00033 GDM(gdm), 00034 refCount(0) { 00035 stateMgr->getStoreManager().incrementReferenceCount(store); 00036 } 00037 00038 GRState::GRState(const GRState &RHS) 00039 : llvm::FoldingSetNode(), 00040 stateMgr(RHS.stateMgr), 00041 Env(RHS.Env), 00042 store(RHS.store), 00043 GDM(RHS.GDM), 00044 refCount(0) { 00045 stateMgr->getStoreManager().incrementReferenceCount(store); 00046 } 00047 00048 GRState::~GRState() { 00049 if (store) 00050 stateMgr->getStoreManager().decrementReferenceCount(store); 00051 } 00052 00053 GRStateManager::~GRStateManager() { 00054 for (std::vector<GRState::Printer*>::iterator I=Printers.begin(), 00055 E=Printers.end(); I!=E; ++I) 00056 delete *I; 00057 00058 for (GDMContextsTy::iterator I=GDMContexts.begin(), E=GDMContexts.end(); 00059 I!=E; ++I) 00060 I->second.second(I->second.first); 00061 } 00062 00063 const GRState* 00064 GRStateManager::removeDeadBindings(const GRState *state, 00065 const StackFrameContext *LCtx, 00066 SymbolReaper& SymReaper) { 00067 00068 // This code essentially performs a "mark-and-sweep" of the VariableBindings. 00069 // The roots are any Block-level exprs and Decls that our liveness algorithm 00070 // tells us are live. We then see what Decls they may reference, and keep 00071 // those around. This code more than likely can be made faster, and the 00072 // frequency of which this method is called should be experimented with 00073 // for optimum performance. 00074 GRState NewState = *state; 00075 00076 NewState.Env = EnvMgr.removeDeadBindings(NewState.Env, SymReaper, state); 00077 00078 // Clean up the store. 00079 StoreRef newStore = StoreMgr->removeDeadBindings(NewState.getStore(), LCtx, 00080 SymReaper); 00081 NewState.setStore(newStore); 00082 SymReaper.setReapedStore(newStore); 00083 00084 return getPersistentState(NewState); 00085 } 00086 00087 const GRState *GRStateManager::MarshalState(const GRState *state, 00088 const StackFrameContext *InitLoc) { 00089 // make up an empty state for now. 00090 GRState State(this, 00091 EnvMgr.getInitialEnvironment(), 00092 StoreMgr->getInitialStore(InitLoc), 00093 GDMFactory.getEmptyMap()); 00094 00095 return getPersistentState(State); 00096 } 00097 00098 const GRState *GRState::bindCompoundLiteral(const CompoundLiteralExpr *CL, 00099 const LocationContext *LC, 00100 SVal V) const { 00101 const StoreRef &newStore = 00102 getStateManager().StoreMgr->BindCompoundLiteral(getStore(), CL, LC, V); 00103 return makeWithStore(newStore); 00104 } 00105 00106 const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const { 00107 const StoreRef &newStore = 00108 getStateManager().StoreMgr->BindDecl(getStore(), VR, IVal); 00109 return makeWithStore(newStore); 00110 } 00111 00112 const GRState *GRState::bindDeclWithNoInit(const VarRegion* VR) const { 00113 const StoreRef &newStore = 00114 getStateManager().StoreMgr->BindDeclWithNoInit(getStore(), VR); 00115 return makeWithStore(newStore); 00116 } 00117 00118 const GRState *GRState::bindLoc(Loc LV, SVal V) const { 00119 GRStateManager &Mgr = getStateManager(); 00120 const GRState *newState = makeWithStore(Mgr.StoreMgr->Bind(getStore(), 00121 LV, V)); 00122 const MemRegion *MR = LV.getAsRegion(); 00123 if (MR && Mgr.getOwningEngine()) 00124 return Mgr.getOwningEngine()->processRegionChange(newState, MR); 00125 00126 return newState; 00127 } 00128 00129 const GRState *GRState::bindDefault(SVal loc, SVal V) const { 00130 GRStateManager &Mgr = getStateManager(); 00131 const MemRegion *R = cast<loc::MemRegionVal>(loc).getRegion(); 00132 const StoreRef &newStore = Mgr.StoreMgr->BindDefault(getStore(), R, V); 00133 const GRState *new_state = makeWithStore(newStore); 00134 return Mgr.getOwningEngine() ? 00135 Mgr.getOwningEngine()->processRegionChange(new_state, R) : 00136 new_state; 00137 } 00138 00139 const GRState *GRState::invalidateRegions(const MemRegion * const *Begin, 00140 const MemRegion * const *End, 00141 const Expr *E, unsigned Count, 00142 StoreManager::InvalidatedSymbols *IS, 00143 bool invalidateGlobals) const { 00144 if (!IS) { 00145 StoreManager::InvalidatedSymbols invalidated; 00146 return invalidateRegionsImpl(Begin, End, E, Count, 00147 invalidated, invalidateGlobals); 00148 } 00149 return invalidateRegionsImpl(Begin, End, E, Count, *IS, invalidateGlobals); 00150 } 00151 00152 const GRState * 00153 GRState::invalidateRegionsImpl(const MemRegion * const *Begin, 00154 const MemRegion * const *End, 00155 const Expr *E, unsigned Count, 00156 StoreManager::InvalidatedSymbols &IS, 00157 bool invalidateGlobals) const { 00158 GRStateManager &Mgr = getStateManager(); 00159 SubEngine* Eng = Mgr.getOwningEngine(); 00160 00161 if (Eng && Eng->wantsRegionChangeUpdate(this)) { 00162 StoreManager::InvalidatedRegions Regions; 00163 const StoreRef &newStore 00164 = Mgr.StoreMgr->invalidateRegions(getStore(), Begin, End, E, Count, IS, 00165 invalidateGlobals, &Regions); 00166 const GRState *newState = makeWithStore(newStore); 00167 return Eng->processRegionChanges(newState, &IS, 00168 &Regions.front(), 00169 &Regions.back()+1); 00170 } 00171 00172 const StoreRef &newStore = 00173 Mgr.StoreMgr->invalidateRegions(getStore(), Begin, End, E, Count, IS, 00174 invalidateGlobals, NULL); 00175 return makeWithStore(newStore); 00176 } 00177 00178 const GRState *GRState::unbindLoc(Loc LV) const { 00179 assert(!isa<loc::MemRegionVal>(LV) && "Use invalidateRegion instead."); 00180 00181 Store OldStore = getStore(); 00182 const StoreRef &newStore = getStateManager().StoreMgr->Remove(OldStore, LV); 00183 00184 if (newStore.getStore() == OldStore) 00185 return this; 00186 00187 return makeWithStore(newStore); 00188 } 00189 00190 const GRState *GRState::enterStackFrame(const StackFrameContext *frame) const { 00191 const StoreRef &new_store = 00192 getStateManager().StoreMgr->enterStackFrame(this, frame); 00193 return makeWithStore(new_store); 00194 } 00195 00196 SVal GRState::getSValAsScalarOrLoc(const MemRegion *R) const { 00197 // We only want to do fetches from regions that we can actually bind 00198 // values. For example, SymbolicRegions of type 'id<...>' cannot 00199 // have direct bindings (but their can be bindings on their subregions). 00200 if (!R->isBoundable()) 00201 return UnknownVal(); 00202 00203 if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { 00204 QualType T = TR->getValueType(); 00205 if (Loc::isLocType(T) || T->isIntegerType()) 00206 return getSVal(R); 00207 } 00208 00209 return UnknownVal(); 00210 } 00211 00212 SVal GRState::getSVal(Loc location, QualType T) const { 00213 SVal V = getRawSVal(cast<Loc>(location), T); 00214 00215 // If 'V' is a symbolic value that is *perfectly* constrained to 00216 // be a constant value, use that value instead to lessen the burden 00217 // on later analysis stages (so we have less symbolic values to reason 00218 // about). 00219 if (!T.isNull()) { 00220 if (SymbolRef sym = V.getAsSymbol()) { 00221 if (const llvm::APSInt *Int = getSymVal(sym)) { 00222 // FIXME: Because we don't correctly model (yet) sign-extension 00223 // and truncation of symbolic values, we need to convert 00224 // the integer value to the correct signedness and bitwidth. 00225 // 00226 // This shows up in the following: 00227 // 00228 // char foo(); 00229 // unsigned x = foo(); 00230 // if (x == 54) 00231 // ... 00232 // 00233 // The symbolic value stored to 'x' is actually the conjured 00234 // symbol for the call to foo(); the type of that symbol is 'char', 00235 // not unsigned. 00236 const llvm::APSInt &NewV = getBasicVals().Convert(T, *Int); 00237 00238 if (isa<Loc>(V)) 00239 return loc::ConcreteInt(NewV); 00240 else 00241 return nonloc::ConcreteInt(NewV); 00242 } 00243 } 00244 } 00245 00246 return V; 00247 } 00248 00249 const GRState *GRState::BindExpr(const Stmt *S, SVal V, bool Invalidate) const{ 00250 Environment NewEnv = getStateManager().EnvMgr.bindExpr(Env, S, V, 00251 Invalidate); 00252 if (NewEnv == Env) 00253 return this; 00254 00255 GRState NewSt = *this; 00256 NewSt.Env = NewEnv; 00257 return getStateManager().getPersistentState(NewSt); 00258 } 00259 00260 const GRState *GRState::bindExprAndLocation(const Stmt *S, SVal location, 00261 SVal V) const { 00262 Environment NewEnv = 00263 getStateManager().EnvMgr.bindExprAndLocation(Env, S, location, V); 00264 00265 if (NewEnv == Env) 00266 return this; 00267 00268 GRState NewSt = *this; 00269 NewSt.Env = NewEnv; 00270 return getStateManager().getPersistentState(NewSt); 00271 } 00272 00273 const GRState *GRState::assumeInBound(DefinedOrUnknownSVal Idx, 00274 DefinedOrUnknownSVal UpperBound, 00275 bool Assumption) const { 00276 if (Idx.isUnknown() || UpperBound.isUnknown()) 00277 return this; 00278 00279 // Build an expression for 0 <= Idx < UpperBound. 00280 // This is the same as Idx + MIN < UpperBound + MIN, if overflow is allowed. 00281 // FIXME: This should probably be part of SValBuilder. 00282 GRStateManager &SM = getStateManager(); 00283 SValBuilder &svalBuilder = SM.getSValBuilder(); 00284 ASTContext &Ctx = svalBuilder.getContext(); 00285 00286 // Get the offset: the minimum value of the array index type. 00287 BasicValueFactory &BVF = svalBuilder.getBasicValueFactory(); 00288 // FIXME: This should be using ValueManager::ArrayindexTy...somehow. 00289 QualType indexTy = Ctx.IntTy; 00290 nonloc::ConcreteInt Min(BVF.getMinValue(indexTy)); 00291 00292 // Adjust the index. 00293 SVal newIdx = svalBuilder.evalBinOpNN(this, BO_Add, 00294 cast<NonLoc>(Idx), Min, indexTy); 00295 if (newIdx.isUnknownOrUndef()) 00296 return this; 00297 00298 // Adjust the upper bound. 00299 SVal newBound = 00300 svalBuilder.evalBinOpNN(this, BO_Add, cast<NonLoc>(UpperBound), 00301 Min, indexTy); 00302 00303 if (newBound.isUnknownOrUndef()) 00304 return this; 00305 00306 // Build the actual comparison. 00307 SVal inBound = svalBuilder.evalBinOpNN(this, BO_LT, 00308 cast<NonLoc>(newIdx), cast<NonLoc>(newBound), 00309 Ctx.IntTy); 00310 if (inBound.isUnknownOrUndef()) 00311 return this; 00312 00313 // Finally, let the constraint manager take care of it. 00314 ConstraintManager &CM = SM.getConstraintManager(); 00315 return CM.assume(this, cast<DefinedSVal>(inBound), Assumption); 00316 } 00317 00318 const GRState *GRStateManager::getInitialState(const LocationContext *InitLoc) { 00319 GRState State(this, 00320 EnvMgr.getInitialEnvironment(), 00321 StoreMgr->getInitialStore(InitLoc), 00322 GDMFactory.getEmptyMap()); 00323 00324 return getPersistentState(State); 00325 } 00326 00327 void GRStateManager::recycleUnusedStates() { 00328 for (std::vector<GRState*>::iterator i = recentlyAllocatedStates.begin(), 00329 e = recentlyAllocatedStates.end(); i != e; ++i) { 00330 GRState *state = *i; 00331 if (state->referencedByExplodedNode()) 00332 continue; 00333 StateSet.RemoveNode(state); 00334 freeStates.push_back(state); 00335 state->~GRState(); 00336 } 00337 recentlyAllocatedStates.clear(); 00338 } 00339 00340 const GRState *GRStateManager::getPersistentStateWithGDM( 00341 const GRState *FromState, 00342 const GRState *GDMState) { 00343 GRState NewState = *FromState; 00344 NewState.GDM = GDMState->GDM; 00345 return getPersistentState(NewState); 00346 } 00347 00348 const GRState *GRStateManager::getPersistentState(GRState &State) { 00349 00350 llvm::FoldingSetNodeID ID; 00351 State.Profile(ID); 00352 void *InsertPos; 00353 00354 if (GRState *I = StateSet.FindNodeOrInsertPos(ID, InsertPos)) 00355 return I; 00356 00357 GRState *newState = 0; 00358 if (!freeStates.empty()) { 00359 newState = freeStates.back(); 00360 freeStates.pop_back(); 00361 } 00362 else { 00363 newState = (GRState*) Alloc.Allocate<GRState>(); 00364 } 00365 new (newState) GRState(State); 00366 StateSet.InsertNode(newState, InsertPos); 00367 recentlyAllocatedStates.push_back(newState); 00368 return newState; 00369 } 00370 00371 const GRState *GRState::makeWithStore(const StoreRef &store) const { 00372 GRState NewSt = *this; 00373 NewSt.setStore(store); 00374 return getStateManager().getPersistentState(NewSt); 00375 } 00376 00377 void GRState::setStore(const StoreRef &newStore) { 00378 Store newStoreStore = newStore.getStore(); 00379 if (newStoreStore) 00380 stateMgr->getStoreManager().incrementReferenceCount(newStoreStore); 00381 if (store) 00382 stateMgr->getStoreManager().decrementReferenceCount(store); 00383 store = newStoreStore; 00384 } 00385 00386 //===----------------------------------------------------------------------===// 00387 // State pretty-printing. 00388 //===----------------------------------------------------------------------===// 00389 00390 static bool IsEnvLoc(const Stmt *S) { 00391 // FIXME: This is a layering violation. Should be in environment. 00392 return (bool) (((uintptr_t) S) & 0x1); 00393 } 00394 00395 void GRState::print(raw_ostream &Out, CFG &C, const char* nl, 00396 const char* sep) const { 00397 // Print the store. 00398 GRStateManager &Mgr = getStateManager(); 00399 Mgr.getStoreManager().print(getStore(), Out, nl, sep); 00400 00401 // Print Subexpression bindings. 00402 bool isFirst = true; 00403 00404 // FIXME: All environment printing should be moved inside Environment. 00405 for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { 00406 if (C.isBlkExpr(I.getKey()) || IsEnvLoc(I.getKey())) 00407 continue; 00408 00409 if (isFirst) { 00410 Out << nl << nl << "Sub-Expressions:" << nl; 00411 isFirst = false; 00412 } 00413 else { Out << nl; } 00414 00415 Out << " (" << (void*) I.getKey() << ") "; 00416 LangOptions LO; // FIXME. 00417 I.getKey()->printPretty(Out, 0, PrintingPolicy(LO)); 00418 Out << " : " << I.getData(); 00419 } 00420 00421 // Print block-expression bindings. 00422 isFirst = true; 00423 00424 for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { 00425 if (!C.isBlkExpr(I.getKey())) 00426 continue; 00427 00428 if (isFirst) { 00429 Out << nl << nl << "Block-level Expressions:" << nl; 00430 isFirst = false; 00431 } 00432 else { Out << nl; } 00433 00434 Out << " (" << (void*) I.getKey() << ") "; 00435 LangOptions LO; // FIXME. 00436 I.getKey()->printPretty(Out, 0, PrintingPolicy(LO)); 00437 Out << " : " << I.getData(); 00438 } 00439 00440 // Print locations. 00441 isFirst = true; 00442 00443 for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { 00444 if (!IsEnvLoc(I.getKey())) 00445 continue; 00446 00447 if (isFirst) { 00448 Out << nl << nl << "Load/store locations:" << nl; 00449 isFirst = false; 00450 } 00451 else { Out << nl; } 00452 00453 const Stmt *S = (Stmt*) (((uintptr_t) I.getKey()) & ((uintptr_t) ~0x1)); 00454 00455 Out << " (" << (void*) S << ") "; 00456 LangOptions LO; // FIXME. 00457 S->printPretty(Out, 0, PrintingPolicy(LO)); 00458 Out << " : " << I.getData(); 00459 } 00460 00461 Mgr.getConstraintManager().print(this, Out, nl, sep); 00462 00463 // Print checker-specific data. 00464 for (std::vector<Printer*>::iterator I = Mgr.Printers.begin(), 00465 E = Mgr.Printers.end(); I != E; ++I) { 00466 (*I)->Print(Out, this, nl, sep); 00467 } 00468 } 00469 00470 void GRState::printDOT(raw_ostream &Out, CFG &C) const { 00471 print(Out, C, "\\l", "\\|"); 00472 } 00473 00474 void GRState::printStdErr(CFG &C) const { 00475 print(llvm::errs(), C); 00476 } 00477 00478 //===----------------------------------------------------------------------===// 00479 // Generic Data Map. 00480 //===----------------------------------------------------------------------===// 00481 00482 void *const* GRState::FindGDM(void *K) const { 00483 return GDM.lookup(K); 00484 } 00485 00486 void* 00487 GRStateManager::FindGDMContext(void *K, 00488 void *(*CreateContext)(llvm::BumpPtrAllocator&), 00489 void (*DeleteContext)(void*)) { 00490 00491 std::pair<void*, void (*)(void*)>& p = GDMContexts[K]; 00492 if (!p.first) { 00493 p.first = CreateContext(Alloc); 00494 p.second = DeleteContext; 00495 } 00496 00497 return p.first; 00498 } 00499 00500 const GRState *GRStateManager::addGDM(const GRState *St, void *Key, void *Data){ 00501 GRState::GenericDataMap M1 = St->getGDM(); 00502 GRState::GenericDataMap M2 = GDMFactory.add(M1, Key, Data); 00503 00504 if (M1 == M2) 00505 return St; 00506 00507 GRState NewSt = *St; 00508 NewSt.GDM = M2; 00509 return getPersistentState(NewSt); 00510 } 00511 00512 const GRState *GRStateManager::removeGDM(const GRState *state, void *Key) { 00513 GRState::GenericDataMap OldM = state->getGDM(); 00514 GRState::GenericDataMap NewM = GDMFactory.remove(OldM, Key); 00515 00516 if (NewM == OldM) 00517 return state; 00518 00519 GRState NewState = *state; 00520 NewState.GDM = NewM; 00521 return getPersistentState(NewState); 00522 } 00523 00524 //===----------------------------------------------------------------------===// 00525 // Utility. 00526 //===----------------------------------------------------------------------===// 00527 00528 namespace { 00529 class ScanReachableSymbols : public SubRegionMap::Visitor { 00530 typedef llvm::DenseMap<const void*, unsigned> VisitedItems; 00531 00532 VisitedItems visited; 00533 const GRState *state; 00534 SymbolVisitor &visitor; 00535 llvm::OwningPtr<SubRegionMap> SRM; 00536 public: 00537 00538 ScanReachableSymbols(const GRState *st, SymbolVisitor& v) 00539 : state(st), visitor(v) {} 00540 00541 bool scan(nonloc::CompoundVal val); 00542 bool scan(SVal val); 00543 bool scan(const MemRegion *R); 00544 bool scan(const SymExpr *sym); 00545 00546 // From SubRegionMap::Visitor. 00547 bool Visit(const MemRegion* Parent, const MemRegion* SubRegion) { 00548 return scan(SubRegion); 00549 } 00550 }; 00551 } 00552 00553 bool ScanReachableSymbols::scan(nonloc::CompoundVal val) { 00554 for (nonloc::CompoundVal::iterator I=val.begin(), E=val.end(); I!=E; ++I) 00555 if (!scan(*I)) 00556 return false; 00557 00558 return true; 00559 } 00560 00561 bool ScanReachableSymbols::scan(const SymExpr *sym) { 00562 unsigned &isVisited = visited[sym]; 00563 if (isVisited) 00564 return true; 00565 isVisited = 1; 00566 00567 if (const SymbolData *sData = dyn_cast<SymbolData>(sym)) 00568 if (!visitor.VisitSymbol(sData)) 00569 return false; 00570 00571 switch (sym->getKind()) { 00572 case SymExpr::RegionValueKind: 00573 case SymExpr::ConjuredKind: 00574 case SymExpr::DerivedKind: 00575 case SymExpr::ExtentKind: 00576 case SymExpr::MetadataKind: 00577 break; 00578 case SymExpr::SymIntKind: 00579 return scan(cast<SymIntExpr>(sym)->getLHS()); 00580 case SymExpr::SymSymKind: { 00581 const SymSymExpr *x = cast<SymSymExpr>(sym); 00582 return scan(x->getLHS()) && scan(x->getRHS()); 00583 } 00584 } 00585 return true; 00586 } 00587 00588 bool ScanReachableSymbols::scan(SVal val) { 00589 if (loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(&val)) 00590 return scan(X->getRegion()); 00591 00592 if (nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(&val)) 00593 return scan(X->getLoc()); 00594 00595 if (SymbolRef Sym = val.getAsSymbol()) 00596 return scan(Sym); 00597 00598 if (const SymExpr *Sym = val.getAsSymbolicExpression()) 00599 return scan(Sym); 00600 00601 if (nonloc::CompoundVal *X = dyn_cast<nonloc::CompoundVal>(&val)) 00602 return scan(*X); 00603 00604 return true; 00605 } 00606 00607 bool ScanReachableSymbols::scan(const MemRegion *R) { 00608 if (isa<MemSpaceRegion>(R)) 00609 return true; 00610 00611 unsigned &isVisited = visited[R]; 00612 if (isVisited) 00613 return true; 00614 isVisited = 1; 00615 00616 // If this is a symbolic region, visit the symbol for the region. 00617 if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) 00618 if (!visitor.VisitSymbol(SR->getSymbol())) 00619 return false; 00620 00621 // If this is a subregion, also visit the parent regions. 00622 if (const SubRegion *SR = dyn_cast<SubRegion>(R)) 00623 if (!scan(SR->getSuperRegion())) 00624 return false; 00625 00626 // Now look at the binding to this region (if any). 00627 if (!scan(state->getSValAsScalarOrLoc(R))) 00628 return false; 00629 00630 // Now look at the subregions. 00631 if (!SRM.get()) 00632 SRM.reset(state->getStateManager().getStoreManager(). 00633 getSubRegionMap(state->getStore())); 00634 00635 return SRM->iterSubRegions(R, *this); 00636 } 00637 00638 bool GRState::scanReachableSymbols(SVal val, SymbolVisitor& visitor) const { 00639 ScanReachableSymbols S(this, visitor); 00640 return S.scan(val); 00641 } 00642 00643 bool GRState::scanReachableSymbols(const SVal *I, const SVal *E, 00644 SymbolVisitor &visitor) const { 00645 ScanReachableSymbols S(this, visitor); 00646 for ( ; I != E; ++I) { 00647 if (!S.scan(*I)) 00648 return false; 00649 } 00650 return true; 00651 } 00652 00653 bool GRState::scanReachableSymbols(const MemRegion * const *I, 00654 const MemRegion * const *E, 00655 SymbolVisitor &visitor) const { 00656 ScanReachableSymbols S(this, visitor); 00657 for ( ; I != E; ++I) { 00658 if (!S.scan(*I)) 00659 return false; 00660 } 00661 return true; 00662 }