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