ProgramStateTrait.h revision 9946fc735d7285f2195f89635370f534afd9877e
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
23namespace 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
31namespace clang {
32
33namespace 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  (void*) 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} // end GR namespace
227
228} // end clang namespace
229
230#endif
231