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