diff options
-rw-r--r-- | include/clang/Analysis/PathSensitive/MemRegion.h | 63 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/ValueManager.h | 3 | ||||
-rw-r--r-- | lib/Analysis/CFRefCount.cpp | 2 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 4 | ||||
-rw-r--r-- | lib/Analysis/MemRegion.cpp | 32 | ||||
-rw-r--r-- | lib/Analysis/RegionStore.cpp | 2 | ||||
-rw-r--r-- | lib/Analysis/ValueManager.cpp | 10 |
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); } |