Home | History | Annotate | Download | only in PathSensitive
      1 //ProgramStateTrait.h - Partial implementations of ProgramStateTrait -*- C++ -*-
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 //  This file defines partial implementations of template specializations of
     11 //  the class ProgramStateTrait<>.  ProgramStateTrait<> is used by ProgramState
     12 //  to implement set/get methods for manipulating a ProgramState's
     13 //  generic data map.
     14 //
     15 //===----------------------------------------------------------------------===//
     16 
     17 
     18 #ifndef LLVM_CLANG_GR_PROGRAMSTATETRAIT_H
     19 #define LLVM_CLANG_GR_PROGRAMSTATETRAIT_H
     20 
     21 #include "llvm/Support/DataTypes.h"
     22 
     23 namespace llvm {
     24   class BumpPtrAllocator;
     25   template <typename K, typename D, typename I> class ImmutableMap;
     26   template <typename K, typename I> class ImmutableSet;
     27   template <typename T> class ImmutableList;
     28   template <typename T> class ImmutableListImpl;
     29 }
     30 
     31 namespace clang {
     32 
     33 namespace ento {
     34   template <typename T> struct ProgramStatePartialTrait;
     35 
     36   /// Declares a program state trait for type \p Type called \p Name, and
     37   /// introduce a typedef named \c NameTy.
     38   /// The macro should not be used inside namespaces, or for traits that must
     39   /// be accessible from more than one translation unit.
     40   #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \
     41     namespace { \
     42       class Name {}; \
     43       typedef Type Name ## Ty; \
     44     } \
     45     namespace clang { \
     46     namespace ento { \
     47       template <> \
     48       struct ProgramStateTrait<Name> \
     49         : public ProgramStatePartialTrait<Name ## Ty> { \
     50         static void *GDMIndex() { static int Index; return &Index; } \
     51       }; \
     52     } \
     53     }
     54 
     55 
     56   // Partial-specialization for ImmutableMap.
     57 
     58   template <typename Key, typename Data, typename Info>
     59   struct ProgramStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > {
     60     typedef llvm::ImmutableMap<Key,Data,Info> data_type;
     61     typedef typename data_type::Factory&      context_type;
     62     typedef Key                               key_type;
     63     typedef Data                              value_type;
     64     typedef const value_type*                 lookup_type;
     65 
     66     static inline data_type MakeData(void *const* p) {
     67       return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0);
     68     }
     69     static inline void *MakeVoidPtr(data_type B) {
     70       return B.getRoot();
     71     }
     72     static lookup_type Lookup(data_type B, key_type K) {
     73       return B.lookup(K);
     74     }
     75     static data_type Set(data_type B, key_type K, value_type E,context_type F){
     76       return F.add(B, K, E);
     77     }
     78 
     79     static data_type Remove(data_type B, key_type K, context_type F) {
     80       return F.remove(B, K);
     81     }
     82 
     83     static inline context_type MakeContext(void *p) {
     84       return *((typename data_type::Factory*) p);
     85     }
     86 
     87     static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
     88       return new typename data_type::Factory(Alloc);
     89     }
     90 
     91     static void DeleteContext(void *Ctx) {
     92       delete (typename data_type::Factory*) Ctx;
     93     }
     94   };
     95 
     96   /// Helper for registering a map trait.
     97   ///
     98   /// If the map type were written directly in the invocation of
     99   /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments
    100   /// would be treated as a macro argument separator, which is wrong.
    101   /// This allows the user to specify a map type in a way that the preprocessor
    102   /// can deal with.
    103   #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value>
    104 
    105 
    106   // Partial-specialization for ImmutableSet.
    107 
    108   template <typename Key, typename Info>
    109   struct ProgramStatePartialTrait< llvm::ImmutableSet<Key,Info> > {
    110     typedef llvm::ImmutableSet<Key,Info>      data_type;
    111     typedef typename data_type::Factory&      context_type;
    112     typedef Key                               key_type;
    113 
    114     static inline data_type MakeData(void *const* p) {
    115       return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0);
    116     }
    117 
    118     static inline void *MakeVoidPtr(data_type B) {
    119       return B.getRoot();
    120     }
    121 
    122     static data_type Add(data_type B, key_type K, context_type F) {
    123       return F.add(B, K);
    124     }
    125 
    126     static data_type Remove(data_type B, key_type K, context_type F) {
    127       return F.remove(B, K);
    128     }
    129 
    130     static bool Contains(data_type B, key_type K) {
    131       return B.contains(K);
    132     }
    133 
    134     static inline context_type MakeContext(void *p) {
    135       return *((typename data_type::Factory*) p);
    136     }
    137 
    138     static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
    139       return new typename data_type::Factory(Alloc);
    140     }
    141 
    142     static void DeleteContext(void *Ctx) {
    143       delete (typename data_type::Factory*) Ctx;
    144     }
    145   };
    146 
    147 
    148   // Partial-specialization for ImmutableList.
    149 
    150   template <typename T>
    151   struct ProgramStatePartialTrait< llvm::ImmutableList<T> > {
    152     typedef llvm::ImmutableList<T>            data_type;
    153     typedef T                                 key_type;
    154     typedef typename data_type::Factory&      context_type;
    155 
    156     static data_type Add(data_type L, key_type K, context_type F) {
    157       return F.add(K, L);
    158     }
    159 
    160     static bool Contains(data_type L, key_type K) {
    161       return L.contains(K);
    162     }
    163 
    164     static inline data_type MakeData(void *const* p) {
    165       return p ? data_type((const llvm::ImmutableListImpl<T>*) *p)
    166                : data_type(0);
    167     }
    168 
    169     static inline void *MakeVoidPtr(data_type D) {
    170       return const_cast<llvm::ImmutableListImpl<T> *>(D.getInternalPointer());
    171     }
    172 
    173     static inline context_type MakeContext(void *p) {
    174       return *((typename data_type::Factory*) p);
    175     }
    176 
    177     static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
    178       return new typename data_type::Factory(Alloc);
    179     }
    180 
    181     static void DeleteContext(void *Ctx) {
    182       delete (typename data_type::Factory*) Ctx;
    183     }
    184   };
    185 
    186 
    187   // Partial specialization for bool.
    188   template <> struct ProgramStatePartialTrait<bool> {
    189     typedef bool data_type;
    190 
    191     static inline data_type MakeData(void *const* p) {
    192       return p ? (data_type) (uintptr_t) *p
    193                : data_type();
    194     }
    195     static inline void *MakeVoidPtr(data_type d) {
    196       return (void*) (uintptr_t) d;
    197     }
    198   };
    199 
    200   // Partial specialization for unsigned.
    201   template <> struct ProgramStatePartialTrait<unsigned> {
    202     typedef unsigned data_type;
    203 
    204     static inline data_type MakeData(void *const* p) {
    205       return p ? (data_type) (uintptr_t) *p
    206                : data_type();
    207     }
    208     static inline void *MakeVoidPtr(data_type d) {
    209       return (void*) (uintptr_t) d;
    210     }
    211   };
    212 
    213   // Partial specialization for void*.
    214   template <> struct ProgramStatePartialTrait<void*> {
    215     typedef void *data_type;
    216 
    217     static inline data_type MakeData(void *const* p) {
    218       return p ? *p
    219                : data_type();
    220     }
    221     static inline void *MakeVoidPtr(data_type d) {
    222       return d;
    223     }
    224   };
    225 
    226   // Partial specialization for const void *.
    227   template <> struct ProgramStatePartialTrait<const void *> {
    228     typedef const void *data_type;
    229 
    230     static inline data_type MakeData(void * const *p) {
    231       return p ? *p : data_type();
    232     }
    233 
    234     static inline void *MakeVoidPtr(data_type d) {
    235       return const_cast<void *>(d);
    236     }
    237   };
    238 
    239 } // end ento namespace
    240 
    241 } // end clang namespace
    242 
    243 #endif
    244