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