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