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