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_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H
     19 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H
     20 
     21 #include "llvm/Support/Allocator.h"
     22 #include "llvm/Support/DataTypes.h"
     23 
     24 namespace llvm {
     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)
     68                : data_type(nullptr);
     69     }
     70     static inline void *MakeVoidPtr(data_type B) {
     71       return B.getRoot();
     72     }
     73     static lookup_type Lookup(data_type B, key_type K) {
     74       return B.lookup(K);
     75     }
     76     static data_type Set(data_type B, key_type K, value_type E,context_type F){
     77       return F.add(B, K, E);
     78     }
     79 
     80     static data_type Remove(data_type B, key_type K, context_type F) {
     81       return F.remove(B, K);
     82     }
     83 
     84     static bool Contains(data_type B, key_type K) {
     85       return B.contains(K);
     86     }
     87 
     88     static inline context_type MakeContext(void *p) {
     89       return *((typename data_type::Factory*) p);
     90     }
     91 
     92     static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
     93       return new typename data_type::Factory(Alloc);
     94     }
     95 
     96     static void DeleteContext(void *Ctx) {
     97       delete (typename data_type::Factory*) Ctx;
     98     }
     99   };
    100 
    101   /// Helper for registering a map trait.
    102   ///
    103   /// If the map type were written directly in the invocation of
    104   /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments
    105   /// would be treated as a macro argument separator, which is wrong.
    106   /// This allows the user to specify a map type in a way that the preprocessor
    107   /// can deal with.
    108   #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value>
    109 
    110 
    111   // Partial-specialization for ImmutableSet.
    112 
    113   template <typename Key, typename Info>
    114   struct ProgramStatePartialTrait< llvm::ImmutableSet<Key,Info> > {
    115     typedef llvm::ImmutableSet<Key,Info>      data_type;
    116     typedef typename data_type::Factory&      context_type;
    117     typedef Key                               key_type;
    118 
    119     static inline data_type MakeData(void *const* p) {
    120       return p ? data_type((typename data_type::TreeTy*) *p)
    121                : data_type(nullptr);
    122     }
    123 
    124     static inline void *MakeVoidPtr(data_type B) {
    125       return B.getRoot();
    126     }
    127 
    128     static data_type Add(data_type B, key_type K, context_type F) {
    129       return F.add(B, K);
    130     }
    131 
    132     static data_type Remove(data_type B, key_type K, context_type F) {
    133       return F.remove(B, K);
    134     }
    135 
    136     static bool Contains(data_type B, key_type K) {
    137       return B.contains(K);
    138     }
    139 
    140     static inline context_type MakeContext(void *p) {
    141       return *((typename data_type::Factory*) p);
    142     }
    143 
    144     static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
    145       return new typename data_type::Factory(Alloc);
    146     }
    147 
    148     static void DeleteContext(void *Ctx) {
    149       delete (typename data_type::Factory*) Ctx;
    150     }
    151   };
    152 
    153 
    154   // Partial-specialization for ImmutableList.
    155 
    156   template <typename T>
    157   struct ProgramStatePartialTrait< llvm::ImmutableList<T> > {
    158     typedef llvm::ImmutableList<T>            data_type;
    159     typedef T                                 key_type;
    160     typedef typename data_type::Factory&      context_type;
    161 
    162     static data_type Add(data_type L, key_type K, context_type F) {
    163       return F.add(K, L);
    164     }
    165 
    166     static bool Contains(data_type L, key_type K) {
    167       return L.contains(K);
    168     }
    169 
    170     static inline data_type MakeData(void *const* p) {
    171       return p ? data_type((const llvm::ImmutableListImpl<T>*) *p)
    172                : data_type(nullptr);
    173     }
    174 
    175     static inline void *MakeVoidPtr(data_type D) {
    176       return const_cast<llvm::ImmutableListImpl<T> *>(D.getInternalPointer());
    177     }
    178 
    179     static inline context_type MakeContext(void *p) {
    180       return *((typename data_type::Factory*) p);
    181     }
    182 
    183     static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
    184       return new typename data_type::Factory(Alloc);
    185     }
    186 
    187     static void DeleteContext(void *Ctx) {
    188       delete (typename data_type::Factory*) Ctx;
    189     }
    190   };
    191 
    192 
    193   // Partial specialization for bool.
    194   template <> struct ProgramStatePartialTrait<bool> {
    195     typedef bool data_type;
    196 
    197     static inline data_type MakeData(void *const* p) {
    198       return p ? (data_type) (uintptr_t) *p
    199                : data_type();
    200     }
    201     static inline void *MakeVoidPtr(data_type d) {
    202       return (void*) (uintptr_t) d;
    203     }
    204   };
    205 
    206   // Partial specialization for unsigned.
    207   template <> struct ProgramStatePartialTrait<unsigned> {
    208     typedef unsigned data_type;
    209 
    210     static inline data_type MakeData(void *const* p) {
    211       return p ? (data_type) (uintptr_t) *p
    212                : data_type();
    213     }
    214     static inline void *MakeVoidPtr(data_type d) {
    215       return (void*) (uintptr_t) d;
    216     }
    217   };
    218 
    219   // Partial specialization for void*.
    220   template <> struct ProgramStatePartialTrait<void*> {
    221     typedef void *data_type;
    222 
    223     static inline data_type MakeData(void *const* p) {
    224       return p ? *p
    225                : data_type();
    226     }
    227     static inline void *MakeVoidPtr(data_type d) {
    228       return d;
    229     }
    230   };
    231 
    232   // Partial specialization for const void *.
    233   template <> struct ProgramStatePartialTrait<const void *> {
    234     typedef const void *data_type;
    235 
    236     static inline data_type MakeData(void * const *p) {
    237       return p ? *p : data_type();
    238     }
    239 
    240     static inline void *MakeVoidPtr(data_type d) {
    241       return const_cast<void *>(d);
    242     }
    243   };
    244 
    245 } // end ento namespace
    246 
    247 } // end clang namespace
    248 
    249 #endif
    250