diff options
author | Ted Kremenek <kremenek@apple.com> | 2012-05-04 21:48:42 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2012-05-04 21:48:42 +0000 |
commit | 85d87df66a50a15a1957f7213802000b451a8ec9 (patch) | |
tree | 24a4c26b96e7d536b8f72a538e9916ea7a330659 /lib/StaticAnalyzer/Core/ExprEngineC.cpp | |
parent | 396663b22cd72e2a0164a6655d92d3a69d28b579 (diff) |
Explicitly model capturing variables for blocks in the static analyzer. Fixes <rdar://problem/11125868>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156211 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngineC.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineC.cpp | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/lib/StaticAnalyzer/Core/ExprEngineC.cpp index d5555daecd..cf94ac3060 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -182,14 +182,35 @@ void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, ExplodedNodeSet &Dst) { CanQualType T = getContext().getCanonicalType(BE->getType()); + + // Get the value of the block itself. SVal V = svalBuilder.getBlockPointer(BE->getBlockDecl(), T, Pred->getLocationContext()); + ProgramStateRef State = Pred->getState(); + + // If we created a new MemRegion for the block, we should explicitly bind + // the captured variables. + if (const BlockDataRegion *BDR = + dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) { + + BlockDataRegion::referenced_vars_iterator I = BDR->referenced_vars_begin(), + E = BDR->referenced_vars_end(); + + for (; I != E; ++I) { + const MemRegion *capturedR = I.getCapturedRegion(); + const MemRegion *originalR = I.getOriginalRegion(); + if (capturedR != originalR) { + SVal originalV = State->getSVal(loc::MemRegionVal(originalR)); + State = State->bindLoc(loc::MemRegionVal(capturedR), originalV); + } + } + } + ExplodedNodeSet Tmp; StmtNodeBuilder Bldr(Pred, Tmp, *currentBuilderContext); Bldr.generateNode(BE, Pred, - Pred->getState()->BindExpr(BE, Pred->getLocationContext(), - V), + State->BindExpr(BE, Pred->getLocationContext(), V), false, 0, ProgramPoint::PostLValueKind); |