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 28 namespace llvm { 29 class raw_ostream; 30 } // namespace llvm 31 32 namespace clang { 33 34 struct PrintingPolicy; 35 36 /// Defines how we descend a level in the AST when we pass 37 /// through expressions. 38 enum 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. 51 class ASTNodeKind { 52 public: 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 127 private: 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 }; 200 KIND_TO_KIND_ID(CXXCtorInitializer) 201 KIND_TO_KIND_ID(TemplateArgument) 202 KIND_TO_KIND_ID(TemplateArgumentLoc) 203 KIND_TO_KIND_ID(LambdaCapture) 204 KIND_TO_KIND_ID(TemplateName) 205 KIND_TO_KIND_ID(NestedNameSpecifier) 206 KIND_TO_KIND_ID(NestedNameSpecifierLoc) 207 KIND_TO_KIND_ID(QualType) 208 #define TYPELOC(CLASS, PARENT) KIND_TO_KIND_ID(CLASS##TypeLoc) 209 #include "clang/AST/TypeLocNodes.def" 210 KIND_TO_KIND_ID(TypeLoc) 211 KIND_TO_KIND_ID(Decl) 212 KIND_TO_KIND_ID(Stmt) 213 KIND_TO_KIND_ID(Type) 214 KIND_TO_KIND_ID(OMPClause) 215 KIND_TO_KIND_ID(Attr) 216 KIND_TO_KIND_ID(ObjCProtocolLoc) 217 KIND_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 231 inline 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. 248 class DynTypedNode { 249 public: 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 405 private: 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 507 template <typename T> 508 struct DynTypedNode::BaseConverter< 509 T, std::enable_if_t<std::is_base_of<Decl, T>::value>> 510 : public DynCastPtrConverter<T, Decl> {}; 511 512 template <typename T> 513 struct DynTypedNode::BaseConverter< 514 T, std::enable_if_t<std::is_base_of<Stmt, T>::value>> 515 : public DynCastPtrConverter<T, Stmt> {}; 516 517 template <typename T> 518 struct DynTypedNode::BaseConverter< 519 T, std::enable_if_t<std::is_base_of<Type, T>::value>> 520 : public DynCastPtrConverter<T, Type> {}; 521 522 template <typename T> 523 struct DynTypedNode::BaseConverter< 524 T, std::enable_if_t<std::is_base_of<OMPClause, T>::value>> 525 : public DynCastPtrConverter<T, OMPClause> {}; 526 527 template <typename T> 528 struct DynTypedNode::BaseConverter< 529 T, std::enable_if_t<std::is_base_of<Attr, T>::value>> 530 : public DynCastPtrConverter<T, Attr> {}; 531 532 template <> 533 struct DynTypedNode::BaseConverter< 534 NestedNameSpecifier, void> : public PtrConverter<NestedNameSpecifier> {}; 535 536 template <> 537 struct DynTypedNode::BaseConverter< 538 CXXCtorInitializer, void> : public PtrConverter<CXXCtorInitializer> {}; 539 540 template <> 541 struct DynTypedNode::BaseConverter< 542 TemplateArgument, void> : public ValueConverter<TemplateArgument> {}; 543 544 template <> 545 struct DynTypedNode::BaseConverter<TemplateArgumentLoc, void> 546 : public ValueConverter<TemplateArgumentLoc> {}; 547 548 template <> 549 struct DynTypedNode::BaseConverter<LambdaCapture, void> 550 : public ValueConverter<LambdaCapture> {}; 551 552 template <> 553 struct DynTypedNode::BaseConverter< 554 TemplateName, void> : public ValueConverter<TemplateName> {}; 555 556 template <> 557 struct DynTypedNode::BaseConverter< 558 NestedNameSpecifierLoc, 559 void> : public ValueConverter<NestedNameSpecifierLoc> {}; 560 561 template <> 562 struct DynTypedNode::BaseConverter<QualType, 563 void> : public ValueConverter<QualType> {}; 564 565 template <typename T> 566 struct DynTypedNode::BaseConverter< 567 T, std::enable_if_t<std::is_base_of<TypeLoc, T>::value>> 568 : public DynCastValueConverter<T, TypeLoc> {}; 569 570 template <> 571 struct DynTypedNode::BaseConverter<CXXBaseSpecifier, void> 572 : public PtrConverter<CXXBaseSpecifier> {}; 573 574 template <> 575 struct 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. 582 template <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 590 namespace llvm { 591 592 template <> 593 struct DenseMapInfo<clang::ASTNodeKind> : clang::ASTNodeKind::DenseMapInfo {}; 594 595 template <> 596 struct DenseMapInfo<clang::DynTypedNode> : clang::DynTypedNode::DenseMapInfo {}; 597 598 } // end namespace llvm 599 600 #endif 601