diff --git a/clang/include/clang/Analysis/PathSensitive/MemRegion.h b/clang/include/clang/Analysis/PathSensitive/MemRegion.h index 06d0d976df011555b3bb103c36163b0fe98a367d..df9caedefc0d851a43eb2c981108691a1b4df0a3 100644 --- a/clang/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/clang/include/clang/Analysis/PathSensitive/MemRegion.h @@ -48,7 +48,8 @@ public: AllocaRegionKind, // Typed regions. BEG_TYPED_REGIONS, - CodeTextRegionKind, + FunctionTextRegionKind, + BlockTextRegionKind, CompoundLiteralRegionKind, StringRegionKind, ElementRegionKind, // Decl Regions. @@ -237,43 +238,78 @@ public: } }; -/// CodeTextRegion - A region that represents code texts of a function. It wraps -/// two kinds of code texts: real function and symbolic function. Real function -/// is a function declared in the program. Symbolic function is a function -/// pointer that we don't know which function it points to. -class CodeTextRegion : public TypedRegion { - const FunctionDecl *FD; +class CodeTextRegion : public TypedRegion { +protected: + CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {} public: - - CodeTextRegion(const FunctionDecl* fd, const MemRegion* sreg) - : TypedRegion(sreg, CodeTextRegionKind), FD(fd) {} - QualType getValueType(ASTContext &C) const { // Do not get the object type of a CodeTextRegion. assert(0); return QualType(); } + + bool isBoundable() const { return false; } + + static bool classof(const MemRegion* R) { + Kind k = R->getKind(); + return k >= FunctionTextRegionKind && k <= BlockTextRegionKind; + } +}; +/// FunctionTextRegion - A region that represents code texts of function. +class FunctionTextRegion : public CodeTextRegion { + const FunctionDecl *FD; +public: + FunctionTextRegion(const FunctionDecl* fd, const MemRegion* sreg) + : CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {} + QualType getLocationType(ASTContext &C) const { return C.getPointerType(FD->getType()); } - + const FunctionDecl *getDecl() const { return FD; } - - bool isBoundable() const { return false; } - + virtual void dumpToStream(llvm::raw_ostream& os) const; - + void Profile(llvm::FoldingSetNodeID& ID) const; - + static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FunctionDecl *FD, const MemRegion*); - + static bool classof(const MemRegion* R) { - return R->getKind() == CodeTextRegionKind; + return R->getKind() == FunctionTextRegionKind; + } +}; + + +/// BlockTextRegion - A region that represents code texts of blocks (closures). +class BlockTextRegion : public CodeTextRegion { + const BlockDecl *BD; + CanQualType locTy; +public: + BlockTextRegion(const BlockDecl *bd, CanQualType lTy, const MemRegion* sreg) + : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), locTy(lTy) {} + + QualType getLocationType(ASTContext &C) const { + return locTy; + } + + const BlockDecl *getDecl() const { + return BD; + } + + 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*); + + static bool classof(const MemRegion* R) { + return R->getKind() == BlockTextRegionKind; } }; @@ -656,7 +692,9 @@ public: ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl* ivd, const MemRegion* superRegion); - CodeTextRegion *getCodeTextRegion(const FunctionDecl *FD); + FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD); + BlockTextRegion *getBlockTextRegion(const BlockDecl *BD, CanQualType locTy); + template RegionTy* getRegion(const A1 a1); @@ -801,18 +839,21 @@ template <> struct MemRegionManagerTrait { } }; -template<> struct MemRegionManagerTrait { +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, - SymbolRef, QualType) { + const BlockDecl*, CanQualType) { return MRMgr.getCodeRegion(); } }; - + } // end clang namespace //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/Analysis/PathSensitive/ValueManager.h b/clang/include/clang/Analysis/PathSensitive/ValueManager.h index 8d162a681c446ddb684c914c3c5af36ba5bc673e..66d431586424a3e8ca6a5fc9c63d5d1d9297f5e2 100644 --- a/clang/include/clang/Analysis/PathSensitive/ValueManager.h +++ b/clang/include/clang/Analysis/PathSensitive/ValueManager.h @@ -114,6 +114,8 @@ public: const TypedRegion *R); DefinedSVal getFunctionPointer(const FunctionDecl *FD); + + DefinedSVal getBlockPointer(const BlockDecl *BD, CanQualType locTy); NonLoc makeCompoundVal(QualType T, llvm::ImmutableList Vals) { return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals)); diff --git a/clang/lib/Analysis/MemRegion.cpp b/clang/lib/Analysis/MemRegion.cpp index 8c0b85c0c729689c6cf848b1da10d5f6ede43608..8b4c7a6a24078f525743ab6c2f60b30761b70f51 100644 --- a/clang/lib/Analysis/MemRegion.cpp +++ b/clang/lib/Analysis/MemRegion.cpp @@ -126,15 +126,26 @@ void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const { ElementRegion::ProfileRegion(ID, ElementType, Index, superRegion); } -void CodeTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, - const FunctionDecl *FD, - const MemRegion*) { - ID.AddInteger(MemRegion::CodeTextRegionKind); +void FunctionTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, + const FunctionDecl *FD, + const MemRegion*) { + ID.AddInteger(MemRegion::FunctionTextRegionKind); ID.AddPointer(FD); } -void CodeTextRegion::Profile(llvm::FoldingSetNodeID& ID) const { - CodeTextRegion::ProfileRegion(ID, FD, superRegion); +void FunctionTextRegion::Profile(llvm::FoldingSetNodeID& ID) const { + FunctionTextRegion::ProfileRegion(ID, FD, superRegion); +} + +void BlockTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, + const BlockDecl *BD, CanQualType, + const MemRegion*) { + ID.AddInteger(MemRegion::BlockTextRegionKind); + ID.AddPointer(BD); +} + +void BlockTextRegion::Profile(llvm::FoldingSetNodeID& ID) const { + BlockTextRegion::ProfileRegion(ID, BD, locTy, superRegion); } //===----------------------------------------------------------------------===// @@ -160,10 +171,14 @@ void AllocaRegion::dumpToStream(llvm::raw_ostream& os) const { os << "alloca{" << (void*) Ex << ',' << Cnt << '}'; } -void CodeTextRegion::dumpToStream(llvm::raw_ostream& os) const { +void FunctionTextRegion::dumpToStream(llvm::raw_ostream& os) const { os << "code{" << getDecl()->getDeclName().getAsString() << '}'; } +void BlockTextRegion::dumpToStream(llvm::raw_ostream& os) const { + os << "block{" << (void*) this << '}'; +} + void CompoundLiteralRegion::dumpToStream(llvm::raw_ostream& os) const { // FIXME: More elaborate pretty-printing. os << "{ " << (void*) CL << " }"; @@ -287,10 +302,17 @@ MemRegionManager::getElementRegion(QualType elementType, SVal Idx, return R; } -CodeTextRegion *MemRegionManager::getCodeTextRegion(const FunctionDecl *FD) { - return getRegion(FD); +FunctionTextRegion * +MemRegionManager::getFunctionTextRegion(const FunctionDecl *FD) { + return getRegion(FD); } +BlockTextRegion *MemRegionManager::getBlockTextRegion(const BlockDecl *BD, + CanQualType locTy) { + return getRegion(BD, locTy); +} + + /// getSymbolicRegion - Retrieve or create a "symbolic" memory region. SymbolicRegion* MemRegionManager::getSymbolicRegion(SymbolRef sym) { return getRegion(sym); diff --git a/clang/lib/Analysis/PthreadLockChecker.cpp b/clang/lib/Analysis/PthreadLockChecker.cpp index 66206616b0089789cec2ca7b2583cba2475663f3..dc6a63dd07934dff01c119b6df6791dccc3f095b 100644 --- a/clang/lib/Analysis/PthreadLockChecker.cpp +++ b/clang/lib/Analysis/PthreadLockChecker.cpp @@ -59,8 +59,8 @@ void PthreadLockChecker::PostVisitCallExpr(CheckerContext &C, const CallExpr *CE) { const GRState *state = C.getState(); const Expr *Callee = CE->getCallee(); - const CodeTextRegion *R = - dyn_cast_or_null(state->getSVal(Callee).getAsRegion()); + const FunctionTextRegion *R = + dyn_cast_or_null(state->getSVal(Callee).getAsRegion()); if (!R) return; diff --git a/clang/lib/Analysis/RegionStore.cpp b/clang/lib/Analysis/RegionStore.cpp index af2e359a00e4d92b546dc6b279b68211067343aa..16a4690f95ad1ce44df11e471e60b18ea88caf3a 100644 --- a/clang/lib/Analysis/RegionStore.cpp +++ b/clang/lib/Analysis/RegionStore.cpp @@ -712,7 +712,8 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state, assert(0 && "Cannot index into a MemSpace"); return UnknownVal(); - case MemRegion::CodeTextRegionKind: + case MemRegion::FunctionTextRegionKind: + case MemRegion::BlockTextRegionKind: // Technically this can happen if people do funny things with casts. return UnknownVal(); @@ -857,7 +858,8 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state, case MemRegion::ObjCIvarRegionKind: return UnknownVal(); - case MemRegion::CodeTextRegionKind: + case MemRegion::FunctionTextRegionKind: + case MemRegion::BlockTextRegionKind: // Technically this can happen if people do funny things with casts. return UnknownVal(); diff --git a/clang/lib/Analysis/SVals.cpp b/clang/lib/Analysis/SVals.cpp index d5d36e3b90909b884a8647a897fa4d6de4eb6f89..9163b2725273ae2b6567b50f04606d1a8a5aae76 100644 --- a/clang/lib/Analysis/SVals.cpp +++ b/clang/lib/Analysis/SVals.cpp @@ -51,7 +51,7 @@ bool SVal::hasConjuredSymbol() const { const FunctionDecl *SVal::getAsFunctionDecl() const { if (const loc::MemRegionVal* X = dyn_cast(this)) { const MemRegion* R = X->getRegion(); - if (const CodeTextRegion *CTR = R->getAs()) + if (const FunctionTextRegion *CTR = R->getAs()) return CTR->getDecl(); } diff --git a/clang/lib/Analysis/Store.cpp b/clang/lib/Analysis/Store.cpp index 4183a73158b5001831e6ac61347720df774ef82e..14f55fd75fafdebda6619d67bdc3bbc61e50fdfa 100644 --- a/clang/lib/Analysis/Store.cpp +++ b/clang/lib/Analysis/Store.cpp @@ -85,7 +85,9 @@ const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy) assert(0 && "Invalid region cast"); break; } - case MemRegion::CodeTextRegionKind: { + + case MemRegion::FunctionTextRegionKind: + case MemRegion::BlockTextRegionKind: { // CodeTextRegion should be cast to only a function or block pointer type, // although they can in practice be casted to anything, e.g, void*, char*, // etc. diff --git a/clang/lib/Analysis/ValueManager.cpp b/clang/lib/Analysis/ValueManager.cpp index fe670e79b3b534da49831a57aab65c31ed69d0f3..37df44360226e192434eeb7f143073681bc6f192 100644 --- a/clang/lib/Analysis/ValueManager.cpp +++ b/clang/lib/Analysis/ValueManager.cpp @@ -138,6 +138,13 @@ ValueManager::getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, } DefinedSVal ValueManager::getFunctionPointer(const FunctionDecl* FD) { - CodeTextRegion *R = MemMgr.getCodeTextRegion(FD); + CodeTextRegion *R = MemMgr.getFunctionTextRegion(FD); return loc::MemRegionVal(R); } + +DefinedSVal ValueManager::getBlockPointer(const BlockDecl *BD, + CanQualType locTy) { + CodeTextRegion *R = MemMgr.getBlockTextRegion(BD, locTy); + return loc::MemRegionVal(R); +} +