]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / include / clang / StaticAnalyzer / Core / PathSensitive / ProgramStateTrait.h
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 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H
18 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H
19
20 #include "llvm/ADT/ImmutableList.h"
21 #include "llvm/ADT/ImmutableMap.h"
22 #include "llvm/ADT/ImmutableSet.h"
23 #include "llvm/Support/Allocator.h"
24 #include <cstdint>
25
26 namespace clang {
27 namespace ento {
28
29   template <typename T> struct ProgramStatePartialTrait;
30
31   /// Declares a program state trait for type \p Type called \p Name, and
32   /// introduce a type named \c NameTy.
33   /// The macro should not be used inside namespaces.
34   #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \
35     namespace { \
36       class Name {}; \
37       using Name ## Ty = Type; \
38     } \
39     namespace clang { \
40     namespace ento { \
41       template <> \
42       struct ProgramStateTrait<Name> \
43         : public ProgramStatePartialTrait<Name ## Ty> { \
44         static void *GDMIndex() { static int Index; return &Index; } \
45       }; \
46     } \
47     }
48
49   /// Declares a factory for objects of type \p Type in the program state
50   /// manager. The type must provide a ::Factory sub-class. Commonly used for
51   /// ImmutableMap, ImmutableSet, ImmutableList. The macro should not be used
52   /// inside namespaces.
53   #define REGISTER_FACTORY_WITH_PROGRAMSTATE(Type) \
54     namespace clang { \
55     namespace ento { \
56       template <> \
57       struct ProgramStateTrait<Type> \
58         : public ProgramStatePartialTrait<Type> { \
59         static void *GDMIndex() { static int Index; return &Index; } \
60       }; \
61     } \
62     }
63
64   /// Helper for registering a map trait.
65   ///
66   /// If the map type were written directly in the invocation of
67   /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments
68   /// would be treated as a macro argument separator, which is wrong.
69   /// This allows the user to specify a map type in a way that the preprocessor
70   /// can deal with.
71   #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value>
72
73   /// Declares an immutable map of type \p NameTy, suitable for placement into
74   /// the ProgramState. This is implementing using llvm::ImmutableMap.
75   ///
76   /// \code
77   /// State = State->set<Name>(K, V);
78   /// const Value *V = State->get<Name>(K); // Returns NULL if not in the map.
79   /// State = State->remove<Name>(K);
80   /// NameTy Map = State->get<Name>();
81   /// \endcode
82   ///
83   /// The macro should not be used inside namespaces, or for traits that must
84   /// be accessible from more than one translation unit.
85   #define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value) \
86     REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, \
87                                      CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value))
88
89   /// Declares an immutable map type \p Name and registers the factory
90   /// for such maps in the program state, but does not add the map itself
91   /// to the program state. Useful for managing lifetime of maps that are used
92   /// as elements of other program state data structures.
93   #define REGISTER_MAP_FACTORY_WITH_PROGRAMSTATE(Name, Key, Value) \
94     using Name = llvm::ImmutableMap<Key, Value>; \
95     REGISTER_FACTORY_WITH_PROGRAMSTATE(Name)
96
97
98   /// Declares an immutable set of type \p NameTy, suitable for placement into
99   /// the ProgramState. This is implementing using llvm::ImmutableSet.
100   ///
101   /// \code
102   /// State = State->add<Name>(E);
103   /// State = State->remove<Name>(E);
104   /// bool Present = State->contains<Name>(E);
105   /// NameTy Set = State->get<Name>();
106   /// \endcode
107   ///
108   /// The macro should not be used inside namespaces, or for traits that must
109   /// be accessible from more than one translation unit.
110   #define REGISTER_SET_WITH_PROGRAMSTATE(Name, Elem) \
111     REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableSet<Elem>)
112
113   /// Declares an immutable set type \p Name and registers the factory
114   /// for such sets in the program state, but does not add the set itself
115   /// to the program state. Useful for managing lifetime of sets that are used
116   /// as elements of other program state data structures.
117   #define REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(Name, Elem) \
118     using Name = llvm::ImmutableSet<Elem>; \
119     REGISTER_FACTORY_WITH_PROGRAMSTATE(Name)
120
121
122   /// Declares an immutable list type \p NameTy, suitable for placement into
123   /// the ProgramState. This is implementing using llvm::ImmutableList.
124   ///
125   /// \code
126   /// State = State->add<Name>(E); // Adds to the /end/ of the list.
127   /// bool Present = State->contains<Name>(E);
128   /// NameTy List = State->get<Name>();
129   /// \endcode
130   ///
131   /// The macro should not be used inside namespaces, or for traits that must
132   /// be accessible from more than one translation unit.
133   #define REGISTER_LIST_WITH_PROGRAMSTATE(Name, Elem) \
134     REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, llvm::ImmutableList<Elem>)
135
136   /// Declares an immutable list of type \p Name and registers the factory
137   /// for such lists in the program state, but does not add the list itself
138   /// to the program state. Useful for managing lifetime of lists that are used
139   /// as elements of other program state data structures.
140   #define REGISTER_LIST_FACTORY_WITH_PROGRAMSTATE(Name, Elem) \
141     using Name = llvm::ImmutableList<Elem>; \
142     REGISTER_FACTORY_WITH_PROGRAMSTATE(Name)
143
144
145   // Partial-specialization for ImmutableMap.
146   template <typename Key, typename Data, typename Info>
147   struct ProgramStatePartialTrait<llvm::ImmutableMap<Key, Data, Info>> {
148     using data_type = llvm::ImmutableMap<Key, Data, Info>;
149     using context_type = typename data_type::Factory &;
150     using key_type = Key;
151     using value_type = Data;
152     using lookup_type = const value_type *;
153
154     static data_type MakeData(void *const *p) {
155       return p ? data_type((typename data_type::TreeTy *) *p)
156                : data_type(nullptr);
157     }
158
159     static void *MakeVoidPtr(data_type B) {
160       return B.getRoot();
161     }
162
163     static lookup_type Lookup(data_type B, key_type K) {
164       return B.lookup(K);
165     }
166
167     static data_type Set(data_type B, key_type K, value_type E,
168                          context_type F) {
169       return F.add(B, K, E);
170     }
171
172     static data_type Remove(data_type B, key_type K, context_type F) {
173       return F.remove(B, K);
174     }
175
176     static bool Contains(data_type B, key_type K) {
177       return B.contains(K);
178     }
179
180     static context_type MakeContext(void *p) {
181       return *((typename data_type::Factory *) p);
182     }
183
184     static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
185       return new typename data_type::Factory(Alloc);
186     }
187
188     static void DeleteContext(void *Ctx) {
189       delete (typename data_type::Factory *) Ctx;
190     }
191   };
192
193   // Partial-specialization for ImmutableSet.
194   template <typename Key, typename Info>
195   struct ProgramStatePartialTrait<llvm::ImmutableSet<Key, Info>> {
196     using data_type = llvm::ImmutableSet<Key, Info>;
197     using context_type = typename data_type::Factory &;
198     using key_type = Key;
199
200     static data_type MakeData(void *const *p) {
201       return p ? data_type((typename data_type::TreeTy *) *p)
202                : data_type(nullptr);
203     }
204
205     static void *MakeVoidPtr(data_type B) {
206       return B.getRoot();
207     }
208
209     static data_type Add(data_type B, key_type K, context_type F) {
210       return F.add(B, K);
211     }
212
213     static data_type Remove(data_type B, key_type K, context_type F) {
214       return F.remove(B, K);
215     }
216
217     static bool Contains(data_type B, key_type K) {
218       return B.contains(K);
219     }
220
221     static context_type MakeContext(void *p) {
222       return *((typename data_type::Factory *) p);
223     }
224
225     static void *CreateContext(llvm::BumpPtrAllocator &Alloc) {
226       return new typename data_type::Factory(Alloc);
227     }
228
229     static void DeleteContext(void *Ctx) {
230       delete (typename data_type::Factory *) Ctx;
231     }
232   };
233
234   // Partial-specialization for ImmutableList.
235   template <typename T>
236   struct ProgramStatePartialTrait<llvm::ImmutableList<T>> {
237     using data_type = llvm::ImmutableList<T>;
238     using key_type = T;
239     using context_type = typename data_type::Factory &;
240
241     static data_type Add(data_type L, key_type K, context_type F) {
242       return F.add(K, L);
243     }
244
245     static bool Contains(data_type L, key_type K) {
246       return L.contains(K);
247     }
248
249     static data_type MakeData(void *const *p) {
250       return p ? data_type((const llvm::ImmutableListImpl<T> *) *p)
251                : data_type(nullptr);
252     }
253
254     static void *MakeVoidPtr(data_type D) {
255       return const_cast<llvm::ImmutableListImpl<T> *>(D.getInternalPointer());
256     }
257
258     static context_type MakeContext(void *p) {
259       return *((typename data_type::Factory *) p);
260     }
261
262     static void *CreateContext(llvm::BumpPtrAllocator &Alloc) {
263       return new typename data_type::Factory(Alloc);
264     }
265
266     static void DeleteContext(void *Ctx) {
267       delete (typename data_type::Factory *) Ctx;
268     }
269   };
270
271   // Partial specialization for bool.
272   template <> struct ProgramStatePartialTrait<bool> {
273     using data_type = bool;
274
275     static data_type MakeData(void *const *p) {
276       return p ? (data_type) (uintptr_t) *p
277                : data_type();
278     }
279
280     static void *MakeVoidPtr(data_type d) {
281       return (void *) (uintptr_t) d;
282     }
283   };
284
285   // Partial specialization for unsigned.
286   template <> struct ProgramStatePartialTrait<unsigned> {
287     using data_type = unsigned;
288
289     static data_type MakeData(void *const *p) {
290       return p ? (data_type) (uintptr_t) *p
291                : data_type();
292     }
293
294     static void *MakeVoidPtr(data_type d) {
295       return (void *) (uintptr_t) d;
296     }
297   };
298
299   // Partial specialization for void*.
300   template <> struct ProgramStatePartialTrait<void *> {
301     using data_type = void *;
302
303     static data_type MakeData(void *const *p) {
304       return p ? *p
305                : data_type();
306     }
307
308     static void *MakeVoidPtr(data_type d) {
309       return d;
310     }
311   };
312
313   // Partial specialization for const void *.
314   template <> struct ProgramStatePartialTrait<const void *> {
315     using data_type = const void *;
316
317     static data_type MakeData(void *const *p) {
318       return p ? *p : data_type();
319     }
320
321     static void *MakeVoidPtr(data_type d) {
322       return const_cast<void *>(d);
323     }
324   };
325
326 } // namespace ento
327 } // namespace clang
328
329 #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H