From 4240096011a187807058f887eb81df750ffa17fe Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 26 Nov 2009 02:34:36 +0000 Subject: [PATCH] Add iterators to BlockDataRegion that allow clients to iterate over the VarRegions for "captured" variables for a block. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89927 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../clang/Analysis/PathSensitive/MemRegion.h | 15 ++++- lib/Analysis/MemRegion.cpp | 62 ++++++++++++++++++- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h index 9a361501ce..ed964978a4 100644 --- a/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/include/clang/Analysis/PathSensitive/MemRegion.h @@ -35,6 +35,7 @@ namespace clang { class MemRegionManager; class MemSpaceRegion; class LocationContext; +class VarRegion; //===----------------------------------------------------------------------===// // Base region classes. @@ -42,6 +43,7 @@ class LocationContext; /// MemRegion - The root abstract class for all memory regions. class MemRegion : public llvm::FoldingSetNode { + friend class MemRegionManager; public: enum Kind { MemSpaceRegionKind, SymbolicRegionKind, @@ -329,13 +331,18 @@ public: class BlockDataRegion : public SubRegion { const BlockTextRegion *BC; const LocationContext *LC; + void *ReferencedVars; public: BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc, const MemRegion *sreg) - : SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc) {} + : SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), ReferencedVars(0) {} const BlockTextRegion *getCodeRegion() const { return BC; } + + typedef const MemRegion * const * referenced_vars_iterator; + referenced_vars_iterator referenced_vars_begin() const; + referenced_vars_iterator referenced_vars_end() const; virtual void dumpToStream(llvm::raw_ostream& os) const; @@ -348,6 +355,8 @@ public: static bool classof(const MemRegion* R) { return R->getKind() == BlockDataRegionKind; } +private: + void LazyInitializeReferencedVars(); }; /// SymbolicRegion - A special, "non-concrete" region. Unlike other region @@ -650,9 +659,11 @@ public: : C(c), A(a), globals(0), stack(0), stackArguments(0), heap(0), unknown(0), code(0) {} - ~MemRegionManager() {} + ~MemRegionManager(); ASTContext &getContext() { return C; } + + llvm::BumpPtrAllocator &getAllocator() { return A; } /// getStackRegion - Retrieve the memory region associated with the /// current stack frame. diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp index 430ec238c8..af8bd16ee6 100644 --- a/lib/Analysis/MemRegion.cpp +++ b/lib/Analysis/MemRegion.cpp @@ -17,15 +17,25 @@ #include "clang/Analysis/PathSensitive/MemRegion.h" #include "clang/Analysis/PathSensitive/ValueManager.h" #include "clang/Analysis/PathSensitive/AnalysisContext.h" +#include "clang/AST/StmtVisitor.h" using namespace clang; //===----------------------------------------------------------------------===// -// Basic methods. +// Object destruction. //===----------------------------------------------------------------------===// MemRegion::~MemRegion() {} +MemRegionManager::~MemRegionManager() { + // All regions and their data are BumpPtrAllocated. No need to call + // their destructors. +} + +//===----------------------------------------------------------------------===// +// Basic methods. +//===----------------------------------------------------------------------===// + bool SubRegion::isSubRegionOf(const MemRegion* R) const { const MemRegion* r = getSuperRegion(); while (r != 0) { @@ -525,3 +535,53 @@ RegionRawOffset ElementRegion::getAsRawOffset() const { return RegionRawOffset(superR, offset); } +//===----------------------------------------------------------------------===// +// BlockDataRegion +//===----------------------------------------------------------------------===// + +void BlockDataRegion::LazyInitializeReferencedVars() { + if (ReferencedVars) + return; + + AnalysisContext *AC = LC->getAnalysisContext(); + AnalysisContext::referenced_decls_iterator I, E; + llvm::tie(I, E) = AC->getReferencedBlockVars(BC->getDecl()); + + if (I == E) { + ReferencedVars = (void*) 0x1; + return; + } + + MemRegionManager &MemMgr = *getMemRegionManager(); + llvm::BumpPtrAllocator &A = MemMgr.getAllocator(); + BumpVectorContext BC(A); + + typedef BumpVector VarVec; + VarVec *BV = (VarVec*) A.Allocate(); + new (BV) VarVec(BC, (E - I) / sizeof(*I)); + + for ( ; I != E; ++I) + BV->push_back(MemMgr.getVarRegion(*I, LC), BC); + + ReferencedVars = BV; +} + +BlockDataRegion::referenced_vars_iterator +BlockDataRegion::referenced_vars_begin() const { + const_cast(this)->LazyInitializeReferencedVars(); + + BumpVector *Vec = + static_cast*>(ReferencedVars); + + return Vec == (void*) 0x1 ? NULL : Vec->begin(); +} + +BlockDataRegion::referenced_vars_iterator +BlockDataRegion::referenced_vars_end() const { + const_cast(this)->LazyInitializeReferencedVars(); + + BumpVector *Vec = + static_cast*>(ReferencedVars); + + return Vec == (void*) 0x1 ? NULL : Vec->end(); +} -- 2.40.0