summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2010-01-05 02:18:06 +0000
committerTed Kremenek <kremenek@apple.com>2010-01-05 02:18:06 +0000
commitacd71a456254f3b4b1f9a860ab09f93026b1e0ef (patch)
tree4c9fa59f091f7744526ca1ebd231c3b8ae79abf8 /clang/lib
parenta0e1ee828a071b619324cab8ae438c7c3d5198d2 (diff)
downloadbcm5719-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.cpp9
-rw-r--r--clang/lib/Analysis/MemRegion.cpp45
-rw-r--r--clang/lib/Analysis/RegionStore.cpp16
-rw-r--r--clang/lib/Analysis/Store.cpp6
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);
-}
OpenPOWER on IntegriCloud