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