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:
Ted Kremenek 2010-04-01 00:15:55 +00:00
parent 7c90d22f4c
commit c3e1f2f9ba
2 changed files with 46 additions and 31 deletions

View File

@ -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);
} }

View File

@ -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
}
}