[cfe-commits] r92675 - in /cfe/trunk: include/clang/Analysis/PathSensitive/MemRegion.h include/clang/Analysis/PathSensitive/Store.h lib/Analysis/GRExprEngine.cpp lib/Analysis/MemRegion.cpp lib/Analysis/RegionStore.cpp lib/Analysis/Store.cpp test/Analysis/misc-ps-region-store.cpp

Ted Kremenek kremenek at apple.com
Mon Jan 4 18:18:06 PST 2010


Author: kremenek
Date: Mon Jan  4 20:18:06 2010
New Revision: 92675

URL: http://llvm.org/viewvc/llvm-project?rev=92675&view=rev
Log:
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.

Modified:
    cfe/trunk/include/clang/Analysis/PathSensitive/MemRegion.h
    cfe/trunk/include/clang/Analysis/PathSensitive/Store.h
    cfe/trunk/lib/Analysis/GRExprEngine.cpp
    cfe/trunk/lib/Analysis/MemRegion.cpp
    cfe/trunk/lib/Analysis/RegionStore.cpp
    cfe/trunk/lib/Analysis/Store.cpp
    cfe/trunk/test/Analysis/misc-ps-region-store.cpp

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/MemRegion.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/MemRegion.h?rev=92675&r1=92674&r2=92675&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/MemRegion.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/MemRegion.h Mon Jan  4 20:18:06 2010
@@ -65,6 +65,7 @@
     BlockTextRegionKind,
     BlockDataRegionKind,
     CompoundLiteralRegionKind,
+    CXXThisRegionKind,
     StringRegionKind,
     ElementRegionKind,
     // Decl Regions.
@@ -99,17 +100,13 @@
 
   const MemRegion *StripCasts() const;
 
-  bool hasStackStorage() const;
-
-  bool hasParametersStorage() const;
-
-  bool hasGlobalsStorage() const;
-
   bool hasGlobalsOrParametersStorage() const;
 
-  bool hasHeapStorage() const;
-
-  bool hasHeapOrStackStorage() const;
+  bool hasStackStorage() const;
+  
+  bool hasStackNonParametersStorage() const;
+  
+  bool hasStackParametersStorage() const;
 
   virtual void dumpToStream(llvm::raw_ostream& os) const;
 
@@ -634,6 +631,36 @@
     return R->getKind() == VarRegionKind;
   }
 };
+  
+/// CXXThisRegion - Represents the region for the implicit 'this' parameter
+///  in a call to a C++ method.  This region doesn't represent the object
+///  referred to by 'this', but rather 'this' itself.
+class CXXThisRegion : public TypedRegion {
+  friend class MemRegionManager;
+  CXXThisRegion(const PointerType *thisPointerTy,
+                const MemRegion *sReg)
+    : TypedRegion(sReg, CXXThisRegionKind), ThisPointerTy(thisPointerTy) {}
+
+  static void ProfileRegion(llvm::FoldingSetNodeID &ID,
+                            const PointerType *PT,
+                            const MemRegion *sReg);
+
+  void Profile(llvm::FoldingSetNodeID &ID) const;
+
+public:  
+  QualType getValueType(ASTContext &C) const {
+    return QualType(ThisPointerTy, 0);
+  }
+  
+  void dumpToStream(llvm::raw_ostream& os) const;
+  
+  static bool classof(const MemRegion* R) {
+    return R->getKind() == CXXThisRegionKind;
+  }
+
+private:
+  const PointerType *ThisPointerTy;
+};
 
 class FieldRegion : public DeclRegion {
   friend class MemRegionManager;
@@ -824,6 +851,11 @@
   const CompoundLiteralRegion*
   getCompoundLiteralRegion(const CompoundLiteralExpr* CL,
                            const LocationContext *LC);
+  
+  /// getCXXThisRegion - Retrieve the [artifical] region associated with the
+  ///  parameter 'this'.
+  const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy,
+                                        const LocationContext *LC);
 
   /// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
   const SymbolicRegion* getSymbolicRegion(SymbolRef sym);

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/Store.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/Store.h?rev=92675&r1=92674&r2=92675&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/Store.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/Store.h Mon Jan  4 20:18:06 2010
@@ -103,9 +103,6 @@
 
   virtual SVal getLValueElement(QualType elementType, SVal offset, SVal Base)=0;
 
-  // T - the object type.
-  Loc getThisObject(QualType T);
-
   // FIXME: Make out-of-line.
   virtual DefinedOrUnknownSVal getSizeInElements(const GRState *state, 
                                                  const MemRegion *region) {

Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=92675&r1=92674&r2=92675&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Mon Jan  4 20:18:06 2010
@@ -2711,8 +2711,13 @@
 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, 

Modified: cfe/trunk/lib/Analysis/MemRegion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/MemRegion.cpp?rev=92675&r1=92674&r2=92675&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/MemRegion.cpp (original)
+++ cfe/trunk/lib/Analysis/MemRegion.cpp Mon Jan  4 20:18:06 2010
@@ -215,6 +215,18 @@
   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 @@
   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 @@
   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 @@
   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 @@
   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());
 }
 

Modified: cfe/trunk/lib/Analysis/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/RegionStore.cpp?rev=92675&r1=92674&r2=92675&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/RegionStore.cpp (original)
+++ cfe/trunk/lib/Analysis/RegionStore.cpp Mon Jan  4 20:18:06 2010
@@ -28,7 +28,6 @@
 
 using namespace clang;
 
-#define HEAP_UNDEFINED 0
 #define USE_EXPLICIT_COMPOUND 0
 
 namespace {
@@ -723,6 +722,8 @@
                                                            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 @@
       // 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 @@
   // 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 @@
                          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.

Modified: cfe/trunk/lib/Analysis/Store.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/Store.cpp?rev=92675&r1=92674&r2=92675&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/Store.cpp (original)
+++ cfe/trunk/lib/Analysis/Store.cpp Mon Jan  4 20:18:06 2010
@@ -77,6 +77,7 @@
 
   // 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 @@
                                             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);
-}

Modified: cfe/trunk/test/Analysis/misc-ps-region-store.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps-region-store.cpp?rev=92675&r1=92674&r2=92675&view=diff

==============================================================================
--- cfe/trunk/test/Analysis/misc-ps-region-store.cpp (original)
+++ cfe/trunk/test/Analysis/misc-ps-region-store.cpp Mon Jan  4 20:18:06 2010
@@ -34,6 +34,10 @@
   return test3_aux(x);
 }
 
+//===---------------------------------------------------------------------===//
+// Test CFG support for C++ condition variables.
+//===---------------------------------------------------------------------===//
+
 int test_init_in_condition_aux();
 int test_init_in_condition() {
   if (int x = test_init_in_condition_aux()) { // no-warning
@@ -89,3 +93,42 @@
   *p = 0xDEADBEEF; // no-warning
   return 0;
 }
+
+//===---------------------------------------------------------------------===//
+// Test handling of 'this' pointer.
+//===---------------------------------------------------------------------===//
+
+class TestHandleThis {
+  int x;
+
+  TestHandleThis();  
+  int foo();
+  int null_deref_negative();
+  int null_deref_positive();  
+};
+
+int TestHandleThis::foo() {
+  // Assume that 'x' is initialized.
+  return x + 1; // no-warning
+}
+
+int TestHandleThis::null_deref_negative() {
+  x = 10;
+  if (x == 10) {
+    return 1;
+  }
+  int *p = 0;
+  *p = 0xDEADBEEF; // no-warning
+  return 0;  
+}
+
+int TestHandleThis::null_deref_positive() {
+  x = 10;
+  if (x == 9) {
+    return 1;
+  }
+  int *p = 0;
+  *p = 0xDEADBEEF; // expected-warning{{null pointer}}
+  return 0;  
+}
+





More information about the cfe-commits mailing list