1139823Simp//ProgramStateTrait.h - Partial implementations of ProgramStateTrait -*- C++ -*- 2122922Sandre// 3122922Sandre// The LLVM Compiler Infrastructure 4122922Sandre// 5122922Sandre// This file is distributed under the University of Illinois Open Source 6122922Sandre// License. See LICENSE.TXT for details. 7122922Sandre// 8122922Sandre//===----------------------------------------------------------------------===// 9122922Sandre// 10122922Sandre// This file defines partial implementations of template specializations of 11122922Sandre// the class ProgramStateTrait<>. ProgramStateTrait<> is used by ProgramState 12122922Sandre// to implement set/get methods for manipulating a ProgramState's 13122922Sandre// generic data map. 14122922Sandre// 15122922Sandre//===----------------------------------------------------------------------===// 16122922Sandre 17122922Sandre 18122922Sandre#ifndef LLVM_CLANG_GR_PROGRAMSTATETRAIT_H 19122922Sandre#define LLVM_CLANG_GR_PROGRAMSTATETRAIT_H 20122922Sandre 21122922Sandre#include "llvm/Support/DataTypes.h" 22122922Sandre 23122922Sandrenamespace llvm { 24122922Sandre class BumpPtrAllocator; 25122922Sandre template <typename K, typename D, typename I> class ImmutableMap; 26122922Sandre template <typename K, typename I> class ImmutableSet; 27122922Sandre template <typename T> class ImmutableList; 28122922Sandre template <typename T> class ImmutableListImpl; 29122922Sandre} 30122922Sandre 31170030Srwatsonnamespace clang { 32170030Srwatson 33170030Srwatsonnamespace ento { 34170030Srwatson template <typename T> struct ProgramStatePartialTrait; 35170030Srwatson 36170030Srwatson /// Declares a program state trait for type \p Type called \p Name, and 37170030Srwatson /// introduce a typedef named \c NameTy. 38122922Sandre /// The macro should not be used inside namespaces, or for traits that must 39170030Srwatson /// be accessible from more than one translation unit. 40170030Srwatson #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \ 41170030Srwatson namespace { \ 42170030Srwatson class Name {}; \ 43170030Srwatson typedef Type Name ## Ty; \ 44122922Sandre } \ 45170030Srwatson namespace clang { \ 46170030Srwatson namespace ento { \ 47170030Srwatson template <> \ 48170030Srwatson struct ProgramStateTrait<Name> \ 49170030Srwatson : public ProgramStatePartialTrait<Name ## Ty> { \ 50170030Srwatson static void *GDMIndex() { static int Index; return &Index; } \ 51170030Srwatson }; \ 52170030Srwatson } \ 53170030Srwatson } 54170030Srwatson 55170030Srwatson 56170030Srwatson // Partial-specialization for ImmutableMap. 57170030Srwatson 58122922Sandre template <typename Key, typename Data, typename Info> 59122922Sandre struct ProgramStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > { 60122922Sandre typedef llvm::ImmutableMap<Key,Data,Info> data_type; 61122922Sandre typedef typename data_type::Factory& context_type; 62122922Sandre typedef Key key_type; 63122922Sandre typedef Data value_type; 64122922Sandre typedef const value_type* lookup_type; 65172467Ssilby 66172467Ssilby static inline data_type MakeData(void *const* p) { 67172467Ssilby return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0); 68122922Sandre } 69122922Sandre static inline void *MakeVoidPtr(data_type B) { 70122922Sandre return B.getRoot(); 71122922Sandre } 72122922Sandre static lookup_type Lookup(data_type B, key_type K) { 73122922Sandre return B.lookup(K); 74122922Sandre } 75122922Sandre static data_type Set(data_type B, key_type K, value_type E,context_type F){ 76122922Sandre return F.add(B, K, E); 77122922Sandre } 78122922Sandre 79181803Sbz static data_type Remove(data_type B, key_type K, context_type F) { 80122922Sandre return F.remove(B, K); 81122922Sandre } 82122922Sandre 83122922Sandre static inline context_type MakeContext(void *p) { 84122922Sandre return *((typename data_type::Factory*) p); 85122922Sandre } 86122922Sandre 87122922Sandre static void *CreateContext(llvm::BumpPtrAllocator& Alloc) { 88122922Sandre return new typename data_type::Factory(Alloc); 89122922Sandre } 90122922Sandre 91122922Sandre static void DeleteContext(void *Ctx) { 92122922Sandre delete (typename data_type::Factory*) Ctx; 93122922Sandre } 94122922Sandre }; 95122922Sandre 96122922Sandre /// Helper for registering a map trait. 97122922Sandre /// 98122922Sandre /// If the map type were written directly in the invocation of 99122922Sandre /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments 100122922Sandre /// would be treated as a macro argument separator, which is wrong. 101122922Sandre /// This allows the user to specify a map type in a way that the preprocessor 102122922Sandre /// can deal with. 103122922Sandre #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value> 104122922Sandre 105122922Sandre 106122922Sandre // Partial-specialization for ImmutableSet. 107122922Sandre 108122922Sandre template <typename Key, typename Info> 109122922Sandre struct ProgramStatePartialTrait< llvm::ImmutableSet<Key,Info> > { 110122922Sandre typedef llvm::ImmutableSet<Key,Info> data_type; 111122922Sandre typedef typename data_type::Factory& context_type; 112122922Sandre typedef Key key_type; 113122922Sandre 114122922Sandre static inline data_type MakeData(void *const* p) { 115122922Sandre return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0); 116170030Srwatson } 117122922Sandre 118122922Sandre static inline void *MakeVoidPtr(data_type B) { 119122922Sandre return B.getRoot(); 120122922Sandre } 121122922Sandre 122122922Sandre static data_type Add(data_type B, key_type K, context_type F) { 123122922Sandre return F.add(B, K); 124122922Sandre } 125170030Srwatson 126122922Sandre static data_type Remove(data_type B, key_type K, context_type F) { 127122922Sandre return F.remove(B, K); 128122922Sandre } 129122922Sandre 130122922Sandre static bool Contains(data_type B, key_type K) { 131122922Sandre return B.contains(K); 132122922Sandre } 133122922Sandre 134122922Sandre static inline context_type MakeContext(void *p) { 135122922Sandre return *((typename data_type::Factory*) p); 136122922Sandre } 137122922Sandre 138122922Sandre static void *CreateContext(llvm::BumpPtrAllocator& Alloc) { 139122922Sandre return new typename data_type::Factory(Alloc); 140122922Sandre } 141122922Sandre 142122922Sandre static void DeleteContext(void *Ctx) { 143122922Sandre delete (typename data_type::Factory*) Ctx; 144122922Sandre } 145122922Sandre }; 146170434Syar 147122922Sandre 148122922Sandre // Partial-specialization for ImmutableList. 149122922Sandre 150122922Sandre template <typename T> 151122922Sandre struct ProgramStatePartialTrait< llvm::ImmutableList<T> > { 152122922Sandre typedef llvm::ImmutableList<T> data_type; 153122922Sandre typedef T key_type; 154122922Sandre typedef typename data_type::Factory& context_type; 155122922Sandre 156122922Sandre static data_type Add(data_type L, key_type K, context_type F) { 157122922Sandre return F.add(K, L); 158122922Sandre } 159122922Sandre 160122922Sandre static bool Contains(data_type L, key_type K) { 161167784Sandre return L.contains(K); 162122922Sandre } 163122922Sandre 164167784Sandre static inline data_type MakeData(void *const* p) { 165122922Sandre return p ? data_type((const llvm::ImmutableListImpl<T>*) *p) 166122922Sandre : data_type(0); 167167784Sandre } 168122922Sandre 169122922Sandre static inline void *MakeVoidPtr(data_type D) { 170167784Sandre return const_cast<llvm::ImmutableListImpl<T> *>(D.getInternalPointer()); 171122922Sandre } 172122922Sandre 173167784Sandre static inline context_type MakeContext(void *p) { 174122922Sandre return *((typename data_type::Factory*) p); 175170434Syar } 176170434Syar 177170434Syar static void *CreateContext(llvm::BumpPtrAllocator& Alloc) { 178122922Sandre return new typename data_type::Factory(Alloc); 179167784Sandre } 180122922Sandre 181122922Sandre static void DeleteContext(void *Ctx) { 182167784Sandre delete (typename data_type::Factory*) Ctx; 183167784Sandre } 184122922Sandre }; 185122922Sandre 186122922Sandre 187122922Sandre // Partial specialization for bool. 188122922Sandre template <> struct ProgramStatePartialTrait<bool> { 189133874Srwatson typedef bool data_type; 190181803Sbz 191122922Sandre static inline data_type MakeData(void *const* p) { 192122922Sandre return p ? (data_type) (uintptr_t) *p 193133874Srwatson : data_type(); 194122922Sandre } 195122922Sandre static inline void *MakeVoidPtr(data_type d) { 196122922Sandre return (void*) (uintptr_t) d; 197122922Sandre } 198181803Sbz }; 199122922Sandre 200122922Sandre // Partial specialization for unsigned. 201122922Sandre template <> struct ProgramStatePartialTrait<unsigned> { 202122922Sandre typedef unsigned data_type; 203122922Sandre 204122922Sandre static inline data_type MakeData(void *const* p) { 205122922Sandre return p ? (data_type) (uintptr_t) *p 206122922Sandre : data_type(); 207122922Sandre } 208122922Sandre static inline void *MakeVoidPtr(data_type d) { 209170030Srwatson return (void*) (uintptr_t) d; 210122922Sandre } 211181803Sbz }; 212181803Sbz 213181803Sbz // Partial specialization for void*. 214181803Sbz template <> struct ProgramStatePartialTrait<void*> { 215181803Sbz typedef void *data_type; 216181803Sbz 217181803Sbz static inline data_type MakeData(void *const* p) { 218122922Sandre return p ? *p 219133874Srwatson : data_type(); 220181803Sbz } 221133874Srwatson static inline void *MakeVoidPtr(data_type d) { 222181803Sbz return d; 223133874Srwatson } 224181803Sbz }; 225181803Sbz 226133874Srwatson // Partial specialization for const void *. 227181803Sbz template <> struct ProgramStatePartialTrait<const void *> { 228133874Srwatson typedef const void *data_type; 229181803Sbz 230122922Sandre static inline data_type MakeData(void * const *p) { 231122922Sandre return p ? *p : data_type(); 232170030Srwatson } 233122922Sandre 234181803Sbz static inline void *MakeVoidPtr(data_type d) { 235181803Sbz return const_cast<void *>(d); 236122922Sandre } 237122922Sandre }; 238122922Sandre 239170030Srwatson} // end ento namespace 240122922Sandre 241181803Sbz} // end clang namespace 242181803Sbz 243181803Sbz#endif 244181803Sbz