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