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