]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/clang/include/clang/AST/ASTTypeTraits.h
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / tools / clang / include / clang / AST / ASTTypeTraits.h
1 //===--- ASTTypeTraits.h ----------------------------------------*- 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 //  Provides a dynamic type identifier and a dynamically typed node container
11 //  that can be used to store an AST base node at runtime in the same storage in
12 //  a type safe way.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #ifndef LLVM_CLANG_AST_AST_TYPE_TRAITS_H
17 #define LLVM_CLANG_AST_AST_TYPE_TRAITS_H
18
19 #include "clang/AST/ASTFwd.h"
20 #include "clang/AST/Decl.h"
21 #include "clang/AST/NestedNameSpecifier.h"
22 #include "clang/AST/Stmt.h"
23 #include "clang/AST/TemplateBase.h"
24 #include "clang/AST/TypeLoc.h"
25 #include "clang/Basic/LLVM.h"
26 #include "llvm/Support/AlignOf.h"
27
28 namespace llvm {
29
30 class raw_ostream;
31
32 }
33
34 namespace clang {
35
36 struct PrintingPolicy;
37
38 namespace ast_type_traits {
39
40 /// \brief Kind identifier.
41 ///
42 /// It can be constructed from any node kind and allows for runtime type
43 /// hierarchy checks.
44 /// Use getFromNodeKind<T>() to construct them.
45 class ASTNodeKind {
46 public:
47   /// \brief Empty identifier. It matches nothing.
48   ASTNodeKind() : KindId(NKI_None) {}
49
50   /// \brief Construct an identifier for T.
51   template <class T>
52   static ASTNodeKind getFromNodeKind() {
53     return ASTNodeKind(KindToKindId<T>::Id);
54   }
55
56   /// \brief Returns \c true if \c this and \c Other represent the same kind.
57   bool isSame(ASTNodeKind Other) const;
58
59   /// \brief Returns \c true if \c this is a base kind of (or same as) \c Other.
60   bool isBaseOf(ASTNodeKind Other) const;
61
62   /// \brief String representation of the kind.
63   StringRef asStringRef() const;
64
65 private:
66   /// \brief Kind ids.
67   ///
68   /// Includes all possible base and derived kinds.
69   enum NodeKindId {
70     NKI_None,
71     NKI_CXXCtorInitializer,
72     NKI_TemplateArgument,
73     NKI_NestedNameSpecifier,
74     NKI_NestedNameSpecifierLoc,
75     NKI_QualType,
76     NKI_TypeLoc,
77     NKI_Decl,
78 #define DECL(DERIVED, BASE) NKI_##DERIVED##Decl,
79 #include "clang/AST/DeclNodes.inc"
80     NKI_Stmt,
81 #define STMT(DERIVED, BASE) NKI_##DERIVED,
82 #include "clang/AST/StmtNodes.inc"
83     NKI_Type,
84 #define TYPE(DERIVED, BASE) NKI_##DERIVED##Type,
85 #include "clang/AST/TypeNodes.def"
86     NKI_NumberOfKinds
87   };
88
89   /// \brief Use getFromNodeKind<T>() to construct the kind.
90   ASTNodeKind(NodeKindId KindId) : KindId(KindId) {}
91
92   /// \brief Returns \c true if \c Base is a base kind of (or same as) \c
93   ///   Derived.
94   static bool isBaseOf(NodeKindId Base, NodeKindId Derived);
95
96   /// \brief Helper meta-function to convert a kind T to its enum value.
97   ///
98   /// This struct is specialized below for all known kinds.
99   template <class T> struct KindToKindId {
100     static const NodeKindId Id = NKI_None;
101   };
102
103   /// \brief Per kind info.
104   struct KindInfo {
105     /// \brief The id of the parent kind, or None if it has no parent.
106     NodeKindId ParentId;
107     /// \brief Name of the kind.
108     const char *Name;
109   };
110   static const KindInfo AllKindInfo[NKI_NumberOfKinds];
111
112   NodeKindId KindId;
113 };
114
115 #define KIND_TO_KIND_ID(Class)                                                 \
116   template <> struct ASTNodeKind::KindToKindId<Class> {                        \
117     static const NodeKindId Id = NKI_##Class;                                  \
118   };
119 KIND_TO_KIND_ID(CXXCtorInitializer)
120 KIND_TO_KIND_ID(TemplateArgument)
121 KIND_TO_KIND_ID(NestedNameSpecifier)
122 KIND_TO_KIND_ID(NestedNameSpecifierLoc)
123 KIND_TO_KIND_ID(QualType)
124 KIND_TO_KIND_ID(TypeLoc)
125 KIND_TO_KIND_ID(Decl)
126 KIND_TO_KIND_ID(Stmt)
127 KIND_TO_KIND_ID(Type)
128 #define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl)
129 #include "clang/AST/DeclNodes.inc"
130 #define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED)
131 #include "clang/AST/StmtNodes.inc"
132 #define TYPE(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Type)
133 #include "clang/AST/TypeNodes.def"
134 #undef KIND_TO_KIND_ID
135
136 /// \brief A dynamically typed AST node container.
137 ///
138 /// Stores an AST node in a type safe way. This allows writing code that
139 /// works with different kinds of AST nodes, despite the fact that they don't
140 /// have a common base class.
141 ///
142 /// Use \c create(Node) to create a \c DynTypedNode from an AST node,
143 /// and \c get<T>() to retrieve the node as type T if the types match.
144 ///
145 /// See \c ASTNodeKind for which node base types are currently supported;
146 /// You can create DynTypedNodes for all nodes in the inheritance hierarchy of
147 /// the supported base types.
148 class DynTypedNode {
149 public:
150   /// \brief Creates a \c DynTypedNode from \c Node.
151   template <typename T>
152   static DynTypedNode create(const T &Node) {
153     return BaseConverter<T>::create(Node);
154   }
155
156   /// \brief Retrieve the stored node as type \c T.
157   ///
158   /// Returns NULL if the stored node does not have a type that is
159   /// convertible to \c T.
160   ///
161   /// For types that have identity via their pointer in the AST
162   /// (like \c Stmt, \c Decl, \c Type and \c NestedNameSpecifier) the returned
163   /// pointer points to the referenced AST node.
164   /// For other types (like \c QualType) the value is stored directly
165   /// in the \c DynTypedNode, and the returned pointer points at
166   /// the storage inside DynTypedNode. For those nodes, do not
167   /// use the pointer outside the scope of the DynTypedNode.
168   template <typename T>
169   const T *get() const {
170     return BaseConverter<T>::get(NodeKind, Storage.buffer);
171   }
172
173   /// \brief Returns a pointer that identifies the stored AST node.
174   ///
175   /// Note that this is not supported by all AST nodes. For AST nodes
176   /// that don't have a pointer-defined identity inside the AST, this
177   /// method returns NULL.
178   const void *getMemoizationData() const;
179
180   /// \brief Prints the node to the given output stream.
181   void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const;
182
183   /// \brief Dumps the node to the given output stream.
184   void dump(llvm::raw_ostream &OS, SourceManager &SM) const;
185
186   /// \brief For nodes which represent textual entities in the source code,
187   /// return their SourceRange.  For all other nodes, return SourceRange().
188   SourceRange getSourceRange() const;
189
190   /// @{
191   /// \brief Imposes an order on \c DynTypedNode.
192   ///
193   /// Supports comparison of nodes that support memoization.
194   /// FIXME: Implement comparsion for other node types (currently
195   /// only Stmt, Decl, Type and NestedNameSpecifier return memoization data).
196   bool operator<(const DynTypedNode &Other) const {
197     assert(getMemoizationData() && Other.getMemoizationData());
198     return getMemoizationData() < Other.getMemoizationData();
199   }
200   bool operator==(const DynTypedNode &Other) const {
201     // Nodes with different types cannot be equal.
202     if (!NodeKind.isSame(Other.NodeKind))
203       return false;
204
205     // FIXME: Implement for other types.
206     if (ASTNodeKind::getFromNodeKind<QualType>().isBaseOf(NodeKind)) {
207       return *get<QualType>() == *Other.get<QualType>();
208     }
209     assert(getMemoizationData() && Other.getMemoizationData());
210     return getMemoizationData() == Other.getMemoizationData();
211   }
212   bool operator!=(const DynTypedNode &Other) const {
213     return !operator==(Other);
214   }
215   /// @}
216
217 private:
218   /// \brief Takes care of converting from and to \c T.
219   template <typename T, typename EnablerT = void> struct BaseConverter;
220
221   /// \brief Converter that uses dyn_cast<T> from a stored BaseT*.
222   template <typename T, typename BaseT> struct DynCastPtrConverter {
223     static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
224       if (ASTNodeKind::getFromNodeKind<BaseT>().isBaseOf(NodeKind))
225         return dyn_cast<T>(*reinterpret_cast<BaseT *const *>(Storage));
226       return NULL;
227     }
228     static DynTypedNode create(const BaseT &Node) {
229       DynTypedNode Result;
230       Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
231       new (Result.Storage.buffer) const BaseT * (&Node);
232       return Result;
233     }
234   };
235
236   /// \brief Converter that stores T* (by pointer).
237   template <typename T> struct PtrConverter {
238     static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
239       if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
240         return *reinterpret_cast<T *const *>(Storage);
241       return NULL;
242     }
243     static DynTypedNode create(const T &Node) {
244       DynTypedNode Result;
245       Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
246       new (Result.Storage.buffer) const T * (&Node);
247       return Result;
248     }
249   };
250
251   /// \brief Converter that stores T (by value).
252   template <typename T> struct ValueConverter {
253     static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
254       if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
255         return reinterpret_cast<const T *>(Storage);
256       return NULL;
257     }
258     static DynTypedNode create(const T &Node) {
259       DynTypedNode Result;
260       Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
261       new (Result.Storage.buffer) T(Node);
262       return Result;
263     }
264   };
265
266   ASTNodeKind NodeKind;
267
268   /// \brief Stores the data of the node.
269   ///
270   /// Note that we can store \c Decls, \c Stmts, \c Types,
271   /// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are
272   /// guaranteed to be unique pointers pointing to dedicated storage in the AST.
273   /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and
274   /// \c TemplateArguments on the other hand do not have storage or unique
275   /// pointers and thus need to be stored by value.
276   typedef llvm::AlignedCharArrayUnion<
277       Decl *, Stmt *, Type *, NestedNameSpecifier *, CXXCtorInitializer *>
278       KindsByPointer;
279   llvm::AlignedCharArrayUnion<KindsByPointer, TemplateArgument,
280                               NestedNameSpecifierLoc, QualType, TypeLoc>
281       Storage;
282 };
283
284 template <typename T>
285 struct DynTypedNode::BaseConverter<
286     T, typename llvm::enable_if<llvm::is_base_of<
287            Decl, T> >::type> : public DynCastPtrConverter<T, Decl> {};
288
289 template <typename T>
290 struct DynTypedNode::BaseConverter<
291     T, typename llvm::enable_if<llvm::is_base_of<
292            Stmt, T> >::type> : public DynCastPtrConverter<T, Stmt> {};
293
294 template <typename T>
295 struct DynTypedNode::BaseConverter<
296     T, typename llvm::enable_if<llvm::is_base_of<
297            Type, T> >::type> : public DynCastPtrConverter<T, Type> {};
298
299 template <>
300 struct DynTypedNode::BaseConverter<
301     NestedNameSpecifier, void> : public PtrConverter<NestedNameSpecifier> {};
302
303 template <>
304 struct DynTypedNode::BaseConverter<
305     CXXCtorInitializer, void> : public PtrConverter<CXXCtorInitializer> {};
306
307 template <>
308 struct DynTypedNode::BaseConverter<
309     TemplateArgument, void> : public ValueConverter<TemplateArgument> {};
310
311 template <>
312 struct DynTypedNode::BaseConverter<
313     NestedNameSpecifierLoc,
314     void> : public ValueConverter<NestedNameSpecifierLoc> {};
315
316 template <>
317 struct DynTypedNode::BaseConverter<QualType,
318                                    void> : public ValueConverter<QualType> {};
319
320 template <>
321 struct DynTypedNode::BaseConverter<
322     TypeLoc, void> : public ValueConverter<TypeLoc> {};
323
324 // The only operation we allow on unsupported types is \c get.
325 // This allows to conveniently use \c DynTypedNode when having an arbitrary
326 // AST node that is not supported, but prevents misuse - a user cannot create
327 // a DynTypedNode from arbitrary types.
328 template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter {
329   static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
330     return NULL;
331   }
332 };
333
334 inline const void *DynTypedNode::getMemoizationData() const {
335   if (ASTNodeKind::getFromNodeKind<Decl>().isBaseOf(NodeKind)) {
336     return BaseConverter<Decl>::get(NodeKind, Storage.buffer);
337   } else if (ASTNodeKind::getFromNodeKind<Stmt>().isBaseOf(NodeKind)) {
338     return BaseConverter<Stmt>::get(NodeKind, Storage.buffer);
339   } else if (ASTNodeKind::getFromNodeKind<Type>().isBaseOf(NodeKind)) {
340     return BaseConverter<Type>::get(NodeKind, Storage.buffer);
341   } else if (ASTNodeKind::getFromNodeKind<NestedNameSpecifier>().isBaseOf(NodeKind)) {
342     return BaseConverter<NestedNameSpecifier>::get(NodeKind, Storage.buffer);
343   }
344   return NULL;
345 }
346
347 } // end namespace ast_type_traits
348 } // end namespace clang
349
350 #endif // LLVM_CLANG_AST_AST_TYPE_TRAITS_H