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