diff options
author | Ted Kremenek <kremenek@apple.com> | 2009-12-07 22:05:27 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2009-12-07 22:05:27 +0000 |
commit | 67d1287035767f4f6c8ca0c2bb755990012a44ca (patch) | |
tree | e0b721e7e3b29b9e6a8b396ac17b602ada92951f | |
parent | 3cdff236e23e68fa19ed0b69f79ab7eb04593d28 (diff) |
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
-rw-r--r-- | include/clang/Analysis/PathSensitive/AnalysisContext.h | 5 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/GRExprEngine.h | 7 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/GRState.h | 16 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/MemRegion.h | 239 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/Store.h | 8 | ||||
-rw-r--r-- | lib/Analysis/AnalysisContext.cpp | 14 | ||||
-rw-r--r-- | lib/Analysis/BasicStore.cpp | 8 | ||||
-rw-r--r-- | lib/Analysis/CFRefCount.cpp | 19 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 32 | ||||
-rw-r--r-- | lib/Analysis/MemRegion.cpp | 277 | ||||
-rw-r--r-- | lib/Analysis/RegionStore.cpp | 45 | ||||
-rw-r--r-- | lib/Analysis/Store.cpp | 23 | ||||
-rw-r--r-- | lib/Analysis/ValueManager.cpp | 4 |
13 files changed, 436 insertions, 261 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<DefinedSVal>(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) {} + MemSpaceRegion(MemRegionManager *mgr, Kind k = GenericMemSpaceRegionKind) + : MemRegion(k), Mgr(mgr) { + assert(classof(this)); + } + + MemRegionManager* getMemRegionManager() const { return Mgr; } - MemRegionManager* getMemRegionManager() const { - return Mgr; +public: + bool isBoundable() const { return false; } + + void Profile(llvm::FoldingSetNodeID &ID) const; + + 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: - void Profile(llvm::FoldingSetNodeID& ID) const; + 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; - bool isBoundable() const { return false; } +protected: + StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc) + : MemSpaceRegion(mgr, k), SFC(sfc) { + assert(classof(this)); + } - static bool classof(const MemRegion* R) { - return R->getKind() == MemSpaceRegionKind; +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<VarDecl>(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<MemRegion> 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 <typename RegionTy, typename A1, typename A2, typename A3> + RegionTy* getSubRegion(const A1 a1, const A2 a2, const A3 a3, + const MemRegion* superRegion); + + template <typename REG> + const REG* LazyAllocate(REG*& region); + + template <typename REG, typename ARG> + 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 @@ -166,6 +166,20 @@ LocationContextManager::getBlockInvocation(AnalysisContext *ctx, } //===----------------------------------------------------------------------===// +// LocationContext methods. +//===----------------------------------------------------------------------===// + +const StackFrameContext *LocationContext::getCurrentStackFrame() const { + const LocationContext *LC = this; + while (LC) { + if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(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<StopTrackingCallback>(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<const MemRegion*, 10> 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<StopTrackingCallback>(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<AsmStmt>(S), Pred, Dst); break; + + case Stmt::BlockDeclRefExprClass: + VisitBlockDeclRefExpr(cast<BlockDeclRefExpr>(S), Pred, Dst, false); + break; case Stmt::BlockExprClass: VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst); @@ -644,6 +648,10 @@ void GRExprEngine::VisitLValue(Expr* Ex, ExplodedNode* Pred, VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(Ex), Pred, Dst, true); return; + case Stmt::BlockDeclRefExprClass: + VisitBlockDeclRefExpr(cast<BlockDeclRefExpr>(Ex), Pred, Dst, true); + return; + case Stmt::DeclRefExprClass: VisitDeclRefExpr(cast<DeclRefExpr>(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<VarDecl>(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<AllocaRegion> { - typedef MemRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - const Expr *, unsigned) { - return MRMgr.getStackRegion(); - } -}; - -template <> struct MemRegionManagerTrait<CompoundLiteralRegion> { - typedef MemRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - const CompoundLiteralExpr *CL) { - - return CL->isFileScope() ? MRMgr.getGlobalsRegion() - : MRMgr.getStackRegion(); - } -}; - -template <> struct MemRegionManagerTrait<StringRegion> { - typedef MemSpaceRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - const StringLiteral*) { - return MRMgr.getGlobalsRegion(); - } -}; - -template <> struct MemRegionManagerTrait<VarRegion> { - 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<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D) - ? MRMgr.getStackArgumentsRegion() : MRMgr.getStackRegion(); - } - - return MRMgr.getGlobalsRegion(); - } -}; - -template <> struct MemRegionManagerTrait<SymbolicRegion> { - typedef MemRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - SymbolRef) { - return MRMgr.getUnknownRegion(); - } -}; - -template<> struct MemRegionManagerTrait<FunctionTextRegion> { - typedef MemSpaceRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - const FunctionDecl*) { - return MRMgr.getCodeRegion(); - } -}; -template<> struct MemRegionManagerTrait<BlockTextRegion> { - typedef MemSpaceRegion SuperRegionTy; - static const SuperRegionTy* getSuperRegion(MemRegionManager& MRMgr, - const BlockDecl*, CanQualType) { - return MRMgr.getCodeRegion(); +template <typename RegionTy, typename A1, typename A2, typename A3> +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<RegionTy>(Regions.FindNodeOrInsertPos(ID, + InsertPos)); + + if (!R) { + R = (RegionTy*) A.Allocate<RegionTy>(); + new (R) RegionTy(a1, a2, a3, superRegion); + Regions.InsertNode(R, InsertPos); } -}; + + 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); |