[cfe-commits] r156211 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h lib/StaticAnalyzer/Core/ExprEngineC.cpp lib/StaticAnalyzer/Core/MemRegion.cpp lib/StaticAnalyzer/Core/RegionStore.cpp test/Analysis/misc-ps-region-store.m
Ted Kremenek
kremenek at apple.com
Fri May 4 14:48:42 PDT 2012
Author: kremenek
Date: Fri May 4 16:48:42 2012
New Revision: 156211
URL: http://llvm.org/viewvc/llvm-project?rev=156211&view=rev
Log:
Explicitly model capturing variables for blocks in the static analyzer. Fixes <rdar://problem/11125868>.
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
cfe/trunk/test/Analysis/misc-ps-region-store.m
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h?rev=156211&r1=156210&r2=156211&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h Fri May 4 16:48:42 2012
@@ -580,25 +580,37 @@
const BlockTextRegion *BC;
const LocationContext *LC; // Can be null */
void *ReferencedVars;
+ void *OriginalVars;
BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc,
const MemRegion *sreg)
- : SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), ReferencedVars(0) {}
+ : SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
+ ReferencedVars(0), OriginalVars(0) {}
-public:
+public:
const BlockTextRegion *getCodeRegion() const { return BC; }
const BlockDecl *getDecl() const { return BC->getDecl(); }
class referenced_vars_iterator {
const MemRegion * const *R;
+ const MemRegion * const *OriginalR;
public:
- explicit referenced_vars_iterator(const MemRegion * const *r) : R(r) {}
+ explicit referenced_vars_iterator(const MemRegion * const *r,
+ const MemRegion * const *originalR)
+ : R(r), OriginalR(originalR) {}
operator const MemRegion * const *() const {
return R;
}
-
+
+ const MemRegion *getCapturedRegion() const {
+ return *R;
+ }
+ const MemRegion *getOriginalRegion() const {
+ return *OriginalR;
+ }
+
const VarRegion* operator*() const {
return cast<VarRegion>(*R);
}
@@ -611,6 +623,7 @@
}
referenced_vars_iterator &operator++() {
++R;
+ ++OriginalR;
return *this;
}
};
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=156211&r1=156210&r2=156211&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Fri May 4 16:48:42 2012
@@ -182,14 +182,35 @@
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);
Modified: cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp?rev=156211&r1=156210&r2=156211&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp Fri May 4 16:48:42 2012
@@ -1056,26 +1056,37 @@
typedef BumpVector<const MemRegion*> VarVec;
VarVec *BV = (VarVec*) A.Allocate<VarVec>();
new (BV) VarVec(BC, E - I);
+ VarVec *BVOriginal = (VarVec*) A.Allocate<VarVec>();
+ new (BVOriginal) VarVec(BC, E - I);
for ( ; I != E; ++I) {
const VarDecl *VD = *I;
const VarRegion *VR = 0;
+ const VarRegion *OriginalVR = 0;
- if (!VD->getAttr<BlocksAttr>() && VD->hasLocalStorage())
+ if (!VD->getAttr<BlocksAttr>() && VD->hasLocalStorage()) {
VR = MemMgr.getVarRegion(VD, this);
+ OriginalVR = MemMgr.getVarRegion(VD, LC);
+ }
else {
- if (LC)
+ if (LC) {
VR = MemMgr.getVarRegion(VD, LC);
+ OriginalVR = VR;
+ }
else {
VR = MemMgr.getVarRegion(VD, MemMgr.getUnknownRegion());
+ OriginalVR = MemMgr.getVarRegion(VD, LC);
}
}
assert(VR);
+ assert(OriginalVR);
BV->push_back(VR, BC);
+ BVOriginal->push_back(OriginalVR, BC);
}
ReferencedVars = BV;
+ OriginalVars = BVOriginal;
}
BlockDataRegion::referenced_vars_iterator
@@ -1085,8 +1096,14 @@
BumpVector<const MemRegion*> *Vec =
static_cast<BumpVector<const MemRegion*>*>(ReferencedVars);
- return BlockDataRegion::referenced_vars_iterator(Vec == (void*) 0x1 ?
- NULL : Vec->begin());
+ if (Vec == (void*) 0x1)
+ return BlockDataRegion::referenced_vars_iterator(0, 0);
+
+ BumpVector<const MemRegion*> *VecOriginal =
+ static_cast<BumpVector<const MemRegion*>*>(OriginalVars);
+
+ return BlockDataRegion::referenced_vars_iterator(Vec->begin(),
+ VecOriginal->begin());
}
BlockDataRegion::referenced_vars_iterator
@@ -1096,6 +1113,12 @@
BumpVector<const MemRegion*> *Vec =
static_cast<BumpVector<const MemRegion*>*>(ReferencedVars);
- return BlockDataRegion::referenced_vars_iterator(Vec == (void*) 0x1 ?
- NULL : Vec->end());
+ if (Vec == (void*) 0x1)
+ return BlockDataRegion::referenced_vars_iterator(0, 0);
+
+ BumpVector<const MemRegion*> *VecOriginal =
+ static_cast<BumpVector<const MemRegion*>*>(OriginalVars);
+
+ return BlockDataRegion::referenced_vars_iterator(Vec->end(),
+ VecOriginal->end());
}
Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=156211&r1=156210&r2=156211&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Fri May 4 16:48:42 2012
@@ -681,8 +681,22 @@
BI != BE; ++BI) {
const VarRegion *VR = *BI;
const VarDecl *VD = VR->getDecl();
- if (VD->getAttr<BlocksAttr>() || !VD->hasLocalStorage())
+ if (VD->getAttr<BlocksAttr>() || !VD->hasLocalStorage()) {
AddToWorkList(VR);
+ }
+ else if (Loc::isLocType(VR->getValueType())) {
+ // Map the current bindings to a Store to retrieve the value
+ // of the binding. If that binding itself is a region, we should
+ // invalidate that region. This is because a block may capture
+ // a pointer value, but the thing pointed by that pointer may
+ // get invalidated.
+ Store store = B.getRootWithoutRetain();
+ SVal V = RM.getBinding(store, loc::MemRegionVal(VR));
+ if (const Loc *L = dyn_cast<Loc>(&V)) {
+ if (const MemRegion *LR = L->getAsRegion())
+ AddToWorkList(LR);
+ }
+ }
}
return;
}
Modified: cfe/trunk/test/Analysis/misc-ps-region-store.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps-region-store.m?rev=156211&r1=156210&r2=156211&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/misc-ps-region-store.m (original)
+++ cfe/trunk/test/Analysis/misc-ps-region-store.m Fri May 4 16:48:42 2012
@@ -1341,3 +1341,23 @@
return values[index].value;
}
+// Test handling invalidating arrays passed to a block via captured
+// pointer value (not a __block variable).
+typedef void (^radar11125868_cb)(int *, unsigned);
+
+void rdar11125868_aux(radar11125868_cb cb);
+
+int rdar11125868() {
+ int integersStackArray[1];
+ int *integers = integersStackArray;
+ rdar11125868_aux(^(int *integerValue, unsigned index) {
+ integers[index] = integerValue[index];
+ });
+ return integers[0] == 0; // no-warning
+}
+
+int rdar11125868_positive() {
+ int integersStackArray[1];
+ int *integers = integersStackArray;
+ return integers[0] == 0; // expected-warning {{he left operand of '==' is a}}
+}
More information about the cfe-commits
mailing list