1139823Simp//ProgramStateTrait.h - Partial implementations of ProgramStateTrait -*- C++ -*-
2122922Sandre//
3122922Sandre//                     The LLVM Compiler Infrastructure
4122922Sandre//
5122922Sandre// This file is distributed under the University of Illinois Open Source
6122922Sandre// License. See LICENSE.TXT for details.
7122922Sandre//
8122922Sandre//===----------------------------------------------------------------------===//
9122922Sandre//
10122922Sandre//  This file defines partial implementations of template specializations of
11122922Sandre//  the class ProgramStateTrait<>.  ProgramStateTrait<> is used by ProgramState
12122922Sandre//  to implement set/get methods for manipulating a ProgramState's
13122922Sandre//  generic data map.
14122922Sandre//
15122922Sandre//===----------------------------------------------------------------------===//
16122922Sandre
17122922Sandre
18122922Sandre#ifndef LLVM_CLANG_GR_PROGRAMSTATETRAIT_H
19122922Sandre#define LLVM_CLANG_GR_PROGRAMSTATETRAIT_H
20122922Sandre
21122922Sandre#include "llvm/Support/DataTypes.h"
22122922Sandre
23122922Sandrenamespace llvm {
24122922Sandre  class BumpPtrAllocator;
25122922Sandre  template <typename K, typename D, typename I> class ImmutableMap;
26122922Sandre  template <typename K, typename I> class ImmutableSet;
27122922Sandre  template <typename T> class ImmutableList;
28122922Sandre  template <typename T> class ImmutableListImpl;
29122922Sandre}
30122922Sandre
31170030Srwatsonnamespace clang {
32170030Srwatson
33170030Srwatsonnamespace ento {
34170030Srwatson  template <typename T> struct ProgramStatePartialTrait;
35170030Srwatson
36170030Srwatson  /// Declares a program state trait for type \p Type called \p Name, and
37170030Srwatson  /// introduce a typedef named \c NameTy.
38122922Sandre  /// The macro should not be used inside namespaces, or for traits that must
39170030Srwatson  /// be accessible from more than one translation unit.
40170030Srwatson  #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \
41170030Srwatson    namespace { \
42170030Srwatson      class Name {}; \
43170030Srwatson      typedef Type Name ## Ty; \
44122922Sandre    } \
45170030Srwatson    namespace clang { \
46170030Srwatson    namespace ento { \
47170030Srwatson      template <> \
48170030Srwatson      struct ProgramStateTrait<Name> \
49170030Srwatson        : public ProgramStatePartialTrait<Name ## Ty> { \
50170030Srwatson        static void *GDMIndex() { static int Index; return &Index; } \
51170030Srwatson      }; \
52170030Srwatson    } \
53170030Srwatson    }
54170030Srwatson
55170030Srwatson
56170030Srwatson  // Partial-specialization for ImmutableMap.
57170030Srwatson
58122922Sandre  template <typename Key, typename Data, typename Info>
59122922Sandre  struct ProgramStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > {
60122922Sandre    typedef llvm::ImmutableMap<Key,Data,Info> data_type;
61122922Sandre    typedef typename data_type::Factory&      context_type;
62122922Sandre    typedef Key                               key_type;
63122922Sandre    typedef Data                              value_type;
64122922Sandre    typedef const value_type*                 lookup_type;
65172467Ssilby
66172467Ssilby    static inline data_type MakeData(void *const* p) {
67172467Ssilby      return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0);
68122922Sandre    }
69122922Sandre    static inline void *MakeVoidPtr(data_type B) {
70122922Sandre      return B.getRoot();
71122922Sandre    }
72122922Sandre    static lookup_type Lookup(data_type B, key_type K) {
73122922Sandre      return B.lookup(K);
74122922Sandre    }
75122922Sandre    static data_type Set(data_type B, key_type K, value_type E,context_type F){
76122922Sandre      return F.add(B, K, E);
77122922Sandre    }
78122922Sandre
79181803Sbz    static data_type Remove(data_type B, key_type K, context_type F) {
80122922Sandre      return F.remove(B, K);
81122922Sandre    }
82122922Sandre
83122922Sandre    static inline context_type MakeContext(void *p) {
84122922Sandre      return *((typename data_type::Factory*) p);
85122922Sandre    }
86122922Sandre
87122922Sandre    static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
88122922Sandre      return new typename data_type::Factory(Alloc);
89122922Sandre    }
90122922Sandre
91122922Sandre    static void DeleteContext(void *Ctx) {
92122922Sandre      delete (typename data_type::Factory*) Ctx;
93122922Sandre    }
94122922Sandre  };
95122922Sandre
96122922Sandre  /// Helper for registering a map trait.
97122922Sandre  ///
98122922Sandre  /// If the map type were written directly in the invocation of
99122922Sandre  /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments
100122922Sandre  /// would be treated as a macro argument separator, which is wrong.
101122922Sandre  /// This allows the user to specify a map type in a way that the preprocessor
102122922Sandre  /// can deal with.
103122922Sandre  #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value>
104122922Sandre
105122922Sandre
106122922Sandre  // Partial-specialization for ImmutableSet.
107122922Sandre
108122922Sandre  template <typename Key, typename Info>
109122922Sandre  struct ProgramStatePartialTrait< llvm::ImmutableSet<Key,Info> > {
110122922Sandre    typedef llvm::ImmutableSet<Key,Info>      data_type;
111122922Sandre    typedef typename data_type::Factory&      context_type;
112122922Sandre    typedef Key                               key_type;
113122922Sandre
114122922Sandre    static inline data_type MakeData(void *const* p) {
115122922Sandre      return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0);
116170030Srwatson    }
117122922Sandre
118122922Sandre    static inline void *MakeVoidPtr(data_type B) {
119122922Sandre      return B.getRoot();
120122922Sandre    }
121122922Sandre
122122922Sandre    static data_type Add(data_type B, key_type K, context_type F) {
123122922Sandre      return F.add(B, K);
124122922Sandre    }
125170030Srwatson
126122922Sandre    static data_type Remove(data_type B, key_type K, context_type F) {
127122922Sandre      return F.remove(B, K);
128122922Sandre    }
129122922Sandre
130122922Sandre    static bool Contains(data_type B, key_type K) {
131122922Sandre      return B.contains(K);
132122922Sandre    }
133122922Sandre
134122922Sandre    static inline context_type MakeContext(void *p) {
135122922Sandre      return *((typename data_type::Factory*) p);
136122922Sandre    }
137122922Sandre
138122922Sandre    static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
139122922Sandre      return new typename data_type::Factory(Alloc);
140122922Sandre    }
141122922Sandre
142122922Sandre    static void DeleteContext(void *Ctx) {
143122922Sandre      delete (typename data_type::Factory*) Ctx;
144122922Sandre    }
145122922Sandre  };
146170434Syar
147122922Sandre
148122922Sandre  // Partial-specialization for ImmutableList.
149122922Sandre
150122922Sandre  template <typename T>
151122922Sandre  struct ProgramStatePartialTrait< llvm::ImmutableList<T> > {
152122922Sandre    typedef llvm::ImmutableList<T>            data_type;
153122922Sandre    typedef T                                 key_type;
154122922Sandre    typedef typename data_type::Factory&      context_type;
155122922Sandre
156122922Sandre    static data_type Add(data_type L, key_type K, context_type F) {
157122922Sandre      return F.add(K, L);
158122922Sandre    }
159122922Sandre
160122922Sandre    static bool Contains(data_type L, key_type K) {
161167784Sandre      return L.contains(K);
162122922Sandre    }
163122922Sandre
164167784Sandre    static inline data_type MakeData(void *const* p) {
165122922Sandre      return p ? data_type((const llvm::ImmutableListImpl<T>*) *p)
166122922Sandre               : data_type(0);
167167784Sandre    }
168122922Sandre
169122922Sandre    static inline void *MakeVoidPtr(data_type D) {
170167784Sandre      return const_cast<llvm::ImmutableListImpl<T> *>(D.getInternalPointer());
171122922Sandre    }
172122922Sandre
173167784Sandre    static inline context_type MakeContext(void *p) {
174122922Sandre      return *((typename data_type::Factory*) p);
175170434Syar    }
176170434Syar
177170434Syar    static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
178122922Sandre      return new typename data_type::Factory(Alloc);
179167784Sandre    }
180122922Sandre
181122922Sandre    static void DeleteContext(void *Ctx) {
182167784Sandre      delete (typename data_type::Factory*) Ctx;
183167784Sandre    }
184122922Sandre  };
185122922Sandre
186122922Sandre
187122922Sandre  // Partial specialization for bool.
188122922Sandre  template <> struct ProgramStatePartialTrait<bool> {
189133874Srwatson    typedef bool data_type;
190181803Sbz
191122922Sandre    static inline data_type MakeData(void *const* p) {
192122922Sandre      return p ? (data_type) (uintptr_t) *p
193133874Srwatson               : data_type();
194122922Sandre    }
195122922Sandre    static inline void *MakeVoidPtr(data_type d) {
196122922Sandre      return (void*) (uintptr_t) d;
197122922Sandre    }
198181803Sbz  };
199122922Sandre
200122922Sandre  // Partial specialization for unsigned.
201122922Sandre  template <> struct ProgramStatePartialTrait<unsigned> {
202122922Sandre    typedef unsigned data_type;
203122922Sandre
204122922Sandre    static inline data_type MakeData(void *const* p) {
205122922Sandre      return p ? (data_type) (uintptr_t) *p
206122922Sandre               : data_type();
207122922Sandre    }
208122922Sandre    static inline void *MakeVoidPtr(data_type d) {
209170030Srwatson      return (void*) (uintptr_t) d;
210122922Sandre    }
211181803Sbz  };
212181803Sbz
213181803Sbz  // Partial specialization for void*.
214181803Sbz  template <> struct ProgramStatePartialTrait<void*> {
215181803Sbz    typedef void *data_type;
216181803Sbz
217181803Sbz    static inline data_type MakeData(void *const* p) {
218122922Sandre      return p ? *p
219133874Srwatson               : data_type();
220181803Sbz    }
221133874Srwatson    static inline void *MakeVoidPtr(data_type d) {
222181803Sbz      return d;
223133874Srwatson    }
224181803Sbz  };
225181803Sbz
226133874Srwatson  // Partial specialization for const void *.
227181803Sbz  template <> struct ProgramStatePartialTrait<const void *> {
228133874Srwatson    typedef const void *data_type;
229181803Sbz
230122922Sandre    static inline data_type MakeData(void * const *p) {
231122922Sandre      return p ? *p : data_type();
232170030Srwatson    }
233122922Sandre
234181803Sbz    static inline void *MakeVoidPtr(data_type d) {
235181803Sbz      return const_cast<void *>(d);
236122922Sandre    }
237122922Sandre  };
238122922Sandre
239170030Srwatson} // end ento namespace
240122922Sandre
241181803Sbz} // end clang namespace
242181803Sbz
243181803Sbz#endif
244181803Sbz