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_ASTTYPETRAITS_H
17 #define LLVM_CLANG_AST_ASTTYPETRAITS_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/ADT/DenseMapInfo.h"
27 #include "llvm/Support/AlignOf.h"
28 
29 namespace llvm {
30 
31 class raw_ostream;
32 
33 }
34 
35 namespace clang {
36 
37 struct PrintingPolicy;
38 
39 namespace ast_type_traits {
40 
41 /// \brief Kind identifier.
42 ///
43 /// It can be constructed from any node kind and allows for runtime type
44 /// hierarchy checks.
45 /// Use getFromNodeKind<T>() to construct them.
46 class ASTNodeKind {
47 public:
48   /// \brief Empty identifier. It matches nothing.
ASTNodeKind()49   ASTNodeKind() : KindId(NKI_None) {}
50 
51   /// \brief Construct an identifier for T.
52   template <class T>
getFromNodeKind()53   static ASTNodeKind getFromNodeKind() {
54     return ASTNodeKind(KindToKindId<T>::Id);
55   }
56 
57   /// \{
58   /// \brief Construct an identifier for the dynamic type of the node
59   static ASTNodeKind getFromNode(const Decl &D);
60   static ASTNodeKind getFromNode(const Stmt &S);
61   static ASTNodeKind getFromNode(const Type &T);
62   /// \}
63 
64   /// \brief Returns \c true if \c this and \c Other represent the same kind.
65   bool isSame(ASTNodeKind Other) const;
66 
67   /// \brief Returns \c true only for the default \c ASTNodeKind()
isNone()68   bool isNone() const { return KindId == NKI_None; }
69 
70   /// \brief Returns \c true if \c this is a base kind of (or same as) \c Other.
71   /// \param Distance If non-null, used to return the distance between \c this
72   /// and \c Other in the class hierarchy.
73   bool isBaseOf(ASTNodeKind Other, unsigned *Distance = nullptr) const;
74 
75   /// \brief String representation of the kind.
76   StringRef asStringRef() const;
77 
78   /// \brief Strict weak ordering for ASTNodeKind.
79   bool operator<(const ASTNodeKind &Other) const {
80     return KindId < Other.KindId;
81   }
82 
83   /// \brief Return the most derived type between \p Kind1 and \p Kind2.
84   ///
85   /// Return ASTNodeKind() if they are not related.
86   static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2);
87 
88   /// \brief Return the most derived common ancestor between Kind1 and Kind2.
89   ///
90   /// Return ASTNodeKind() if they are not related.
91   static ASTNodeKind getMostDerivedCommonAncestor(ASTNodeKind Kind1,
92                                                   ASTNodeKind Kind2);
93 
94   /// \brief Hooks for using ASTNodeKind as a key in a DenseMap.
95   struct DenseMapInfo {
96     // ASTNodeKind() is a good empty key because it is represented as a 0.
getEmptyKeyDenseMapInfo97     static inline ASTNodeKind getEmptyKey() { return ASTNodeKind(); }
98     // NKI_NumberOfKinds is not a valid value, so it is good for a
99     // tombstone key.
getTombstoneKeyDenseMapInfo100     static inline ASTNodeKind getTombstoneKey() {
101       return ASTNodeKind(NKI_NumberOfKinds);
102     }
getHashValueDenseMapInfo103     static unsigned getHashValue(const ASTNodeKind &Val) { return Val.KindId; }
isEqualDenseMapInfo104     static bool isEqual(const ASTNodeKind &LHS, const ASTNodeKind &RHS) {
105       return LHS.KindId == RHS.KindId;
106     }
107   };
108 
109 private:
110   /// \brief Kind ids.
111   ///
112   /// Includes all possible base and derived kinds.
113   enum NodeKindId {
114     NKI_None,
115     NKI_CXXCtorInitializer,
116     NKI_TemplateArgument,
117     NKI_NestedNameSpecifier,
118     NKI_NestedNameSpecifierLoc,
119     NKI_QualType,
120     NKI_TypeLoc,
121     NKI_Decl,
122 #define DECL(DERIVED, BASE) NKI_##DERIVED##Decl,
123 #include "clang/AST/DeclNodes.inc"
124     NKI_Stmt,
125 #define STMT(DERIVED, BASE) NKI_##DERIVED,
126 #include "clang/AST/StmtNodes.inc"
127     NKI_Type,
128 #define TYPE(DERIVED, BASE) NKI_##DERIVED##Type,
129 #include "clang/AST/TypeNodes.def"
130     NKI_NumberOfKinds
131   };
132 
133   /// \brief Use getFromNodeKind<T>() to construct the kind.
ASTNodeKind(NodeKindId KindId)134   ASTNodeKind(NodeKindId KindId) : KindId(KindId) {}
135 
136   /// \brief Returns \c true if \c Base is a base kind of (or same as) \c
137   ///   Derived.
138   /// \param Distance If non-null, used to return the distance between \c Base
139   /// and \c Derived in the class hierarchy.
140   static bool isBaseOf(NodeKindId Base, NodeKindId Derived, unsigned *Distance);
141 
142   /// \brief Helper meta-function to convert a kind T to its enum value.
143   ///
144   /// This struct is specialized below for all known kinds.
145   template <class T> struct KindToKindId {
146     static const NodeKindId Id = NKI_None;
147   };
148   template <class T>
149   struct KindToKindId<const T> : KindToKindId<T> {};
150 
151   /// \brief Per kind info.
152   struct KindInfo {
153     /// \brief The id of the parent kind, or None if it has no parent.
154     NodeKindId ParentId;
155     /// \brief Name of the kind.
156     const char *Name;
157   };
158   static const KindInfo AllKindInfo[NKI_NumberOfKinds];
159 
160   NodeKindId KindId;
161 };
162 
163 #define KIND_TO_KIND_ID(Class)                                                 \
164   template <> struct ASTNodeKind::KindToKindId<Class> {                        \
165     static const NodeKindId Id = NKI_##Class;                                  \
166   };
167 KIND_TO_KIND_ID(CXXCtorInitializer)
168 KIND_TO_KIND_ID(TemplateArgument)
169 KIND_TO_KIND_ID(NestedNameSpecifier)
170 KIND_TO_KIND_ID(NestedNameSpecifierLoc)
171 KIND_TO_KIND_ID(QualType)
172 KIND_TO_KIND_ID(TypeLoc)
173 KIND_TO_KIND_ID(Decl)
174 KIND_TO_KIND_ID(Stmt)
175 KIND_TO_KIND_ID(Type)
176 #define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl)
177 #include "clang/AST/DeclNodes.inc"
178 #define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED)
179 #include "clang/AST/StmtNodes.inc"
180 #define TYPE(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Type)
181 #include "clang/AST/TypeNodes.def"
182 #undef KIND_TO_KIND_ID
183 
184 inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) {
185   OS << K.asStringRef();
186   return OS;
187 }
188 
189 /// \brief A dynamically typed AST node container.
190 ///
191 /// Stores an AST node in a type safe way. This allows writing code that
192 /// works with different kinds of AST nodes, despite the fact that they don't
193 /// have a common base class.
194 ///
195 /// Use \c create(Node) to create a \c DynTypedNode from an AST node,
196 /// and \c get<T>() to retrieve the node as type T if the types match.
197 ///
198 /// See \c ASTNodeKind for which node base types are currently supported;
199 /// You can create DynTypedNodes for all nodes in the inheritance hierarchy of
200 /// the supported base types.
201 class DynTypedNode {
202 public:
203   /// \brief Creates a \c DynTypedNode from \c Node.
204   template <typename T>
205   static DynTypedNode create(const T &Node) {
206     return BaseConverter<T>::create(Node);
207   }
208 
209   /// \brief Retrieve the stored node as type \c T.
210   ///
211   /// Returns NULL if the stored node does not have a type that is
212   /// convertible to \c T.
213   ///
214   /// For types that have identity via their pointer in the AST
215   /// (like \c Stmt, \c Decl, \c Type and \c NestedNameSpecifier) the returned
216   /// pointer points to the referenced AST node.
217   /// For other types (like \c QualType) the value is stored directly
218   /// in the \c DynTypedNode, and the returned pointer points at
219   /// the storage inside DynTypedNode. For those nodes, do not
220   /// use the pointer outside the scope of the DynTypedNode.
221   template <typename T>
222   const T *get() const {
223     return BaseConverter<T>::get(NodeKind, Storage.buffer);
224   }
225 
226   /// \brief Retrieve the stored node as type \c T.
227   ///
228   /// Similar to \c get(), but asserts that the type is what we are expecting.
229   template <typename T>
230   const T &getUnchecked() const {
231     return BaseConverter<T>::getUnchecked(NodeKind, Storage.buffer);
232   }
233 
234   ASTNodeKind getNodeKind() const { return NodeKind; }
235 
236   /// \brief Returns a pointer that identifies the stored AST node.
237   ///
238   /// Note that this is not supported by all AST nodes. For AST nodes
239   /// that don't have a pointer-defined identity inside the AST, this
240   /// method returns NULL.
241   const void *getMemoizationData() const { return MemoizationData; }
242 
243   /// \brief Prints the node to the given output stream.
244   void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const;
245 
246   /// \brief Dumps the node to the given output stream.
247   void dump(llvm::raw_ostream &OS, SourceManager &SM) const;
248 
249   /// \brief For nodes which represent textual entities in the source code,
250   /// return their SourceRange.  For all other nodes, return SourceRange().
251   SourceRange getSourceRange() const;
252 
253   /// @{
254   /// \brief Imposes an order on \c DynTypedNode.
255   ///
256   /// Supports comparison of nodes that support memoization.
257   /// FIXME: Implement comparsion for other node types (currently
258   /// only Stmt, Decl, Type and NestedNameSpecifier return memoization data).
259   bool operator<(const DynTypedNode &Other) const {
260     assert(getMemoizationData() && Other.getMemoizationData());
261     return getMemoizationData() < Other.getMemoizationData();
262   }
263   bool operator==(const DynTypedNode &Other) const {
264     // DynTypedNode::create() stores the exact kind of the node in NodeKind.
265     // If they contain the same node, their NodeKind must be the same.
266     if (!NodeKind.isSame(Other.NodeKind))
267       return false;
268 
269     // FIXME: Implement for other types.
270     if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind))
271       return getUnchecked<QualType>() == Other.getUnchecked<QualType>();
272 
273     assert(getMemoizationData() && Other.getMemoizationData());
274     return getMemoizationData() == Other.getMemoizationData();
275   }
276   bool operator!=(const DynTypedNode &Other) const {
277     return !operator==(Other);
278   }
279   /// @}
280 
281 private:
282   /// \brief Takes care of converting from and to \c T.
283   template <typename T, typename EnablerT = void> struct BaseConverter;
284 
285   /// \brief Converter that uses dyn_cast<T> from a stored BaseT*.
286   template <typename T, typename BaseT> struct DynCastPtrConverter {
287     static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
288       if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind))
289         return cast<T>(*reinterpret_cast<BaseT *const *>(Storage));
290       return nullptr;
291     }
292     static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
293       assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind));
294       return *cast<T>(*reinterpret_cast<BaseT *const *>(Storage));
295     }
296     static DynTypedNode create(const BaseT &Node) {
297       DynTypedNode Result;
298       Result.NodeKind = ASTNodeKind::getFromNode(Node);
299       Result.MemoizationData = &Node;
300       new (Result.Storage.buffer) const BaseT * (&Node);
301       return Result;
302     }
303   };
304 
305   /// \brief Converter that stores T* (by pointer).
306   template <typename T> struct PtrConverter {
307     static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
308       if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
309         return *reinterpret_cast<T *const *>(Storage);
310       return nullptr;
311     }
312     static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
313       assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind));
314       return **reinterpret_cast<T *const *>(Storage);
315     }
316     static DynTypedNode create(const T &Node) {
317       DynTypedNode Result;
318       Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
319       Result.MemoizationData = &Node;
320       new (Result.Storage.buffer) const T * (&Node);
321       return Result;
322     }
323   };
324 
325   /// \brief Converter that stores T (by value).
326   template <typename T> struct ValueConverter {
327     static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
328       if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
329         return reinterpret_cast<const T *>(Storage);
330       return nullptr;
331     }
332     static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) {
333       assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind));
334       return *reinterpret_cast<const T *>(Storage);
335     }
336     static DynTypedNode create(const T &Node) {
337       DynTypedNode Result;
338       Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
339       Result.MemoizationData = nullptr;
340       new (Result.Storage.buffer) T(Node);
341       return Result;
342     }
343   };
344 
345   ASTNodeKind NodeKind;
346   const void *MemoizationData;
347 
348   /// \brief Stores the data of the node.
349   ///
350   /// Note that we can store \c Decls, \c Stmts, \c Types,
351   /// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are
352   /// guaranteed to be unique pointers pointing to dedicated storage in the AST.
353   /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and
354   /// \c TemplateArguments on the other hand do not have storage or unique
355   /// pointers and thus need to be stored by value.
356   typedef llvm::AlignedCharArrayUnion<
357       Decl *, Stmt *, Type *, NestedNameSpecifier *, CXXCtorInitializer *>
358       KindsByPointer;
359   llvm::AlignedCharArrayUnion<KindsByPointer, TemplateArgument,
360                               NestedNameSpecifierLoc, QualType, TypeLoc>
361       Storage;
362 };
363 
364 template <typename T>
365 struct DynTypedNode::BaseConverter<
366     T, typename std::enable_if<std::is_base_of<Decl, T>::value>::type>
367     : public DynCastPtrConverter<T, Decl> {};
368 
369 template <typename T>
370 struct DynTypedNode::BaseConverter<
371     T, typename std::enable_if<std::is_base_of<Stmt, T>::value>::type>
372     : public DynCastPtrConverter<T, Stmt> {};
373 
374 template <typename T>
375 struct DynTypedNode::BaseConverter<
376     T, typename std::enable_if<std::is_base_of<Type, T>::value>::type>
377     : public DynCastPtrConverter<T, Type> {};
378 
379 template <>
380 struct DynTypedNode::BaseConverter<
381     NestedNameSpecifier, void> : public PtrConverter<NestedNameSpecifier> {};
382 
383 template <>
384 struct DynTypedNode::BaseConverter<
385     CXXCtorInitializer, void> : public PtrConverter<CXXCtorInitializer> {};
386 
387 template <>
388 struct DynTypedNode::BaseConverter<
389     TemplateArgument, void> : public ValueConverter<TemplateArgument> {};
390 
391 template <>
392 struct DynTypedNode::BaseConverter<
393     NestedNameSpecifierLoc,
394     void> : public ValueConverter<NestedNameSpecifierLoc> {};
395 
396 template <>
397 struct DynTypedNode::BaseConverter<QualType,
398                                    void> : public ValueConverter<QualType> {};
399 
400 template <>
401 struct DynTypedNode::BaseConverter<
402     TypeLoc, void> : public ValueConverter<TypeLoc> {};
403 
404 // The only operation we allow on unsupported types is \c get.
405 // This allows to conveniently use \c DynTypedNode when having an arbitrary
406 // AST node that is not supported, but prevents misuse - a user cannot create
407 // a DynTypedNode from arbitrary types.
408 template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter {
409   static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
410     return NULL;
411   }
412 };
413 
414 } // end namespace ast_type_traits
415 } // end namespace clang
416 
417 namespace llvm {
418 
419 template <>
420 struct DenseMapInfo<clang::ast_type_traits::ASTNodeKind>
421     : clang::ast_type_traits::ASTNodeKind::DenseMapInfo {};
422 
423 }  // end namespace llvm
424 
425 #endif
426