diff options
author | Ted Kremenek <kremenek@apple.com> | 2010-01-05 02:18:06 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2010-01-05 02:18:06 +0000 |
commit | acd71a456254f3b4b1f9a860ab09f93026b1e0ef (patch) | |
tree | 4c9fa59f091f7744526ca1ebd231c3b8ae79abf8 /clang/lib | |
parent | a0e1ee828a071b619324cab8ae438c7c3d5198d2 (diff) | |
download | bcm5719-llvm-acd71a456254f3b4b1f9a860ab09f93026b1e0ef.tar.gz bcm5719-llvm-acd71a456254f3b4b1f9a860ab09f93026b1e0ef.zip |
Make static analysis support for C++ 'this' expression context-sensitive. Essentially treat 'this' as a implicit parameter to the method call, and associate a region with it.
llvm-svn: 92675
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Analysis/GRExprEngine.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Analysis/MemRegion.cpp | 45 | ||||
-rw-r--r-- | clang/lib/Analysis/RegionStore.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Analysis/Store.cpp | 6 |
4 files changed, 46 insertions, 30 deletions
diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp index 013bed04f99..3c2512215a3 100644 --- a/clang/lib/Analysis/GRExprEngine.cpp +++ b/clang/lib/Analysis/GRExprEngine.cpp @@ -2711,8 +2711,13 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, ExplodedNode* Pred, void GRExprEngine::VisitCXXThisExpr(CXXThisExpr *TE, ExplodedNode *Pred, ExplodedNodeSet & Dst) { // Get the this object region from StoreManager. - Loc V = getStoreManager().getThisObject(TE->getType()->getPointeeType()); - MakeNode(Dst, TE, Pred, GetState(Pred)->BindExpr(TE, V)); + const MemRegion *R = + ValMgr.getRegionManager().getCXXThisRegion(TE->getType(), + Pred->getLocationContext()); + + const GRState *state = GetState(Pred); + SVal V = state->getSVal(loc::MemRegionVal(R)); + MakeNode(Dst, TE, Pred, state->BindExpr(TE, V)); } void GRExprEngine::VisitAsmStmt(AsmStmt* A, ExplodedNode* Pred, diff --git a/clang/lib/Analysis/MemRegion.cpp b/clang/lib/Analysis/MemRegion.cpp index 74fe3bf5ee5..5be882ad549 100644 --- a/clang/lib/Analysis/MemRegion.cpp +++ b/clang/lib/Analysis/MemRegion.cpp @@ -215,6 +215,18 @@ void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, ID.AddPointer(superRegion); } +void CXXThisRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, + const PointerType *PT, + const MemRegion *sRegion) { + ID.AddInteger((unsigned) CXXThisRegionKind); + ID.AddPointer(PT); + ID.AddPointer(sRegion); +} + +void CXXThisRegion::Profile(llvm::FoldingSetNodeID &ID) const { + CXXThisRegion::ProfileRegion(ID, ThisPointerTy, superRegion); +} + void DeclRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D, const MemRegion* superRegion, Kind k) { ID.AddInteger((unsigned) k); @@ -343,6 +355,10 @@ void CompoundLiteralRegion::dumpToStream(llvm::raw_ostream& os) const { os << "{ " << (void*) CL << " }"; } +void CXXThisRegion::dumpToStream(llvm::raw_ostream &os) const { + os << "this"; +} + void ElementRegion::dumpToStream(llvm::raw_ostream& os) const { os << "element{" << superRegion << ',' << Index << ',' << getElementType().getAsString() << '}'; @@ -551,7 +567,7 @@ const SymbolicRegion *MemRegionManager::getSymbolicRegion(SymbolRef sym) { return getSubRegion<SymbolicRegion>(sym, getUnknownRegion()); } -const FieldRegion * +const FieldRegion* MemRegionManager::getFieldRegion(const FieldDecl* d, const MemRegion* superRegion){ return getSubRegion<FieldRegion>(d, superRegion); @@ -563,11 +579,21 @@ MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d, return getSubRegion<ObjCIvarRegion>(d, superRegion); } -const CXXObjectRegion * +const CXXObjectRegion* MemRegionManager::getCXXObjectRegion(QualType T) { return getSubRegion<CXXObjectRegion>(T, getUnknownRegion()); } +const CXXThisRegion* +MemRegionManager::getCXXThisRegion(QualType thisPointerTy, + const LocationContext *LC) { + const StackFrameContext *STC = LC->getCurrentStackFrame(); + assert(STC); + const PointerType *PT = thisPointerTy->getAs<PointerType>(); + assert(PT); + return getSubRegion<CXXThisRegion>(PT, getStackArgumentsRegion(STC)); +} + const AllocaRegion* MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt, const LocationContext *LC) { @@ -592,20 +618,11 @@ bool MemRegion::hasStackStorage() const { return isa<StackSpaceRegion>(getMemorySpace()); } -bool MemRegion::hasHeapStorage() const { - return isa<HeapSpaceRegion>(getMemorySpace()); -} - -bool MemRegion::hasHeapOrStackStorage() const { - const MemSpaceRegion *MS = getMemorySpace(); - return isa<StackSpaceRegion>(MS) || isa<HeapSpaceRegion>(MS); -} - -bool MemRegion::hasGlobalsStorage() const { - return isa<GlobalsSpaceRegion>(getMemorySpace()); +bool MemRegion::hasStackNonParametersStorage() const { + return isa<StackLocalsSpaceRegion>(getMemorySpace()); } -bool MemRegion::hasParametersStorage() const { +bool MemRegion::hasStackParametersStorage() const { return isa<StackArgumentsSpaceRegion>(getMemorySpace()); } diff --git a/clang/lib/Analysis/RegionStore.cpp b/clang/lib/Analysis/RegionStore.cpp index 3bc9dccda6b..ba63308c5da 100644 --- a/clang/lib/Analysis/RegionStore.cpp +++ b/clang/lib/Analysis/RegionStore.cpp @@ -28,7 +28,6 @@ using namespace clang; -#define HEAP_UNDEFINED 0 #define USE_EXPLICIT_COMPOUND 0 namespace { @@ -723,6 +722,8 @@ DefinedOrUnknownSVal RegionStoreManager::getSizeInElements(const GRState *state, const MemRegion *R) { switch (R->getKind()) { + case MemRegion::CXXThisRegionKind: + assert(0 && "Cannot get size of 'this' region"); case MemRegion::GenericMemSpaceRegionKind: case MemRegion::StackLocalsSpaceRegionKind: case MemRegion::StackArgumentsSpaceRegionKind: @@ -877,6 +878,9 @@ SVal RegionStoreManager::EvalBinOp(const GRState *state, // Technically this can happen if people do funny things with casts. return UnknownVal(); + case MemRegion::CXXThisRegionKind: + assert(0 && + "Cannot perform pointer arithmetic on implicit argument 'this'"); case MemRegion::GenericMemSpaceRegionKind: case MemRegion::StackLocalsSpaceRegionKind: case MemRegion::StackArgumentsSpaceRegionKind: @@ -1076,12 +1080,7 @@ RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) { // The location does not have a bound value. This means that it has // the value it had upon its creation and/or entry to the analyzed // function/method. These are either symbolic values or 'undefined'. - -#if HEAP_UNDEFINED - if (R->hasHeapOrStackStorage()) { -#else - if (R->hasStackStorage()) { -#endif + if (R->hasStackNonParametersStorage()) { // All stack variables are considered to have undefined values // upon creation. All heap allocated blocks are considered to // have undefined values as well unless they are explicitly bound @@ -1240,8 +1239,7 @@ SVal RegionStoreManager::RetrieveFieldOrElementCommon(const GRState *state, cast<FieldRegion>(lazyBindingRegion)); } - if (R->hasStackStorage() && !R->hasParametersStorage()) { - + if (R->hasStackNonParametersStorage()) { if (isa<ElementRegion>(R)) { // Currently we don't reason specially about Clang-style vectors. Check // if superR is a vector and if so return Unknown. diff --git a/clang/lib/Analysis/Store.cpp b/clang/lib/Analysis/Store.cpp index 8d911b844fc..4d150230013 100644 --- a/clang/lib/Analysis/Store.cpp +++ b/clang/lib/Analysis/Store.cpp @@ -77,6 +77,7 @@ 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::CXXThisRegionKind: case MemRegion::GenericMemSpaceRegionKind: case MemRegion::StackLocalsSpaceRegionKind: case MemRegion::StackArgumentsSpaceRegionKind: @@ -240,8 +241,3 @@ SVal StoreManager::getLValueCompoundLiteral(const CompoundLiteralExpr* CL, const LocationContext *LC) { return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL, LC)); } - -Loc StoreManager::getThisObject(QualType T) { - const CXXObjectRegion *R = MRMgr.getCXXObjectRegion(T); - return loc::MemRegionVal(R); -} |