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

source code of clang/include/clang/AST/ASTTypeTraits.h