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