From 85248734f404fbb9b2f88ecd5296761a8578def6 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Sat, 6 Feb 2010 00:30:00 +0000 Subject: [PATCH] Teach RegionStore::InvalidateRegions() to also invalidate static variables referenced by blocks. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@95459 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/AnalysisContext.cpp | 22 +++++++++++++++-- lib/Checker/MemRegion.cpp | 2 +- lib/Checker/RegionStore.cpp | 9 +++---- test/Analysis/misc-ps-region-store.m | 36 ++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 7 deletions(-) diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp index 0c64610bea..ccd5088f2e 100644 --- a/lib/Analysis/AnalysisContext.cpp +++ b/lib/Analysis/AnalysisContext.cpp @@ -194,6 +194,7 @@ namespace { class FindBlockDeclRefExprsVals : public StmtVisitor{ BumpVector &BEVals; BumpVectorContext &BC; + llvm::DenseMap Visited; public: FindBlockDeclRefExprsVals(BumpVector &bevals, BumpVectorContext &bc) @@ -204,10 +205,27 @@ public: if (Stmt *child = *I) Visit(child); } + + void VisitDeclRefExpr(const DeclRefExpr *DR) { + // Non-local variables are also directly modified. + if (const VarDecl *VD = dyn_cast(DR->getDecl())) + if (!VD->hasLocalStorage()) { + unsigned &flag = Visited[VD]; + if (!flag) { + flag = 1; + BEVals.push_back(VD, BC); + } + } + } void VisitBlockDeclRefExpr(BlockDeclRefExpr *DR) { - if (const VarDecl *VD = dyn_cast(DR->getDecl())) - BEVals.push_back(VD, BC); + if (const VarDecl *VD = dyn_cast(DR->getDecl())) { + unsigned &flag = Visited[VD]; + if (!flag) { + flag = 1; + BEVals.push_back(VD, BC); + } + } } }; } // end anonymous namespace diff --git a/lib/Checker/MemRegion.cpp b/lib/Checker/MemRegion.cpp index 1e82883a68..cfa855e195 100644 --- a/lib/Checker/MemRegion.cpp +++ b/lib/Checker/MemRegion.cpp @@ -759,7 +759,7 @@ void BlockDataRegion::LazyInitializeReferencedVars() { const VarDecl *VD = *I; const VarRegion *VR = 0; - if (!VD->getAttr()) + if (!VD->getAttr() && VD->hasLocalStorage()) VR = MemMgr.getVarRegion(VD, this); else { if (LC) diff --git a/lib/Checker/RegionStore.cpp b/lib/Checker/RegionStore.cpp index 528419f0a8..341bfe7a72 100644 --- a/lib/Checker/RegionStore.cpp +++ b/lib/Checker/RegionStore.cpp @@ -606,10 +606,11 @@ Store InvalidateRegionsWorker::InvalidateRegions(RegionStoreManager &RM, // by reference. if (const BlockDataRegion *BR = dyn_cast(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()) + BI = BR->referenced_vars_begin(), BE = BR->referenced_vars_end() ; + BI != BE; ++BI) { + const VarRegion *VR = *BI; + const VarDecl *VD = VR->getDecl(); + if (VD->getAttr() || !VD->hasLocalStorage()) AddToWorkList(VR); } continue; diff --git a/test/Analysis/misc-ps-region-store.m b/test/Analysis/misc-ps-region-store.m index 6666dae2ed..46a8720c19 100644 --- a/test/Analysis/misc-ps-region-store.m +++ b/test/Analysis/misc-ps-region-store.m @@ -595,14 +595,50 @@ int blocks_2(int *p, int z) { typedef void (^RDar7582031CB)(void); @interface RDar7582031 - rdar7582031:RDar7582031CB; +- rdar7582031_b:RDar7582031CB; @end +// Test with one block. unsigned rdar7582031(RDar7582031 *o) { __block unsigned x; [o rdar7582031:^{ x = 1; }]; return x; // no-warning } +// Test with two blocks. +unsigned long rdar7582031_b(RDar7582031 *o) { + __block unsigned y; + __block unsigned long x; + [o rdar7582031:^{ y = 1; }]; + [o rdar7582031_b:^{ x = 1LL; }]; + return x + (unsigned long) y; // no-warning +} + +// Show we get an error when 'o' is null because the message +// expression has no effect. +unsigned long rdar7582031_b2(RDar7582031 *o) { + __block unsigned y; + __block unsigned long x; + if (o) + return 1; + [o rdar7582031:^{ y = 1; }]; + [o rdar7582031_b:^{ x = 1LL; }]; + return x + (unsigned long) y; // expected-warning{{The left operand of '+' is a garbage value}} +} + +// Show that we handle static variables also getting invalidated. +void rdar7582031_aux(void (^)(void)); +RDar7582031 *rdar7582031_aux_2(); + +unsigned rdar7582031_static() { + static RDar7582031 *o = 0; + rdar7582031_aux(^{ o = rdar7582031_aux_2(); }); + + __block unsigned x; + [o rdar7582031:^{ x = 1; }]; + return x; // no-warning +} + //===----------------------------------------------------------------------===// // - Test that variables passed using __blocks // are not treated as being uninitialized. -- 2.40.0