]> granicus.if.org Git - clang/commitdiff
Enhances SCA to process untyped region to typed region conversion.
authorZhongxing Xu <xuzhongxing@gmail.com>
Sun, 16 Nov 2008 04:07:26 +0000 (04:07 +0000)
committerZhongxing Xu <xuzhongxing@gmail.com>
Sun, 16 Nov 2008 04:07:26 +0000 (04:07 +0000)
 - RegionView and RegionViewMap is introduced to assist back-mapping from
   super region to subregions.
 - GDM is used to carry RegionView information.
 - AnonTypedRegion is added to represent a typed region introduced by pointer
   casting. Later AnonTypedRegion can be used in other similar cases, e.g.,
   malloc()'ed region.
 - The specific conversion is delegated to store manager.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59382 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/PathSensitive/MemRegion.h
include/clang/Analysis/PathSensitive/Store.h
lib/Analysis/BasicStore.cpp
lib/Analysis/GRExprEngine.cpp
lib/Analysis/MemRegion.cpp
lib/Analysis/RegionStore.cpp

index 04d904623e2b0d9cb261ffb295041c6282cb5f3f..287dd09c2bec7a5e385f110e7f9336bce57fca29 100644 (file)
@@ -23,6 +23,8 @@
 #include "clang/AST/ASTContext.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/ImmutableList.h"
+#include "llvm/ADT/ImmutableMap.h"
 #include "llvm/Support/Allocator.h"
 #include <string>
 
@@ -42,12 +44,13 @@ public:
               BEG_TYPED_REGIONS,
                CompoundLiteralRegionKind,
                StringRegionKind, ElementRegionKind,
+               AnonTypedRegionKind,
+               AnonPointeeRegionKind,
                // Decl Regions.
                  BEG_DECL_REGIONS,
                   VarRegionKind, FieldRegionKind,
                   ObjCIvarRegionKind, ObjCObjectRegionKind,
                  END_DECL_REGIONS,
-               AnonPointeeRegionKind,
               END_TYPED_REGIONS };  
 private:
   const Kind kind;
@@ -201,6 +204,32 @@ public:
   }
 };
 
+class AnonTypedRegion : public TypedRegion {
+  friend class MemRegionManager;
+
+  QualType T;
+
+  AnonTypedRegion(QualType t, const MemRegion* sreg)
+    : TypedRegion(sreg, AnonTypedRegionKind), T(t) {}
+
+  static void ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T, 
+                            const MemRegion* superRegion);
+
+public:
+
+  QualType getType(ASTContext& C) const {
+    return T;
+  }
+
+  void Profile(llvm::FoldingSetNodeID& ID) const {
+    ProfileRegion(ID, T, superRegion);
+  }
+
+  static bool classof(const MemRegion* R) {
+    return R->getKind() == AnonTypedRegionKind;
+  }
+};
+
 /// AnonPointeeRegion - anonymous regions pointed-to by pointer function
 ///  parameters or pointer globals. In RegionStoreManager, we assume pointer
 ///  parameters or globals point at some anonymous region. Such regions are not
@@ -494,7 +523,7 @@ class MemRegionManager {
   MemSpaceRegion* stack;
   MemSpaceRegion* heap;
   MemSpaceRegion* unknown;
-  
+
 public:
   MemRegionManager(llvm::BumpPtrAllocator& a)
   : A(a), globals(0), stack(0), heap(0) {}
@@ -559,10 +588,12 @@ public:
   ObjCIvarRegion* getObjCIvarRegion(const ObjCIvarDecl* ivd,
                                     const MemRegion* superRegion);
 
+  AnonTypedRegion* getAnonTypedRegion(QualType t, const MemRegion* superRegion);
+
   AnonPointeeRegion* getAnonPointeeRegion(const VarDecl* d);
 
   bool hasStackStorage(const MemRegion* R);
-  
+
 private:
   MemSpaceRegion* LazyAllocate(MemSpaceRegion*& region);
 };
index 5ec732fda8f0d3de18a72796a7ea323be6f15cca..06c49cb85cc4f4ba99e982b63277b1367ed6c3e7 100644 (file)
@@ -80,6 +80,9 @@ public:
   /// ArrayToPointer - Used by GRExprEngine::VistCast to handle implicit
   ///  conversions between arrays and pointers.
   virtual SVal ArrayToPointer(SVal Array) = 0;
+
+  virtual const GRState* CastRegion(const GRState* St, SVal VoidPtr, 
+                                    QualType CastToTy, Stmt* CastE) = 0;
   
   /// getSelfRegion - Returns the region for the 'self' (Objective-C) or
   ///  'this' object (C++).  When used when analyzing a normal function this
index 4197c08a9cfca32a4f52e80220caa62865146005..8b5ef6ee865a1cc1035eb147354ea732628e4d3f 100644 (file)
@@ -65,6 +65,12 @@ public:
   /// ArrayToPointer - Used by GRExprEngine::VistCast to handle implicit
   ///  conversions between arrays and pointers.
   SVal ArrayToPointer(SVal Array) { return Array; }
+
+  const GRState* CastRegion(const GRState* St, SVal VoidPtr, QualType CastToTy,
+                            Stmt* CastE) {
+    return St;
+  }
+
   
   /// getSelfRegion - Returns the region for the 'self' (Objective-C) or
   ///  'this' object (C++).  When used when analyzing a normal function this
index 55fbf1874a5fc45d799b9e8a0a0b41ffee56e6ad..e002c1363722c4e9336b29459466f49445dbbe57 100644 (file)
@@ -1692,6 +1692,21 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
       continue;
     }
 
+    // Check for casts from AllocaRegion pointer to typed pointer.
+    if (isa<loc::MemRegionVal>(V)) {
+      assert(Loc::IsLocType(T));
+      assert(Loc::IsLocType(ExTy));
+
+      // Delegate to store manager.
+      const GRState* NewSt = getStoreManager().CastRegion(St, V, T, CastE);
+
+      // If no new region is created, fall through to the default case.
+      if (NewSt != St) {
+        MakeNode(Dst, CastE, N, NewSt);
+        continue;
+      }
+    }
+
     // All other cases.
     MakeNode(Dst, CastE, N, BindExpr(St, CastE, EvalCast(V, CastE->getType())));
   }
index a292d98e60525b6c5b9137e07e881a7a74e97ff9..4636eaef11f15adfdf967294aa73b69c74480c73 100644 (file)
@@ -44,6 +44,13 @@ void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const {
   ProfileRegion(ID, Ex, Cnt);
 }
 
+void AnonTypedRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T, 
+                                    const MemRegion* superRegion) {
+  ID.AddInteger((unsigned) AnonTypedRegionKind);
+  ID.Add(T);
+  ID.AddPointer(superRegion);
+}
+
 QualType AnonPointeeRegion::getType(ASTContext& C) const {
   QualType T = C.getCanonicalType(Pointer->getType());
   PointerType* PTy = cast<PointerType>(T.getTypePtr());
@@ -110,7 +117,7 @@ QualType ElementRegion::getType(ASTContext& C) const {
     ArrayType* AT = cast<ArrayType>(T.getTypePtr());
     return AT->getElementType();
   }
-  else if (isa<AllocaRegion>(superRegion)) {
+  else if (isa<AnonTypedRegion>(superRegion)) {
     PointerType* PtrT = cast<PointerType>(T.getTypePtr());
     QualType PTy = PtrT->getPointeeType();
     return C.getCanonicalType(PTy);
@@ -369,6 +376,23 @@ MemRegionManager::getObjCObjectRegion(const ObjCInterfaceDecl* d,
   return R;
 }
 
+AnonTypedRegion* 
+MemRegionManager::getAnonTypedRegion(QualType t, const MemRegion* superRegion) {
+  llvm::FoldingSetNodeID ID;
+  AnonTypedRegion::ProfileRegion(ID, t, superRegion);
+
+  void* InsertPos;
+  MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
+  AnonTypedRegion* R = cast_or_null<AnonTypedRegion>(data);
+
+  if (!R) {
+    R = (AnonTypedRegion*) A.Allocate<AnonTypedRegion>();
+    new (R) AnonTypedRegion(t, superRegion);
+    Regions.InsertNode(R, InsertPos);
+  }
+
+  return R;
+}
 
 AnonPointeeRegion* MemRegionManager::getAnonPointeeRegion(const VarDecl* d) {
   llvm::FoldingSetNodeID ID;
index f1c57b33bdf183f92572e8d489388955fbdc121f..732785c0f7201e678143728bd673352d7f8a1860 100644 (file)
 //===----------------------------------------------------------------------===//
 #include "clang/Analysis/PathSensitive/MemRegion.h"
 #include "clang/Analysis/PathSensitive/GRState.h"
+#include "clang/Analysis/PathSensitive/GRStateTrait.h"
 #include "clang/Analysis/Analyses/LiveVariables.h"
 
 #include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/ImmutableList.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/Compiler.h"
 
 using namespace clang;
 
 typedef llvm::ImmutableMap<const MemRegion*, SVal> RegionBindingsTy;
+typedef llvm::ImmutableList<const MemRegion*> RegionViewTy;
+typedef llvm::ImmutableMap<const MemRegion*, RegionViewTy> RegionViewMapTy;
+
+static int RegionViewMapTyIndex = 0;
+
+namespace clang {
+template<> struct GRStateTrait<RegionViewMapTy> 
+  : public GRStatePartialTrait<RegionViewMapTy> {
+  static void* GDMIndex() { return &RegionViewMapTyIndex; }
+};
+}
 
 namespace {
 
 class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager {
   RegionBindingsTy::Factory RBFactory;
+  RegionViewTy::Factory RVFactory;
+  RegionViewMapTy::Factory RVMFactory;
+
   GRStateManager& StateMgr;
   MemRegionManager MRMgr;
 
 public:
   RegionStoreManager(GRStateManager& mgr) 
-    : StateMgr(mgr), MRMgr(StateMgr.getAllocator()) {}
+    : RBFactory(mgr.getAllocator()),
+      RVFactory(mgr.getAllocator()),
+      RVMFactory(mgr.getAllocator()),
+      StateMgr(mgr), 
+      MRMgr(StateMgr.getAllocator()) {}
 
   virtual ~RegionStoreManager() {}
 
@@ -62,6 +82,9 @@ public:
 
   SVal ArrayToPointer(SVal Array);
 
+  const GRState* CastRegion(const GRState* St, SVal VoidPtr, 
+                            QualType CastToTy, Stmt* CastE);
+
   SVal Retrieve(Store S, Loc L, QualType T = QualType());
 
   Store Bind(Store St, Loc LV, SVal V);
@@ -112,6 +135,9 @@ private:
   // Utility methods.
   BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
   ASTContext& getContext() { return StateMgr.getContext(); }
+
+  const GRState* AddRegionView(const GRState* St,
+                               const MemRegion* View, const MemRegion* Base);
 };
 
 } // end anonymous namespace
@@ -238,6 +264,30 @@ SVal RegionStoreManager::ArrayToPointer(SVal Array) {
   return loc::MemRegionVal(ER);                    
 }
 
+const GRState* RegionStoreManager::CastRegion(const GRState* St,
+                                              SVal VoidPtr, 
+                                              QualType CastToTy,
+                                              Stmt* CastE) {
+  if (const AllocaRegion* AR =
+      dyn_cast<AllocaRegion>(cast<loc::MemRegionVal>(VoidPtr).getRegion())) {
+
+    // Create a new region to attach type information to it.
+    const AnonTypedRegion* TR = MRMgr.getAnonTypedRegion(CastToTy, AR);
+
+    // Get the pointer to the first element.
+    nonloc::ConcreteInt Idx(getBasicVals().getZeroWithPtrWidth(false));
+    const ElementRegion* ER = MRMgr.getElementRegion(Idx, TR);
+
+    St = StateMgr.BindExpr(St, CastE, loc::MemRegionVal(ER));
+
+    // Add a RegionView to base region.
+    return AddRegionView(St, TR, AR);
+  }
+
+  // Default case.
+  return St;
+}
+
 SVal RegionStoreManager::Retrieve(Store S, Loc L, QualType T) {
   assert(!isa<UnknownVal>(L) && "location unknown");
   assert(!isa<UndefinedVal>(L) && "location undefined");
@@ -600,3 +650,19 @@ Store RegionStoreManager::BindStructToVal(Store store, const TypedRegion* BaseR,
 
   return store;
 }
+
+const GRState* RegionStoreManager::AddRegionView(const GRState* St,
+                                                 const MemRegion* View,
+                                                 const MemRegion* Base) {
+  GRStateRef state(St, StateMgr);
+
+  // First, retrieve the region view of the base region.
+  RegionViewMapTy::data_type* d = state.get<RegionViewMapTy>(Base);
+  RegionViewTy L = d ? *d : RVFactory.GetEmptyList();
+
+  // Now add View to the region view.
+  L = RVFactory.Add(View, L);
+
+  // Create a new state with the new region view.
+  return state.set<RegionViewMapTy>(Base, L);
+}