friend class MemRegionManager;
const BlockTextRegion *BC;
const LocationContext *LC; // Can be null */
+ unsigned BlockCount;
void *ReferencedVars;
void *OriginalVars;
BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc,
- const MemRegion *sreg)
+ unsigned count, const MemRegion *sreg)
: TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
+ BlockCount(count),
ReferencedVars(0), OriginalVars(0) {}
public:
void Profile(llvm::FoldingSetNodeID& ID) const;
static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockTextRegion *,
- const LocationContext *, const MemRegion *);
+ const LocationContext *, unsigned,
+ const MemRegion *);
static bool classof(const MemRegion* R) {
return R->getKind() == BlockDataRegionKind;
/// argument is allowed to be NULL for cases where we have no known
/// context.
const BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc,
- const LocationContext *lc = NULL);
+ const LocationContext *lc,
+ unsigned blockCount);
/// Create a CXXTempObjectRegion for temporaries which are lifetime-extended
/// by static references. This differs from getCXXTempObjectRegion in the
DefinedSVal getFunctionPointer(const FunctionDecl *func);
DefinedSVal getBlockPointer(const BlockDecl *block, CanQualType locTy,
- const LocationContext *locContext);
+ const LocationContext *locContext,
+ unsigned blockCount);
/// Returns the value of \p E, if it can be determined in a non-path-sensitive
/// manner.
// Get the value of the block itself.
SVal V = svalBuilder.getBlockPointer(BE->getBlockDecl(), T,
- Pred->getLocationContext());
+ Pred->getLocationContext(),
+ currBldrCtx->blockCount());
ProgramStateRef State = Pred->getState();
void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
const BlockTextRegion *BC,
const LocationContext *LC,
+ unsigned BlkCount,
const MemRegion *sReg) {
ID.AddInteger(MemRegion::BlockDataRegionKind);
ID.AddPointer(BC);
ID.AddPointer(LC);
+ ID.AddInteger(BlkCount);
ID.AddPointer(sReg);
}
void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const {
- BlockDataRegion::ProfileRegion(ID, BC, LC, getSuperRegion());
+ BlockDataRegion::ProfileRegion(ID, BC, LC, BlockCount, getSuperRegion());
}
void CXXTempObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
}
void BlockDataRegion::dumpToStream(raw_ostream &os) const {
- os << "block_data{" << BC << '}';
+ os << "block_data{" << BC;
+ os << "; ";
+ for (BlockDataRegion::referenced_vars_iterator
+ I = referenced_vars_begin(),
+ E = referenced_vars_end(); I != E; ++I)
+ os << "(" << I.getCapturedRegion() << "," <<
+ I.getOriginalRegion() << ") ";
+ os << '}';
}
void CompoundLiteralRegion::dumpToStream(raw_ostream &os) const {
const BlockDataRegion *
MemRegionManager::getBlockDataRegion(const BlockTextRegion *BC,
- const LocationContext *LC) {
+ const LocationContext *LC,
+ unsigned blockCount) {
const MemRegion *sReg = 0;
const BlockDecl *BD = BC->getDecl();
if (!BD->hasCaptures()) {
}
}
- return getSubRegion<BlockDataRegion>(BC, LC, sReg);
+ return getSubRegion<BlockDataRegion>(BC, LC, blockCount, sReg);
}
const CXXTempObjectRegion *
DefinedSVal SValBuilder::getBlockPointer(const BlockDecl *block,
CanQualType locTy,
- const LocationContext *locContext) {
+ const LocationContext *locContext,
+ unsigned blockCount) {
const BlockTextRegion *BC =
MemMgr.getBlockTextRegion(block, locTy, locContext->getAnalysisDeclContext());
- const BlockDataRegion *BD = MemMgr.getBlockDataRegion(BC, locContext);
+ const BlockDataRegion *BD = MemMgr.getBlockDataRegion(BC, locContext,
+ blockCount);
return loc::MemRegionVal(BD);
}
return 42;
}();
}
+
+// This test used to cause infinite loop in the region invalidation.
+void blockCapturesItselfInTheLoop(int x, int m) {
+ void (^assignData)(int) = ^(int x){
+ x++;
+ };
+ while (m < 0) {
+ void (^loop)(int);
+ loop = ^(int x) {
+ assignData(x);
+ };
+ assignData = loop;
+ m++;
+ }
+ assignData(x);
+}