1ff9a01000ff74a994aa3da26ea2ec732c97291b7Manuel Klimek//===--- ASTTypeTraits.h ----------------------------------------*- C++ -*-===// 266341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek// 366341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek// The LLVM Compiler Infrastructure 466341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek// 566341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek// This file is distributed under the University of Illinois Open Source 666341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek// License. See LICENSE.TXT for details. 766341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek// 866341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek//===----------------------------------------------------------------------===// 966341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek// 10d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen// Provides a dynamic type identifier and a dynamically typed node container 11d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen// that can be used to store an AST base node at runtime in the same storage in 12d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen// a type safe way. 1366341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek// 1466341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek//===----------------------------------------------------------------------===// 1566341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek 16176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#ifndef LLVM_CLANG_AST_ASTTYPETRAITS_H 17176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#define LLVM_CLANG_AST_ASTTYPETRAITS_H 1866341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek 19d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen#include "clang/AST/ASTFwd.h" 2066341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek#include "clang/AST/Decl.h" 21bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen#include "clang/AST/NestedNameSpecifier.h" 2266341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek#include "clang/AST/Stmt.h" 23bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen#include "clang/AST/TemplateBase.h" 249946fc735d7285f2195f89635370f534afd9877eDmitri Gribenko#include "clang/AST/TypeLoc.h" 25d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen#include "clang/Basic/LLVM.h" 260e2c34f92f00628d48968dfea096d36381f494cbStephen Hines#include "llvm/ADT/DenseMapInfo.h" 27a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek#include "llvm/Support/AlignOf.h" 2866341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek 2900841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbournenamespace llvm { 3000841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbourne 3100841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbourneclass raw_ostream; 3200841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbourne 3300841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbourne} 3400841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbourne 3566341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimeknamespace clang { 3600841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbourne 3700841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbournestruct PrintingPolicy; 3800841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbourne 3966341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimeknamespace ast_type_traits { 4066341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek 41d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen/// \brief Kind identifier. 42d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen/// 43d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen/// It can be constructed from any node kind and allows for runtime type 44d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen/// hierarchy checks. 45d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen/// Use getFromNodeKind<T>() to construct them. 46d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquenclass ASTNodeKind { 47d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquenpublic: 48d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen /// \brief Empty identifier. It matches nothing. 49d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen ASTNodeKind() : KindId(NKI_None) {} 50d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen 51d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen /// \brief Construct an identifier for T. 52d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen template <class T> 53d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen static ASTNodeKind getFromNodeKind() { 54d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen return ASTNodeKind(KindToKindId<T>::Id); 55d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen } 56d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen 57176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines /// \{ 58176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines /// \brief Construct an identifier for the dynamic type of the node 59176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines static ASTNodeKind getFromNode(const Decl &D); 60176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines static ASTNodeKind getFromNode(const Stmt &S); 61176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines static ASTNodeKind getFromNode(const Type &T); 62176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines /// \} 63176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 64d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen /// \brief Returns \c true if \c this and \c Other represent the same kind. 654967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar bool isSame(ASTNodeKind Other) const { 664967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar return KindId != NKI_None && KindId == Other.KindId; 674967a710c84587c654b56c828382219c3937dacbPirama Arumuga Nainar } 68d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen 69176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines /// \brief Returns \c true only for the default \c ASTNodeKind() 70176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines bool isNone() const { return KindId == NKI_None; } 71176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 72bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen /// \brief Returns \c true if \c this is a base kind of (or same as) \c Other. 73651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /// \param Distance If non-null, used to return the distance between \c this 74651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /// and \c Other in the class hierarchy. 756bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines bool isBaseOf(ASTNodeKind Other, unsigned *Distance = nullptr) const; 76d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen 77d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen /// \brief String representation of the kind. 78d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen StringRef asStringRef() const; 79d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen 80651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /// \brief Strict weak ordering for ASTNodeKind. 81651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines bool operator<(const ASTNodeKind &Other) const { 82651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return KindId < Other.KindId; 83651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines } 84651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 85176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines /// \brief Return the most derived type between \p Kind1 and \p Kind2. 86176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines /// 87176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines /// Return ASTNodeKind() if they are not related. 88176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2); 89176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 90176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines /// \brief Return the most derived common ancestor between Kind1 and Kind2. 91176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines /// 92176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines /// Return ASTNodeKind() if they are not related. 93176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines static ASTNodeKind getMostDerivedCommonAncestor(ASTNodeKind Kind1, 94176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ASTNodeKind Kind2); 95176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 960e2c34f92f00628d48968dfea096d36381f494cbStephen Hines /// \brief Hooks for using ASTNodeKind as a key in a DenseMap. 970e2c34f92f00628d48968dfea096d36381f494cbStephen Hines struct DenseMapInfo { 980e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // ASTNodeKind() is a good empty key because it is represented as a 0. 990e2c34f92f00628d48968dfea096d36381f494cbStephen Hines static inline ASTNodeKind getEmptyKey() { return ASTNodeKind(); } 1000e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // NKI_NumberOfKinds is not a valid value, so it is good for a 1010e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // tombstone key. 1020e2c34f92f00628d48968dfea096d36381f494cbStephen Hines static inline ASTNodeKind getTombstoneKey() { 1030e2c34f92f00628d48968dfea096d36381f494cbStephen Hines return ASTNodeKind(NKI_NumberOfKinds); 1040e2c34f92f00628d48968dfea096d36381f494cbStephen Hines } 1050e2c34f92f00628d48968dfea096d36381f494cbStephen Hines static unsigned getHashValue(const ASTNodeKind &Val) { return Val.KindId; } 1060e2c34f92f00628d48968dfea096d36381f494cbStephen Hines static bool isEqual(const ASTNodeKind &LHS, const ASTNodeKind &RHS) { 1070e2c34f92f00628d48968dfea096d36381f494cbStephen Hines return LHS.KindId == RHS.KindId; 1080e2c34f92f00628d48968dfea096d36381f494cbStephen Hines } 1090e2c34f92f00628d48968dfea096d36381f494cbStephen Hines }; 1100e2c34f92f00628d48968dfea096d36381f494cbStephen Hines 11187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar /// Check if the given ASTNodeKind identifies a type that offers pointer 11287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar /// identity. This is useful for the fast path in DynTypedNode. 11387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar bool hasPointerIdentity() const { 11487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return KindId > NKI_LastKindWithoutPointerIdentity; 11587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 11687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 117d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquenprivate: 118d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen /// \brief Kind ids. 119d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen /// 120d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen /// Includes all possible base and derived kinds. 121d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen enum NodeKindId { 122d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen NKI_None, 123bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen NKI_TemplateArgument, 124d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen NKI_NestedNameSpecifierLoc, 125d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen NKI_QualType, 126d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen NKI_TypeLoc, 12787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar NKI_LastKindWithoutPointerIdentity = NKI_TypeLoc, 12887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar NKI_CXXCtorInitializer, 12987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar NKI_NestedNameSpecifier, 130d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen NKI_Decl, 131d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen#define DECL(DERIVED, BASE) NKI_##DERIVED##Decl, 132d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen#include "clang/AST/DeclNodes.inc" 133d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen NKI_Stmt, 134d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen#define STMT(DERIVED, BASE) NKI_##DERIVED, 135d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen#include "clang/AST/StmtNodes.inc" 136d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen NKI_Type, 137d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen#define TYPE(DERIVED, BASE) NKI_##DERIVED##Type, 138d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen#include "clang/AST/TypeNodes.def" 139d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen NKI_NumberOfKinds 140d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen }; 141d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen 142d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen /// \brief Use getFromNodeKind<T>() to construct the kind. 143d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen ASTNodeKind(NodeKindId KindId) : KindId(KindId) {} 144d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen 145d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen /// \brief Returns \c true if \c Base is a base kind of (or same as) \c 146bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen /// Derived. 147651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /// \param Distance If non-null, used to return the distance between \c Base 148651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines /// and \c Derived in the class hierarchy. 149651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines static bool isBaseOf(NodeKindId Base, NodeKindId Derived, unsigned *Distance); 150d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen 151d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen /// \brief Helper meta-function to convert a kind T to its enum value. 152d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen /// 153d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen /// This struct is specialized below for all known kinds. 154d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen template <class T> struct KindToKindId { 155d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen static const NodeKindId Id = NKI_None; 156d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen }; 1570e2c34f92f00628d48968dfea096d36381f494cbStephen Hines template <class T> 1580e2c34f92f00628d48968dfea096d36381f494cbStephen Hines struct KindToKindId<const T> : KindToKindId<T> {}; 159d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen 160d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen /// \brief Per kind info. 161d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen struct KindInfo { 162d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen /// \brief The id of the parent kind, or None if it has no parent. 163d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen NodeKindId ParentId; 164d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen /// \brief Name of the kind. 165d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen const char *Name; 166d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen }; 167d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen static const KindInfo AllKindInfo[NKI_NumberOfKinds]; 168d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen 169d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen NodeKindId KindId; 170d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen}; 171d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen 172d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen#define KIND_TO_KIND_ID(Class) \ 173d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen template <> struct ASTNodeKind::KindToKindId<Class> { \ 174d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen static const NodeKindId Id = NKI_##Class; \ 175d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen }; 176bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel BenzaquenKIND_TO_KIND_ID(CXXCtorInitializer) 177bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel BenzaquenKIND_TO_KIND_ID(TemplateArgument) 178d5fbb2910fe934a61176b94503b0cf495f129253Samuel BenzaquenKIND_TO_KIND_ID(NestedNameSpecifier) 179d5fbb2910fe934a61176b94503b0cf495f129253Samuel BenzaquenKIND_TO_KIND_ID(NestedNameSpecifierLoc) 180d5fbb2910fe934a61176b94503b0cf495f129253Samuel BenzaquenKIND_TO_KIND_ID(QualType) 181d5fbb2910fe934a61176b94503b0cf495f129253Samuel BenzaquenKIND_TO_KIND_ID(TypeLoc) 182d5fbb2910fe934a61176b94503b0cf495f129253Samuel BenzaquenKIND_TO_KIND_ID(Decl) 183d5fbb2910fe934a61176b94503b0cf495f129253Samuel BenzaquenKIND_TO_KIND_ID(Stmt) 184d5fbb2910fe934a61176b94503b0cf495f129253Samuel BenzaquenKIND_TO_KIND_ID(Type) 185d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen#define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl) 186d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen#include "clang/AST/DeclNodes.inc" 187d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen#define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED) 188d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen#include "clang/AST/StmtNodes.inc" 189d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen#define TYPE(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Type) 190d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen#include "clang/AST/TypeNodes.def" 191d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen#undef KIND_TO_KIND_ID 192d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen 193651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesinline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) { 194651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines OS << K.asStringRef(); 195651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines return OS; 196651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines} 197651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 19866341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek/// \brief A dynamically typed AST node container. 19966341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek/// 200a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek/// Stores an AST node in a type safe way. This allows writing code that 201a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek/// works with different kinds of AST nodes, despite the fact that they don't 202a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek/// have a common base class. 203a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek/// 20466341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek/// Use \c create(Node) to create a \c DynTypedNode from an AST node, 20566341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek/// and \c get<T>() to retrieve the node as type T if the types match. 206a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek/// 207bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen/// See \c ASTNodeKind for which node base types are currently supported; 208a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek/// You can create DynTypedNodes for all nodes in the inheritance hierarchy of 209a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek/// the supported base types. 21066341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimekclass DynTypedNode { 21166341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimekpublic: 21266341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek /// \brief Creates a \c DynTypedNode from \c Node. 21366341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek template <typename T> 214a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek static DynTypedNode create(const T &Node) { 21566341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek return BaseConverter<T>::create(Node); 21666341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek } 21766341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek 21866341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek /// \brief Retrieve the stored node as type \c T. 21966341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek /// 22066341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek /// Returns NULL if the stored node does not have a type that is 22166341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek /// convertible to \c T. 222a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek /// 223a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek /// For types that have identity via their pointer in the AST 224cf52ca6bb6dd76a1bd967bc422287fafafa1e45aManuel Klimek /// (like \c Stmt, \c Decl, \c Type and \c NestedNameSpecifier) the returned 225cf52ca6bb6dd76a1bd967bc422287fafafa1e45aManuel Klimek /// pointer points to the referenced AST node. 226a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek /// For other types (like \c QualType) the value is stored directly 227a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek /// in the \c DynTypedNode, and the returned pointer points at 228a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek /// the storage inside DynTypedNode. For those nodes, do not 229a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek /// use the pointer outside the scope of the DynTypedNode. 23066341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek template <typename T> 231a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek const T *get() const { 232d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen return BaseConverter<T>::get(NodeKind, Storage.buffer); 23366341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek } 23466341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek 2350e2c34f92f00628d48968dfea096d36381f494cbStephen Hines /// \brief Retrieve the stored node as type \c T. 2360e2c34f92f00628d48968dfea096d36381f494cbStephen Hines /// 2370e2c34f92f00628d48968dfea096d36381f494cbStephen Hines /// Similar to \c get(), but asserts that the type is what we are expecting. 2380e2c34f92f00628d48968dfea096d36381f494cbStephen Hines template <typename T> 2390e2c34f92f00628d48968dfea096d36381f494cbStephen Hines const T &getUnchecked() const { 2400e2c34f92f00628d48968dfea096d36381f494cbStephen Hines return BaseConverter<T>::getUnchecked(NodeKind, Storage.buffer); 2410e2c34f92f00628d48968dfea096d36381f494cbStephen Hines } 2420e2c34f92f00628d48968dfea096d36381f494cbStephen Hines 243176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines ASTNodeKind getNodeKind() const { return NodeKind; } 244176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines 245a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek /// \brief Returns a pointer that identifies the stored AST node. 246a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek /// 247a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek /// Note that this is not supported by all AST nodes. For AST nodes 248a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek /// that don't have a pointer-defined identity inside the AST, this 249a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek /// method returns NULL. 25087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar const void *getMemoizationData() const { 25187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return NodeKind.hasPointerIdentity() 25287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar ? *reinterpret_cast<void *const *>(Storage.buffer) 25387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar : nullptr; 25487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 255a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek 25600841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbourne /// \brief Prints the node to the given output stream. 25700841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbourne void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const; 25800841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbourne 25900841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbourne /// \brief Dumps the node to the given output stream. 26000841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbourne void dump(llvm::raw_ostream &OS, SourceManager &SM) const; 26100841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbourne 26200841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbourne /// \brief For nodes which represent textual entities in the source code, 26300841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbourne /// return their SourceRange. For all other nodes, return SourceRange(). 26400841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbourne SourceRange getSourceRange() const; 26500841f5d6273d9088cfe308bacf6f5a80470c829Peter Collingbourne 266054d049174eb1ec8e93a4a0831c0d8caac00cb3aManuel Klimek /// @{ 267054d049174eb1ec8e93a4a0831c0d8caac00cb3aManuel Klimek /// \brief Imposes an order on \c DynTypedNode. 268054d049174eb1ec8e93a4a0831c0d8caac00cb3aManuel Klimek /// 269054d049174eb1ec8e93a4a0831c0d8caac00cb3aManuel Klimek /// Supports comparison of nodes that support memoization. 270054d049174eb1ec8e93a4a0831c0d8caac00cb3aManuel Klimek /// FIXME: Implement comparsion for other node types (currently 271cf52ca6bb6dd76a1bd967bc422287fafafa1e45aManuel Klimek /// only Stmt, Decl, Type and NestedNameSpecifier return memoization data). 272054d049174eb1ec8e93a4a0831c0d8caac00cb3aManuel Klimek bool operator<(const DynTypedNode &Other) const { 27387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (!NodeKind.isSame(Other.NodeKind)) 27487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return NodeKind < Other.NodeKind; 27587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 27687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind)) 27787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return getUnchecked<QualType>().getAsOpaquePtr() < 27887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Other.getUnchecked<QualType>().getAsOpaquePtr(); 27987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 28087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind)) { 28187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar auto TLA = getUnchecked<TypeLoc>(); 28287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar auto TLB = Other.getUnchecked<TypeLoc>(); 28387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return std::make_pair(TLA.getType().getAsOpaquePtr(), 28487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar TLA.getOpaqueData()) < 28587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar std::make_pair(TLB.getType().getAsOpaquePtr(), 28687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar TLB.getOpaqueData()); 28787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 28887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 28987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame( 29087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar NodeKind)) { 29187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar auto NNSLA = getUnchecked<NestedNameSpecifierLoc>(); 29287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar auto NNSLB = Other.getUnchecked<NestedNameSpecifierLoc>(); 29387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return std::make_pair(NNSLA.getNestedNameSpecifier(), 29487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar NNSLA.getOpaqueData()) < 29587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar std::make_pair(NNSLB.getNestedNameSpecifier(), 29687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar NNSLB.getOpaqueData()); 29787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 29887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 299054d049174eb1ec8e93a4a0831c0d8caac00cb3aManuel Klimek assert(getMemoizationData() && Other.getMemoizationData()); 300054d049174eb1ec8e93a4a0831c0d8caac00cb3aManuel Klimek return getMemoizationData() < Other.getMemoizationData(); 301054d049174eb1ec8e93a4a0831c0d8caac00cb3aManuel Klimek } 302054d049174eb1ec8e93a4a0831c0d8caac00cb3aManuel Klimek bool operator==(const DynTypedNode &Other) const { 3030e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // DynTypedNode::create() stores the exact kind of the node in NodeKind. 3040e2c34f92f00628d48968dfea096d36381f494cbStephen Hines // If they contain the same node, their NodeKind must be the same. 3050e2c34f92f00628d48968dfea096d36381f494cbStephen Hines if (!NodeKind.isSame(Other.NodeKind)) 306cf52ca6bb6dd76a1bd967bc422287fafafa1e45aManuel Klimek return false; 307cf52ca6bb6dd76a1bd967bc422287fafafa1e45aManuel Klimek 308cf52ca6bb6dd76a1bd967bc422287fafafa1e45aManuel Klimek // FIXME: Implement for other types. 3090e2c34f92f00628d48968dfea096d36381f494cbStephen Hines if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind)) 3100e2c34f92f00628d48968dfea096d36381f494cbStephen Hines return getUnchecked<QualType>() == Other.getUnchecked<QualType>(); 3110e2c34f92f00628d48968dfea096d36381f494cbStephen Hines 31287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(NodeKind)) 31387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return getUnchecked<TypeLoc>() == Other.getUnchecked<TypeLoc>(); 31487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 31587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame(NodeKind)) 31687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return getUnchecked<NestedNameSpecifierLoc>() == 31787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Other.getUnchecked<NestedNameSpecifierLoc>(); 31887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 319054d049174eb1ec8e93a4a0831c0d8caac00cb3aManuel Klimek assert(getMemoizationData() && Other.getMemoizationData()); 320054d049174eb1ec8e93a4a0831c0d8caac00cb3aManuel Klimek return getMemoizationData() == Other.getMemoizationData(); 321054d049174eb1ec8e93a4a0831c0d8caac00cb3aManuel Klimek } 322054d049174eb1ec8e93a4a0831c0d8caac00cb3aManuel Klimek bool operator!=(const DynTypedNode &Other) const { 323054d049174eb1ec8e93a4a0831c0d8caac00cb3aManuel Klimek return !operator==(Other); 324054d049174eb1ec8e93a4a0831c0d8caac00cb3aManuel Klimek } 325054d049174eb1ec8e93a4a0831c0d8caac00cb3aManuel Klimek /// @} 326054d049174eb1ec8e93a4a0831c0d8caac00cb3aManuel Klimek 32787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar /// \brief Hooks for using DynTypedNode as a key in a DenseMap. 32887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar struct DenseMapInfo { 32987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar static inline DynTypedNode getEmptyKey() { 33087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar DynTypedNode Node; 33187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Node.NodeKind = ASTNodeKind::DenseMapInfo::getEmptyKey(); 33287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return Node; 33387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 33487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar static inline DynTypedNode getTombstoneKey() { 33587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar DynTypedNode Node; 33687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Node.NodeKind = ASTNodeKind::DenseMapInfo::getTombstoneKey(); 33787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return Node; 33887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 33987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar static unsigned getHashValue(const DynTypedNode &Val) { 34087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar // FIXME: Add hashing support for the remaining types. 34187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (ASTNodeKind::getFromNodeKind<TypeLoc>().isSame(Val.NodeKind)) { 34287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar auto TL = Val.getUnchecked<TypeLoc>(); 34387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return llvm::hash_combine(TL.getType().getAsOpaquePtr(), 34487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar TL.getOpaqueData()); 34587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 34687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 34787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar if (ASTNodeKind::getFromNodeKind<NestedNameSpecifierLoc>().isSame( 34887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar Val.NodeKind)) { 34987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar auto NNSL = Val.getUnchecked<NestedNameSpecifierLoc>(); 35087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return llvm::hash_combine(NNSL.getNestedNameSpecifier(), 35187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar NNSL.getOpaqueData()); 35287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 35387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 35487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar assert(Val.getMemoizationData()); 35587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return llvm::hash_value(Val.getMemoizationData()); 35687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 35787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar static bool isEqual(const DynTypedNode &LHS, const DynTypedNode &RHS) { 35887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar auto Empty = ASTNodeKind::DenseMapInfo::getEmptyKey(); 35987d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar auto TombStone = ASTNodeKind::DenseMapInfo::getTombstoneKey(); 36087d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, Empty) && 36187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, Empty)) || 36287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar (ASTNodeKind::DenseMapInfo::isEqual(LHS.NodeKind, TombStone) && 36387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar ASTNodeKind::DenseMapInfo::isEqual(RHS.NodeKind, TombStone)) || 36487d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar LHS == RHS; 36587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar } 36687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar }; 36787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 36866341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimekprivate: 36966341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek /// \brief Takes care of converting from and to \c T. 37066341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek template <typename T, typename EnablerT = void> struct BaseConverter; 37166341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek 372bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen /// \brief Converter that uses dyn_cast<T> from a stored BaseT*. 373bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen template <typename T, typename BaseT> struct DynCastPtrConverter { 374bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen static const T *get(ASTNodeKind NodeKind, const char Storage[]) { 3750e2c34f92f00628d48968dfea096d36381f494cbStephen Hines if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind)) 37687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return &getUnchecked(NodeKind, Storage); 3776bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 378bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen } 3790e2c34f92f00628d48968dfea096d36381f494cbStephen Hines static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { 3800e2c34f92f00628d48968dfea096d36381f494cbStephen Hines assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind)); 38187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return *cast<T>(static_cast<const BaseT *>( 38287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar *reinterpret_cast<const void *const *>(Storage))); 3830e2c34f92f00628d48968dfea096d36381f494cbStephen Hines } 384bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen static DynTypedNode create(const BaseT &Node) { 385bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen DynTypedNode Result; 386176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines Result.NodeKind = ASTNodeKind::getFromNode(Node); 38787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar new (Result.Storage.buffer) const void *(&Node); 388bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen return Result; 389bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen } 390bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen }; 391bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen 392bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen /// \brief Converter that stores T* (by pointer). 393bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen template <typename T> struct PtrConverter { 394bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen static const T *get(ASTNodeKind NodeKind, const char Storage[]) { 395bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)) 39687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return &getUnchecked(NodeKind, Storage); 3976bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 398bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen } 3990e2c34f92f00628d48968dfea096d36381f494cbStephen Hines static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { 4000e2c34f92f00628d48968dfea096d36381f494cbStephen Hines assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)); 40187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar return *static_cast<const T *>( 40287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar *reinterpret_cast<const void *const *>(Storage)); 4030e2c34f92f00628d48968dfea096d36381f494cbStephen Hines } 404bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen static DynTypedNode create(const T &Node) { 405bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen DynTypedNode Result; 406bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); 40787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar new (Result.Storage.buffer) const void *(&Node); 408bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen return Result; 409bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen } 410bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen }; 411bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen 412bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen /// \brief Converter that stores T (by value). 413bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen template <typename T> struct ValueConverter { 414bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen static const T *get(ASTNodeKind NodeKind, const char Storage[]) { 415bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)) 416bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen return reinterpret_cast<const T *>(Storage); 4176bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 418bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen } 4190e2c34f92f00628d48968dfea096d36381f494cbStephen Hines static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { 4200e2c34f92f00628d48968dfea096d36381f494cbStephen Hines assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)); 4210e2c34f92f00628d48968dfea096d36381f494cbStephen Hines return *reinterpret_cast<const T *>(Storage); 4220e2c34f92f00628d48968dfea096d36381f494cbStephen Hines } 423bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen static DynTypedNode create(const T &Node) { 424bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen DynTypedNode Result; 425bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); 426bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen new (Result.Storage.buffer) T(Node); 427bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen return Result; 428bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen } 429bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen }; 430bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen 431d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen ASTNodeKind NodeKind; 43266341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek 43366341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek /// \brief Stores the data of the node. 434a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek /// 435bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen /// Note that we can store \c Decls, \c Stmts, \c Types, 436bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen /// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are 437bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen /// guaranteed to be unique pointers pointing to dedicated storage in the AST. 438bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and 439bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen /// \c TemplateArguments on the other hand do not have storage or unique 440bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen /// pointers and thus need to be stored by value. 44187d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar llvm::AlignedCharArrayUnion<const void *, TemplateArgument, 44287d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar NestedNameSpecifierLoc, QualType, 44387d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar TypeLoc> Storage; 44466341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek}; 445ce62007526cdf718faed10df5e9fc7c3cd160cdeDaniel Jasper 446bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquentemplate <typename T> 447bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquenstruct DynTypedNode::BaseConverter< 448651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines T, typename std::enable_if<std::is_base_of<Decl, T>::value>::type> 449651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines : public DynCastPtrConverter<T, Decl> {}; 450bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen 451bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquentemplate <typename T> 452bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquenstruct DynTypedNode::BaseConverter< 453651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines T, typename std::enable_if<std::is_base_of<Stmt, T>::value>::type> 454651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines : public DynCastPtrConverter<T, Stmt> {}; 455bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen 456bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquentemplate <typename T> 457bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquenstruct DynTypedNode::BaseConverter< 458651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines T, typename std::enable_if<std::is_base_of<Type, T>::value>::type> 459651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines : public DynCastPtrConverter<T, Type> {}; 460bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen 461bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquentemplate <> 462bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquenstruct DynTypedNode::BaseConverter< 463bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen NestedNameSpecifier, void> : public PtrConverter<NestedNameSpecifier> {}; 464bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen 465bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquentemplate <> 466bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquenstruct DynTypedNode::BaseConverter< 467bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen CXXCtorInitializer, void> : public PtrConverter<CXXCtorInitializer> {}; 468bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen 469bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquentemplate <> 470bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquenstruct DynTypedNode::BaseConverter< 471bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen TemplateArgument, void> : public ValueConverter<TemplateArgument> {}; 472bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen 473bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquentemplate <> 474bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquenstruct DynTypedNode::BaseConverter< 475bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen NestedNameSpecifierLoc, 476bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen void> : public ValueConverter<NestedNameSpecifierLoc> {}; 477bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen 478bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquentemplate <> 479bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquenstruct DynTypedNode::BaseConverter<QualType, 480bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen void> : public ValueConverter<QualType> {}; 481bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen 482bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquentemplate <> 483bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquenstruct DynTypedNode::BaseConverter< 484bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen TypeLoc, void> : public ValueConverter<TypeLoc> {}; 485bdfacea02fa37b64e4eb815448bc5c4d42a67a8eSamuel Benzaquen 486a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek// The only operation we allow on unsupported types is \c get. 487a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek// This allows to conveniently use \c DynTypedNode when having an arbitrary 488a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek// AST node that is not supported, but prevents misuse - a user cannot create 489a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek// a DynTypedNode from arbitrary types. 490a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimektemplate <typename T, typename EnablerT> struct DynTypedNode::BaseConverter { 491d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen static const T *get(ASTNodeKind NodeKind, const char Storage[]) { 492d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen return NULL; 493d5fbb2910fe934a61176b94503b0cf495f129253Samuel Benzaquen } 494a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek}; 495a78d0d6203a990b88c9c3e4c4f2a277001e8bd46Manuel Klimek 49666341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek} // end namespace ast_type_traits 49766341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek} // end namespace clang 49866341c596f93d0c6475d839db94072b8ebd1cf5bManuel Klimek 4990e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesnamespace llvm { 5000e2c34f92f00628d48968dfea096d36381f494cbStephen Hines 5010e2c34f92f00628d48968dfea096d36381f494cbStephen Hinestemplate <> 5020e2c34f92f00628d48968dfea096d36381f494cbStephen Hinesstruct DenseMapInfo<clang::ast_type_traits::ASTNodeKind> 5030e2c34f92f00628d48968dfea096d36381f494cbStephen Hines : clang::ast_type_traits::ASTNodeKind::DenseMapInfo {}; 5040e2c34f92f00628d48968dfea096d36381f494cbStephen Hines 50587d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainartemplate <> 50687d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainarstruct DenseMapInfo<clang::ast_type_traits::DynTypedNode> 50787d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar : clang::ast_type_traits::DynTypedNode::DenseMapInfo {}; 50887d948ecccffea9e9e37d0d053b246e2d6d6c47bPirama Arumuga Nainar 5090e2c34f92f00628d48968dfea096d36381f494cbStephen Hines} // end namespace llvm 5100e2c34f92f00628d48968dfea096d36381f494cbStephen Hines 511176edba5311f6eff0cad2631449885ddf4fbc9eaStephen Hines#endif 512