aboutsummaryrefslogtreecommitdiff
path: root/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h
blob: 6b4da7db244df122a7e4e2c20d35fea344b32737 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
//ProgramStateTrait.h - Partial implementations of ProgramStateTrait -*- C++ -*-
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file defines partial implementations of template specializations of
//  the class ProgramStateTrait<>.  ProgramStateTrait<> is used by ProgramState 
//  to implement set/get methods for manipulating a ProgramState's
//  generic data map.
//
//===----------------------------------------------------------------------===//


#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H
#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H

#include "llvm/Support/Allocator.h"
#include "llvm/Support/DataTypes.h"

namespace llvm {
  template <typename K, typename D, typename I> class ImmutableMap;
  template <typename K, typename I> class ImmutableSet;
  template <typename T> class ImmutableList;
  template <typename T> class ImmutableListImpl;
}

namespace clang {

namespace ento {
  template <typename T> struct ProgramStatePartialTrait;

  /// Declares a program state trait for type \p Type called \p Name, and
  /// introduce a typedef named \c NameTy.
  /// The macro should not be used inside namespaces, or for traits that must
  /// be accessible from more than one translation unit.
  #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \
    namespace { \
      class Name {}; \
      typedef Type Name ## Ty; \
    } \
    namespace clang { \
    namespace ento { \
      template <> \
      struct ProgramStateTrait<Name> \
        : public ProgramStatePartialTrait<Name ## Ty> { \
        static void *GDMIndex() { static int Index; return &Index; } \
      }; \
    } \
    }


  // Partial-specialization for ImmutableMap.

  template <typename Key, typename Data, typename Info>
  struct ProgramStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > {
    typedef llvm::ImmutableMap<Key,Data,Info> data_type;
    typedef typename data_type::Factory&      context_type;
    typedef Key                               key_type;
    typedef Data                              value_type;
    typedef const value_type*                 lookup_type;

    static inline data_type MakeData(void *const* p) {
      return p ? data_type((typename data_type::TreeTy*) *p)
               : data_type(nullptr);
    }
    static inline void *MakeVoidPtr(data_type B) {
      return B.getRoot();
    }
    static lookup_type Lookup(data_type B, key_type K) {
      return B.lookup(K);
    }
    static data_type Set(data_type B, key_type K, value_type E,context_type F){
      return F.add(B, K, E);
    }

    static data_type Remove(data_type B, key_type K, context_type F) {
      return F.remove(B, K);
    }

    static inline context_type MakeContext(void *p) {
      return *((typename data_type::Factory*) p);
    }

    static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
      return new typename data_type::Factory(Alloc);
    }

    static void DeleteContext(void *Ctx) {
      delete (typename data_type::Factory*) Ctx;
    }
  };

  /// Helper for registering a map trait.
  ///
  /// If the map type were written directly in the invocation of
  /// REGISTER_TRAIT_WITH_PROGRAMSTATE, the comma in the template arguments
  /// would be treated as a macro argument separator, which is wrong.
  /// This allows the user to specify a map type in a way that the preprocessor
  /// can deal with.
  #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value>


  // Partial-specialization for ImmutableSet.

  template <typename Key, typename Info>
  struct ProgramStatePartialTrait< llvm::ImmutableSet<Key,Info> > {
    typedef llvm::ImmutableSet<Key,Info>      data_type;
    typedef typename data_type::Factory&      context_type;
    typedef Key                               key_type;

    static inline data_type MakeData(void *const* p) {
      return p ? data_type((typename data_type::TreeTy*) *p)
               : data_type(nullptr);
    }

    static inline void *MakeVoidPtr(data_type B) {
      return B.getRoot();
    }

    static data_type Add(data_type B, key_type K, context_type F) {
      return F.add(B, K);
    }

    static data_type Remove(data_type B, key_type K, context_type F) {
      return F.remove(B, K);
    }

    static bool Contains(data_type B, key_type K) {
      return B.contains(K);
    }

    static inline context_type MakeContext(void *p) {
      return *((typename data_type::Factory*) p);
    }

    static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
      return new typename data_type::Factory(Alloc);
    }

    static void DeleteContext(void *Ctx) {
      delete (typename data_type::Factory*) Ctx;
    }
  };


  // Partial-specialization for ImmutableList.

  template <typename T>
  struct ProgramStatePartialTrait< llvm::ImmutableList<T> > {
    typedef llvm::ImmutableList<T>            data_type;
    typedef T                                 key_type;
    typedef typename data_type::Factory&      context_type;

    static data_type Add(data_type L, key_type K, context_type F) {
      return F.add(K, L);
    }

    static bool Contains(data_type L, key_type K) {
      return L.contains(K);
    }

    static inline data_type MakeData(void *const* p) {
      return p ? data_type((const llvm::ImmutableListImpl<T>*) *p)
               : data_type(nullptr);
    }

    static inline void *MakeVoidPtr(data_type D) {
      return const_cast<llvm::ImmutableListImpl<T> *>(D.getInternalPointer());
    }

    static inline context_type MakeContext(void *p) {
      return *((typename data_type::Factory*) p);
    }

    static void *CreateContext(llvm::BumpPtrAllocator& Alloc) {
      return new typename data_type::Factory(Alloc);
    }

    static void DeleteContext(void *Ctx) {
      delete (typename data_type::Factory*) Ctx;
    }
  };

  
  // Partial specialization for bool.
  template <> struct ProgramStatePartialTrait<bool> {
    typedef bool data_type;

    static inline data_type MakeData(void *const* p) {
      return p ? (data_type) (uintptr_t) *p
               : data_type();
    }
    static inline void *MakeVoidPtr(data_type d) {
      return (void*) (uintptr_t) d;
    }
  };
  
  // Partial specialization for unsigned.
  template <> struct ProgramStatePartialTrait<unsigned> {
    typedef unsigned data_type;

    static inline data_type MakeData(void *const* p) {
      return p ? (data_type) (uintptr_t) *p
               : data_type();
    }
    static inline void *MakeVoidPtr(data_type d) {
      return (void*) (uintptr_t) d;
    }
  };

  // Partial specialization for void*.
  template <> struct ProgramStatePartialTrait<void*> {
    typedef void *data_type;

    static inline data_type MakeData(void *const* p) {
      return p ? *p
               : data_type();
    }
    static inline void *MakeVoidPtr(data_type d) {
      return d;
    }
  };

  // Partial specialization for const void *.
  template <> struct ProgramStatePartialTrait<const void *> {
    typedef const void *data_type;

    static inline data_type MakeData(void * const *p) {
      return p ? *p : data_type();
    }

    static inline void *MakeVoidPtr(data_type d) {
      return const_cast<void *>(d);
    }
  };

} // end ento namespace

} // end clang namespace

#endif