1//===--- ASTTypeTraits.h ----------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9//  Provides a dynamic type identifier and a dynamically typed node container
10//  that can be used to store an AST base node at runtime in the same storage in
11//  a type safe way.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_AST_ASTTYPETRAITS_H
16#define LLVM_CLANG_AST_ASTTYPETRAITS_H
17
18#include "clang/AST/ASTFwd.h"
19#include "clang/AST/DeclCXX.h"
20#include "clang/AST/LambdaCapture.h"
21#include "clang/AST/NestedNameSpecifier.h"
22#include "clang/AST/TemplateBase.h"
23#include "clang/AST/TypeLoc.h"
24#include "clang/Basic/LLVM.h"
25#include "llvm/ADT/DenseMapInfo.h"
26#include "llvm/Support/AlignOf.h"
27
28namespace llvm {
29class raw_ostream;
30} // namespace llvm
31
32namespace clang {
33
34struct PrintingPolicy;
35
36/// Defines how we descend a level in the AST when we pass
37/// through expressions.
38enum TraversalKind {
39  /// Will traverse all child nodes.
40  TK_AsIs,
41
42  /// Ignore AST nodes not written in the source
43  TK_IgnoreUnlessSpelledInSource
44};
45
46/// Kind identifier.
47///
48/// It can be constructed from any node kind and allows for runtime type
49/// hierarchy checks.
50/// Use getFromNodeKind<T>() to construct them.
51class ASTNodeKind {
52public:
53  /// Empty identifier. It matches nothing.
54  constexpr ASTNodeKind() : KindId(NKI_None) {}
55
56  /// Construct an identifier for T.
57  template <class T> static constexpr ASTNodeKind getFromNodeKind() {
58    return ASTNodeKind(KindToKindId<T>::Id);
59  }
60
61  /// \{
62  /// Construct an identifier for the dynamic type of the node
63  static ASTNodeKind getFromNode(const Decl &D);
64  static ASTNodeKind getFromNode(const Stmt &S);
65  static ASTNodeKind getFromNode(const Type &T);
66  static ASTNodeKind getFromNode(const TypeLoc &T);
67  static ASTNodeKind getFromNode(const LambdaCapture &L);
68  static ASTNodeKind getFromNode(const OMPClause &C);
69  static ASTNodeKind getFromNode(const Attr &A);
70  /// \}
71
72  /// Returns \c true if \c this and \c Other represent the same kind.
73  constexpr bool isSame(ASTNodeKind Other) const {
74    return KindId != NKI_None && KindId == Other.KindId;
75  }
76
77  /// Returns \c true only for the default \c ASTNodeKind()
78  constexpr bool isNone() const { return KindId == NKI_None; }
79
80  /// Returns \c true if \c this is a base kind of (or same as) \c Other.
81  /// \param Distance If non-null, used to return the distance between \c this
82  /// and \c Other in the class hierarchy.
83  bool isBaseOf(ASTNodeKind Other, unsigned *Distance = nullptr) const;
84
85  /// String representation of the kind.
86  StringRef asStringRef() const;
87
88  /// Strict weak ordering for ASTNodeKind.
89  constexpr bool operator<(const ASTNodeKind &Other) const {
90    return KindId < Other.KindId;
91  }
92
93  /// Return the most derived type between \p Kind1 and \p Kind2.
94  ///
95  /// Return ASTNodeKind() if they are not related.
96  static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2);
97
98  /// Return the most derived common ancestor between Kind1 and Kind2.
99  ///
100  /// Return ASTNodeKind() if they are not related.
101  static ASTNodeKind getMostDerivedCommonAncestor(ASTNodeKind Kind1,
102                                                  ASTNodeKind Kind2);
103
104  ASTNodeKind getCladeKind() const;
105
106  /// Hooks for using ASTNodeKind as a key in a DenseMap.
107  struct DenseMapInfo {
108    // ASTNodeKind() is a good empty key because it is represented as a 0.
109    static inline ASTNodeKind getEmptyKey() { return ASTNodeKind(); }
110    // NKI_NumberOfKinds is not a valid value, so it is good for a
111    // tombstone key.
112    static inline ASTNodeKind getTombstoneKey() {
113      return ASTNodeKind(NKI_NumberOfKinds);
114    }
115    static unsigned getHashValue(const ASTNodeKind &Val) { return Val.KindId; }
116    static bool isEqual(const ASTNodeKind &LHS, const ASTNodeKind &RHS) {
117      return LHS.KindId == RHS.KindId;
118    }
119  };
120
121  /// Check if the given ASTNodeKind identifies a type that offers pointer
122  /// identity. This is useful for the fast path in DynTypedNode.
123  constexpr bool hasPointerIdentity() const {
124    return KindId > NKI_LastKindWithoutPointerIdentity;
125  }
126
127private:
128  /// Kind ids.
129  ///
130  /// Includes all possible base and derived kinds.
131  enum NodeKindId {
132    NKI_None,
133    NKI_TemplateArgument,
134    NKI_TemplateArgumentLoc,
135    NKI_LambdaCapture,
136    NKI_TemplateName,
137    NKI_NestedNameSpecifierLoc,
138    NKI_QualType,
139#define TYPELOC(CLASS, PARENT) NKI_##CLASS##TypeLoc,
140#include "clang/AST/TypeLocNodes.def"
141    NKI_TypeLoc,
142    NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc,
143    NKI_CXXBaseSpecifier,
144    NKI_CXXCtorInitializer,
145    NKI_NestedNameSpecifier,
146    NKI_Decl,
147#define DECL(DERIVED, BASE) NKI_##DERIVED##Decl,
148#include "clang/AST/DeclNodes.inc"
149    NKI_Stmt,
150#define STMT(DERIVED, BASE) NKI_##DERIVED,
151#include "clang/AST/StmtNodes.inc"
152    NKI_Type,
153#define TYPE(DERIVED, BASE) NKI_##DERIVED##Type,
154#include "clang/AST/TypeNodes.inc"
155    NKI_OMPClause,
156#define GEN_CLANG_CLAUSE_CLASS
157#define CLAUSE_CLASS(Enum, Str, Class) NKI_##Class,
158#include "llvm/Frontend/OpenMP/OMP.inc"
159    NKI_Attr,
160#define ATTR(A) NKI_##A##Attr,
161#include "clang/Basic/AttrList.inc"
162    NKI_ObjCProtocolLoc,
163    NKI_NumberOfKinds
164  };
165
166  /// Use getFromNodeKind<T>() to construct the kind.
167  constexpr ASTNodeKind(NodeKindId KindId) : KindId(KindId) {}
168
169  /// Returns \c true if \c Base is a base kind of (or same as) \c
170  ///   Derived.
171  /// \param Distance If non-null, used to return the distance between \c Base
172  /// and \c Derived in the class hierarchy.
173  static bool isBaseOf(NodeKindId Base, NodeKindId Derived, unsigned *Distance);
174
175  /// Helper meta-function to convert a kind T to its enum value.
176  ///
177  /// This struct is specialized below for all known kinds.
178  template <class T> struct KindToKindId {
179    static const NodeKindId Id = NKI_None;
180  };
181  template <class T>
182  struct KindToKindId<const T> : KindToKindId<T> {};
183
184  /// Per kind info.
185  struct KindInfo {
186    /// The id of the parent kind, or None if it has no parent.
187    NodeKindId ParentId;
188    /// Name of the kind.
189    const char *Name;
190  };
191  static const KindInfo AllKindInfo[NKI_NumberOfKinds];
192
193  NodeKindId KindId;
194};
195
196#define KIND_TO_KIND_ID(Class)                                                 \
197  template <> struct ASTNodeKind::KindToKindId<Class> {                        \
198    static const NodeKindId Id = NKI_##Class;                                  \
199  };
200KIND_TO_KIND_ID(CXXCtorInitializer)
201KIND_TO_KIND_ID(TemplateArgument)
202KIND_TO_KIND_ID(TemplateArgumentLoc)
203KIND_TO_KIND_ID(LambdaCapture)
204KIND_TO_KIND_ID(TemplateName)
205KIND_TO_KIND_ID(NestedNameSpecifier)
206KIND_TO_KIND_ID(NestedNameSpecifierLoc)
207KIND_TO_KIND_ID(QualType)
208#define TYPELOC(CLASS, PARENT) KIND_TO_KIND_ID(CLASS##TypeLoc)
209#include "clang/AST/TypeLocNodes.def"
210KIND_TO_KIND_ID(TypeLoc)
211KIND_TO_KIND_ID(Decl)
212KIND_TO_KIND_ID(Stmt)
213KIND_TO_KIND_ID(Type)
214KIND_TO_KIND_ID(OMPClause)
215KIND_TO_KIND_ID(Attr)
216KIND_TO_KIND_ID(ObjCProtocolLoc)
217KIND_TO_KIND_ID(CXXBaseSpecifier)
218#define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl)
219#include "clang/AST/DeclNodes.inc"
220#define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED)
221#include "clang/AST/StmtNodes.inc"
222#define TYPE(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Type)
223#include "clang/AST/TypeNodes.inc"
224#define GEN_CLANG_CLAUSE_CLASS
225#define CLAUSE_CLASS(Enum, Str, Class) KIND_TO_KIND_ID(Class)
226#include "llvm/Frontend/OpenMP/OMP.inc"
227#define ATTR(A) KIND_TO_KIND_ID(A##Attr)
228#include "clang/Basic/AttrList.inc"
229#undef KIND_TO_KIND_ID
230
231inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) {
232  OS << K.asStringRef();
233  return OS;
234}
235
236/// A dynamically typed AST node container.
237///
238/// Stores an AST node in a type safe way. This allows writing code that
239/// works with different kinds of AST nodes, despite the fact that they don't
240/// have a common base class.
241///
242/// Use \c create(Node) to create a \c DynTypedNode from an AST node,
243/// and \c get<T>() to retrieve the node as type T if the types match.
244///
245/// See \c ASTNodeKind for which node base types are currently supported;
246/// You can create DynTypedNodes for all nodes in the inheritance hierarchy of
247/// the supported base types.
248class DynTypedNode {
249public:
250  /// Creates a \c DynTypedNode from \c Node.
251  template <typename T>
252  static DynTypedNode create(const T &Node) {
253    return BaseConverter<T>::create(Node);
254  }
255
256  /// Retrieve the stored node as type \c T.
257  ///
258  /// Returns NULL if the stored node does not have a type that is
259  /// convertible to \c T.
260  ///
261  /// For types that have identity via their pointer in the AST
262  /// (like \c Stmt, \c Decl, \c Type and \c NestedNameSpecifier) the returned
263  /// pointer points to the referenced AST node.
264  /// For other types (like \c QualType) the value is stored directly
265  /// in the \c DynTypedNode, and the returned pointer points at
266  /// the storage inside DynTypedNode. For those nodes, do not
267  /// use the pointer outside the scope of the DynTypedNode.
268  template <typename T> const T *get() const {
269    return BaseConverter<T>::get(NodeKind, &Storage);
270  }
271
272  /// Retrieve the stored node as type \c T.
273  ///
274  /// Similar to \c get(), but asserts that the type is what we are expecting.
275  template <typename T>
276  const T &getUnchecked() const {
277    return BaseConverter<T>::getUnchecked(NodeKind, &Storage);
278  }
279
280  ASTNodeKind getNodeKind() const { return NodeKind; }
281
282  /// Returns a pointer that identifies the stored AST node.
283  ///
284  /// Note that this is not supported by all AST nodes. For AST nodes
285  /// that don't have a pointer-defined identity inside the AST, this
286  /// method returns NULL.
287  const void *getMemoizationData() const {
288    return NodeKind.hasPointerIdentity()
289               ? *reinterpret_cast<void *const *>(&Storage)
290               : nullptr;
291  }
292
293  /// Prints the node to the given output stream.
294  void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const;
295
296  /// Dumps the node to the given output stream.
297  void dump(llvm::raw_ostream &OS, const ASTContext &Context) const;
298
299  /// For nodes which represent textual entities in the source code,
300  /// return their SourceRange.  For all other nodes, return SourceRange().
301  SourceRange getSourceRange() const;
302
303  /// @{
304  /// Imposes an order on \c DynTypedNode.
305  ///
306  /// Supports comparison of nodes that support memoization.
307  /// FIXME: Implement comparison for other node types (currently
308  /// only Stmt, Decl, Type and NestedNameSpecifier return memoization data).
309  bool operator<(const DynTypedNode &Other) const {
310    if (!NodeKind.isSame(Other.NodeKind))
311      return NodeKind < Other.NodeKind;
312
313    if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind))
314      return getUnchecked<QualType>().getAsOpaquePtr() <
315             Other.getUnchecked<QualType>().getAsOpaquePtr();
316
317    if (ASTNodeKind::getFromNodeKind<TypeLoc>().isBaseOf(NodeKind)) {
318      auto TLA = getUnchecked<TypeLoc>();
319      auto TLB = Other.getUnchecked<TypeLoc>();
320      return std::make_pair(TLA.getType().getAsOpaquePtr(),
321                            TLA.getOpaqueData()) <
322             std::make_pair(TLB.getType().getAsOpaquePtr(),
323                            TLB.getOpaqueData());
324    }
325
326    if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(
327            NodeKind)) {
328      auto NNSLA = getUnchecked<NestedNameSpecifierLoc>();
329      auto NNSLB = Other.getUnchecked<NestedNameSpecifierLoc>();
330      return std::make_pair(NNSLA.getNestedNameSpecifier(),
331                            NNSLA.getOpaqueData()) <
332             std::make_pair(NNSLB.getNestedNameSpecifier(),
333                            NNSLB.getOpaqueData());
334    }
335
336    assert(getMemoizationData() && Other.getMemoizationData());
337    return getMemoizationData() < Other.getMemoizationData();
338  }
339  bool operator==(const DynTypedNode &Other) const {
340    // DynTypedNode::create() stores the exact kind of the node in NodeKind.
341    // If they contain the same node, their NodeKind must be the same.
342    if (!NodeKind.isSame(Other.NodeKind))
343      return false;
344
345    // FIXME: Implement for other types.
346    if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind))
347      return getUnchecked<QualType>() == Other.getUnchecked<QualType>();
348
349    if (ASTNodeKind::getFromNodeKind<TypeLoc>().isBaseOf(NodeKind))
350      return getUnchecked<TypeLoc>() == Other.getUnchecked<TypeLoc>();
351
352    if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(NodeKind))
353      return getUnchecked<NestedNameSpecifierLoc>() ==
354             Other.getUnchecked<NestedNameSpecifierLoc>();
355
356    assert(getMemoizationData() && Other.getMemoizationData());
357    return getMemoizationData() == Other.getMemoizationData();
358  }
359  bool operator!=(const DynTypedNode &Other) const {
360    return !operator==(Other);
361  }
362  /// @}
363
364  /// Hooks for using DynTypedNode as a key in a DenseMap.
365  struct DenseMapInfo {
366    static inline DynTypedNode getEmptyKey() {
367      DynTypedNode Node;
368      Node.NodeKind = ASTNodeKind::DenseMapInfo::getEmptyKey();
369      return Node;
370    }
371    static inline DynTypedNode getTombstoneKey() {
372      DynTypedNode Node;
373      Node.NodeKind = ASTNodeKind::DenseMapInfo::getTombstoneKey();
374      return Node;
375    }
376    static unsigned getHashValue(const DynTypedNode &Val) {
377      // FIXME: Add hashing support for the remaining types.
378      if (ASTNodeKind::getFromNodeKind<TypeLoc>().isBaseOf(Val.NodeKind)) {
379        auto TL = Val.getUnchecked<TypeLoc>();
380        return llvm::hash_combine(TL.getType().getAsOpaquePtr(),
381                                  TL.getOpaqueData());
382      }
383
384      if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(
385              Val.NodeKind)) {
386        auto NNSL = Val.getUnchecked<NestedNameSpecifierLoc>();
387        return llvm::hash_combine(NNSL.getNestedNameSpecifier(),
388                                  NNSL.getOpaqueData());
389      }
390
391      assert(Val.getMemoizationData());
392      return llvm::hash_value(Val.getMemoizationData());
393    }
394    static bool isEqual(const DynTypedNode &LHS, const DynTypedNode &RHS) {
395      auto Empty = ASTNodeKind::DenseMapInfo::getEmptyKey();
396      auto TombStone = ASTNodeKind::DenseMapInfo::getTombstoneKey();
397      return (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, Empty) &&
398              ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, Empty)) ||
399             (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, TombStone) &&
400              ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, TombStone)) ||
401             LHS == RHS;
402    }
403  };
404
405private:
406  /// Takes care of converting from and to \c T.
407  template <typename T, typename EnablerT = void> struct BaseConverter;
408
409  /// Converter that uses dyn_cast<T> from a stored BaseT*.
410  template <typename T, typename BaseT> struct DynCastPtrConverter {
411    static const T *get(ASTNodeKind NodeKind, const void *Storage) {
412      if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind))
413        return &getUnchecked(NodeKind, Storage);
414      return nullptr;
415    }
416    static const T &getUnchecked(ASTNodeKind NodeKind, const void *Storage) {
417      assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind));
418      return *cast<T>(static_cast<const BaseT *>(
419          *reinterpret_cast<const void *const *>(Storage)));
420    }
421    static DynTypedNode create(const BaseT &Node) {
422      DynTypedNode Result;
423      Result.NodeKind = ASTNodeKind::getFromNode(Node);
424      new (&Result.Storage) const void *(&Node);
425      return Result;
426    }
427  };
428
429  /// Converter that stores T* (by pointer).
430  template <typename T> struct PtrConverter {
431    static const T *get(ASTNodeKind NodeKind, const void *Storage) {
432      if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
433        return &getUnchecked(NodeKind, Storage);
434      return nullptr;
435    }
436    static const T &getUnchecked(ASTNodeKind NodeKind, const void *Storage) {
437      assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind));
438      return *static_cast<const T *>(
439          *reinterpret_cast<const void *const *>(Storage));
440    }
441    static DynTypedNode create(const T &Node) {
442      DynTypedNode Result;
443      Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
444      new (&Result.Storage) const void *(&Node);
445      return Result;
446    }
447  };
448
449  /// Converter that stores T (by value).
450  template <typename T> struct ValueConverter {
451    static const T *get(ASTNodeKind NodeKind, const void *Storage) {
452      if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
453        return reinterpret_cast<const T *>(Storage);
454      return nullptr;
455    }
456    static const T &getUnchecked(ASTNodeKind NodeKind, const void *Storage) {
457      assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind));
458      return *reinterpret_cast<const T *>(Storage);
459    }
460    static DynTypedNode create(const T &Node) {
461      DynTypedNode Result;
462      Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
463      new (&Result.Storage) T(Node);
464      return Result;
465    }
466  };
467
468  /// Converter that stores nodes by value. It must be possible to dynamically
469  /// cast the stored node within a type hierarchy without breaking (especially
470  /// through slicing).
471  template <typename T, typename BaseT,
472            typename = std::enable_if_t<(sizeof(T) == sizeof(BaseT))>>
473  struct DynCastValueConverter {
474    static const T *get(ASTNodeKind NodeKind, const void *Storage) {
475      if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind))
476        return &getUnchecked(NodeKind, Storage);
477      return nullptr;
478    }
479    static const T &getUnchecked(ASTNodeKind NodeKind, const void *Storage) {
480      assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind));
481      return *static_cast<const T *>(reinterpret_cast<const BaseT *>(Storage));
482    }
483    static DynTypedNode create(const T &Node) {
484      DynTypedNode Result;
485      Result.NodeKind = ASTNodeKind::getFromNode(Node);
486      new (&Result.Storage) T(Node);
487      return Result;
488    }
489  };
490
491  ASTNodeKind NodeKind;
492
493  /// Stores the data of the node.
494  ///
495  /// Note that we can store \c Decls, \c Stmts, \c Types,
496  /// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are
497  /// guaranteed to be unique pointers pointing to dedicated storage in the AST.
498  /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs,
499  /// \c TemplateArguments and \c TemplateArgumentLocs on the other hand do not
500  /// have storage or unique pointers and thus need to be stored by value.
501  llvm::AlignedCharArrayUnion<const void *, TemplateArgument,
502                              TemplateArgumentLoc, NestedNameSpecifierLoc,
503                              QualType, TypeLoc, ObjCProtocolLoc>
504      Storage;
505};
506
507template <typename T>
508struct DynTypedNode::BaseConverter<
509    T, std::enable_if_t<std::is_base_of<Decl, T>::value>>
510    : public DynCastPtrConverter<T, Decl> {};
511
512template <typename T>
513struct DynTypedNode::BaseConverter<
514    T, std::enable_if_t<std::is_base_of<Stmt, T>::value>>
515    : public DynCastPtrConverter<T, Stmt> {};
516
517template <typename T>
518struct DynTypedNode::BaseConverter<
519    T, std::enable_if_t<std::is_base_of<Type, T>::value>>
520    : public DynCastPtrConverter<T, Type> {};
521
522template <typename T>
523struct DynTypedNode::BaseConverter<
524    T, std::enable_if_t<std::is_base_of<OMPClause, T>::value>>
525    : public DynCastPtrConverter<T, OMPClause> {};
526
527template <typename T>
528struct DynTypedNode::BaseConverter<
529    T, std::enable_if_t<std::is_base_of<Attr, T>::value>>
530    : public DynCastPtrConverter<T, Attr> {};
531
532template <>
533struct DynTypedNode::BaseConverter<
534    NestedNameSpecifier, void> : public PtrConverter<NestedNameSpecifier> {};
535
536template <>
537struct DynTypedNode::BaseConverter<
538    CXXCtorInitializer, void> : public PtrConverter<CXXCtorInitializer> {};
539
540template <>
541struct DynTypedNode::BaseConverter<
542    TemplateArgument, void> : public ValueConverter<TemplateArgument> {};
543
544template <>
545struct DynTypedNode::BaseConverter<TemplateArgumentLoc, void>
546    : public ValueConverter<TemplateArgumentLoc> {};
547
548template <>
549struct DynTypedNode::BaseConverter<LambdaCapture, void>
550    : public ValueConverter<LambdaCapture> {};
551
552template <>
553struct DynTypedNode::BaseConverter<
554    TemplateName, void> : public ValueConverter<TemplateName> {};
555
556template <>
557struct DynTypedNode::BaseConverter<
558    NestedNameSpecifierLoc,
559    void> : public ValueConverter<NestedNameSpecifierLoc> {};
560
561template <>
562struct DynTypedNode::BaseConverter<QualType,
563                                   void> : public ValueConverter<QualType> {};
564
565template <typename T>
566struct DynTypedNode::BaseConverter<
567    T, std::enable_if_t<std::is_base_of<TypeLoc, T>::value>>
568    : public DynCastValueConverter<T, TypeLoc> {};
569
570template <>
571struct DynTypedNode::BaseConverter<CXXBaseSpecifier, void>
572    : public PtrConverter<CXXBaseSpecifier> {};
573
574template <>
575struct DynTypedNode::BaseConverter<ObjCProtocolLoc, void>
576    : public ValueConverter<ObjCProtocolLoc> {};
577
578// The only operation we allow on unsupported types is \c get.
579// This allows to conveniently use \c DynTypedNode when having an arbitrary
580// AST node that is not supported, but prevents misuse - a user cannot create
581// a DynTypedNode from arbitrary types.
582template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter {
583  static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
584    return NULL;
585  }
586};
587
588} // end namespace clang
589
590namespace llvm {
591
592template <>
593struct DenseMapInfo<clang::ASTNodeKind> : clang::ASTNodeKind::DenseMapInfo {};
594
595template <>
596struct DenseMapInfo<clang::DynTypedNode> : clang::DynTypedNode::DenseMapInfo {};
597
598}  // end namespace llvm
599
600#endif
601