From 554bcb69c2d785a011a30e7db87a36a87fe7db10 Mon Sep 17 00:00:00 2001 From: dim Date: Wed, 15 Aug 2012 20:02:54 +0000 Subject: Vendor import of clang trunk r161861: http://llvm.org/svn/llvm-project/cfe/trunk@161861 --- lib/StaticAnalyzer/Core/ProgramState.cpp | 99 ++++++++++++++++++++++++++------ 1 file changed, 80 insertions(+), 19 deletions(-) (limited to 'lib/StaticAnalyzer/Core/ProgramState.cpp') diff --git a/lib/StaticAnalyzer/Core/ProgramState.cpp b/lib/StaticAnalyzer/Core/ProgramState.cpp index b9cfa27..dc988cc 100644 --- a/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/CFG.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h" @@ -70,6 +71,19 @@ ProgramState::~ProgramState() { stateMgr->getStoreManager().decrementReferenceCount(store); } +ProgramStateManager::ProgramStateManager(ASTContext &Ctx, + StoreManagerCreator CreateSMgr, + ConstraintManagerCreator CreateCMgr, + llvm::BumpPtrAllocator &alloc, + SubEngine &SubEng) + : Eng(&SubEng), EnvMgr(alloc), GDMFactory(alloc), + svalBuilder(createSimpleSValBuilder(alloc, Ctx, *this)), + CallEventMgr(new CallEventManager(alloc)), Alloc(alloc) { + StoreMgr.reset((*CreateSMgr)(*this)); + ConstraintMgr.reset((*CreateCMgr)(*this, SubEng)); +} + + ProgramStateManager::~ProgramStateManager() { for (GDMContextsTy::iterator I=GDMContexts.begin(), E=GDMContexts.end(); I!=E; ++I) @@ -157,7 +171,7 @@ ProgramState::invalidateRegions(ArrayRef Regions, const Expr *E, unsigned Count, const LocationContext *LCtx, StoreManager::InvalidatedSymbols *IS, - const CallOrObjCMessage *Call) const { + const CallEvent *Call) const { if (!IS) { StoreManager::InvalidatedSymbols invalidated; return invalidateRegionsImpl(Regions, E, Count, LCtx, @@ -171,7 +185,7 @@ ProgramState::invalidateRegionsImpl(ArrayRef Regions, const Expr *E, unsigned Count, const LocationContext *LCtx, StoreManager::InvalidatedSymbols &IS, - const CallOrObjCMessage *Call) const { + const CallEvent *Call) const { ProgramStateManager &Mgr = getStateManager(); SubEngine* Eng = Mgr.getOwningEngine(); @@ -203,11 +217,11 @@ ProgramStateRef ProgramState::unbindLoc(Loc LV) const { } ProgramStateRef -ProgramState::enterStackFrame(const LocationContext *callerCtx, - const StackFrameContext *calleeCtx) const { - const StoreRef &new_store = - getStateManager().StoreMgr->enterStackFrame(this, callerCtx, calleeCtx); - return makeWithStore(new_store); +ProgramState::enterStackFrame(const CallEvent &Call, + const StackFrameContext *CalleeCtx) const { + const StoreRef &NewStore = + getStateManager().StoreMgr->enterStackFrame(getStore(), Call, CalleeCtx); + return makeWithStore(NewStore); } SVal ProgramState::getSValAsScalarOrLoc(const MemRegion *R) const { @@ -485,8 +499,6 @@ ProgramStateRef ProgramStateManager::removeGDM(ProgramStateRef state, void *Key) return getPersistentState(NewState); } -void ScanReachableSymbols::anchor() { } - bool ScanReachableSymbols::scan(nonloc::CompoundVal val) { for (nonloc::CompoundVal::iterator I=val.begin(), E=val.end(); I!=E; ++I) if (!scan(*I)) @@ -530,6 +542,9 @@ bool ScanReachableSymbols::scan(SVal val) { if (loc::MemRegionVal *X = dyn_cast(&val)) return scan(X->getRegion()); + if (nonloc::LazyCompoundVal *X = dyn_cast(&val)) + return scan(X->getRegion()); + if (nonloc::LocAsInteger *X = dyn_cast(&val)) return scan(X->getLoc()); @@ -564,20 +579,30 @@ bool ScanReachableSymbols::scan(const MemRegion *R) { return false; // If this is a subregion, also visit the parent regions. - if (const SubRegion *SR = dyn_cast(R)) - if (!scan(SR->getSuperRegion())) + if (const SubRegion *SR = dyn_cast(R)) { + const MemRegion *Super = SR->getSuperRegion(); + if (!scan(Super)) return false; - // Now look at the binding to this region (if any). - if (!scan(state->getSValAsScalarOrLoc(R))) - return false; + // When we reach the topmost region, scan all symbols in it. + if (isa(Super)) { + StoreManager &StoreMgr = state->getStateManager().getStoreManager(); + if (!StoreMgr.scanReachableSymbols(state->getStore(), SR, *this)) + return false; + } + } - // Now look at the subregions. - if (!SRM.get()) - SRM.reset(state->getStateManager().getStoreManager(). - getSubRegionMap(state->getStore())); + // Regions captured by a block are also implicitly reachable. + if (const BlockDataRegion *BDR = dyn_cast(R)) { + BlockDataRegion::referenced_vars_iterator I = BDR->referenced_vars_begin(), + E = BDR->referenced_vars_end(); + for ( ; I != E; ++I) { + if (!scan(I.getCapturedRegion())) + return false; + } + } - return SRM->iterSubRegions(R, *this); + return true; } bool ProgramState::scanReachableSymbols(SVal val, SymbolVisitor& visitor) const { @@ -707,3 +732,39 @@ bool ProgramState::isTainted(SymbolRef Sym, TaintTagType Kind) const { return Tainted; } + +/// The GDM component containing the dynamic type info. This is a map from a +/// symbol to it's most likely type. +namespace clang { +namespace ento { +typedef llvm::ImmutableMap DynamicTypeMap; +template<> struct ProgramStateTrait + : public ProgramStatePartialTrait { + static void *GDMIndex() { static int index; return &index; } +}; +}} + +DynamicTypeInfo ProgramState::getDynamicTypeInfo(const MemRegion *Reg) const { + // Look up the dynamic type in the GDM. + const DynamicTypeInfo *GDMType = get(Reg); + if (GDMType) + return *GDMType; + + // Otherwise, fall back to what we know about the region. + if (const TypedValueRegion *TR = dyn_cast(Reg)) + return DynamicTypeInfo(TR->getValueType()); + + if (const SymbolicRegion *SR = dyn_cast(Reg)) { + SymbolRef Sym = SR->getSymbol(); + return DynamicTypeInfo(Sym->getType(getStateManager().getContext())); + } + + return DynamicTypeInfo(); +} + +ProgramStateRef ProgramState::setDynamicTypeInfo(const MemRegion *Reg, + DynamicTypeInfo NewTy) const { + ProgramStateRef NewState = set(Reg, NewTy); + assert(NewState); + return NewState; +} -- cgit v1.1