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