Fix regression in RegionStore due to recent changes in

RegionStoreManager::InvalidateRegions() by adjusting the worklist to
iterate over BindingKeys instead of MemRegions.  We also only need to
do the actual invalidation work on base regions, and for non-base
regions just blow away their bindings.

llvm-svn: 95200
This commit is contained in:
Ted Kremenek 2010-02-03 04:16:00 +00:00
parent a16b0dd1ae
commit d960564b76
2 changed files with 108 additions and 89 deletions

View File

@ -506,9 +506,10 @@ void RegionStoreManager::RemoveSubRegionBindings(RegionBindings &B,
namespace {
class InvalidateRegionsWorker {
typedef BumpVector<const MemRegion *> RegionCluster;
typedef BumpVector<BindingKey> RegionCluster;
typedef llvm::DenseMap<const MemRegion *, RegionCluster *> ClusterMap;
typedef llvm::SmallVector<RegionCluster*, 10> WorkList;
typedef llvm::SmallVector<std::pair<const MemRegion *,RegionCluster*>, 10>
WorkList;
BumpVectorContext BVC;
ClusterMap ClusterM;
@ -523,25 +524,30 @@ public:
StoreManager::InvalidatedSymbols *IS);
private:
void AddToWorkList(BindingKey K);
void AddToWorkList(const MemRegion *R);
void AddToCluster(const MemRegion *R);
void AddToCluster(BindingKey K);
RegionCluster **getCluster(const MemRegion *R);
};
}
void InvalidateRegionsWorker::AddToCluster(const MemRegion *R) {
void InvalidateRegionsWorker::AddToCluster(BindingKey K) {
const MemRegion *R = K.getRegion();
const MemRegion *baseR = R->getBaseRegion();
RegionCluster **CPtr = getCluster(baseR);
if (R != baseR) {
assert(*CPtr);
(*CPtr)->push_back(R, BVC);
}
assert(*CPtr);
(*CPtr)->push_back(K, BVC);
}
void InvalidateRegionsWorker::AddToWorkList(BindingKey K) {
AddToWorkList(K.getRegion());
}
void InvalidateRegionsWorker::AddToWorkList(const MemRegion *R) {
RegionCluster **CPtr = getCluster( R->getBaseRegion());
const MemRegion *baseR = R->getBaseRegion();
RegionCluster **CPtr = getCluster(baseR);
if (RegionCluster *C = *CPtr) {
WL.push_back(C);
WL.push_back(std::make_pair(baseR, C));
*CPtr = NULL;
}
}
@ -552,7 +558,6 @@ InvalidateRegionsWorker::getCluster(const MemRegion *R) {
if (!CRef) {
void *Mem = BVC.getAllocator().Allocate<RegionCluster>();
CRef = new (Mem) RegionCluster(BVC, 10);
CRef->push_back(R, BVC);
}
return &CRef;
}
@ -571,9 +576,12 @@ InvalidateRegionsWorker::InvalidateRegions(RegionStoreManager &RM,
// Scan the entire store and make the region clusters.
for (RegionBindings::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI) {
AddToCluster(RI.getKey().getRegion());
if (const MemRegion *R = RI.getData().getAsRegion())
AddToCluster(R);
AddToCluster(RI.getKey());
if (const MemRegion *R = RI.getData().getAsRegion()) {
// Generate a cluster, but don't add the region to the cluster
// if there aren't any bindings.
getCluster(R->getBaseRegion());
}
}
// Add the cluster for I .. E to a worklist.
@ -581,94 +589,92 @@ InvalidateRegionsWorker::InvalidateRegions(RegionStoreManager &RM,
AddToWorkList(*I);
while (!WL.empty()) {
RegionCluster *C = WL.back();
const MemRegion *baseR;
RegionCluster *C;
llvm::tie(baseR, C) = WL.back();
WL.pop_back();
for (RegionCluster::iterator I = C->begin(), E = C->end(); I != E; ++I) {
const MemRegion *R = *I;
BindingKey K = *I;
// Get the old binding. Is it a region? If so, add it to the worklist.
if (Optional<SVal> V = RM.getDirectBinding(B, R)) {
if (const MemRegion *RV = V->getAsRegion())
AddToWorkList(RV);
if (const SVal *V = RM.Lookup(B, K)) {
if (const MemRegion *R = V->getAsRegion())
AddToWorkList(R);
// A symbol? Mark it touched by the invalidation.
if (IS)
if (SymbolRef Sym = V->getAsSymbol())
IS->insert(Sym);
}
// Symbolic region? Mark that symbol touched by the invalidation.
if (IS)
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
IS->insert(SR->getSymbol());
// BlockDataRegion? If so, invalidate captured variables that are passed
// by reference.
if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
for (BlockDataRegion::referenced_vars_iterator
I = BR->referenced_vars_begin(), E = BR->referenced_vars_end() ;
I != E; ++I) {
const VarRegion *VR = *I;
if (VR->getDecl()->getAttr<BlocksAttr>())
AddToWorkList(VR);
}
continue;
}
// Handle the region itself.
if (isa<AllocaRegion>(R) || isa<SymbolicRegion>(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);
B = RM.Add(B, R, BindingKey::Default, V);
continue;
}
if (!R->isBoundable())
continue;
const TypedRegion *TR = cast<TypedRegion>(R);
QualType T = TR->getValueType(Ctx);
// Invalidate the binding.
if (const RecordType *RT = T->getAsStructureType()) {
const RecordDecl *RD = RT->getDecl()->getDefinition(Ctx);
// No record definition. There is nothing we can do.
if (!RD) {
B = RM.Remove(B, R);
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);
B = RM.Add(B, R, BindingKey::Default, 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);
B = RM.Add(B, R, BindingKey::Default, V);
continue;
}
// For fields and elements that aren't themselves structs or arrays,
// just remove the binding. Base regions will get default values from
// which the fields and elements will get lazily symbolicated.
if (isa<FieldRegion>(R) || isa<ElementRegion>(R)) {
B = RM.Remove(B, R, BindingKey::Direct);
continue;
}
DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(R, Ex, T, Count);
assert(SymbolManager::canSymbolicate(T) || V.isUnknown());
B = RM.Add(B, R, BindingKey::Direct, V);
B = RM.Remove(B, K);
}
// Now inspect the base region.
if (IS) {
// Symbolic region? Mark that symbol touched by the invalidation.
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR))
IS->insert(SR->getSymbol());
}
// BlockDataRegion? If so, invalidate captured variables that are passed
// by reference.
if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(baseR)) {
for (BlockDataRegion::referenced_vars_iterator
I = BR->referenced_vars_begin(), E = BR->referenced_vars_end() ;
I != E; ++I) {
const VarRegion *VR = *I;
if (VR->getDecl()->getAttr<BlocksAttr>())
AddToWorkList(VR);
}
continue;
}
if (isa<AllocaRegion>(baseR) || isa<SymbolicRegion>(baseR)) {
// Invalidate the region by setting its default value to
// conjured symbol. The type of the symbol is irrelavant.
DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy,
Count);
B = RM.Add(B, baseR, BindingKey::Default, V);
continue;
}
if (!baseR->isBoundable())
continue;
const TypedRegion *TR = cast<TypedRegion>(baseR);
QualType T = TR->getValueType(Ctx);
// Invalidate the binding.
if (const RecordType *RT = T->getAsStructureType()) {
const RecordDecl *RD = RT->getDecl()->getDefinition(Ctx);
// No record definition. There is nothing we can do.
if (!RD) {
B = RM.Remove(B, baseR);
continue;
}
// Invalidate the region by setting its default value to
// conjured symbol. The type of the symbol is irrelavant.
DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(baseR, Ex, Ctx.IntTy,
Count);
B = RM.Add(B, baseR, BindingKey::Default, V);
continue;
}
if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
// Set the default value of the array to conjured symbol.
DefinedOrUnknownSVal V =
ValMgr.getConjuredSymbolVal(baseR, Ex, AT->getElementType(), Count);
B = RM.Add(B, baseR, BindingKey::Default, V);
continue;
}
DefinedOrUnknownSVal V = ValMgr.getConjuredSymbolVal(baseR, Ex, T, Count);
assert(SymbolManager::canSymbolicate(T) || V.isUnknown());
B = RM.Add(B, baseR, BindingKey::Direct, V);
}
// Create a new state with the updated bindings.

View File

@ -866,3 +866,16 @@ void bar_rev95119() {
baz_rev95119((double)value);
}
//===----------------------------------------------------------------------===//
// Handle loading a symbolic pointer from a symbolic region that was
// invalidated by a call to an unknown function.
//===----------------------------------------------------------------------===//
void bar_rev95192(int **x);
void foo_rev95192(int **x) {
*x = 0;
bar_rev95192(x);
// Not a null dereference.
**x = 1; // no-warning
}