aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Analysis/PathSensitive/MemRegion.h63
-rw-r--r--include/clang/Analysis/PathSensitive/ValueManager.h3
-rw-r--r--lib/Analysis/CFRefCount.cpp2
-rw-r--r--lib/Analysis/GRExprEngine.cpp4
-rw-r--r--lib/Analysis/MemRegion.cpp32
-rw-r--r--lib/Analysis/RegionStore.cpp2
-rw-r--r--lib/Analysis/ValueManager.cpp10
7 files changed, 107 insertions, 9 deletions
diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h
index df9caedefc..9a361501ce 100644
--- a/include/clang/Analysis/PathSensitive/MemRegion.h
+++ b/include/clang/Analysis/PathSensitive/MemRegion.h
@@ -50,6 +50,7 @@ public:
BEG_TYPED_REGIONS,
FunctionTextRegionKind,
BlockTextRegionKind,
+ BlockDataRegionKind,
CompoundLiteralRegionKind,
StringRegionKind, ElementRegionKind,
// Decl Regions.
@@ -286,6 +287,11 @@ public:
/// BlockTextRegion - A region that represents code texts of blocks (closures).
+/// Blocks are represented with two kinds of regions. BlockTextRegions
+/// represent the "code", while BlockDataRegions represent instances of blocks,
+/// which correspond to "code+data". The distinction is important, because
+/// like a closure a block captures the values of externally referenced
+/// variables.
class BlockTextRegion : public CodeTextRegion {
const BlockDecl *BD;
CanQualType locTy;
@@ -312,6 +318,37 @@ public:
return R->getKind() == BlockTextRegionKind;
}
};
+
+/// BlockDataRegion - A region that represents a block instance.
+/// Blocks are represented with two kinds of regions. BlockTextRegions
+/// represent the "code", while BlockDataRegions represent instances of blocks,
+/// which correspond to "code+data". The distinction is important, because
+/// like a closure a block captures the values of externally referenced
+/// variables.
+/// BlockDataRegion - A region that represents code texts of blocks (closures).
+class BlockDataRegion : public SubRegion {
+ const BlockTextRegion *BC;
+ const LocationContext *LC;
+public:
+ BlockDataRegion(const BlockTextRegion *bc,
+ const LocationContext *lc,
+ const MemRegion *sreg)
+ : SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc) {}
+
+ const BlockTextRegion *getCodeRegion() const { return BC; }
+
+ virtual void dumpToStream(llvm::raw_ostream& os) const;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID,
+ const BlockTextRegion *BC,
+ const LocationContext *LC, const MemRegion *);
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == BlockDataRegionKind;
+ }
+};
/// SymbolicRegion - A special, "non-concrete" region. Unlike other region
/// clases, SymbolicRegion represents a region that serves as an alias for
@@ -694,7 +731,8 @@ public:
FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD);
BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, CanQualType locTy);
-
+ BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc,
+ const LocationContext *lc);
template <typename RegionTy, typename A1>
RegionTy* getRegion(const A1 a1);
@@ -705,6 +743,10 @@ public:
template <typename RegionTy, typename A1, typename A2>
RegionTy* getRegion(const A1 a1, const A2 a2);
+ template <typename RegionTy, typename A1, typename A2>
+ RegionTy* getSubRegion(const A1 a1, const A2 a2,
+ const MemRegion* superRegion);
+
bool isGlobalsRegion(const MemRegion* R) {
assert(R);
return R == globals;
@@ -783,6 +825,25 @@ RegionTy* MemRegionManager::getRegion(const A1 a1, const A2 a2) {
return R;
}
+
+template <typename RegionTy, typename A1, typename A2>
+RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2,
+ const MemRegion *superRegion) {
+
+ llvm::FoldingSetNodeID ID;
+ RegionTy::ProfileRegion(ID, a1, a2, superRegion);
+ void* InsertPos;
+ RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
+ InsertPos));
+
+ if (!R) {
+ R = (RegionTy*) A.Allocate<RegionTy>();
+ new (R) RegionTy(a1, a2, superRegion);
+ Regions.InsertNode(R, InsertPos);
+ }
+
+ return R;
+}
//===----------------------------------------------------------------------===//
// Traits for constructing regions.
diff --git a/include/clang/Analysis/PathSensitive/ValueManager.h b/include/clang/Analysis/PathSensitive/ValueManager.h
index 66d4315864..ef4e069ce8 100644
--- a/include/clang/Analysis/PathSensitive/ValueManager.h
+++ b/include/clang/Analysis/PathSensitive/ValueManager.h
@@ -115,7 +115,8 @@ public:
DefinedSVal getFunctionPointer(const FunctionDecl *FD);
- DefinedSVal getBlockPointer(const BlockDecl *BD, CanQualType locTy);
+ DefinedSVal getBlockPointer(const BlockDecl *BD, CanQualType locTy,
+ const LocationContext *LC);
NonLoc makeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals) {
return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals));
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index 10d07762db..06aa6bd279 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -3002,7 +3002,7 @@ void CFRefCount::EvalCall(ExplodedNodeSet& Dst,
// FIXME: Better support for blocks. For now we stop tracking anything
// that is passed to blocks.
// FIXME: Need to handle variables that are "captured" by the block.
- if (dyn_cast_or_null<BlockTextRegion>(L.getAsRegion())) {
+ if (dyn_cast_or_null<BlockDataRegion>(L.getAsRegion())) {
Summ = Summaries.getPersistentStopSummary();
}
else {
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index cb3f68b41d..12e9ba8864 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -1107,7 +1107,9 @@ void GRExprEngine::VisitBlockExpr(BlockExpr *BE, ExplodedNode *Pred,
ExplodedNodeSet Tmp;
CanQualType T = getContext().getCanonicalType(BE->getType());
- SVal V = ValMgr.getBlockPointer(BE->getBlockDecl(), T);
+ SVal V = ValMgr.getBlockPointer(BE->getBlockDecl(), T,
+ Pred->getLocationContext());
+
MakeNode(Tmp, BE, Pred, GetState(Pred)->BindExpr(BE, V),
ProgramPoint::PostLValueKind);
diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp
index 8b4c7a6a24..430ec238c8 100644
--- a/lib/Analysis/MemRegion.cpp
+++ b/lib/Analysis/MemRegion.cpp
@@ -148,6 +148,19 @@ void BlockTextRegion::Profile(llvm::FoldingSetNodeID& ID) const {
BlockTextRegion::ProfileRegion(ID, BD, locTy, superRegion);
}
+void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
+ const BlockTextRegion *BC,
+ const LocationContext *LC,
+ const MemRegion *) {
+ ID.AddInteger(MemRegion::BlockDataRegionKind);
+ ID.AddPointer(BC);
+ ID.AddPointer(LC);
+}
+
+void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const {
+ BlockDataRegion::ProfileRegion(ID, BC, LC, NULL);
+}
+
//===----------------------------------------------------------------------===//
// Region pretty-printing.
//===----------------------------------------------------------------------===//
@@ -176,9 +189,14 @@ void FunctionTextRegion::dumpToStream(llvm::raw_ostream& os) const {
}
void BlockTextRegion::dumpToStream(llvm::raw_ostream& os) const {
- os << "block{" << (void*) this << '}';
+ os << "block_code{" << (void*) this << '}';
}
+void BlockDataRegion::dumpToStream(llvm::raw_ostream& os) const {
+ os << "block_data{" << BC << '}';
+}
+
+
void CompoundLiteralRegion::dumpToStream(llvm::raw_ostream& os) const {
// FIXME: More elaborate pretty-printing.
os << "{ " << (void*) CL << " }";
@@ -274,6 +292,18 @@ VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
return getRegion<VarRegion>(D, LC);
}
+BlockDataRegion *MemRegionManager::getBlockDataRegion(const BlockTextRegion *BC,
+ const LocationContext *LC)
+{
+ // FIXME: Once we implement scope handling, we will need to properly lookup
+ // 'D' to the proper LocationContext. For now, just strip down to the
+ // StackFrame.
+ while (!isa<StackFrameContext>(LC))
+ LC = LC->getParent();
+
+ return getSubRegion<BlockDataRegion>(BC, LC, getStackRegion());
+}
+
CompoundLiteralRegion*
MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL) {
return getRegion<CompoundLiteralRegion>(CL);
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index 16a4690f95..deb6c07852 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -714,6 +714,7 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state,
case MemRegion::FunctionTextRegionKind:
case MemRegion::BlockTextRegionKind:
+ case MemRegion::BlockDataRegionKind:
// Technically this can happen if people do funny things with casts.
return UnknownVal();
@@ -860,6 +861,7 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state,
case MemRegion::FunctionTextRegionKind:
case MemRegion::BlockTextRegionKind:
+ case MemRegion::BlockDataRegionKind:
// Technically this can happen if people do funny things with casts.
return UnknownVal();
diff --git a/lib/Analysis/ValueManager.cpp b/lib/Analysis/ValueManager.cpp
index 37df443602..22a821149d 100644
--- a/lib/Analysis/ValueManager.cpp
+++ b/lib/Analysis/ValueManager.cpp
@@ -142,9 +142,11 @@ DefinedSVal ValueManager::getFunctionPointer(const FunctionDecl* FD) {
return loc::MemRegionVal(R);
}
-DefinedSVal ValueManager::getBlockPointer(const BlockDecl *BD,
- CanQualType locTy) {
- CodeTextRegion *R = MemMgr.getBlockTextRegion(BD, locTy);
- return loc::MemRegionVal(R);
+DefinedSVal ValueManager::getBlockPointer(const BlockDecl *D,
+ CanQualType locTy,
+ const LocationContext *LC) {
+ BlockTextRegion *BC = MemMgr.getBlockTextRegion(D, locTy);
+ BlockDataRegion *BD = MemMgr.getBlockDataRegion(BC, LC);
+ return loc::MemRegionVal(BD);
}