Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:29

0001 //===--- ASTTypeTraits.h ----------------------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 //  Provides a dynamic type identifier and a dynamically typed node container
0010 //  that can be used to store an AST base node at runtime in the same storage in
0011 //  a type safe way.
0012 //
0013 //===----------------------------------------------------------------------===//
0014 
0015 #ifndef LLVM_CLANG_AST_ASTTYPETRAITS_H
0016 #define LLVM_CLANG_AST_ASTTYPETRAITS_H
0017 
0018 #include "clang/AST/ASTFwd.h"
0019 #include "clang/AST/DeclCXX.h"
0020 #include "clang/AST/LambdaCapture.h"
0021 #include "clang/AST/NestedNameSpecifier.h"
0022 #include "clang/AST/TemplateBase.h"
0023 #include "clang/AST/TypeLoc.h"
0024 #include "clang/Basic/LLVM.h"
0025 #include "llvm/ADT/DenseMapInfo.h"
0026 #include "llvm/Support/AlignOf.h"
0027 
0028 namespace llvm {
0029 class raw_ostream;
0030 } // namespace llvm
0031 
0032 namespace clang {
0033 
0034 struct PrintingPolicy;
0035 
0036 /// Defines how we descend a level in the AST when we pass
0037 /// through expressions.
0038 enum TraversalKind {
0039   /// Will traverse all child nodes.
0040   TK_AsIs,
0041 
0042   /// Ignore AST nodes not written in the source
0043   TK_IgnoreUnlessSpelledInSource
0044 };
0045 
0046 /// Kind identifier.
0047 ///
0048 /// It can be constructed from any node kind and allows for runtime type
0049 /// hierarchy checks.
0050 /// Use getFromNodeKind<T>() to construct them.
0051 class ASTNodeKind {
0052 public:
0053   /// Empty identifier. It matches nothing.
0054   constexpr ASTNodeKind() : KindId(NKI_None) {}
0055 
0056   /// Construct an identifier for T.
0057   template <class T> static constexpr ASTNodeKind getFromNodeKind() {
0058     return ASTNodeKind(KindToKindId<T>::Id);
0059   }
0060 
0061   /// \{
0062   /// Construct an identifier for the dynamic type of the node
0063   static ASTNodeKind getFromNode(const Decl &D);
0064   static ASTNodeKind getFromNode(const Stmt &S);
0065   static ASTNodeKind getFromNode(const Type &T);
0066   static ASTNodeKind getFromNode(const TypeLoc &T);
0067   static ASTNodeKind getFromNode(const LambdaCapture &L);
0068   static ASTNodeKind getFromNode(const OMPClause &C);
0069   static ASTNodeKind getFromNode(const Attr &A);
0070   /// \}
0071 
0072   /// Returns \c true if \c this and \c Other represent the same kind.
0073   constexpr bool isSame(ASTNodeKind Other) const {
0074     return KindId != NKI_None && KindId == Other.KindId;
0075   }
0076 
0077   /// Returns \c true only for the default \c ASTNodeKind()
0078   constexpr bool isNone() const { return KindId == NKI_None; }
0079 
0080   /// Returns \c true if \c this is a base kind of (or same as) \c Other.
0081   bool isBaseOf(ASTNodeKind Other) const;
0082 
0083   /// Returns \c true if \c this is a base kind of (or same as) \c Other.
0084   /// \param Distance If non-null, used to return the distance between \c this
0085   /// and \c Other in the class hierarchy.
0086   bool isBaseOf(ASTNodeKind Other, unsigned *Distance) const;
0087 
0088   /// String representation of the kind.
0089   StringRef asStringRef() const;
0090 
0091   /// Strict weak ordering for ASTNodeKind.
0092   constexpr bool operator<(const ASTNodeKind &Other) const {
0093     return KindId < Other.KindId;
0094   }
0095 
0096   /// Return the most derived type between \p Kind1 and \p Kind2.
0097   ///
0098   /// Return ASTNodeKind() if they are not related.
0099   static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2);
0100 
0101   /// Return the most derived common ancestor between Kind1 and Kind2.
0102   ///
0103   /// Return ASTNodeKind() if they are not related.
0104   static ASTNodeKind getMostDerivedCommonAncestor(ASTNodeKind Kind1,
0105                                                   ASTNodeKind Kind2);
0106 
0107   ASTNodeKind getCladeKind() const;
0108 
0109   /// Hooks for using ASTNodeKind as a key in a DenseMap.
0110   struct DenseMapInfo {
0111     // ASTNodeKind() is a good empty key because it is represented as a 0.
0112     static inline ASTNodeKind getEmptyKey() { return ASTNodeKind(); }
0113     // NKI_NumberOfKinds is not a valid value, so it is good for a
0114     // tombstone key.
0115     static inline ASTNodeKind getTombstoneKey() {
0116       return ASTNodeKind(NKI_NumberOfKinds);
0117     }
0118     static unsigned getHashValue(const ASTNodeKind &Val) { return Val.KindId; }
0119     static bool isEqual(const ASTNodeKind &LHS, const ASTNodeKind &RHS) {
0120       return LHS.KindId == RHS.KindId;
0121     }
0122   };
0123 
0124   /// Check if the given ASTNodeKind identifies a type that offers pointer
0125   /// identity. This is useful for the fast path in DynTypedNode.
0126   constexpr bool hasPointerIdentity() const {
0127     return KindId > NKI_LastKindWithoutPointerIdentity;
0128   }
0129 
0130 private:
0131   /// Kind ids.
0132   ///
0133   /// Includes all possible base and derived kinds.
0134   enum NodeKindId {
0135     NKI_None,
0136     NKI_TemplateArgument,
0137     NKI_TemplateArgumentLoc,
0138     NKI_LambdaCapture,
0139     NKI_TemplateName,
0140     NKI_NestedNameSpecifierLoc,
0141     NKI_QualType,
0142 #define TYPELOC(CLASS, PARENT) NKI_##CLASS##TypeLoc,
0143 #include "clang/AST/TypeLocNodes.def"
0144     NKI_TypeLoc,
0145     NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc,
0146     NKI_CXXBaseSpecifier,
0147     NKI_CXXCtorInitializer,
0148     NKI_NestedNameSpecifier,
0149     NKI_Decl,
0150 #define DECL(DERIVED, BASE) NKI_##DERIVED##Decl,
0151 #include "clang/AST/DeclNodes.inc"
0152     NKI_Stmt,
0153 #define STMT(DERIVED, BASE) NKI_##DERIVED,
0154 #include "clang/AST/StmtNodes.inc"
0155     NKI_Type,
0156 #define TYPE(DERIVED, BASE) NKI_##DERIVED##Type,
0157 #include "clang/AST/TypeNodes.inc"
0158     NKI_OMPClause,
0159 #define GEN_CLANG_CLAUSE_CLASS
0160 #define CLAUSE_CLASS(Enum, Str, Class) NKI_##Class,
0161 #include "llvm/Frontend/OpenMP/OMP.inc"
0162     NKI_Attr,
0163 #define ATTR(A) NKI_##A##Attr,
0164 #include "clang/Basic/AttrList.inc"
0165     NKI_ObjCProtocolLoc,
0166     NKI_ConceptReference,
0167     NKI_NumberOfKinds
0168   };
0169 
0170   /// Use getFromNodeKind<T>() to construct the kind.
0171   constexpr ASTNodeKind(NodeKindId KindId) : KindId(KindId) {}
0172 
0173   /// Returns \c true if \c Base is a base kind of (or same as) \c
0174   ///   Derived.
0175   static bool isBaseOf(NodeKindId Base, NodeKindId Derived);
0176 
0177   /// Returns \c true if \c Base is a base kind of (or same as) \c
0178   ///   Derived.
0179   /// \param Distance If non-null, used to return the distance between \c Base
0180   /// and \c Derived in the class hierarchy.
0181   static bool isBaseOf(NodeKindId Base, NodeKindId Derived, unsigned *Distance);
0182 
0183   /// Helper meta-function to convert a kind T to its enum value.
0184   ///
0185   /// This struct is specialized below for all known kinds.
0186   template <class T> struct KindToKindId {
0187     static const NodeKindId Id = NKI_None;
0188   };
0189   template <class T>
0190   struct KindToKindId<const T> : KindToKindId<T> {};
0191 
0192   /// Per kind info.
0193   struct KindInfo {
0194     /// The id of the parent kind, or None if it has no parent.
0195     NodeKindId ParentId;
0196     /// Name of the kind.
0197     const char *Name;
0198   };
0199   static const KindInfo AllKindInfo[NKI_NumberOfKinds];
0200 
0201   NodeKindId KindId;
0202 };
0203 
0204 #define KIND_TO_KIND_ID(Class)                                                 \
0205   template <> struct ASTNodeKind::KindToKindId<Class> {                        \
0206     static const NodeKindId Id = NKI_##Class;                                  \
0207   };
0208 KIND_TO_KIND_ID(CXXCtorInitializer)
0209 KIND_TO_KIND_ID(TemplateArgument)
0210 KIND_TO_KIND_ID(TemplateArgumentLoc)
0211 KIND_TO_KIND_ID(LambdaCapture)
0212 KIND_TO_KIND_ID(TemplateName)
0213 KIND_TO_KIND_ID(NestedNameSpecifier)
0214 KIND_TO_KIND_ID(NestedNameSpecifierLoc)
0215 KIND_TO_KIND_ID(QualType)
0216 #define TYPELOC(CLASS, PARENT) KIND_TO_KIND_ID(CLASS##TypeLoc)
0217 #include "clang/AST/TypeLocNodes.def"
0218 KIND_TO_KIND_ID(TypeLoc)
0219 KIND_TO_KIND_ID(Decl)
0220 KIND_TO_KIND_ID(Stmt)
0221 KIND_TO_KIND_ID(Type)
0222 KIND_TO_KIND_ID(OMPClause)
0223 KIND_TO_KIND_ID(Attr)
0224 KIND_TO_KIND_ID(ObjCProtocolLoc)
0225 KIND_TO_KIND_ID(CXXBaseSpecifier)
0226 KIND_TO_KIND_ID(ConceptReference)
0227 #define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl)
0228 #include "clang/AST/DeclNodes.inc"
0229 #define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED)
0230 #include "clang/AST/StmtNodes.inc"
0231 #define TYPE(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Type)
0232 #include "clang/AST/TypeNodes.inc"
0233 #define GEN_CLANG_CLAUSE_CLASS
0234 #define CLAUSE_CLASS(Enum, Str, Class) KIND_TO_KIND_ID(Class)
0235 #include "llvm/Frontend/OpenMP/OMP.inc"
0236 #define ATTR(A) KIND_TO_KIND_ID(A##Attr)
0237 #include "clang/Basic/AttrList.inc"
0238 #undef KIND_TO_KIND_ID
0239 
0240 inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) {
0241   OS << K.asStringRef();
0242   return OS;
0243 }
0244 
0245 /// A dynamically typed AST node container.
0246 ///
0247 /// Stores an AST node in a type safe way. This allows writing code that
0248 /// works with different kinds of AST nodes, despite the fact that they don't
0249 /// have a common base class.
0250 ///
0251 /// Use \c create(Node) to create a \c DynTypedNode from an AST node,
0252 /// and \c get<T>() to retrieve the node as type T if the types match.
0253 ///
0254 /// See \c ASTNodeKind for which node base types are currently supported;
0255 /// You can create DynTypedNodes for all nodes in the inheritance hierarchy of
0256 /// the supported base types.
0257 class DynTypedNode {
0258 public:
0259   /// Creates a \c DynTypedNode from \c Node.
0260   template <typename T>
0261   static DynTypedNode create(const T &Node) {
0262     return BaseConverter<T>::create(Node);
0263   }
0264 
0265   /// Retrieve the stored node as type \c T.
0266   ///
0267   /// Returns NULL if the stored node does not have a type that is
0268   /// convertible to \c T.
0269   ///
0270   /// For types that have identity via their pointer in the AST
0271   /// (like \c Stmt, \c Decl, \c Type and \c NestedNameSpecifier) the returned
0272   /// pointer points to the referenced AST node.
0273   /// For other types (like \c QualType) the value is stored directly
0274   /// in the \c DynTypedNode, and the returned pointer points at
0275   /// the storage inside DynTypedNode. For those nodes, do not
0276   /// use the pointer outside the scope of the DynTypedNode.
0277   template <typename T> const T *get() const {
0278     return BaseConverter<T>::get(NodeKind, &Storage);
0279   }
0280 
0281   /// Retrieve the stored node as type \c T.
0282   ///
0283   /// Similar to \c get(), but asserts that the type is what we are expecting.
0284   template <typename T>
0285   const T &getUnchecked() const {
0286     return BaseConverter<T>::getUnchecked(NodeKind, &Storage);
0287   }
0288 
0289   ASTNodeKind getNodeKind() const { return NodeKind; }
0290 
0291   /// Returns a pointer that identifies the stored AST node.
0292   ///
0293   /// Note that this is not supported by all AST nodes. For AST nodes
0294   /// that don't have a pointer-defined identity inside the AST, this
0295   /// method returns NULL.
0296   const void *getMemoizationData() const {
0297     return NodeKind.hasPointerIdentity()
0298                ? *reinterpret_cast<void *const *>(&Storage)
0299                : nullptr;
0300   }
0301 
0302   /// Prints the node to the given output stream.
0303   void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const;
0304 
0305   /// Dumps the node to the given output stream.
0306   void dump(llvm::raw_ostream &OS, const ASTContext &Context) const;
0307 
0308   /// For nodes which represent textual entities in the source code,
0309   /// return their SourceRange.  For all other nodes, return SourceRange().
0310   SourceRange getSourceRange() const;
0311 
0312   /// @{
0313   /// Imposes an order on \c DynTypedNode.
0314   ///
0315   /// Supports comparison of nodes that support memoization.
0316   /// FIXME: Implement comparison for other node types (currently
0317   /// only Stmt, Decl, Type and NestedNameSpecifier return memoization data).
0318   bool operator<(const DynTypedNode &Other) const {
0319     if (!NodeKind.isSame(Other.NodeKind))
0320       return NodeKind < Other.NodeKind;
0321 
0322     if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind))
0323       return getUnchecked<QualType>().getAsOpaquePtr() <
0324              Other.getUnchecked<QualType>().getAsOpaquePtr();
0325 
0326     if (ASTNodeKind::getFromNodeKind<TypeLoc>().isBaseOf(NodeKind)) {
0327       auto TLA = getUnchecked<TypeLoc>();
0328       auto TLB = Other.getUnchecked<TypeLoc>();
0329       return std::make_pair(TLA.getType().getAsOpaquePtr(),
0330                             TLA.getOpaqueData()) <
0331              std::make_pair(TLB.getType().getAsOpaquePtr(),
0332                             TLB.getOpaqueData());
0333     }
0334 
0335     if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(
0336             NodeKind)) {
0337       auto NNSLA = getUnchecked<NestedNameSpecifierLoc>();
0338       auto NNSLB = Other.getUnchecked<NestedNameSpecifierLoc>();
0339       return std::make_pair(NNSLA.getNestedNameSpecifier(),
0340                             NNSLA.getOpaqueData()) <
0341              std::make_pair(NNSLB.getNestedNameSpecifier(),
0342                             NNSLB.getOpaqueData());
0343     }
0344 
0345     assert(getMemoizationData() && Other.getMemoizationData());
0346     return getMemoizationData() < Other.getMemoizationData();
0347   }
0348   bool operator==(const DynTypedNode &Other) const {
0349     // DynTypedNode::create() stores the exact kind of the node in NodeKind.
0350     // If they contain the same node, their NodeKind must be the same.
0351     if (!NodeKind.isSame(Other.NodeKind))
0352       return false;
0353 
0354     // FIXME: Implement for other types.
0355     if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind))
0356       return getUnchecked<QualType>() == Other.getUnchecked<QualType>();
0357 
0358     if (ASTNodeKind::getFromNodeKind<TypeLoc>().isBaseOf(NodeKind))
0359       return getUnchecked<TypeLoc>() == Other.getUnchecked<TypeLoc>();
0360 
0361     if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(NodeKind))
0362       return getUnchecked<NestedNameSpecifierLoc>() ==
0363              Other.getUnchecked<NestedNameSpecifierLoc>();
0364 
0365     assert(getMemoizationData() && Other.getMemoizationData());
0366     return getMemoizationData() == Other.getMemoizationData();
0367   }
0368   bool operator!=(const DynTypedNode &Other) const {
0369     return !operator==(Other);
0370   }
0371   /// @}
0372 
0373   /// Hooks for using DynTypedNode as a key in a DenseMap.
0374   struct DenseMapInfo {
0375     static inline DynTypedNode getEmptyKey() {
0376       DynTypedNode Node;
0377       Node.NodeKind = ASTNodeKind::DenseMapInfo::getEmptyKey();
0378       return Node;
0379     }
0380     static inline DynTypedNode getTombstoneKey() {
0381       DynTypedNode Node;
0382       Node.NodeKind = ASTNodeKind::DenseMapInfo::getTombstoneKey();
0383       return Node;
0384     }
0385     static unsigned getHashValue(const DynTypedNode &Val) {
0386       // FIXME: Add hashing support for the remaining types.
0387       if (ASTNodeKind::getFromNodeKind<TypeLoc>().isBaseOf(Val.NodeKind)) {
0388         auto TL = Val.getUnchecked<TypeLoc>();
0389         return llvm::hash_combine(TL.getType().getAsOpaquePtr(),
0390                                   TL.getOpaqueData());
0391       }
0392 
0393       if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(
0394               Val.NodeKind)) {
0395         auto NNSL = Val.getUnchecked<NestedNameSpecifierLoc>();
0396         return llvm::hash_combine(NNSL.getNestedNameSpecifier(),
0397                                   NNSL.getOpaqueData());
0398       }
0399 
0400       assert(Val.getMemoizationData());
0401       return llvm::hash_value(Val.getMemoizationData());
0402     }
0403     static bool isEqual(const DynTypedNode &LHS, const DynTypedNode &RHS) {
0404       auto Empty = ASTNodeKind::DenseMapInfo::getEmptyKey();
0405       auto TombStone = ASTNodeKind::DenseMapInfo::getTombstoneKey();
0406       return (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, Empty) &&
0407               ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, Empty)) ||
0408              (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, TombStone) &&
0409               ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, TombStone)) ||
0410              LHS == RHS;
0411     }
0412   };
0413 
0414 private:
0415   /// Takes care of converting from and to \c T.
0416   template <typename T, typename EnablerT = void> struct BaseConverter;
0417 
0418   /// Converter that uses dyn_cast<T> from a stored BaseT*.
0419   template <typename T, typename BaseT> struct DynCastPtrConverter {
0420     static const T *get(ASTNodeKind NodeKind, const void *Storage) {
0421       if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind))
0422         return &getUnchecked(NodeKind, Storage);
0423       return nullptr;
0424     }
0425     static const T &getUnchecked(ASTNodeKind NodeKind, const void *Storage) {
0426       assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind));
0427       return *cast<T>(static_cast<const BaseT *>(
0428           *reinterpret_cast<const void *const *>(Storage)));
0429     }
0430     static DynTypedNode create(const BaseT &Node) {
0431       DynTypedNode Result;
0432       Result.NodeKind = ASTNodeKind::getFromNode(Node);
0433       new (&Result.Storage) const void *(&Node);
0434       return Result;
0435     }
0436   };
0437 
0438   /// Converter that stores T* (by pointer).
0439   template <typename T> struct PtrConverter {
0440     static const T *get(ASTNodeKind NodeKind, const void *Storage) {
0441       if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
0442         return &getUnchecked(NodeKind, Storage);
0443       return nullptr;
0444     }
0445     static const T &getUnchecked(ASTNodeKind NodeKind, const void *Storage) {
0446       assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind));
0447       return *static_cast<const T *>(
0448           *reinterpret_cast<const void *const *>(Storage));
0449     }
0450     static DynTypedNode create(const T &Node) {
0451       DynTypedNode Result;
0452       Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
0453       new (&Result.Storage) const void *(&Node);
0454       return Result;
0455     }
0456   };
0457 
0458   /// Converter that stores T (by value).
0459   template <typename T> struct ValueConverter {
0460     static const T *get(ASTNodeKind NodeKind, const void *Storage) {
0461       if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind))
0462         return reinterpret_cast<const T *>(Storage);
0463       return nullptr;
0464     }
0465     static const T &getUnchecked(ASTNodeKind NodeKind, const void *Storage) {
0466       assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind));
0467       return *reinterpret_cast<const T *>(Storage);
0468     }
0469     static DynTypedNode create(const T &Node) {
0470       DynTypedNode Result;
0471       Result.NodeKind = ASTNodeKind::getFromNodeKind<T>();
0472       new (&Result.Storage) T(Node);
0473       return Result;
0474     }
0475   };
0476 
0477   /// Converter that stores nodes by value. It must be possible to dynamically
0478   /// cast the stored node within a type hierarchy without breaking (especially
0479   /// through slicing).
0480   template <typename T, typename BaseT,
0481             typename = std::enable_if_t<(sizeof(T) == sizeof(BaseT))>>
0482   struct DynCastValueConverter {
0483     static const T *get(ASTNodeKind NodeKind, const void *Storage) {
0484       if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind))
0485         return &getUnchecked(NodeKind, Storage);
0486       return nullptr;
0487     }
0488     static const T &getUnchecked(ASTNodeKind NodeKind, const void *Storage) {
0489       assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind));
0490       return *static_cast<const T *>(reinterpret_cast<const BaseT *>(Storage));
0491     }
0492     static DynTypedNode create(const T &Node) {
0493       DynTypedNode Result;
0494       Result.NodeKind = ASTNodeKind::getFromNode(Node);
0495       new (&Result.Storage) T(Node);
0496       return Result;
0497     }
0498   };
0499 
0500   ASTNodeKind NodeKind;
0501 
0502   /// Stores the data of the node.
0503   ///
0504   /// Note that we can store \c Decls, \c Stmts, \c Types,
0505   /// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are
0506   /// guaranteed to be unique pointers pointing to dedicated storage in the AST.
0507   /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs,
0508   /// \c TemplateArguments and \c TemplateArgumentLocs on the other hand do not
0509   /// have storage or unique pointers and thus need to be stored by value.
0510   llvm::AlignedCharArrayUnion<const void *, TemplateArgument,
0511                               TemplateArgumentLoc, NestedNameSpecifierLoc,
0512                               QualType, TypeLoc, ObjCProtocolLoc>
0513       Storage;
0514 };
0515 
0516 template <typename T>
0517 struct DynTypedNode::BaseConverter<
0518     T, std::enable_if_t<std::is_base_of<Decl, T>::value>>
0519     : public DynCastPtrConverter<T, Decl> {};
0520 
0521 template <typename T>
0522 struct DynTypedNode::BaseConverter<
0523     T, std::enable_if_t<std::is_base_of<Stmt, T>::value>>
0524     : public DynCastPtrConverter<T, Stmt> {};
0525 
0526 template <typename T>
0527 struct DynTypedNode::BaseConverter<
0528     T, std::enable_if_t<std::is_base_of<Type, T>::value>>
0529     : public DynCastPtrConverter<T, Type> {};
0530 
0531 template <typename T>
0532 struct DynTypedNode::BaseConverter<
0533     T, std::enable_if_t<std::is_base_of<OMPClause, T>::value>>
0534     : public DynCastPtrConverter<T, OMPClause> {};
0535 
0536 template <typename T>
0537 struct DynTypedNode::BaseConverter<
0538     T, std::enable_if_t<std::is_base_of<Attr, T>::value>>
0539     : public DynCastPtrConverter<T, Attr> {};
0540 
0541 template <>
0542 struct DynTypedNode::BaseConverter<
0543     NestedNameSpecifier, void> : public PtrConverter<NestedNameSpecifier> {};
0544 
0545 template <>
0546 struct DynTypedNode::BaseConverter<
0547     CXXCtorInitializer, void> : public PtrConverter<CXXCtorInitializer> {};
0548 
0549 template <>
0550 struct DynTypedNode::BaseConverter<
0551     TemplateArgument, void> : public ValueConverter<TemplateArgument> {};
0552 
0553 template <>
0554 struct DynTypedNode::BaseConverter<TemplateArgumentLoc, void>
0555     : public ValueConverter<TemplateArgumentLoc> {};
0556 
0557 template <>
0558 struct DynTypedNode::BaseConverter<LambdaCapture, void>
0559     : public ValueConverter<LambdaCapture> {};
0560 
0561 template <>
0562 struct DynTypedNode::BaseConverter<
0563     TemplateName, void> : public ValueConverter<TemplateName> {};
0564 
0565 template <>
0566 struct DynTypedNode::BaseConverter<
0567     NestedNameSpecifierLoc,
0568     void> : public ValueConverter<NestedNameSpecifierLoc> {};
0569 
0570 template <>
0571 struct DynTypedNode::BaseConverter<QualType,
0572                                    void> : public ValueConverter<QualType> {};
0573 
0574 template <typename T>
0575 struct DynTypedNode::BaseConverter<
0576     T, std::enable_if_t<std::is_base_of<TypeLoc, T>::value>>
0577     : public DynCastValueConverter<T, TypeLoc> {};
0578 
0579 template <>
0580 struct DynTypedNode::BaseConverter<CXXBaseSpecifier, void>
0581     : public PtrConverter<CXXBaseSpecifier> {};
0582 
0583 template <>
0584 struct DynTypedNode::BaseConverter<ObjCProtocolLoc, void>
0585     : public ValueConverter<ObjCProtocolLoc> {};
0586 
0587 template <>
0588 struct DynTypedNode::BaseConverter<ConceptReference, void>
0589     : public PtrConverter<ConceptReference> {};
0590 
0591 // The only operation we allow on unsupported types is \c get.
0592 // This allows to conveniently use \c DynTypedNode when having an arbitrary
0593 // AST node that is not supported, but prevents misuse - a user cannot create
0594 // a DynTypedNode from arbitrary types.
0595 template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter {
0596   static const T *get(ASTNodeKind NodeKind, const char Storage[]) {
0597     return NULL;
0598   }
0599 };
0600 
0601 } // end namespace clang
0602 
0603 namespace llvm {
0604 
0605 template <>
0606 struct DenseMapInfo<clang::ASTNodeKind> : clang::ASTNodeKind::DenseMapInfo {};
0607 
0608 template <>
0609 struct DenseMapInfo<clang::DynTypedNode> : clang::DynTypedNode::DenseMapInfo {};
0610 
0611 }  // end namespace llvm
0612 
0613 #endif