Fix a bug (PR 6699) in RegionStore::RemoveDeadBindings() where
array values with a non-zero offset would get prematurely pruned from the store. llvm-svn: 100067
This commit is contained in:
parent
7c90d22f4c
commit
c3e1f2f9ba
|
@ -536,15 +536,15 @@ public:
|
||||||
// First visit the cluster.
|
// First visit the cluster.
|
||||||
static_cast<DERIVED*>(this)->VisitCluster(baseR, C->begin(), C->end());
|
static_cast<DERIVED*>(this)->VisitCluster(baseR, C->begin(), C->end());
|
||||||
|
|
||||||
// Next, visit the region.
|
// Next, visit the base region.
|
||||||
static_cast<DERIVED*>(this)->VisitRegion(baseR);
|
static_cast<DERIVED*>(this)->VisitBaseRegion(baseR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void VisitAddedToCluster(const MemRegion *baseR, RegionCluster &C) {}
|
void VisitAddedToCluster(const MemRegion *baseR, RegionCluster &C) {}
|
||||||
void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E) {}
|
void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E) {}
|
||||||
void VisitRegion(const MemRegion *baseR) {}
|
void VisitBaseRegion(const MemRegion *baseR) {}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,7 +580,7 @@ public:
|
||||||
Ex(ex), Count(count), IS(is) {}
|
Ex(ex), Count(count), IS(is) {}
|
||||||
|
|
||||||
void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E);
|
void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E);
|
||||||
void VisitRegion(const MemRegion *baseR);
|
void VisitBaseRegion(const MemRegion *baseR);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void VisitBinding(SVal V);
|
void VisitBinding(SVal V);
|
||||||
|
@ -627,7 +627,7 @@ void InvalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void InvalidateRegionsWorker::VisitRegion(const MemRegion *baseR) {
|
void InvalidateRegionsWorker::VisitBaseRegion(const MemRegion *baseR) {
|
||||||
if (IS) {
|
if (IS) {
|
||||||
// Symbolic region? Mark that symbol touched by the invalidation.
|
// Symbolic region? Mark that symbol touched by the invalidation.
|
||||||
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR))
|
if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR))
|
||||||
|
@ -1706,8 +1706,8 @@ public:
|
||||||
// Called by ClusterAnalysis.
|
// Called by ClusterAnalysis.
|
||||||
void VisitAddedToCluster(const MemRegion *baseR, RegionCluster &C);
|
void VisitAddedToCluster(const MemRegion *baseR, RegionCluster &C);
|
||||||
void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E);
|
void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E);
|
||||||
void VisitRegion(const MemRegion *baseR);
|
|
||||||
|
|
||||||
|
void VisitBindingKey(BindingKey K);
|
||||||
bool UpdatePostponed();
|
bool UpdatePostponed();
|
||||||
void VisitBinding(SVal V);
|
void VisitBinding(SVal V);
|
||||||
};
|
};
|
||||||
|
@ -1744,11 +1744,8 @@ void RemoveDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR,
|
||||||
|
|
||||||
void RemoveDeadBindingsWorker::VisitCluster(const MemRegion *baseR,
|
void RemoveDeadBindingsWorker::VisitCluster(const MemRegion *baseR,
|
||||||
BindingKey *I, BindingKey *E) {
|
BindingKey *I, BindingKey *E) {
|
||||||
for ( ; I != E; ++I) {
|
for ( ; I != E; ++I)
|
||||||
const MemRegion *R = I->getRegion();
|
VisitBindingKey(*I);
|
||||||
if (R != baseR)
|
|
||||||
VisitRegion(R);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveDeadBindingsWorker::VisitBinding(SVal V) {
|
void RemoveDeadBindingsWorker::VisitBinding(SVal V) {
|
||||||
|
@ -1776,34 +1773,36 @@ void RemoveDeadBindingsWorker::VisitBinding(SVal V) {
|
||||||
SymReaper.markLive(*SI);
|
SymReaper.markLive(*SI);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveDeadBindingsWorker::VisitRegion(const MemRegion *R) {
|
void RemoveDeadBindingsWorker::VisitBindingKey(BindingKey K) {
|
||||||
|
const MemRegion *R = K.getRegion();
|
||||||
|
|
||||||
// Mark this region "live" by adding it to the worklist. This will cause
|
// Mark this region "live" by adding it to the worklist. This will cause
|
||||||
// use to visit all regions in the cluster (if we haven't visited them
|
// use to visit all regions in the cluster (if we haven't visited them
|
||||||
// already).
|
// already).
|
||||||
AddToWorkList(R);
|
if (AddToWorkList(R)) {
|
||||||
|
// Mark the symbol for any live SymbolicRegion as "live". This means we
|
||||||
|
// should continue to track that symbol.
|
||||||
|
if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R))
|
||||||
|
SymReaper.markLive(SymR->getSymbol());
|
||||||
|
|
||||||
// Mark the symbol for any live SymbolicRegion as "live". This means we
|
// For BlockDataRegions, enqueue the VarRegions for variables marked
|
||||||
// should continue to track that symbol.
|
// with __block (passed-by-reference).
|
||||||
if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R))
|
// via BlockDeclRefExprs.
|
||||||
SymReaper.markLive(SymR->getSymbol());
|
if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(R)) {
|
||||||
|
for (BlockDataRegion::referenced_vars_iterator
|
||||||
|
RI = BD->referenced_vars_begin(), RE = BD->referenced_vars_end();
|
||||||
|
RI != RE; ++RI) {
|
||||||
|
if ((*RI)->getDecl()->getAttr<BlocksAttr>())
|
||||||
|
AddToWorkList(*RI);
|
||||||
|
}
|
||||||
|
|
||||||
// For BlockDataRegions, enqueue the VarRegions for variables marked
|
// No possible data bindings on a BlockDataRegion.
|
||||||
// with __block (passed-by-reference).
|
return;
|
||||||
// via BlockDeclRefExprs.
|
|
||||||
if (const BlockDataRegion *BD = dyn_cast<BlockDataRegion>(R)) {
|
|
||||||
for (BlockDataRegion::referenced_vars_iterator
|
|
||||||
RI = BD->referenced_vars_begin(), RE = BD->referenced_vars_end();
|
|
||||||
RI != RE; ++RI) {
|
|
||||||
if ((*RI)->getDecl()->getAttr<BlocksAttr>())
|
|
||||||
AddToWorkList(*RI);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// No possible data bindings on a BlockDataRegion.
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the data binding for R (if any).
|
// Visit the data binding for K.
|
||||||
if (const Optional<SVal> &V = RM.getBinding(B, R))
|
if (const SVal *V = RM.Lookup(B, K))
|
||||||
VisitBinding(*V);
|
VisitBinding(*V);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,3 +207,19 @@ void rdar7283470_2_positive(void) {
|
||||||
[numbers[i] release];
|
[numbers[i] release];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pr6699(int x) {
|
||||||
|
CFDateRef values[2];
|
||||||
|
values[0] = values[1] = 0;
|
||||||
|
|
||||||
|
if (x) {
|
||||||
|
CFAbsoluteTime t = CFAbsoluteTimeGetCurrent();
|
||||||
|
values[1] = CFDateCreate(0, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (values[1]) {
|
||||||
|
// A bug in RegionStore::RemoveDeadBindings caused 'values[1]' to get prematurely
|
||||||
|
// pruned from the store.
|
||||||
|
CFRelease(values[1]); // no-warning
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue