1226586Sdim//ProgramStateTrait.h - Partial implementations of ProgramStateTrait -*- C++ -*-
2226586Sdim//
3226586Sdim//                     The LLVM Compiler Infrastructure
4226586Sdim//
5226586Sdim// This file is distributed under the University of Illinois Open Source
6226586Sdim// License. See LICENSE.TXT for details.
7226586Sdim//
8226586Sdim//===----------------------------------------------------------------------===//
9226586Sdim//
10226586Sdim//  This file defines partial implementations of template specializations of
11226586Sdim//  the class ProgramStateTrait<>.  ProgramStateTrait<> is used by ProgramState
12235633Sdim//  to implement set/get methods for manipulating a ProgramState's
13235633Sdim//  generic data map.
14226586Sdim//
15226586Sdim//===----------------------------------------------------------------------===//
16226586Sdim
17226586Sdim
18226586Sdim#ifndef LLVM_CLANG_GR_PROGRAMSTATETRAIT_H
19226586Sdim#define LLVM_CLANG_GR_PROGRAMSTATETRAIT_H
20226586Sdim
21252723Sdim#include "llvm/Support/DataTypes.h"
22252723Sdim
23226586Sdimnamespace llvm {
24226586Sdim  class BumpPtrAllocator;
25226586Sdim  template <typename K, typename D, typename I> class ImmutableMap;
26226586Sdim  template <typename K, typename I> class ImmutableSet;
27226586Sdim  template <typename T> class ImmutableList;
28226586Sdim  template <typename T> class ImmutableListImpl;
29226586Sdim}
30226586Sdim
31226586Sdimnamespace clang {
32226586Sdim
33226586Sdimnamespace ento {
34226586Sdim  template <typename T> struct ProgramStatePartialTrait;
35226586Sdim
36245431Sdim  /// Declares a program state trait for type \p Type called \p Name, and
37245431Sdim  /// introduce a typedef named \c NameTy.
38245431Sdim  /// The macro should not be used inside namespaces, or for traits that must
39245431Sdim  /// be accessible from more than one translation unit.
40245431Sdim  #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \
41245431Sdim    namespace { \
42245431Sdim      class Name {}; \
43245431Sdim      typedef Type Name ## Ty; \
44245431Sdim    } \
45245431Sdim    namespace clang { \
46245431Sdim    namespace ento { \
47245431Sdim      template <> \
48245431Sdim      struct ProgramStateTrait<Name> \
49245431Sdim        : public ProgramStatePartialTrait<Name ## Ty> { \
50245431Sdim        static void *GDMIndex() { static int Index; return &Index; } \
51245431Sdim      }; \
52245431Sdim    } \
53245431Sdim    }
54245431Sdim
55245431Sdim
56226586Sdim  // Partial-specialization for ImmutableMap.
57226586Sdim
58226586Sdim  template <typename Key, typename Data, typename Info>
59226586Sdim  struct ProgramStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > {
60226586Sdim    typedef llvm::ImmutableMap<Key,Data,Info> data_type;
61226586Sdim    typedef typename data_type::Factory&      context_type;
62226586Sdim    typedef Key                               key_type;
63226586Sdim    typedef Data                              value_type;
64226586Sdim    typedef const value_type*                 lookup_type;
65226586Sdim
66226586Sdim    static inline data_type MakeData(void *const* p) {
67226586Sdim      return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0);
68226586Sdim    }
69226586Sdim    static inline void *MakeVoidPtr(data_type B) {
70226586Sdim      return B.getRoot();
71226586Sdim    }
72226586Sdim    static lookup_type Lookup(data_type B, key_type K) {
73226586Sdim      return B.lookup(K);
74226586Sdim    }
75226586Sdim    static data_type Set(data_type B, key_type K, value_type E,context_type F){
76226586Sdim      return F.add(B, K, E);
77226586Sdim    }
78226586Sdim
79226586Sdim    static data_type Remove(data_type B, key_type K, context_type F) {
80226586Sdim      return F.remove(B, K);
81226586Sdim    }
82226586Sdim
83226586Sdim    static inline context_type MakeContext(void *p) {
84226586Sdim      return *((typename data_type::Factory*) p);
85226586Sdim    }
86226586Sdim
87226586Sdim    static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
88226586Sdim      return new typename data_type::Factory(Alloc);
89226586Sdim    }
90226586Sdim
91226586Sdim    static void DeleteContext(void *Ctx) {
92226586Sdim      delete (typename data_type::Factory*) Ctx;
93226586Sdim    }
94226586Sdim  };
95226586Sdim
96245431Sdim  /// Helper for registering a map trait.
97245431Sdim  ///
98245431Sdim  /// If the map type were written directly in the invocation of
99245431Sdim  /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments
100245431Sdim  /// would be treated as a macro argument separator, which is wrong.
101245431Sdim  /// This allows the user to specify a map type in a way that the preprocessor
102245431Sdim  /// can deal with.
103245431Sdim  #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value>
104226586Sdim
105245431Sdim
106226586Sdim  // Partial-specialization for ImmutableSet.
107226586Sdim
108226586Sdim  template <typename Key, typename Info>
109226586Sdim  struct ProgramStatePartialTrait< llvm::ImmutableSet<Key,Info> > {
110226586Sdim    typedef llvm::ImmutableSet<Key,Info>      data_type;
111226586Sdim    typedef typename data_type::Factory&      context_type;
112226586Sdim    typedef Key                               key_type;
113226586Sdim
114226586Sdim    static inline data_type MakeData(void *const* p) {
115226586Sdim      return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0);
116226586Sdim    }
117226586Sdim
118226586Sdim    static inline void *MakeVoidPtr(data_type B) {
119226586Sdim      return B.getRoot();
120226586Sdim    }
121226586Sdim
122226586Sdim    static data_type Add(data_type B, key_type K, context_type F) {
123226586Sdim      return F.add(B, K);
124226586Sdim    }
125226586Sdim
126226586Sdim    static data_type Remove(data_type B, key_type K, context_type F) {
127226586Sdim      return F.remove(B, K);
128226586Sdim    }
129226586Sdim
130226586Sdim    static bool Contains(data_type B, key_type K) {
131226586Sdim      return B.contains(K);
132226586Sdim    }
133226586Sdim
134226586Sdim    static inline context_type MakeContext(void *p) {
135226586Sdim      return *((typename data_type::Factory*) p);
136226586Sdim    }
137226586Sdim
138226586Sdim    static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
139226586Sdim      return new typename data_type::Factory(Alloc);
140226586Sdim    }
141226586Sdim
142226586Sdim    static void DeleteContext(void *Ctx) {
143226586Sdim      delete (typename data_type::Factory*) Ctx;
144226586Sdim    }
145226586Sdim  };
146226586Sdim
147245431Sdim
148226586Sdim  // Partial-specialization for ImmutableList.
149226586Sdim
150226586Sdim  template <typename T>
151226586Sdim  struct ProgramStatePartialTrait< llvm::ImmutableList<T> > {
152226586Sdim    typedef llvm::ImmutableList<T>            data_type;
153226586Sdim    typedef T                                 key_type;
154226586Sdim    typedef typename data_type::Factory&      context_type;
155226586Sdim
156226586Sdim    static data_type Add(data_type L, key_type K, context_type F) {
157226586Sdim      return F.add(K, L);
158226586Sdim    }
159226586Sdim
160226586Sdim    static bool Contains(data_type L, key_type K) {
161226586Sdim      return L.contains(K);
162226586Sdim    }
163226586Sdim
164226586Sdim    static inline data_type MakeData(void *const* p) {
165226586Sdim      return p ? data_type((const llvm::ImmutableListImpl<T>*) *p)
166226586Sdim               : data_type(0);
167226586Sdim    }
168226586Sdim
169226586Sdim    static inline void *MakeVoidPtr(data_type D) {
170252723Sdim      return const_cast<llvm::ImmutableListImpl<T> *>(D.getInternalPointer());
171226586Sdim    }
172226586Sdim
173226586Sdim    static inline context_type MakeContext(void *p) {
174226586Sdim      return *((typename data_type::Factory*) p);
175226586Sdim    }
176226586Sdim
177226586Sdim    static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
178226586Sdim      return new typename data_type::Factory(Alloc);
179226586Sdim    }
180226586Sdim
181226586Sdim    static void DeleteContext(void *Ctx) {
182226586Sdim      delete (typename data_type::Factory*) Ctx;
183226586Sdim    }
184226586Sdim  };
185245431Sdim
186226586Sdim
187226586Sdim  // Partial specialization for bool.
188226586Sdim  template <> struct ProgramStatePartialTrait<bool> {
189226586Sdim    typedef bool data_type;
190226586Sdim
191226586Sdim    static inline data_type MakeData(void *const* p) {
192226586Sdim      return p ? (data_type) (uintptr_t) *p
193226586Sdim               : data_type();
194226586Sdim    }
195226586Sdim    static inline void *MakeVoidPtr(data_type d) {
196226586Sdim      return (void*) (uintptr_t) d;
197226586Sdim    }
198226586Sdim  };
199226586Sdim
200226586Sdim  // Partial specialization for unsigned.
201226586Sdim  template <> struct ProgramStatePartialTrait<unsigned> {
202226586Sdim    typedef unsigned data_type;
203226586Sdim
204226586Sdim    static inline data_type MakeData(void *const* p) {
205226586Sdim      return p ? (data_type) (uintptr_t) *p
206226586Sdim               : data_type();
207226586Sdim    }
208226586Sdim    static inline void *MakeVoidPtr(data_type d) {
209226586Sdim      return (void*) (uintptr_t) d;
210226586Sdim    }
211226586Sdim  };
212235633Sdim
213235633Sdim  // Partial specialization for void*.
214235633Sdim  template <> struct ProgramStatePartialTrait<void*> {
215235633Sdim    typedef void *data_type;
216235633Sdim
217235633Sdim    static inline data_type MakeData(void *const* p) {
218235633Sdim      return p ? *p
219235633Sdim               : data_type();
220235633Sdim    }
221235633Sdim    static inline void *MakeVoidPtr(data_type d) {
222235633Sdim      return d;
223235633Sdim    }
224235633Sdim  };
225235633Sdim
226252723Sdim  // Partial specialization for const void *.
227252723Sdim  template <> struct ProgramStatePartialTrait<const void *> {
228252723Sdim    typedef const void *data_type;
229226586Sdim
230252723Sdim    static inline data_type MakeData(void * const *p) {
231252723Sdim      return p ? *p : data_type();
232252723Sdim    }
233252723Sdim
234252723Sdim    static inline void *MakeVoidPtr(data_type d) {
235252723Sdim      return const_cast<void *>(d);
236252723Sdim    }
237252723Sdim  };
238252723Sdim
239252723Sdim} // end ento namespace
240252723Sdim
241226586Sdim} // end clang namespace
242226586Sdim
243226586Sdim#endif
244