diff options
author | Ted Kremenek <kremenek@apple.com> | 2009-09-27 20:45:21 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2009-09-27 20:45:21 +0000 |
commit | 8780679b02bea5ab6360f3f8ebf3b221aaeda93f (patch) | |
tree | c9a0f9eb4bc2acdfb1b1f347cd0d2f85deffe238 /lib/Analysis/RegionStore.cpp | |
parent | 50755b0dcc81eed9dcf27abe9162527013f26bd4 (diff) |
Fix:
<rdar://problem/6914474> checker doesn't realize that variable might
have been assigned if a pointer to that variable was passed to another
function via a structure
The problem here was the RegionStoreManager::InvalidateRegion didn't
invalidate the bindings of invalidated regions. This required a
rewrite of this method using a worklist.
As part of this fix, changed ValueManager::getConjuredSymbolVal() to
require a 'void*' SymbolTag argument. This tag is used to
differentiate two different symbols created at the same location.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82920 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/RegionStore.cpp')
-rw-r--r-- | lib/Analysis/RegionStore.cpp | 133 |
1 files changed, 81 insertions, 52 deletions
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp index 75907da55e..6b7799c505 100644 --- a/lib/Analysis/RegionStore.cpp +++ b/lib/Analysis/RegionStore.cpp @@ -436,69 +436,98 @@ RegionStoreManager::RemoveSubRegionBindings(RegionBindings &B, DVM = DVMFactory.Remove(DVM, R); } - const GRState *RegionStoreManager::InvalidateRegion(const GRState *state, const MemRegion *R, - const Expr *E, + const Expr *Ex, unsigned Count) { ASTContext& Ctx = StateMgr.getContext(); // Strip away casts. R = R->getBaseRegion(); - // Remove the bindings to subregions. - { - // Get the mapping of regions -> subregions. - llvm::OwningPtr<RegionStoreSubRegionMap> - SubRegions(getRegionStoreSubRegionMap(state)); - - RegionBindings B = GetRegionBindings(state->getStore()); - RegionDefaultBindings DVM = state->get<RegionDefaultValue>(); - RegionDefaultBindings::Factory &DVMFactory = - state->get_context<RegionDefaultValue>(); - - RemoveSubRegionBindings(B, DVM, DVMFactory, R, *SubRegions.get()); - state = state->makeWithStore(B.getRoot())->set<RegionDefaultValue>(DVM); - } - - if (!R->isBoundable()) - return state; - - if (isa<AllocaRegion>(R) || isa<SymbolicRegion>(R) || - isa<ObjCObjectRegion>(R)) { - // Invalidate the region by setting its default value to - // conjured symbol. The type of the symbol is irrelavant. - SVal V = ValMgr.getConjuredSymbolVal(E, Ctx.IntTy, Count); - return setDefaultValue(state, R, V); - } - - const TypedRegion *TR = cast<TypedRegion>(R); - QualType T = TR->getValueType(Ctx); - - if (const RecordType *RT = T->getAsStructureType()) { - // FIXME: handle structs with default region value. - const RecordDecl *RD = RT->getDecl()->getDefinition(Ctx); - - // No record definition. There is nothing we can do. - if (!RD) - return state; - - // Invalidate the region by setting its default value to - // conjured symbol. The type of the symbol is irrelavant. - SVal V = ValMgr.getConjuredSymbolVal(E, Ctx.IntTy, Count); - return setDefaultValue(state, R, V); - } + // Get the mapping of regions -> subregions. + llvm::OwningPtr<RegionStoreSubRegionMap> + SubRegions(getRegionStoreSubRegionMap(state)); + + RegionBindings B = GetRegionBindings(state->getStore()); + RegionDefaultBindings DVM = state->get<RegionDefaultValue>(); + RegionDefaultBindings::Factory &DVMFactory = + state->get_context<RegionDefaultValue>(); + + llvm::DenseMap<const MemRegion *, unsigned> Visited; + llvm::SmallVector<const MemRegion *, 10> WorkList; + WorkList.push_back(R); + + while (!WorkList.empty()) { + R = WorkList.back(); + WorkList.pop_back(); + + // Have we visited this region before? + unsigned &visited = Visited[R]; + if (visited) + continue; + visited = 1; + + // Add subregions to work list. + RegionStoreSubRegionMap::iterator I, E; + for (llvm::tie(I, E) = SubRegions->begin_end(R); I!=E; ++I) + WorkList.push_back(*I); + + // Handle region. + if (isa<AllocaRegion>(R) || isa<SymbolicRegion>(R) || + isa<ObjCObjectRegion>(R)) { + // Invalidate the region by setting its default value to + // conjured symbol. The type of the symbol is irrelavant. + DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, Ctx.IntTy, + Count); + DVM = DVMFactory.Add(DVM, R, V); + continue; + } - if (const ArrayType *AT = Ctx.getAsArrayType(T)) { - // Set the default value of the array to conjured symbol. - SVal V = ValMgr.getConjuredSymbolVal(E, AT->getElementType(), - Count); - return setDefaultValue(state, TR, V); + if (!R->isBoundable()) + continue; + + const TypedRegion *TR = cast<TypedRegion>(R); + QualType T = TR->getValueType(Ctx); + + if (const RecordType *RT = T->getAsStructureType()) { + // FIXME: handle structs with default region value. + const RecordDecl *RD = RT->getDecl()->getDefinition(Ctx); + + // No record definition. There is nothing we can do. + if (!RD) + continue; + + // Invalidate the region by setting its default value to + // conjured symbol. The type of the symbol is irrelavant. + DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, Ctx.IntTy, + Count); + DVM = DVMFactory.Add(DVM, R, V); + continue; + } + + if (const ArrayType *AT = Ctx.getAsArrayType(T)) { + // Set the default value of the array to conjured symbol. + DefinedOrUnknownSVal V = + ValMgr.getConjuredSymbolVal(R, Ex, AT->getElementType(), Count); + DVM = DVMFactory.Add(DVM, R, V); + continue; + } + + // Get the old binding. Is it a region? If so, add it to the worklist. + if (const SVal *OldV = B.lookup(R)) { + if (const MemRegion *RV = OldV->getAsRegion()) + WorkList.push_back(RV); + } + + // Invalidate the binding. + DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, T, Count); + assert(SymbolManager::canSymbolicate(T) || V.isUnknown()); + B = RBFactory.Add(B, R, V); } - SVal V = ValMgr.getConjuredSymbolVal(E, T, Count); - assert(SymbolManager::canSymbolicate(T) || V.isUnknown()); - return Bind(state, ValMgr.makeLoc(TR), V); + // Create a new state with the updated bindings. + return state->makeWithStore(B.getRoot())->set<RegionDefaultValue>(DVM); } //===----------------------------------------------------------------------===// |