diff options
| -rw-r--r-- | clang/include/clang/Analysis/PathSensitive/MemRegion.h | 37 | ||||
| -rw-r--r-- | clang/include/clang/Analysis/PathSensitive/Store.h | 3 | ||||
| -rw-r--r-- | clang/lib/Analysis/BasicStore.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Analysis/GRExprEngine.cpp | 15 | ||||
| -rw-r--r-- | clang/lib/Analysis/MemRegion.cpp | 26 | ||||
| -rw-r--r-- | clang/lib/Analysis/RegionStore.cpp | 68 | 
6 files changed, 150 insertions, 5 deletions
| diff --git a/clang/include/clang/Analysis/PathSensitive/MemRegion.h b/clang/include/clang/Analysis/PathSensitive/MemRegion.h index 04d904623e2..287dd09c2be 100644 --- a/clang/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/clang/include/clang/Analysis/PathSensitive/MemRegion.h @@ -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);  }; diff --git a/clang/include/clang/Analysis/PathSensitive/Store.h b/clang/include/clang/Analysis/PathSensitive/Store.h index 5ec732fda8f..06c49cb85cc 100644 --- a/clang/include/clang/Analysis/PathSensitive/Store.h +++ b/clang/include/clang/Analysis/PathSensitive/Store.h @@ -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 diff --git a/clang/lib/Analysis/BasicStore.cpp b/clang/lib/Analysis/BasicStore.cpp index 4197c08a9cf..8b5ef6ee865 100644 --- a/clang/lib/Analysis/BasicStore.cpp +++ b/clang/lib/Analysis/BasicStore.cpp @@ -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 diff --git a/clang/lib/Analysis/GRExprEngine.cpp b/clang/lib/Analysis/GRExprEngine.cpp index 55fbf1874a5..e002c136372 100644 --- a/clang/lib/Analysis/GRExprEngine.cpp +++ b/clang/lib/Analysis/GRExprEngine.cpp @@ -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())));    } diff --git a/clang/lib/Analysis/MemRegion.cpp b/clang/lib/Analysis/MemRegion.cpp index a292d98e605..4636eaef11f 100644 --- a/clang/lib/Analysis/MemRegion.cpp +++ b/clang/lib/Analysis/MemRegion.cpp @@ -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; diff --git a/clang/lib/Analysis/RegionStore.cpp b/clang/lib/Analysis/RegionStore.cpp index f1c57b33bdf..732785c0f72 100644 --- a/clang/lib/Analysis/RegionStore.cpp +++ b/clang/lib/Analysis/RegionStore.cpp @@ -16,26 +16,46 @@  //===----------------------------------------------------------------------===//  #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); +} | 

