From 67d1287035767f4f6c8ca0c2bb755990012a44ca Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Mon, 7 Dec 2009 22:05:27 +0000 Subject: [PATCH] Add analysis support for blocks. This includes a few key changes: - Refactor the MemRegion hierarchy to distinguish between different StackSpaceRegions for locals and parameters. - VarRegions for "captured" variables now have the BlockDataRegion as their super region (except those passed by reference) - Add transfer function support to GRExprEngine for BlockDeclRefExprs. This change also supports analyzing blocks as an analysis entry point (top-of-the-stack), which required pushing more context-sensitivity around in the MemRegion hierarchy via the use of LocationContext objects. Functionally almost everything is the same, except we track LocationContexts in a few more areas and StackSpaceRegions now refer to a StackFrameContext object. In the future we will need to modify MemRegionManager to allow multiple StackSpaceRegions in flight at once (for the analysis of multiple stack frames). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90809 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Analysis/PathSensitive/AnalysisContext.h | 5 +- .../Analysis/PathSensitive/GRExprEngine.h | 7 + .../clang/Analysis/PathSensitive/GRState.h | 16 +- .../clang/Analysis/PathSensitive/MemRegion.h | 241 ++++++++++----- include/clang/Analysis/PathSensitive/Store.h | 8 +- lib/Analysis/AnalysisContext.cpp | 14 + lib/Analysis/BasicStore.cpp | 8 +- lib/Analysis/CFRefCount.cpp | 19 +- lib/Analysis/GRExprEngine.cpp | 32 +- lib/Analysis/MemRegion.cpp | 277 +++++++++--------- lib/Analysis/RegionStore.cpp | 45 ++- lib/Analysis/Store.cpp | 23 +- lib/Analysis/ValueManager.cpp | 4 +- 13 files changed, 437 insertions(+), 262 deletions(-) diff --git a/include/clang/Analysis/PathSensitive/AnalysisContext.h b/include/clang/Analysis/PathSensitive/AnalysisContext.h index 08b7f094a9..0a6646e550 100644 --- a/include/clang/Analysis/PathSensitive/AnalysisContext.h +++ b/include/clang/Analysis/PathSensitive/AnalysisContext.h @@ -32,7 +32,8 @@ class ParentMap; class ImplicitParamDecl; class LocationContextManager; class BlockDataRegion; - +class StackFrameContext; + /// AnalysisContext contains the context data for the function or method under /// analysis. class AnalysisContext { @@ -117,6 +118,8 @@ public: const ImplicitParamDecl *getSelfDecl() const { return Ctx->getSelfDecl(); } + + const StackFrameContext *getCurrentStackFrame() const; virtual void Profile(llvm::FoldingSetNodeID &ID) = 0; diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index b1023fe968..8b20a823c6 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -281,6 +281,13 @@ protected: void VisitDeclRefExpr(DeclRefExpr* DR, ExplodedNode* Pred, ExplodedNodeSet& Dst, bool asLValue); + /// VisitBlockDeclRefExpr - Transfer function logic for BlockDeclRefExprs. + void VisitBlockDeclRefExpr(BlockDeclRefExpr* DR, ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); + + void VisitCommonDeclRefExpr(Expr* DR, const NamedDecl *D,ExplodedNode* Pred, + ExplodedNodeSet& Dst, bool asLValue); + /// VisitDeclStmt - Transfer function logic for DeclStmts. void VisitDeclStmt(DeclStmt* DS, ExplodedNode* Pred, ExplodedNodeSet& Dst); diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h index d8bc241175..421ebbf9bd 100644 --- a/include/clang/Analysis/PathSensitive/GRState.h +++ b/include/clang/Analysis/PathSensitive/GRState.h @@ -217,6 +217,7 @@ public: /// for the compound literal and 'BegInit' and 'EndInit' represent an /// array of initializer values. const GRState* bindCompoundLiteral(const CompoundLiteralExpr* CL, + const LocationContext *LC, SVal V) const; const GRState *BindExpr(const Stmt *S, SVal V, bool Invalidate = true) const; @@ -237,7 +238,8 @@ public: /// Get the lvalue for a StringLiteral. SVal getLValue(const StringLiteral *literal) const; - SVal getLValue(const CompoundLiteralExpr *literal) const; + SVal getLValue(const CompoundLiteralExpr *literal, + const LocationContext *LC) const; /// Get the lvalue for an ivar reference. SVal getLValue(const ObjCIvarDecl *decl, SVal base) const; @@ -609,9 +611,10 @@ inline const GRState *GRState::AssumeInBound(DefinedOrUnknownSVal Idx, cast(UpperBound), Assumption); } -inline const GRState *GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL, - SVal V) const { - return getStateManager().StoreMgr->BindCompoundLiteral(this, CL, V); +inline const GRState * +GRState::bindCompoundLiteral(const CompoundLiteralExpr* CL, + const LocationContext *LC, SVal V) const { + return getStateManager().StoreMgr->BindCompoundLiteral(this, CL, LC, V); } inline const GRState *GRState::bindDecl(const VarRegion* VR, SVal IVal) const { @@ -639,8 +642,9 @@ inline SVal GRState::getLValue(const StringLiteral *literal) const { return getStateManager().StoreMgr->getLValueString(literal); } -inline SVal GRState::getLValue(const CompoundLiteralExpr *literal) const { - return getStateManager().StoreMgr->getLValueCompoundLiteral(literal); +inline SVal GRState::getLValue(const CompoundLiteralExpr *literal, + const LocationContext *LC) const { + return getStateManager().StoreMgr->getLValueCompoundLiteral(literal, LC); } inline SVal GRState::getLValue(const ObjCIvarDecl *D, SVal Base) const { diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h index 05aacd1e0c..efe4b9bb96 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 StackFrameContext; class VarRegion; //===----------------------------------------------------------------------===// @@ -45,22 +46,36 @@ class VarRegion; class MemRegion : public llvm::FoldingSetNode { friend class MemRegionManager; public: - enum Kind { MemSpaceRegionKind, - SymbolicRegionKind, - AllocaRegionKind, - // Typed regions. - BEG_TYPED_REGIONS, - FunctionTextRegionKind, - BlockTextRegionKind, - BlockDataRegionKind, - CompoundLiteralRegionKind, - StringRegionKind, ElementRegionKind, - // Decl Regions. - BEG_DECL_REGIONS, - VarRegionKind, FieldRegionKind, - ObjCIvarRegionKind, ObjCObjectRegionKind, - END_DECL_REGIONS, - END_TYPED_REGIONS }; + enum Kind { + // Memory spaces. + BEG_MEMSPACES, + GenericMemSpaceRegionKind = BEG_MEMSPACES, + StackLocalsSpaceRegionKind, + StackArgumentsSpaceRegionKind, + HeapSpaceRegionKind, + GlobalsSpaceRegionKind, + END_MEMSPACES = GlobalsSpaceRegionKind, + // Untyped regions. + SymbolicRegionKind, + AllocaRegionKind, + // Typed regions. + BEG_TYPED_REGIONS, + FunctionTextRegionKind = BEG_TYPED_REGIONS, + BlockTextRegionKind, + BlockDataRegionKind, + CompoundLiteralRegionKind, + StringRegionKind, + ElementRegionKind, + // Decl Regions. + BEG_DECL_REGIONS, + VarRegionKind = BEG_DECL_REGIONS, + FieldRegionKind, + ObjCIvarRegionKind, + ObjCObjectRegionKind, + END_DECL_REGIONS = ObjCObjectRegionKind, + END_TYPED_REGIONS = END_DECL_REGIONS + }; + private: const Kind kind; @@ -111,25 +126,92 @@ public: /// MemSpaceRegion - A memory region that represents and "memory space"; /// for example, the set of global variables, the stack frame, etc. class MemSpaceRegion : public MemRegion { - friend class MemRegionManager; - protected: + friend class MemRegionManager; + MemRegionManager *Mgr; - MemSpaceRegion(MemRegionManager *mgr) : MemRegion(MemSpaceRegionKind), - Mgr(mgr) {} - - MemRegionManager* getMemRegionManager() const { - return Mgr; + MemSpaceRegion(MemRegionManager *mgr, Kind k = GenericMemSpaceRegionKind) + : MemRegion(k), Mgr(mgr) { + assert(classof(this)); } + MemRegionManager* getMemRegionManager() const { return Mgr; } + public: - void Profile(llvm::FoldingSetNodeID& ID) const; - bool isBoundable() const { return false; } + + void Profile(llvm::FoldingSetNodeID &ID) const; - static bool classof(const MemRegion* R) { - return R->getKind() == MemSpaceRegionKind; + static bool classof(const MemRegion *R) { + Kind k = R->getKind(); + return k >= BEG_MEMSPACES && k <= END_MEMSPACES; + } +}; + +class GlobalsSpaceRegion : public MemSpaceRegion { + friend class MemRegionManager; + + GlobalsSpaceRegion(MemRegionManager *mgr) + : MemSpaceRegion(mgr, GlobalsSpaceRegionKind) {} +public: + static bool classof(const MemRegion *R) { + return R->getKind() == GlobalsSpaceRegionKind; + } +}; + +class HeapSpaceRegion : public MemSpaceRegion { + friend class MemRegionManager; + + HeapSpaceRegion(MemRegionManager *mgr) + : MemSpaceRegion(mgr, HeapSpaceRegionKind) {} +public: + static bool classof(const MemRegion *R) { + return R->getKind() == HeapSpaceRegionKind; + } +}; + +class StackSpaceRegion : public MemSpaceRegion { +private: + const StackFrameContext *SFC; + +protected: + StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc) + : MemSpaceRegion(mgr, k), SFC(sfc) { + assert(classof(this)); + } + +public: + const StackFrameContext *getStackFrame() const { return SFC; } + + void Profile(llvm::FoldingSetNodeID &ID) const; + + static bool classof(const MemRegion *R) { + Kind k = R->getKind(); + return k >= StackLocalsSpaceRegionKind && + k <= StackArgumentsSpaceRegionKind; + } +}; + +class StackLocalsSpaceRegion : public StackSpaceRegion { +private: + friend class MemRegionManager; + StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) + : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {} +public: + static bool classof(const MemRegion *R) { + return R->getKind() == StackLocalsSpaceRegionKind; + } +}; + +class StackArgumentsSpaceRegion : public StackSpaceRegion { +private: + friend class MemRegionManager; + StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) + : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {} +public: + static bool classof(const MemRegion *R) { + return R->getKind() == StackArgumentsSpaceRegionKind; } }; @@ -149,7 +231,7 @@ public: bool isSubRegionOf(const MemRegion* R) const; static bool classof(const MemRegion* R) { - return R->getKind() > MemSpaceRegionKind; + return R->getKind() > END_MEMSPACES; } }; @@ -237,7 +319,7 @@ public: static bool classof(const MemRegion* R) { unsigned k = R->getKind(); - return k > BEG_TYPED_REGIONS && k < END_TYPED_REGIONS; + return k >= BEG_TYPED_REGIONS && k <= END_TYPED_REGIONS; } }; @@ -295,12 +377,17 @@ public: /// like a closure a block captures the values of externally referenced /// variables. class BlockTextRegion : public CodeTextRegion { + friend class MemRegionManager; + const BlockDecl *BD; + AnalysisContext *AC; CanQualType locTy; -public: - BlockTextRegion(const BlockDecl *bd, CanQualType lTy, const MemRegion* sreg) - : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), locTy(lTy) {} - + + BlockTextRegion(const BlockDecl *bd, CanQualType lTy, + AnalysisContext *ac, const MemRegion* sreg) + : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {} + +public: QualType getLocationType(ASTContext &C) const { return locTy; } @@ -308,13 +395,16 @@ public: const BlockDecl *getDecl() const { return BD; } + + AnalysisContext *getAnalysisContext() const { return AC; } virtual void dumpToStream(llvm::raw_ostream& os) const; void Profile(llvm::FoldingSetNodeID& ID) const; static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD, - CanQualType, const MemRegion*); + CanQualType, const AnalysisContext*, + const MemRegion*); static bool classof(const MemRegion* R) { return R->getKind() == BlockTextRegionKind; @@ -329,15 +419,16 @@ public: /// variables. /// BlockDataRegion - A region that represents code texts of blocks (closures). class BlockDataRegion : public SubRegion { + friend class MemRegionManager; const BlockTextRegion *BC; - const LocationContext *LC; + const LocationContext *LC; // Can be null */ void *ReferencedVars; -public: - BlockDataRegion(const BlockTextRegion *bc, - const LocationContext *lc, + + BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc, const MemRegion *sreg) : SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), ReferencedVars(0) {} +public: const BlockTextRegion *getCodeRegion() const { return BC; } const BlockDecl *getDecl() const { return BC->getDecl(); } @@ -374,9 +465,8 @@ public: void Profile(llvm::FoldingSetNodeID& ID) const; - static void ProfileRegion(llvm::FoldingSetNodeID& ID, - const BlockTextRegion *BC, - const LocationContext *LC, const MemRegion *); + static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockTextRegion *, + const LocationContext *, const MemRegion *); static bool classof(const MemRegion* R) { return R->getKind() == BlockDataRegionKind; @@ -499,25 +589,20 @@ public: static bool classof(const MemRegion* R) { unsigned k = R->getKind(); - return k > BEG_DECL_REGIONS && k < END_DECL_REGIONS; + return k >= BEG_DECL_REGIONS && k <= END_DECL_REGIONS; } }; class VarRegion : public DeclRegion { friend class MemRegionManager; - // Data. - const LocationContext *LC; - // Constructors and private methods. - VarRegion(const VarDecl* vd, const LocationContext *lC, const MemRegion* sReg) - : DeclRegion(vd, sReg, VarRegionKind), LC(lC) {} + VarRegion(const VarDecl* vd, const MemRegion* sReg) + : DeclRegion(vd, sReg, VarRegionKind) {} static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl* VD, - const LocationContext *LC, const MemRegion *superRegion) { DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind); - ID.AddPointer(LC); } void Profile(llvm::FoldingSetNodeID& ID) const; @@ -525,8 +610,6 @@ class VarRegion : public DeclRegion { public: const VarDecl *getDecl() const { return cast(D); } - const LocationContext *getLocationContext() const { return LC; } - QualType getValueType(ASTContext& C) const { // FIXME: We can cache this if needed. return C.getCanonicalType(getDecl()->getType()); @@ -673,16 +756,16 @@ class MemRegionManager { llvm::BumpPtrAllocator& A; llvm::FoldingSet Regions; - MemSpaceRegion *globals; - MemSpaceRegion *stack; - MemSpaceRegion *stackArguments; - MemSpaceRegion *heap; + GlobalsSpaceRegion *globals; + StackLocalsSpaceRegion *stackLocals; + StackArgumentsSpaceRegion *stackArguments; + HeapSpaceRegion *heap; MemSpaceRegion *unknown; MemSpaceRegion *code; public: MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a) - : C(c), A(a), globals(0), stack(0), stackArguments(0), heap(0), + : C(c), A(a), globals(0), stackLocals(0), stackArguments(0), heap(0), unknown(0), code(0) {} ~MemRegionManager(); @@ -691,21 +774,23 @@ public: llvm::BumpPtrAllocator &getAllocator() { return A; } - /// getStackRegion - Retrieve the memory region associated with the - /// current stack frame. - const MemSpaceRegion *getStackRegion(); + /// getStackLocalsRegion - Retrieve the memory region associated with the + /// specified stack frame. + const StackLocalsSpaceRegion * + getStackLocalsRegion(const StackFrameContext *STC); /// getStackArgumentsRegion - Retrieve the memory region associated with - /// function/method arguments of the current stack frame. - const MemSpaceRegion *getStackArgumentsRegion(); + /// function/method arguments of the specified stack frame. + const StackArgumentsSpaceRegion * + getStackArgumentsRegion(const StackFrameContext *STC); /// getGlobalsRegion - Retrieve the memory region associated with /// all global variables. - const MemSpaceRegion *getGlobalsRegion(); + const GlobalsSpaceRegion *getGlobalsRegion(); /// getHeapRegion - Retrieve the memory region associated with the /// generic "heap". - const MemSpaceRegion *getHeapRegion(); + const HeapSpaceRegion *getHeapRegion(); /// getUnknownRegion - Retrieve the memory region associated with unknown /// memory space. @@ -714,12 +799,14 @@ public: const MemSpaceRegion *getCodeRegion(); /// getAllocaRegion - Retrieve a region associated with a call to alloca(). - const AllocaRegion *getAllocaRegion(const Expr* Ex, unsigned Cnt); + const AllocaRegion *getAllocaRegion(const Expr* Ex, unsigned Cnt, + const LocationContext *LC); /// getCompoundLiteralRegion - Retrieve the region associated with a /// given CompoundLiteral. const CompoundLiteralRegion* - getCompoundLiteralRegion(const CompoundLiteralExpr* CL); + getCompoundLiteralRegion(const CompoundLiteralExpr* CL, + const LocationContext *LC); /// getSymbolicRegion - Retrieve or create a "symbolic" memory region. const SymbolicRegion* getSymbolicRegion(SymbolRef sym); @@ -730,6 +817,10 @@ public: /// a specified VarDecl and LocationContext. const VarRegion* getVarRegion(const VarDecl *D, const LocationContext *LC); + /// getVarRegion - Retrieve or create the memory region associated with + /// a specified VarDecl and super region. + const VarRegion* getVarRegion(const VarDecl *D, const MemRegion *superR); + /// getElementRegion - Retrieve the memory region associated with the /// associated element type, index, and super region. const ElementRegion *getElementRegion(QualType elementType, SVal Idx, @@ -768,9 +859,15 @@ public: const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD); const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, - CanQualType locTy); + CanQualType locTy, + AnalysisContext *AC); + + /// getBlockDataRegion - Get the memory region associated with an instance + /// of a block. Unlike many other MemRegions, the LocationContext* + /// argument is allowed to be NULL for cases where we have no known + /// context. const BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc, - const LocationContext *lc); + const LocationContext *lc = NULL); bool isGlobalsRegion(const MemRegion* R) { assert(R); @@ -791,7 +888,15 @@ private: RegionTy* getSubRegion(const A1 a1, const A2 a2, const MemRegion* superRegion); - const MemSpaceRegion* LazyAllocate(MemSpaceRegion*& region); + template + RegionTy* getSubRegion(const A1 a1, const A2 a2, const A3 a3, + const MemRegion* superRegion); + + template + const REG* LazyAllocate(REG*& region); + + template + const REG* LazyAllocate(REG*& region, ARG a); }; //===----------------------------------------------------------------------===// diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h index 51f09c30df..648710f7ad 100644 --- a/include/clang/Analysis/PathSensitive/Store.h +++ b/include/clang/Analysis/PathSensitive/Store.h @@ -73,8 +73,9 @@ public: /// for the compound literal and 'BegInit' and 'EndInit' represent an /// array of initializer values. virtual const GRState *BindCompoundLiteral(const GRState *state, - const CompoundLiteralExpr* cl, - SVal v) = 0; + const CompoundLiteralExpr* cl, + const LocationContext *LC, + SVal v) = 0; /// getInitialStore - Returns the initial "empty" store representing the /// value bindings upon entry to an analyzed function. @@ -93,7 +94,8 @@ public: virtual SVal getLValueString(const StringLiteral* sl) = 0; - virtual SVal getLValueCompoundLiteral(const CompoundLiteralExpr* cl) = 0; + SVal getLValueCompoundLiteral(const CompoundLiteralExpr* cl, + const LocationContext *LC); virtual SVal getLValueIvar(const ObjCIvarDecl* decl, SVal base) = 0; diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp index 6b74b52493..113587f60e 100644 --- a/lib/Analysis/AnalysisContext.cpp +++ b/lib/Analysis/AnalysisContext.cpp @@ -165,6 +165,20 @@ LocationContextManager::getBlockInvocation(AnalysisContext *ctx, BR); } +//===----------------------------------------------------------------------===// +// LocationContext methods. +//===----------------------------------------------------------------------===// + +const StackFrameContext *LocationContext::getCurrentStackFrame() const { + const LocationContext *LC = this; + while (LC) { + if (const StackFrameContext *SFC = dyn_cast(LC)) + return SFC; + LC = LC->getParent(); + } + return NULL; +} + //===----------------------------------------------------------------------===// // Lazily generated map to query the external variables referenced by a Block. //===----------------------------------------------------------------------===// diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp index c2bf7a8d71..a38aaa7eb2 100644 --- a/lib/Analysis/BasicStore.cpp +++ b/lib/Analysis/BasicStore.cpp @@ -68,14 +68,14 @@ public: } const GRState *BindCompoundLiteral(const GRState *state, - const CompoundLiteralExpr* cl, + const CompoundLiteralExpr*, + const LocationContext*, SVal val) { return state; } SVal getLValueVar(const VarDecl *VD, const LocationContext *LC); SVal getLValueString(const StringLiteral *S); - SVal getLValueCompoundLiteral(const CompoundLiteralExpr *CL); SVal getLValueIvar(const ObjCIvarDecl* D, SVal Base); SVal getLValueField(const FieldDecl *D, SVal Base); SVal getLValueElement(QualType elementType, SVal Offset, SVal Base); @@ -130,10 +130,6 @@ SVal BasicStoreManager::getLValueString(const StringLiteral* S) { return ValMgr.makeLoc(MRMgr.getStringRegion(S)); } -SVal BasicStoreManager::getLValueCompoundLiteral(const CompoundLiteralExpr* CL){ - return ValMgr.makeLoc(MRMgr.getCompoundLiteralRegion(CL)); -} - SVal BasicStoreManager::getLValueIvar(const ObjCIvarDecl* D, SVal Base) { if (Base.isUnknownOrUndef()) diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index 288645d227..1df4f7cb51 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -3681,7 +3681,24 @@ void RetainReleaseChecker::PostVisitBlockExpr(CheckerContext &C, if (I == E) return; - state = state->scanReachableSymbols(I, E).getState(); + // FIXME: For now we invalidate the tracking of all symbols passed to blocks + // via captured variables, even though captured variables result in a copy + // and in implicit increment/decrement of a retain count. + llvm::SmallVector Regions; + const LocationContext *LC = C.getPredecessor()->getLocationContext(); + MemRegionManager &MemMgr = C.getValueManager().getRegionManager(); + + for ( ; I != E; ++I) { + const VarRegion *VR = *I; + if (VR->getSuperRegion() == R) { + VR = MemMgr.getVarRegion(VR->getDecl(), LC); + } + Regions.push_back(VR); + } + + state = + state->scanReachableSymbols(Regions.data(), + Regions.data() + Regions.size()).getState(); C.addTransition(state); } diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 57c645e924..8f63128975 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -473,6 +473,10 @@ void GRExprEngine::Visit(Stmt* S, ExplodedNode* Pred, ExplodedNodeSet& Dst) { case Stmt::AsmStmtClass: VisitAsmStmt(cast(S), Pred, Dst); break; + + case Stmt::BlockDeclRefExprClass: + VisitBlockDeclRefExpr(cast(S), Pred, Dst, false); + break; case Stmt::BlockExprClass: VisitBlockExpr(cast(S), Pred, Dst); @@ -644,6 +648,10 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred, VisitArraySubscriptExpr(cast(Ex), Pred, Dst, true); return; + case Stmt::BlockDeclRefExprClass: + VisitBlockDeclRefExpr(cast(Ex), Pred, Dst, true); + return; + case Stmt::DeclRefExprClass: VisitDeclRefExpr(cast(Ex), Pred, Dst, true); return; @@ -1135,9 +1143,20 @@ void GRExprEngine::VisitBlockExpr(BlockExpr *BE, ExplodedNode *Pred, void GRExprEngine::VisitDeclRefExpr(DeclRefExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst, bool asLValue) { + VisitCommonDeclRefExpr(Ex, Ex->getDecl(), Pred, Dst, asLValue); +} + +void GRExprEngine::VisitBlockDeclRefExpr(BlockDeclRefExpr *Ex, + ExplodedNode *Pred, + ExplodedNodeSet &Dst, bool asLValue) { + VisitCommonDeclRefExpr(Ex, Ex->getDecl(), Pred, Dst, asLValue); +} + +void GRExprEngine::VisitCommonDeclRefExpr(Expr *Ex, const NamedDecl *D, + ExplodedNode *Pred, + ExplodedNodeSet &Dst, bool asLValue) { const GRState *state = GetState(Pred); - const NamedDecl *D = Ex->getDecl(); if (const VarDecl* VD = dyn_cast(D)) { @@ -1566,7 +1585,8 @@ bool GRExprEngine::EvalBuiltinFunction(const FunctionDecl *FD, CallExpr *CE, // FIXME: Refactor into StoreManager itself? MemRegionManager& RM = getStateManager().getRegionManager(); const MemRegion* R = - RM.getAllocaRegion(CE, Builder->getCurrentBlockCount()); + RM.getAllocaRegion(CE, Builder->getCurrentBlockCount(), + Pred->getLocationContext()); // Set the extent of the region in bytes. This enables us to use the // SVal of the argument directly. If we save the extent in bits, we @@ -2064,10 +2084,12 @@ void GRExprEngine::VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, for (ExplodedNodeSet::iterator I = Tmp.begin(), EI = Tmp.end(); I!=EI; ++I) { const GRState* state = GetState(*I); SVal ILV = state->getSVal(ILE); - state = state->bindCompoundLiteral(CL, ILV); + const LocationContext *LC = (*I)->getLocationContext(); + state = state->bindCompoundLiteral(CL, LC, ILV); - if (asLValue) - MakeNode(Dst, CL, *I, state->BindExpr(CL, state->getLValue(CL))); + if (asLValue) { + MakeNode(Dst, CL, *I, state->BindExpr(CL, state->getLValue(CL, LC))); + } else MakeNode(Dst, CL, *I, state->BindExpr(CL, ILV)); } diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp index 2eb9d8e3ee..3bf3e5b28a 100644 --- a/lib/Analysis/MemRegion.cpp +++ b/lib/Analysis/MemRegion.cpp @@ -106,75 +106,24 @@ RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2, return R; } -//===----------------------------------------------------------------------===// -// Traits for constructing regions. -//===----------------------------------------------------------------------===// - -template <> struct MemRegionManagerTrait { - typedef MemRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - const Expr *, unsigned) { - return MRMgr.getStackRegion(); +template +RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2, const A3 a3, + const MemRegion *superRegion) { + + llvm::FoldingSetNodeID ID; + RegionTy::ProfileRegion(ID, a1, a2, a3, superRegion); + void* InsertPos; + RegionTy* R = cast_or_null(Regions.FindNodeOrInsertPos(ID, + InsertPos)); + + if (!R) { + R = (RegionTy*) A.Allocate(); + new (R) RegionTy(a1, a2, a3, superRegion); + Regions.InsertNode(R, InsertPos); } -}; - -template <> struct MemRegionManagerTrait { - typedef MemRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - const CompoundLiteralExpr *CL) { - - return CL->isFileScope() ? MRMgr.getGlobalsRegion() - : MRMgr.getStackRegion(); - } -}; - -template <> struct MemRegionManagerTrait { - typedef MemSpaceRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - const StringLiteral*) { - return MRMgr.getGlobalsRegion(); - } -}; - -template <> struct MemRegionManagerTrait { - typedef MemRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager &MRMgr, - const VarDecl *D, - const LocationContext *LC) { - - // FIXME: Make stack regions have a location context? - - if (D->hasLocalStorage()) { - return isa(D) || isa(D) - ? MRMgr.getStackArgumentsRegion() : MRMgr.getStackRegion(); - } - - return MRMgr.getGlobalsRegion(); - } -}; - -template <> struct MemRegionManagerTrait { - typedef MemRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - SymbolRef) { - return MRMgr.getUnknownRegion(); - } -}; - -template<> struct MemRegionManagerTrait { - typedef MemSpaceRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - const FunctionDecl*) { - return MRMgr.getCodeRegion(); - } -}; -template<> struct MemRegionManagerTrait { - typedef MemSpaceRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - const BlockDecl*, CanQualType) { - return MRMgr.getCodeRegion(); - } -}; + + return R; +} //===----------------------------------------------------------------------===// // Object destruction. @@ -220,6 +169,11 @@ void MemSpaceRegion::Profile(llvm::FoldingSetNodeID& ID) const { ID.AddInteger((unsigned)getKind()); } +void StackSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddInteger((unsigned)getKind()); + ID.AddPointer(getStackFrame()); +} + void StringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const StringLiteral* Str, const MemRegion* superRegion) { @@ -264,7 +218,7 @@ void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const { } void VarRegion::Profile(llvm::FoldingSetNodeID &ID) const { - VarRegion::ProfileRegion(ID, getDecl(), LC, superRegion); + VarRegion::ProfileRegion(ID, getDecl(), superRegion); } void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym, @@ -303,27 +257,29 @@ void FunctionTextRegion::Profile(llvm::FoldingSetNodeID& ID) const { } void BlockTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, - const BlockDecl *BD, CanQualType, - const MemRegion*) { + const BlockDecl *BD, CanQualType, + const AnalysisContext *AC, + const MemRegion*) { ID.AddInteger(MemRegion::BlockTextRegionKind); ID.AddPointer(BD); } void BlockTextRegion::Profile(llvm::FoldingSetNodeID& ID) const { - BlockTextRegion::ProfileRegion(ID, BD, locTy, superRegion); + BlockTextRegion::ProfileRegion(ID, BD, locTy, AC, superRegion); } void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockTextRegion *BC, const LocationContext *LC, - const MemRegion *) { + const MemRegion *sReg) { ID.AddInteger(MemRegion::BlockDataRegionKind); ID.AddPointer(BC); ID.AddPointer(LC); + ID.AddPointer(sReg); } void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const { - BlockDataRegion::ProfileRegion(ID, BC, LC, NULL); + BlockDataRegion::ProfileRegion(ID, BC, LC, getSuperRegion()); } //===----------------------------------------------------------------------===// @@ -404,28 +360,41 @@ void RegionRawOffset::dumpToStream(llvm::raw_ostream& os) const { // MemRegionManager methods. //===----------------------------------------------------------------------===// -const MemSpaceRegion *MemRegionManager::LazyAllocate(MemSpaceRegion*& region) { +template +const REG *MemRegionManager::LazyAllocate(REG*& region) { if (!region) { - region = (MemSpaceRegion*) A.Allocate(); - new (region) MemSpaceRegion(this); + region = (REG*) A.Allocate(); + new (region) REG(this); } return region; } -const MemSpaceRegion *MemRegionManager::getStackRegion() { - return LazyAllocate(stack); +template +const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) { + if (!region) { + region = (REG*) A.Allocate(); + new (region) REG(this, a); + } + + return region; } -const MemSpaceRegion *MemRegionManager::getStackArgumentsRegion() { - return LazyAllocate(stackArguments); +const StackLocalsSpaceRegion* +MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) { + return LazyAllocate(stackLocals, STC); } -const MemSpaceRegion *MemRegionManager::getGlobalsRegion() { +const StackArgumentsSpaceRegion * +MemRegionManager::getStackArgumentsRegion(const StackFrameContext *STC) { + return LazyAllocate(stackArguments, STC); +} + +const GlobalsSpaceRegion *MemRegionManager::getGlobalsRegion() { return LazyAllocate(globals); } -const MemSpaceRegion *MemRegionManager::getHeapRegion() { +const HeapSpaceRegion *MemRegionManager::getHeapRegion() { return LazyAllocate(heap); } @@ -442,36 +411,71 @@ const MemSpaceRegion *MemRegionManager::getCodeRegion() { //===----------------------------------------------------------------------===// const StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str) { - return getRegion(Str); + return getSubRegion(Str, getGlobalsRegion()); } const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D, const LocationContext *LC) { + const MemRegion *sReg = 0; - // 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(LC)) - LC = LC->getParent(); + if (D->hasLocalStorage()) { + // FIXME: Once we implement scope handling, we will need to properly lookup + // 'D' to the proper LocationContext. + const StackFrameContext *STC = LC->getCurrentStackFrame(); - return getRegion(D, LC); + assert(STC); + sReg = isa(D) || isa(D) + ? static_cast(getStackArgumentsRegion(STC)) + : static_cast(getStackLocalsRegion(STC)); + } + else { + sReg = getGlobalsRegion(); + } + + return getSubRegion(D, sReg); +} + +const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D, + const MemRegion *superR) { + return getSubRegion(D, superR); } const 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(LC)) - LC = LC->getParent(); + const MemRegion *sReg = 0; - return getSubRegion(BC, LC, getStackRegion()); + if (LC) { + // FIXME: Once we implement scope handling, we want the parent region + // to be the scope. + const StackFrameContext *STC = LC->getCurrentStackFrame(); + assert(STC); + sReg = getStackLocalsRegion(STC); + } + else { + // We allow 'LC' to be NULL for cases where want BlockDataRegions + // without context-sensitivity. + sReg = getUnknownRegion(); + } + + return getSubRegion(BC, LC, sReg); } const CompoundLiteralRegion* -MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL) { - return getRegion(CL); +MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr* CL, + const LocationContext *LC) { + + const MemRegion *sReg = 0; + + if (CL->isFileScope()) + sReg = getGlobalsRegion(); + else { + const StackFrameContext *STC = LC->getCurrentStackFrame(); + assert(STC); + sReg = getStackLocalsRegion(STC); + } + + return getSubRegion(CL, sReg); } const ElementRegion* @@ -499,18 +503,19 @@ MemRegionManager::getElementRegion(QualType elementType, SVal Idx, const FunctionTextRegion * MemRegionManager::getFunctionTextRegion(const FunctionDecl *FD) { - return getRegion(FD); + return getSubRegion(FD, getCodeRegion()); } const BlockTextRegion * -MemRegionManager::getBlockTextRegion(const BlockDecl *BD, CanQualType locTy) { - return getRegion(BD, locTy); +MemRegionManager::getBlockTextRegion(const BlockDecl *BD, CanQualType locTy, + AnalysisContext *AC) { + return getSubRegion(BD, locTy, AC, getCodeRegion()); } /// getSymbolicRegion - Retrieve or create a "symbolic" memory region. const SymbolicRegion *MemRegionManager::getSymbolicRegion(SymbolRef sym) { - return getRegion(sym); + return getSubRegion(sym, getUnknownRegion()); } const FieldRegion * @@ -532,8 +537,11 @@ MemRegionManager::getObjCObjectRegion(const ObjCInterfaceDecl* d, } const AllocaRegion* -MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt) { - return getRegion(E, cnt); +MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt, + const LocationContext *LC) { + const StackFrameContext *STC = LC->getCurrentStackFrame(); + assert(STC); + return getSubRegion(E, cnt, getStackLocalsRegion(STC)); } const MemSpaceRegion *MemRegion::getMemorySpace() const { @@ -549,52 +557,30 @@ const MemSpaceRegion *MemRegion::getMemorySpace() const { } bool MemRegion::hasStackStorage() const { - if (const MemSpaceRegion *MS = getMemorySpace()) { - MemRegionManager *Mgr = getMemRegionManager(); - return MS == Mgr->getStackRegion() || MS == Mgr->getStackArgumentsRegion(); - } - - return false; + return isa(getMemorySpace()); } bool MemRegion::hasHeapStorage() const { - if (const MemSpaceRegion *MS = getMemorySpace()) - return MS == getMemRegionManager()->getHeapRegion(); - - return false; + return isa(getMemorySpace()); } bool MemRegion::hasHeapOrStackStorage() const { - if (const MemSpaceRegion *MS = getMemorySpace()) { - MemRegionManager *Mgr = getMemRegionManager(); - return MS == Mgr->getHeapRegion() - || MS == Mgr->getStackRegion() - || MS == Mgr->getStackArgumentsRegion(); - } - return false; + const MemSpaceRegion *MS = getMemorySpace(); + return isa(MS) || isa(MS); } bool MemRegion::hasGlobalsStorage() const { - if (const MemSpaceRegion *MS = getMemorySpace()) - return MS == getMemRegionManager()->getGlobalsRegion(); - - return false; + return isa(getMemorySpace()); } bool MemRegion::hasParametersStorage() const { - if (const MemSpaceRegion *MS = getMemorySpace()) - return MS == getMemRegionManager()->getStackArgumentsRegion(); - - return false; + return isa(getMemorySpace()); } bool MemRegion::hasGlobalsOrParametersStorage() const { - if (const MemSpaceRegion *MS = getMemorySpace()) { - MemRegionManager *Mgr = getMemRegionManager(); - return MS == Mgr->getGlobalsRegion() - || MS == Mgr->getStackArgumentsRegion(); - } - return false; + const MemSpaceRegion *MS = getMemorySpace(); + return isa(MS) || + isa(MS); } // getBaseRegion strips away all elements and fields, and get the base region @@ -700,7 +686,7 @@ void BlockDataRegion::LazyInitializeReferencedVars() { if (ReferencedVars) return; - AnalysisContext *AC = LC->getAnalysisContext(); + AnalysisContext *AC = getCodeRegion()->getAnalysisContext(); AnalysisContext::referenced_decls_iterator I, E; llvm::tie(I, E) = AC->getReferencedBlockVars(BC->getDecl()); @@ -717,8 +703,23 @@ void BlockDataRegion::LazyInitializeReferencedVars() { VarVec *BV = (VarVec*) A.Allocate(); new (BV) VarVec(BC, E - I); - for ( ; I != E; ++I) - BV->push_back(MemMgr.getVarRegion(*I, LC), BC); + for ( ; I != E; ++I) { + const VarDecl *VD = *I; + const VarRegion *VR = 0; + + if (!VD->getAttr()) + VR = MemMgr.getVarRegion(VD, this); + else { + if (LC) + VR = MemMgr.getVarRegion(VD, LC); + else { + VR = MemMgr.getVarRegion(VD, MemMgr.getUnknownRegion()); + } + } + + assert(VR); + BV->push_back(VR, BC); + } ReferencedVars = BV; } diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp index 4a84eea42f..c718f1fbba 100644 --- a/lib/Analysis/RegionStore.cpp +++ b/lib/Analysis/RegionStore.cpp @@ -287,7 +287,9 @@ public: const GRState *Bind(const GRState *state, Loc LV, SVal V); const GRState *BindCompoundLiteral(const GRState *state, - const CompoundLiteralExpr* CL, SVal V); + const CompoundLiteralExpr* CL, + const LocationContext *LC, + SVal V); const GRState *BindDecl(const GRState *ST, const VarRegion *VR, SVal InitVal); @@ -615,15 +617,6 @@ SVal RegionStoreManager::getLValueVar(const VarDecl *VD, return loc::MemRegionVal(MRMgr.getVarRegion(VD, LC)); } -/// getLValueCompoundLiteral - Returns an SVal representing the lvalue -/// of a compound literal. Within RegionStore a compound literal -/// has an associated region, and the lvalue of the compound literal -/// is the lvalue of that region. -SVal -RegionStoreManager::getLValueCompoundLiteral(const CompoundLiteralExpr* CL) { - return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL)); -} - SVal RegionStoreManager::getLValueIvar(const ObjCIvarDecl* D, SVal Base) { return getLValueFieldOrIvar(D, Base); } @@ -730,7 +723,11 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state, const MemRegion *R) { switch (R->getKind()) { - case MemRegion::MemSpaceRegionKind: + case MemRegion::GenericMemSpaceRegionKind: + case MemRegion::StackLocalsSpaceRegionKind: + case MemRegion::StackArgumentsSpaceRegionKind: + case MemRegion::HeapSpaceRegionKind: + case MemRegion::GlobalsSpaceRegionKind: assert(0 && "Cannot index into a MemSpace"); return UnknownVal(); @@ -775,13 +772,6 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state, // essentially are arrays of size 1. return ValMgr.makeIntVal(1, false); } - - case MemRegion::BEG_DECL_REGIONS: - case MemRegion::END_DECL_REGIONS: - case MemRegion::BEG_TYPED_REGIONS: - case MemRegion::END_TYPED_REGIONS: - assert(0 && "Infeasible region"); - return UnknownVal(); } assert(0 && "Unreachable"); @@ -886,16 +876,13 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state, // Technically this can happen if people do funny things with casts. return UnknownVal(); - case MemRegion::MemSpaceRegionKind: + case MemRegion::GenericMemSpaceRegionKind: + case MemRegion::StackLocalsSpaceRegionKind: + case MemRegion::StackArgumentsSpaceRegionKind: + case MemRegion::HeapSpaceRegionKind: + case MemRegion::GlobalsSpaceRegionKind: assert(0 && "Cannot perform pointer arithmetic on a MemSpace"); return UnknownVal(); - - case MemRegion::BEG_DECL_REGIONS: - case MemRegion::END_DECL_REGIONS: - case MemRegion::BEG_TYPED_REGIONS: - case MemRegion::END_TYPED_REGIONS: - assert(0 && "Infeasible region"); - return UnknownVal(); } SVal Idx = ER->getIndex(); @@ -1462,9 +1449,11 @@ const GRState *RegionStoreManager::BindDecl(const GRState *ST, // FIXME: this method should be merged into Bind(). const GRState * RegionStoreManager::BindCompoundLiteral(const GRState *state, - const CompoundLiteralExpr* CL, + const CompoundLiteralExpr *CL, + const LocationContext *LC, SVal V) { - return Bind(state, loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL)), V); + return Bind(state, loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC)), + V); } const GRState *RegionStoreManager::setImplicitDefaultValue(const GRState *state, diff --git a/lib/Analysis/Store.cpp b/lib/Analysis/Store.cpp index 78eed4619b..e591842838 100644 --- a/lib/Analysis/Store.cpp +++ b/lib/Analysis/Store.cpp @@ -77,11 +77,11 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy) // Process region cast according to the kind of the region being cast. switch (R->getKind()) { - case MemRegion::BEG_TYPED_REGIONS: - case MemRegion::MemSpaceRegionKind: - case MemRegion::BEG_DECL_REGIONS: - case MemRegion::END_DECL_REGIONS: - case MemRegion::END_TYPED_REGIONS: { + case MemRegion::GenericMemSpaceRegionKind: + case MemRegion::StackLocalsSpaceRegionKind: + case MemRegion::StackArgumentsSpaceRegionKind: + case MemRegion::HeapSpaceRegionKind: + case MemRegion::GlobalsSpaceRegionKind: { assert(0 && "Invalid region cast"); break; } @@ -216,3 +216,16 @@ const GRState *StoreManager::InvalidateRegions(const GRState *state, return state; } + +//===----------------------------------------------------------------------===// +// Common getLValueXXX methods. +//===----------------------------------------------------------------------===// + +/// getLValueCompoundLiteral - Returns an SVal representing the lvalue +/// of a compound literal. Within RegionStore a compound literal +/// has an associated region, and the lvalue of the compound literal +/// is the lvalue of that region. +SVal StoreManager::getLValueCompoundLiteral(const CompoundLiteralExpr* CL, + const LocationContext *LC) { + return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC)); +} \ No newline at end of file diff --git a/lib/Analysis/ValueManager.cpp b/lib/Analysis/ValueManager.cpp index 1e7a5fced0..d09137330c 100644 --- a/lib/Analysis/ValueManager.cpp +++ b/lib/Analysis/ValueManager.cpp @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/PathSensitive/ValueManager.h" +#include "clang/Analysis/PathSensitive/AnalysisContext.h" using namespace clang; using namespace llvm; @@ -144,7 +145,8 @@ DefinedSVal ValueManager::getFunctionPointer(const FunctionDecl* FD) { DefinedSVal ValueManager::getBlockPointer(const BlockDecl *D, CanQualType locTy, const LocationContext *LC) { - const BlockTextRegion *BC = MemMgr.getBlockTextRegion(D, locTy); + const BlockTextRegion *BC = + MemMgr.getBlockTextRegion(D, locTy, LC->getAnalysisContext()); const BlockDataRegion *BD = MemMgr.getBlockDataRegion(BC, LC); return loc::MemRegionVal(BD); }