167754Smsmith//ProgramStateTrait.h - Partial implementations of ProgramStateTrait -*- C++ -*-
267754Smsmith//
377424Smsmith//                     The LLVM Compiler Infrastructure
467754Smsmith//
567754Smsmith// This file is distributed under the University of Illinois Open Source
667754Smsmith// License. See LICENSE.TXT for details.
7217365Sjkim//
8245582Sjkim//===----------------------------------------------------------------------===//
970243Smsmith//
1067754Smsmith//  This file defines partial implementations of template specializations of
11217365Sjkim//  the class ProgramStateTrait<>.  ProgramStateTrait<> is used by ProgramState
12217365Sjkim//  to implement set/get methods for manipulating a ProgramState's
13217365Sjkim//  generic data map.
14217365Sjkim//
15217365Sjkim//===----------------------------------------------------------------------===//
16217365Sjkim
17217365Sjkim
18217365Sjkim#ifndef LLVM_CLANG_GR_PROGRAMSTATETRAIT_H
19217365Sjkim#define LLVM_CLANG_GR_PROGRAMSTATETRAIT_H
20217365Sjkim
21217365Sjkim#include "llvm/Support/DataTypes.h"
22217365Sjkim
23217365Sjkimnamespace llvm {
24217365Sjkim  class BumpPtrAllocator;
2567754Smsmith  template <typename K, typename D, typename I> class ImmutableMap;
26217365Sjkim  template <typename K, typename I> class ImmutableSet;
27217365Sjkim  template <typename T> class ImmutableList;
28217365Sjkim  template <typename T> class ImmutableListImpl;
2967754Smsmith}
30217365Sjkim
31217365Sjkimnamespace clang {
32217365Sjkim
33217365Sjkimnamespace ento {
34217365Sjkim  template <typename T> struct ProgramStatePartialTrait;
35217365Sjkim
36217365Sjkim  /// Declares a program state trait for type \p Type called \p Name, and
37217365Sjkim  /// introduce a typedef named \c NameTy.
38217365Sjkim  /// The macro should not be used inside namespaces, or for traits that must
39217365Sjkim  /// be accessible from more than one translation unit.
40217365Sjkim  #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \
41217365Sjkim    namespace { \
42217365Sjkim      class Name {}; \
4367754Smsmith      typedef Type Name ## Ty; \
4477424Smsmith    } \
4577424Smsmith    namespace clang { \
4667754Smsmith    namespace ento { \
4767754Smsmith      template <> \
48167802Sjkim      struct ProgramStateTrait<Name> \
49228110Sjkim        : public ProgramStatePartialTrait<Name ## Ty> { \
50167802Sjkim        static void *GDMIndex() { static int Index; return &Index; } \
51167802Sjkim      }; \
52167802Sjkim    } \
53167802Sjkim    }
54167802Sjkim
55167802Sjkim
56167802Sjkim  // Partial-specialization for ImmutableMap.
57167802Sjkim
58167802Sjkim  template <typename Key, typename Data, typename Info>
59167802Sjkim  struct ProgramStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > {
60167802Sjkim    typedef llvm::ImmutableMap<Key,Data,Info> data_type;
61167802Sjkim    typedef typename data_type::Factory&      context_type;
62167802Sjkim    typedef Key                               key_type;
63167802Sjkim    typedef Data                              value_type;
64167802Sjkim    typedef const value_type*                 lookup_type;
65167802Sjkim
66167802Sjkim    static inline data_type MakeData(void *const* p) {
67167802Sjkim      return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0);
68167802Sjkim    }
69167802Sjkim    static inline void *MakeVoidPtr(data_type B) {
70167802Sjkim      return B.getRoot();
71167802Sjkim    }
72167802Sjkim    static lookup_type Lookup(data_type B, key_type K) {
73228110Sjkim      return B.lookup(K);
74228110Sjkim    }
75228110Sjkim    static data_type Set(data_type B, key_type K, value_type E,context_type F){
76228110Sjkim      return F.add(B, K, E);
77228110Sjkim    }
78228110Sjkim
79228110Sjkim    static data_type Remove(data_type B, key_type K, context_type F) {
80228110Sjkim      return F.remove(B, K);
81228110Sjkim    }
82228110Sjkim
83228110Sjkim    static inline context_type MakeContext(void *p) {
84228110Sjkim      return *((typename data_type::Factory*) p);
85228110Sjkim    }
86228110Sjkim
87228110Sjkim    static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
88228110Sjkim      return new typename data_type::Factory(Alloc);
89167802Sjkim    }
90167802Sjkim
91250838Sjkim    static void DeleteContext(void *Ctx) {
92250838Sjkim      delete (typename data_type::Factory*) Ctx;
93250838Sjkim    }
94250838Sjkim  };
95250838Sjkim
96250838Sjkim  /// Helper for registering a map trait.
97250838Sjkim  ///
98250838Sjkim  /// If the map type were written directly in the invocation of
99250838Sjkim  /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments
100250838Sjkim  /// would be treated as a macro argument separator, which is wrong.
101250838Sjkim  /// This allows the user to specify a map type in a way that the preprocessor
102250838Sjkim  /// can deal with.
103250838Sjkim  #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value>
104250838Sjkim
105250838Sjkim
106250838Sjkim  // Partial-specialization for ImmutableSet.
107250838Sjkim
108250838Sjkim  template <typename Key, typename Info>
109250838Sjkim  struct ProgramStatePartialTrait< llvm::ImmutableSet<Key,Info> > {
110250838Sjkim    typedef llvm::ImmutableSet<Key,Info>      data_type;
111250838Sjkim    typedef typename data_type::Factory&      context_type;
112250838Sjkim    typedef Key                               key_type;
113250838Sjkim
114250838Sjkim    static inline data_type MakeData(void *const* p) {
115250838Sjkim      return p ? data_type((typename data_type::TreeTy*) *p) : data_type(0);
116250838Sjkim    }
117250838Sjkim
118250838Sjkim    static inline void *MakeVoidPtr(data_type B) {
119250838Sjkim      return B.getRoot();
120250838Sjkim    }
121250838Sjkim
122250838Sjkim    static data_type Add(data_type B, key_type K, context_type F) {
123250838Sjkim      return F.add(B, K);
124250838Sjkim    }
125250838Sjkim
126250838Sjkim    static data_type Remove(data_type B, key_type K, context_type F) {
127250838Sjkim      return F.remove(B, K);
128250838Sjkim    }
129250838Sjkim
130250838Sjkim    static bool Contains(data_type B, key_type K) {
131250838Sjkim      return B.contains(K);
132250838Sjkim    }
133250838Sjkim
134167802Sjkim    static inline context_type MakeContext(void *p) {
135167802Sjkim      return *((typename data_type::Factory*) p);
136167802Sjkim    }
137167802Sjkim
138167802Sjkim    static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
139167802Sjkim      return new typename data_type::Factory(Alloc);
140167802Sjkim    }
14173561Smsmith
142167802Sjkim    static void DeleteContext(void *Ctx) {
143167802Sjkim      delete (typename data_type::Factory*) Ctx;
144167802Sjkim    }
145167802Sjkim  };
146167802Sjkim
147245582Sjkim
148167802Sjkim  // Partial-specialization for ImmutableList.
149167802Sjkim
15073561Smsmith  template <typename T>
15173561Smsmith  struct ProgramStatePartialTrait< llvm::ImmutableList<T> > {
15273561Smsmith    typedef llvm::ImmutableList<T>            data_type;
15373561Smsmith    typedef T                                 key_type;
15473561Smsmith    typedef typename data_type::Factory&      context_type;
15573561Smsmith
15673561Smsmith    static data_type Add(data_type L, key_type K, context_type F) {
15773561Smsmith      return F.add(K, L);
15873561Smsmith    }
15991116Smsmith
16073561Smsmith    static bool Contains(data_type L, key_type K) {
16173561Smsmith      return L.contains(K);
162114237Snjl    }
16373561Smsmith
16473561Smsmith    static inline data_type MakeData(void *const* p) {
165249112Sjkim      return p ? data_type((const llvm::ImmutableListImpl<T>*) *p)
166249112Sjkim               : data_type(0);
16767754Smsmith    }
16867754Smsmith
16967754Smsmith    static inline void *MakeVoidPtr(data_type D) {
17077424Smsmith      return const_cast<llvm::ImmutableListImpl<T> *>(D.getInternalPointer());
17167754Smsmith    }
17267754Smsmith
17367754Smsmith    static inline context_type MakeContext(void *p) {
17467754Smsmith      return *((typename data_type::Factory*) p);
17567754Smsmith    }
17667754Smsmith
17767754Smsmith    static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
178151937Sjkim      return new typename data_type::Factory(Alloc);
17967754Smsmith    }
180193267Sjkim
181151937Sjkim    static void DeleteContext(void *Ctx) {
18267754Smsmith      delete (typename data_type::Factory*) Ctx;
18367754Smsmith    }
184102550Siwasaki  };
18569746Smsmith
186114237Snjl
18777424Smsmith  // Partial specialization for bool.
18867754Smsmith  template <> struct ProgramStatePartialTrait<bool> {
18967754Smsmith    typedef bool data_type;
190193267Sjkim
191193267Sjkim    static inline data_type MakeData(void *const* p) {
192193267Sjkim      return p ? (data_type) (uintptr_t) *p
193193267Sjkim               : data_type();
194100966Siwasaki    }
195100966Siwasaki    static inline void *MakeVoidPtr(data_type d) {
196114237Snjl      return (void*) (uintptr_t) d;
19777424Smsmith    }
19891116Smsmith  };
19967754Smsmith
200114237Snjl  // Partial specialization for unsigned.
201123315Snjl  template <> struct ProgramStatePartialTrait<unsigned> {
202123315Snjl    typedef unsigned data_type;
203123315Snjl
204123315Snjl    static inline data_type MakeData(void *const* p) {
205123315Snjl      return p ? (data_type) (uintptr_t) *p
206123315Snjl               : data_type();
207123315Snjl    }
208193267Sjkim    static inline void *MakeVoidPtr(data_type d) {
209193267Sjkim      return (void*) (uintptr_t) d;
210193267Sjkim    }
211193267Sjkim  };
212123315Snjl
21399679Siwasaki  // Partial specialization for void*.
21499679Siwasaki  template <> struct ProgramStatePartialTrait<void*> {
21599679Siwasaki    typedef void *data_type;
216114237Snjl
21777424Smsmith    static inline data_type MakeData(void *const* p) {
21869746Smsmith      return p ? *p
21969746Smsmith               : data_type();
220114237Snjl    }
22191116Smsmith    static inline void *MakeVoidPtr(data_type d) {
22291116Smsmith      return d;
22369746Smsmith    }
22499679Siwasaki  };
22582367Smsmith
226202771Sjkim  // Partial specialization for const void *.
22782367Smsmith  template <> struct ProgramStatePartialTrait<const void *> {
22882367Smsmith    typedef const void *data_type;
22967754Smsmith
23077424Smsmith    static inline data_type MakeData(void * const *p) {
23191116Smsmith      return p ? *p : data_type();
23267754Smsmith    }
23367754Smsmith
234151937Sjkim    static inline void *MakeVoidPtr(data_type d) {
235151937Sjkim      return const_cast<void *>(d);
236151937Sjkim    }
237151937Sjkim  };
238151937Sjkim
239151937Sjkim} // end ento namespace
24067754Smsmith
241151937Sjkim} // end clang namespace
242151937Sjkim
243151937Sjkim#endif
244151937Sjkim