aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/ExprEngineC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngineC.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineC.cpp25
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);