diff --git a/clang/lib/Checker/RegionStore.cpp b/clang/lib/Checker/RegionStore.cpp index d590a86a81cb..b333a5d2830e 100644 --- a/clang/lib/Checker/RegionStore.cpp +++ b/clang/lib/Checker/RegionStore.cpp @@ -536,15 +536,15 @@ public: // First visit the cluster. static_cast(this)->VisitCluster(baseR, C->begin(), C->end()); - // Next, visit the region. - static_cast(this)->VisitRegion(baseR); + // Next, visit the base region. + static_cast(this)->VisitBaseRegion(baseR); } } public: void VisitAddedToCluster(const MemRegion *baseR, RegionCluster &C) {} 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) {} void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E); - void VisitRegion(const MemRegion *baseR); + void VisitBaseRegion(const MemRegion *baseR); private: 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) { // Symbolic region? Mark that symbol touched by the invalidation. if (const SymbolicRegion *SR = dyn_cast(baseR)) @@ -1706,8 +1706,8 @@ public: // Called by ClusterAnalysis. void VisitAddedToCluster(const MemRegion *baseR, RegionCluster &C); void VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E); - void VisitRegion(const MemRegion *baseR); + void VisitBindingKey(BindingKey K); bool UpdatePostponed(); void VisitBinding(SVal V); }; @@ -1744,11 +1744,8 @@ void RemoveDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR, void RemoveDeadBindingsWorker::VisitCluster(const MemRegion *baseR, BindingKey *I, BindingKey *E) { - for ( ; I != E; ++I) { - const MemRegion *R = I->getRegion(); - if (R != baseR) - VisitRegion(R); - } + for ( ; I != E; ++I) + VisitBindingKey(*I); } void RemoveDeadBindingsWorker::VisitBinding(SVal V) { @@ -1776,34 +1773,36 @@ void RemoveDeadBindingsWorker::VisitBinding(SVal V) { 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 // use to visit all regions in the cluster (if we haven't visited them // 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(R)) + SymReaper.markLive(SymR->getSymbol()); - // Mark the symbol for any live SymbolicRegion as "live". This means we - // should continue to track that symbol. - if (const SymbolicRegion *SymR = dyn_cast(R)) - SymReaper.markLive(SymR->getSymbol()); + // For BlockDataRegions, enqueue the VarRegions for variables marked + // with __block (passed-by-reference). + // via BlockDeclRefExprs. + if (const BlockDataRegion *BD = dyn_cast(R)) { + for (BlockDataRegion::referenced_vars_iterator + RI = BD->referenced_vars_begin(), RE = BD->referenced_vars_end(); + RI != RE; ++RI) { + if ((*RI)->getDecl()->getAttr()) + AddToWorkList(*RI); + } - // For BlockDataRegions, enqueue the VarRegions for variables marked - // with __block (passed-by-reference). - // via BlockDeclRefExprs. - if (const BlockDataRegion *BD = dyn_cast(R)) { - for (BlockDataRegion::referenced_vars_iterator - RI = BD->referenced_vars_begin(), RE = BD->referenced_vars_end(); - RI != RE; ++RI) { - if ((*RI)->getDecl()->getAttr()) - AddToWorkList(*RI); + // No possible data bindings on a BlockDataRegion. + return; } - - // No possible data bindings on a BlockDataRegion. - return; } - // Get the data binding for R (if any). - if (const Optional &V = RM.getBinding(B, R)) + // Visit the data binding for K. + if (const SVal *V = RM.Lookup(B, K)) VisitBinding(*V); } diff --git a/clang/test/Analysis/retain-release-region-store.m b/clang/test/Analysis/retain-release-region-store.m index 111d4b92d126..db49b91c27f5 100644 --- a/clang/test/Analysis/retain-release-region-store.m +++ b/clang/test/Analysis/retain-release-region-store.m @@ -207,3 +207,19 @@ void rdar7283470_2_positive(void) { [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 + } +} +