xref: /freebsd/contrib/llvm-project/clang/lib/AST/TextNodeDumper.cpp (revision aa1a8ff2d6dbc51ef058f46f3db5a8bb77967145)
1 //===--- TextNodeDumper.cpp - Printing of AST nodes -----------------------===//
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 // This file implements AST dumping of components of individual AST nodes.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "clang/AST/TextNodeDumper.h"
14 #include "clang/AST/APValue.h"
15 #include "clang/AST/DeclFriend.h"
16 #include "clang/AST/DeclOpenMP.h"
17 #include "clang/AST/DeclTemplate.h"
18 #include "clang/AST/LocInfoType.h"
19 #include "clang/AST/NestedNameSpecifier.h"
20 #include "clang/AST/Type.h"
21 #include "clang/Basic/Module.h"
22 #include "clang/Basic/SourceManager.h"
23 #include "clang/Basic/Specifiers.h"
24 #include "clang/Basic/TypeTraits.h"
25 #include "llvm/ADT/StringExtras.h"
26 
27 #include <algorithm>
28 #include <utility>
29 
30 using namespace clang;
31 
32 static void dumpPreviousDeclImpl(raw_ostream &OS, ...) {}
33 
34 template <typename T>
35 static void dumpPreviousDeclImpl(raw_ostream &OS, const Mergeable<T> *D) {
36   const T *First = D->getFirstDecl();
37   if (First != D)
38     OS << " first " << First;
39 }
40 
41 template <typename T>
42 static void dumpPreviousDeclImpl(raw_ostream &OS, const Redeclarable<T> *D) {
43   const T *Prev = D->getPreviousDecl();
44   if (Prev)
45     OS << " prev " << Prev;
46 }
47 
48 /// Dump the previous declaration in the redeclaration chain for a declaration,
49 /// if any.
50 static void dumpPreviousDecl(raw_ostream &OS, const Decl *D) {
51   switch (D->getKind()) {
52 #define DECL(DERIVED, BASE)                                                    \
53   case Decl::DERIVED:                                                          \
54     return dumpPreviousDeclImpl(OS, cast<DERIVED##Decl>(D));
55 #define ABSTRACT_DECL(DECL)
56 #include "clang/AST/DeclNodes.inc"
57   }
58   llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
59 }
60 
61 TextNodeDumper::TextNodeDumper(raw_ostream &OS, const ASTContext &Context,
62                                bool ShowColors)
63     : TextTreeStructure(OS, ShowColors), OS(OS), ShowColors(ShowColors),
64       Context(&Context), SM(&Context.getSourceManager()),
65       PrintPolicy(Context.getPrintingPolicy()),
66       Traits(&Context.getCommentCommandTraits()) {}
67 
68 TextNodeDumper::TextNodeDumper(raw_ostream &OS, bool ShowColors)
69     : TextTreeStructure(OS, ShowColors), OS(OS), ShowColors(ShowColors) {}
70 
71 void TextNodeDumper::Visit(const comments::Comment *C,
72                            const comments::FullComment *FC) {
73   if (!C) {
74     ColorScope Color(OS, ShowColors, NullColor);
75     OS << "<<<NULL>>>";
76     return;
77   }
78 
79   {
80     ColorScope Color(OS, ShowColors, CommentColor);
81     OS << C->getCommentKindName();
82   }
83   dumpPointer(C);
84   dumpSourceRange(C->getSourceRange());
85 
86   ConstCommentVisitor<TextNodeDumper, void,
87                       const comments::FullComment *>::visit(C, FC);
88 }
89 
90 void TextNodeDumper::Visit(const Attr *A) {
91   {
92     ColorScope Color(OS, ShowColors, AttrColor);
93 
94     switch (A->getKind()) {
95 #define ATTR(X)                                                                \
96   case attr::X:                                                                \
97     OS << #X;                                                                  \
98     break;
99 #include "clang/Basic/AttrList.inc"
100     }
101     OS << "Attr";
102   }
103   dumpPointer(A);
104   dumpSourceRange(A->getRange());
105   if (A->isInherited())
106     OS << " Inherited";
107   if (A->isImplicit())
108     OS << " Implicit";
109 
110   ConstAttrVisitor<TextNodeDumper>::Visit(A);
111 }
112 
113 void TextNodeDumper::Visit(const TemplateArgument &TA, SourceRange R,
114                            const Decl *From, StringRef Label) {
115   OS << "TemplateArgument";
116   if (R.isValid())
117     dumpSourceRange(R);
118 
119   if (From)
120     dumpDeclRef(From, Label);
121 
122   ConstTemplateArgumentVisitor<TextNodeDumper>::Visit(TA);
123 }
124 
125 void TextNodeDumper::Visit(const Stmt *Node) {
126   if (!Node) {
127     ColorScope Color(OS, ShowColors, NullColor);
128     OS << "<<<NULL>>>";
129     return;
130   }
131   {
132     ColorScope Color(OS, ShowColors, StmtColor);
133     OS << Node->getStmtClassName();
134   }
135   dumpPointer(Node);
136   dumpSourceRange(Node->getSourceRange());
137 
138   if (const auto *E = dyn_cast<Expr>(Node)) {
139     dumpType(E->getType());
140 
141     if (E->containsErrors()) {
142       ColorScope Color(OS, ShowColors, ErrorsColor);
143       OS << " contains-errors";
144     }
145 
146     {
147       ColorScope Color(OS, ShowColors, ValueKindColor);
148       switch (E->getValueKind()) {
149       case VK_PRValue:
150         break;
151       case VK_LValue:
152         OS << " lvalue";
153         break;
154       case VK_XValue:
155         OS << " xvalue";
156         break;
157       }
158     }
159 
160     {
161       ColorScope Color(OS, ShowColors, ObjectKindColor);
162       switch (E->getObjectKind()) {
163       case OK_Ordinary:
164         break;
165       case OK_BitField:
166         OS << " bitfield";
167         break;
168       case OK_ObjCProperty:
169         OS << " objcproperty";
170         break;
171       case OK_ObjCSubscript:
172         OS << " objcsubscript";
173         break;
174       case OK_VectorComponent:
175         OS << " vectorcomponent";
176         break;
177       case OK_MatrixComponent:
178         OS << " matrixcomponent";
179         break;
180       }
181     }
182   }
183 
184   ConstStmtVisitor<TextNodeDumper>::Visit(Node);
185 }
186 
187 void TextNodeDumper::Visit(const Type *T) {
188   if (!T) {
189     ColorScope Color(OS, ShowColors, NullColor);
190     OS << "<<<NULL>>>";
191     return;
192   }
193   if (isa<LocInfoType>(T)) {
194     {
195       ColorScope Color(OS, ShowColors, TypeColor);
196       OS << "LocInfo Type";
197     }
198     dumpPointer(T);
199     return;
200   }
201 
202   {
203     ColorScope Color(OS, ShowColors, TypeColor);
204     OS << T->getTypeClassName() << "Type";
205   }
206   dumpPointer(T);
207   OS << " ";
208   dumpBareType(QualType(T, 0), false);
209 
210   QualType SingleStepDesugar =
211       T->getLocallyUnqualifiedSingleStepDesugaredType();
212   if (SingleStepDesugar != QualType(T, 0))
213     OS << " sugar";
214 
215   if (T->containsErrors()) {
216     ColorScope Color(OS, ShowColors, ErrorsColor);
217     OS << " contains-errors";
218   }
219 
220   if (T->isDependentType())
221     OS << " dependent";
222   else if (T->isInstantiationDependentType())
223     OS << " instantiation_dependent";
224 
225   if (T->isVariablyModifiedType())
226     OS << " variably_modified";
227   if (T->containsUnexpandedParameterPack())
228     OS << " contains_unexpanded_pack";
229   if (T->isFromAST())
230     OS << " imported";
231 
232   TypeVisitor<TextNodeDumper>::Visit(T);
233 }
234 
235 void TextNodeDumper::Visit(QualType T) {
236   OS << "QualType";
237   dumpPointer(T.getAsOpaquePtr());
238   OS << " ";
239   dumpBareType(T, false);
240   OS << " " << T.split().Quals.getAsString();
241 }
242 
243 void TextNodeDumper::Visit(const Decl *D) {
244   if (!D) {
245     ColorScope Color(OS, ShowColors, NullColor);
246     OS << "<<<NULL>>>";
247     return;
248   }
249 
250   {
251     ColorScope Color(OS, ShowColors, DeclKindNameColor);
252     OS << D->getDeclKindName() << "Decl";
253   }
254   dumpPointer(D);
255   if (D->getLexicalDeclContext() != D->getDeclContext())
256     OS << " parent " << cast<Decl>(D->getDeclContext());
257   dumpPreviousDecl(OS, D);
258   dumpSourceRange(D->getSourceRange());
259   OS << ' ';
260   dumpLocation(D->getLocation());
261   if (D->isFromASTFile())
262     OS << " imported";
263   if (Module *M = D->getOwningModule())
264     OS << " in " << M->getFullModuleName();
265   if (auto *ND = dyn_cast<NamedDecl>(D))
266     for (Module *M : D->getASTContext().getModulesWithMergedDefinition(
267              const_cast<NamedDecl *>(ND)))
268       AddChild([=] { OS << "also in " << M->getFullModuleName(); });
269   if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
270     if (!ND->isUnconditionallyVisible())
271       OS << " hidden";
272   if (D->isImplicit())
273     OS << " implicit";
274 
275   if (D->isUsed())
276     OS << " used";
277   else if (D->isThisDeclarationReferenced())
278     OS << " referenced";
279 
280   if (D->isInvalidDecl())
281     OS << " invalid";
282   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
283     if (FD->isConstexprSpecified())
284       OS << " constexpr";
285     if (FD->isConsteval())
286       OS << " consteval";
287     else if (FD->isImmediateFunction())
288       OS << " immediate";
289     if (FD->isMultiVersion())
290       OS << " multiversion";
291   }
292 
293   if (!isa<FunctionDecl>(*D)) {
294     const auto *MD = dyn_cast<ObjCMethodDecl>(D);
295     if (!MD || !MD->isThisDeclarationADefinition()) {
296       const auto *DC = dyn_cast<DeclContext>(D);
297       if (DC && DC->hasExternalLexicalStorage()) {
298         ColorScope Color(OS, ShowColors, UndeserializedColor);
299         OS << " <undeserialized declarations>";
300       }
301     }
302   }
303 
304   switch (D->getFriendObjectKind()) {
305   case Decl::FOK_None:
306     break;
307   case Decl::FOK_Declared:
308     OS << " friend";
309     break;
310   case Decl::FOK_Undeclared:
311     OS << " friend_undeclared";
312     break;
313   }
314 
315   ConstDeclVisitor<TextNodeDumper>::Visit(D);
316 }
317 
318 void TextNodeDumper::Visit(const CXXCtorInitializer *Init) {
319   OS << "CXXCtorInitializer";
320   if (Init->isAnyMemberInitializer()) {
321     OS << ' ';
322     dumpBareDeclRef(Init->getAnyMember());
323   } else if (Init->isBaseInitializer()) {
324     dumpType(QualType(Init->getBaseClass(), 0));
325   } else if (Init->isDelegatingInitializer()) {
326     dumpType(Init->getTypeSourceInfo()->getType());
327   } else {
328     llvm_unreachable("Unknown initializer type");
329   }
330 }
331 
332 void TextNodeDumper::Visit(const BlockDecl::Capture &C) {
333   OS << "capture";
334   if (C.isByRef())
335     OS << " byref";
336   if (C.isNested())
337     OS << " nested";
338   if (C.getVariable()) {
339     OS << ' ';
340     dumpBareDeclRef(C.getVariable());
341   }
342 }
343 
344 void TextNodeDumper::Visit(const OMPClause *C) {
345   if (!C) {
346     ColorScope Color(OS, ShowColors, NullColor);
347     OS << "<<<NULL>>> OMPClause";
348     return;
349   }
350   {
351     ColorScope Color(OS, ShowColors, AttrColor);
352     StringRef ClauseName(llvm::omp::getOpenMPClauseName(C->getClauseKind()));
353     OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper()
354        << ClauseName.drop_front() << "Clause";
355   }
356   dumpPointer(C);
357   dumpSourceRange(SourceRange(C->getBeginLoc(), C->getEndLoc()));
358   if (C->isImplicit())
359     OS << " <implicit>";
360 }
361 
362 void TextNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) {
363   const TypeSourceInfo *TSI = A.getTypeSourceInfo();
364   if (TSI) {
365     OS << "case ";
366     dumpType(TSI->getType());
367   } else {
368     OS << "default";
369   }
370 
371   if (A.isSelected())
372     OS << " selected";
373 }
374 
375 void TextNodeDumper::Visit(const ConceptReference *R) {
376   if (!R) {
377     ColorScope Color(OS, ShowColors, NullColor);
378     OS << "<<<NULL>>> ConceptReference";
379     return;
380   }
381 
382   OS << "ConceptReference";
383   dumpPointer(R);
384   dumpSourceRange(R->getSourceRange());
385   OS << ' ';
386   dumpBareDeclRef(R->getNamedConcept());
387 }
388 
389 void TextNodeDumper::Visit(const concepts::Requirement *R) {
390   if (!R) {
391     ColorScope Color(OS, ShowColors, NullColor);
392     OS << "<<<NULL>>> Requirement";
393     return;
394   }
395 
396   {
397     ColorScope Color(OS, ShowColors, StmtColor);
398     switch (R->getKind()) {
399     case concepts::Requirement::RK_Type:
400       OS << "TypeRequirement";
401       break;
402     case concepts::Requirement::RK_Simple:
403       OS << "SimpleRequirement";
404       break;
405     case concepts::Requirement::RK_Compound:
406       OS << "CompoundRequirement";
407       break;
408     case concepts::Requirement::RK_Nested:
409       OS << "NestedRequirement";
410       break;
411     }
412   }
413 
414   dumpPointer(R);
415 
416   if (auto *ER = dyn_cast<concepts::ExprRequirement>(R)) {
417     if (ER->hasNoexceptRequirement())
418       OS << " noexcept";
419   }
420 
421   if (R->isDependent())
422     OS << " dependent";
423   else
424     OS << (R->isSatisfied() ? " satisfied" : " unsatisfied");
425   if (R->containsUnexpandedParameterPack())
426     OS << " contains_unexpanded_pack";
427 }
428 
429 static double GetApproxValue(const llvm::APFloat &F) {
430   llvm::APFloat V = F;
431   bool ignored;
432   V.convert(llvm::APFloat::IEEEdouble(), llvm::APFloat::rmNearestTiesToEven,
433             &ignored);
434   return V.convertToDouble();
435 }
436 
437 /// True if the \p APValue \p Value can be folded onto the current line.
438 static bool isSimpleAPValue(const APValue &Value) {
439   switch (Value.getKind()) {
440   case APValue::None:
441   case APValue::Indeterminate:
442   case APValue::Int:
443   case APValue::Float:
444   case APValue::FixedPoint:
445   case APValue::ComplexInt:
446   case APValue::ComplexFloat:
447   case APValue::LValue:
448   case APValue::MemberPointer:
449   case APValue::AddrLabelDiff:
450     return true;
451   case APValue::Vector:
452   case APValue::Array:
453   case APValue::Struct:
454     return false;
455   case APValue::Union:
456     return isSimpleAPValue(Value.getUnionValue());
457   }
458   llvm_unreachable("unexpected APValue kind!");
459 }
460 
461 /// Dump the children of the \p APValue \p Value.
462 ///
463 /// \param[in] Value          The \p APValue to visit
464 /// \param[in] Ty             The \p QualType passed to \p Visit
465 ///
466 /// \param[in] IdxToChildFun  A function mapping an \p APValue and an index
467 ///                           to one of the child of the \p APValue
468 ///
469 /// \param[in] NumChildren    \p IdxToChildFun will be called on \p Value with
470 ///                           the indices in the range \p [0,NumChildren(
471 ///
472 /// \param[in] LabelSingular  The label to use on a line with a single child
473 /// \param[in] LabelPlurial   The label to use on a line with multiple children
474 void TextNodeDumper::dumpAPValueChildren(
475     const APValue &Value, QualType Ty,
476     const APValue &(*IdxToChildFun)(const APValue &, unsigned),
477     unsigned NumChildren, StringRef LabelSingular, StringRef LabelPlurial) {
478   // To save some vertical space we print up to MaxChildrenPerLine APValues
479   // considered to be simple (by isSimpleAPValue) on a single line.
480   constexpr unsigned MaxChildrenPerLine = 4;
481   unsigned I = 0;
482   while (I < NumChildren) {
483     unsigned J = I;
484     while (J < NumChildren) {
485       if (isSimpleAPValue(IdxToChildFun(Value, J)) &&
486           (J - I < MaxChildrenPerLine)) {
487         ++J;
488         continue;
489       }
490       break;
491     }
492 
493     J = std::max(I + 1, J);
494 
495     // Print [I,J) on a single line.
496     AddChild(J - I > 1 ? LabelPlurial : LabelSingular, [=]() {
497       for (unsigned X = I; X < J; ++X) {
498         Visit(IdxToChildFun(Value, X), Ty);
499         if (X + 1 != J)
500           OS << ", ";
501       }
502     });
503     I = J;
504   }
505 }
506 
507 void TextNodeDumper::Visit(const APValue &Value, QualType Ty) {
508   ColorScope Color(OS, ShowColors, ValueKindColor);
509   switch (Value.getKind()) {
510   case APValue::None:
511     OS << "None";
512     return;
513   case APValue::Indeterminate:
514     OS << "Indeterminate";
515     return;
516   case APValue::Int:
517     OS << "Int ";
518     {
519       ColorScope Color(OS, ShowColors, ValueColor);
520       OS << Value.getInt();
521     }
522     return;
523   case APValue::Float:
524     OS << "Float ";
525     {
526       ColorScope Color(OS, ShowColors, ValueColor);
527       OS << GetApproxValue(Value.getFloat());
528     }
529     return;
530   case APValue::FixedPoint:
531     OS << "FixedPoint ";
532     {
533       ColorScope Color(OS, ShowColors, ValueColor);
534       OS << Value.getFixedPoint();
535     }
536     return;
537   case APValue::Vector: {
538     unsigned VectorLength = Value.getVectorLength();
539     OS << "Vector length=" << VectorLength;
540 
541     dumpAPValueChildren(
542         Value, Ty,
543         [](const APValue &Value, unsigned Index) -> const APValue & {
544           return Value.getVectorElt(Index);
545         },
546         VectorLength, "element", "elements");
547     return;
548   }
549   case APValue::ComplexInt:
550     OS << "ComplexInt ";
551     {
552       ColorScope Color(OS, ShowColors, ValueColor);
553       OS << Value.getComplexIntReal() << " + " << Value.getComplexIntImag()
554          << 'i';
555     }
556     return;
557   case APValue::ComplexFloat:
558     OS << "ComplexFloat ";
559     {
560       ColorScope Color(OS, ShowColors, ValueColor);
561       OS << GetApproxValue(Value.getComplexFloatReal()) << " + "
562          << GetApproxValue(Value.getComplexFloatImag()) << 'i';
563     }
564     return;
565   case APValue::LValue:
566     (void)Context;
567     OS << "LValue <todo>";
568     return;
569   case APValue::Array: {
570     unsigned ArraySize = Value.getArraySize();
571     unsigned NumInitializedElements = Value.getArrayInitializedElts();
572     OS << "Array size=" << ArraySize;
573 
574     dumpAPValueChildren(
575         Value, Ty,
576         [](const APValue &Value, unsigned Index) -> const APValue & {
577           return Value.getArrayInitializedElt(Index);
578         },
579         NumInitializedElements, "element", "elements");
580 
581     if (Value.hasArrayFiller()) {
582       AddChild("filler", [=] {
583         {
584           ColorScope Color(OS, ShowColors, ValueColor);
585           OS << ArraySize - NumInitializedElements << " x ";
586         }
587         Visit(Value.getArrayFiller(), Ty);
588       });
589     }
590 
591     return;
592   }
593   case APValue::Struct: {
594     OS << "Struct";
595 
596     dumpAPValueChildren(
597         Value, Ty,
598         [](const APValue &Value, unsigned Index) -> const APValue & {
599           return Value.getStructBase(Index);
600         },
601         Value.getStructNumBases(), "base", "bases");
602 
603     dumpAPValueChildren(
604         Value, Ty,
605         [](const APValue &Value, unsigned Index) -> const APValue & {
606           return Value.getStructField(Index);
607         },
608         Value.getStructNumFields(), "field", "fields");
609 
610     return;
611   }
612   case APValue::Union: {
613     OS << "Union";
614     {
615       ColorScope Color(OS, ShowColors, ValueColor);
616       if (const FieldDecl *FD = Value.getUnionField())
617         OS << " ." << *cast<NamedDecl>(FD);
618     }
619     // If the union value is considered to be simple, fold it into the
620     // current line to save some vertical space.
621     const APValue &UnionValue = Value.getUnionValue();
622     if (isSimpleAPValue(UnionValue)) {
623       OS << ' ';
624       Visit(UnionValue, Ty);
625     } else {
626       AddChild([=] { Visit(UnionValue, Ty); });
627     }
628 
629     return;
630   }
631   case APValue::MemberPointer:
632     OS << "MemberPointer <todo>";
633     return;
634   case APValue::AddrLabelDiff:
635     OS << "AddrLabelDiff <todo>";
636     return;
637   }
638   llvm_unreachable("Unknown APValue kind!");
639 }
640 
641 void TextNodeDumper::dumpPointer(const void *Ptr) {
642   ColorScope Color(OS, ShowColors, AddressColor);
643   OS << ' ' << Ptr;
644 }
645 
646 void TextNodeDumper::dumpLocation(SourceLocation Loc) {
647   if (!SM)
648     return;
649 
650   ColorScope Color(OS, ShowColors, LocationColor);
651   SourceLocation SpellingLoc = SM->getSpellingLoc(Loc);
652 
653   // The general format we print out is filename:line:col, but we drop pieces
654   // that haven't changed since the last loc printed.
655   PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc);
656 
657   if (PLoc.isInvalid()) {
658     OS << "<invalid sloc>";
659     return;
660   }
661 
662   if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) {
663     OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':'
664        << PLoc.getColumn();
665     LastLocFilename = PLoc.getFilename();
666     LastLocLine = PLoc.getLine();
667   } else if (PLoc.getLine() != LastLocLine) {
668     OS << "line" << ':' << PLoc.getLine() << ':' << PLoc.getColumn();
669     LastLocLine = PLoc.getLine();
670   } else {
671     OS << "col" << ':' << PLoc.getColumn();
672   }
673 }
674 
675 void TextNodeDumper::dumpSourceRange(SourceRange R) {
676   // Can't translate locations if a SourceManager isn't available.
677   if (!SM)
678     return;
679 
680   OS << " <";
681   dumpLocation(R.getBegin());
682   if (R.getBegin() != R.getEnd()) {
683     OS << ", ";
684     dumpLocation(R.getEnd());
685   }
686   OS << ">";
687 
688   // <t2.c:123:421[blah], t2.c:412:321>
689 }
690 
691 void TextNodeDumper::dumpBareType(QualType T, bool Desugar) {
692   ColorScope Color(OS, ShowColors, TypeColor);
693 
694   SplitQualType T_split = T.split();
695   std::string T_str = QualType::getAsString(T_split, PrintPolicy);
696   OS << "'" << T_str << "'";
697 
698   if (Desugar && !T.isNull()) {
699     // If the type is sugared, also dump a (shallow) desugared type when
700     // it is visibly different.
701     SplitQualType D_split = T.getSplitDesugaredType();
702     if (T_split != D_split) {
703       std::string D_str = QualType::getAsString(D_split, PrintPolicy);
704       if (T_str != D_str)
705         OS << ":'" << QualType::getAsString(D_split, PrintPolicy) << "'";
706     }
707   }
708 }
709 
710 void TextNodeDumper::dumpType(QualType T) {
711   OS << ' ';
712   dumpBareType(T);
713 }
714 
715 void TextNodeDumper::dumpBareDeclRef(const Decl *D) {
716   if (!D) {
717     ColorScope Color(OS, ShowColors, NullColor);
718     OS << "<<<NULL>>>";
719     return;
720   }
721 
722   {
723     ColorScope Color(OS, ShowColors, DeclKindNameColor);
724     OS << D->getDeclKindName();
725   }
726   dumpPointer(D);
727 
728   if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
729     ColorScope Color(OS, ShowColors, DeclNameColor);
730     OS << " '" << ND->getDeclName() << '\'';
731   }
732 
733   if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
734     dumpType(VD->getType());
735 }
736 
737 void TextNodeDumper::dumpName(const NamedDecl *ND) {
738   if (ND->getDeclName()) {
739     ColorScope Color(OS, ShowColors, DeclNameColor);
740     OS << ' ' << ND->getDeclName();
741   }
742 }
743 
744 void TextNodeDumper::dumpAccessSpecifier(AccessSpecifier AS) {
745   const auto AccessSpelling = getAccessSpelling(AS);
746   if (AccessSpelling.empty())
747     return;
748   OS << AccessSpelling;
749 }
750 
751 void TextNodeDumper::dumpCleanupObject(
752     const ExprWithCleanups::CleanupObject &C) {
753   if (auto *BD = C.dyn_cast<BlockDecl *>())
754     dumpDeclRef(BD, "cleanup");
755   else if (auto *CLE = C.dyn_cast<CompoundLiteralExpr *>())
756     AddChild([=] {
757       OS << "cleanup ";
758       {
759         ColorScope Color(OS, ShowColors, StmtColor);
760         OS << CLE->getStmtClassName();
761       }
762       dumpPointer(CLE);
763     });
764   else
765     llvm_unreachable("unexpected cleanup type");
766 }
767 
768 void clang::TextNodeDumper::dumpTemplateSpecializationKind(
769     TemplateSpecializationKind TSK) {
770   switch (TSK) {
771   case TSK_Undeclared:
772     break;
773   case TSK_ImplicitInstantiation:
774     OS << " implicit_instantiation";
775     break;
776   case TSK_ExplicitSpecialization:
777     OS << " explicit_specialization";
778     break;
779   case TSK_ExplicitInstantiationDeclaration:
780     OS << " explicit_instantiation_declaration";
781     break;
782   case TSK_ExplicitInstantiationDefinition:
783     OS << " explicit_instantiation_definition";
784     break;
785   }
786 }
787 
788 void clang::TextNodeDumper::dumpNestedNameSpecifier(const NestedNameSpecifier *NNS) {
789   if (!NNS)
790     return;
791 
792   AddChild([=] {
793     OS << "NestedNameSpecifier";
794 
795     switch (NNS->getKind()) {
796     case NestedNameSpecifier::Identifier:
797       OS << " Identifier";
798       OS << " '" << NNS->getAsIdentifier()->getName() << "'";
799       break;
800     case NestedNameSpecifier::Namespace:
801       OS << " "; // "Namespace" is printed as the decl kind.
802       dumpBareDeclRef(NNS->getAsNamespace());
803       break;
804     case NestedNameSpecifier::NamespaceAlias:
805       OS << " "; // "NamespaceAlias" is printed as the decl kind.
806       dumpBareDeclRef(NNS->getAsNamespaceAlias());
807       break;
808     case NestedNameSpecifier::TypeSpec:
809       OS << " TypeSpec";
810       dumpType(QualType(NNS->getAsType(), 0));
811       break;
812     case NestedNameSpecifier::TypeSpecWithTemplate:
813       OS << " TypeSpecWithTemplate";
814       dumpType(QualType(NNS->getAsType(), 0));
815       break;
816     case NestedNameSpecifier::Global:
817       OS << " Global";
818       break;
819     case NestedNameSpecifier::Super:
820       OS << " Super";
821       break;
822     }
823 
824     dumpNestedNameSpecifier(NNS->getPrefix());
825   });
826 }
827 
828 void TextNodeDumper::dumpDeclRef(const Decl *D, StringRef Label) {
829   if (!D)
830     return;
831 
832   AddChild([=] {
833     if (!Label.empty())
834       OS << Label << ' ';
835     dumpBareDeclRef(D);
836   });
837 }
838 
839 const char *TextNodeDumper::getCommandName(unsigned CommandID) {
840   if (Traits)
841     return Traits->getCommandInfo(CommandID)->Name;
842   const comments::CommandInfo *Info =
843       comments::CommandTraits::getBuiltinCommandInfo(CommandID);
844   if (Info)
845     return Info->Name;
846   return "<not a builtin command>";
847 }
848 
849 void TextNodeDumper::printFPOptions(FPOptionsOverride FPO) {
850 #define OPTION(NAME, TYPE, WIDTH, PREVIOUS)                                    \
851   if (FPO.has##NAME##Override())                                               \
852     OS << " " #NAME "=" << FPO.get##NAME##Override();
853 #include "clang/Basic/FPOptions.def"
854 }
855 
856 void TextNodeDumper::visitTextComment(const comments::TextComment *C,
857                                       const comments::FullComment *) {
858   OS << " Text=\"" << C->getText() << "\"";
859 }
860 
861 void TextNodeDumper::visitInlineCommandComment(
862     const comments::InlineCommandComment *C, const comments::FullComment *) {
863   OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
864   switch (C->getRenderKind()) {
865   case comments::InlineCommandRenderKind::Normal:
866     OS << " RenderNormal";
867     break;
868   case comments::InlineCommandRenderKind::Bold:
869     OS << " RenderBold";
870     break;
871   case comments::InlineCommandRenderKind::Monospaced:
872     OS << " RenderMonospaced";
873     break;
874   case comments::InlineCommandRenderKind::Emphasized:
875     OS << " RenderEmphasized";
876     break;
877   case comments::InlineCommandRenderKind::Anchor:
878     OS << " RenderAnchor";
879     break;
880   }
881 
882   for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
883     OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
884 }
885 
886 void TextNodeDumper::visitHTMLStartTagComment(
887     const comments::HTMLStartTagComment *C, const comments::FullComment *) {
888   OS << " Name=\"" << C->getTagName() << "\"";
889   if (C->getNumAttrs() != 0) {
890     OS << " Attrs: ";
891     for (unsigned i = 0, e = C->getNumAttrs(); i != e; ++i) {
892       const comments::HTMLStartTagComment::Attribute &Attr = C->getAttr(i);
893       OS << " \"" << Attr.Name << "=\"" << Attr.Value << "\"";
894     }
895   }
896   if (C->isSelfClosing())
897     OS << " SelfClosing";
898 }
899 
900 void TextNodeDumper::visitHTMLEndTagComment(
901     const comments::HTMLEndTagComment *C, const comments::FullComment *) {
902   OS << " Name=\"" << C->getTagName() << "\"";
903 }
904 
905 void TextNodeDumper::visitBlockCommandComment(
906     const comments::BlockCommandComment *C, const comments::FullComment *) {
907   OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
908   for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
909     OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
910 }
911 
912 void TextNodeDumper::visitParamCommandComment(
913     const comments::ParamCommandComment *C, const comments::FullComment *FC) {
914   OS << " "
915      << comments::ParamCommandComment::getDirectionAsString(C->getDirection());
916 
917   if (C->isDirectionExplicit())
918     OS << " explicitly";
919   else
920     OS << " implicitly";
921 
922   if (C->hasParamName()) {
923     if (C->isParamIndexValid())
924       OS << " Param=\"" << C->getParamName(FC) << "\"";
925     else
926       OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
927   }
928 
929   if (C->isParamIndexValid() && !C->isVarArgParam())
930     OS << " ParamIndex=" << C->getParamIndex();
931 }
932 
933 void TextNodeDumper::visitTParamCommandComment(
934     const comments::TParamCommandComment *C, const comments::FullComment *FC) {
935   if (C->hasParamName()) {
936     if (C->isPositionValid())
937       OS << " Param=\"" << C->getParamName(FC) << "\"";
938     else
939       OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
940   }
941 
942   if (C->isPositionValid()) {
943     OS << " Position=<";
944     for (unsigned i = 0, e = C->getDepth(); i != e; ++i) {
945       OS << C->getIndex(i);
946       if (i != e - 1)
947         OS << ", ";
948     }
949     OS << ">";
950   }
951 }
952 
953 void TextNodeDumper::visitVerbatimBlockComment(
954     const comments::VerbatimBlockComment *C, const comments::FullComment *) {
955   OS << " Name=\"" << getCommandName(C->getCommandID())
956      << "\""
957         " CloseName=\""
958      << C->getCloseName() << "\"";
959 }
960 
961 void TextNodeDumper::visitVerbatimBlockLineComment(
962     const comments::VerbatimBlockLineComment *C,
963     const comments::FullComment *) {
964   OS << " Text=\"" << C->getText() << "\"";
965 }
966 
967 void TextNodeDumper::visitVerbatimLineComment(
968     const comments::VerbatimLineComment *C, const comments::FullComment *) {
969   OS << " Text=\"" << C->getText() << "\"";
970 }
971 
972 void TextNodeDumper::VisitNullTemplateArgument(const TemplateArgument &) {
973   OS << " null";
974 }
975 
976 void TextNodeDumper::VisitTypeTemplateArgument(const TemplateArgument &TA) {
977   OS << " type";
978   dumpType(TA.getAsType());
979 }
980 
981 void TextNodeDumper::VisitDeclarationTemplateArgument(
982     const TemplateArgument &TA) {
983   OS << " decl";
984   dumpDeclRef(TA.getAsDecl());
985 }
986 
987 void TextNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument &) {
988   OS << " nullptr";
989 }
990 
991 void TextNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) {
992   OS << " integral " << TA.getAsIntegral();
993 }
994 
995 void TextNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) {
996   if (TA.getAsTemplate().getKind() == TemplateName::UsingTemplate)
997     OS << " using";
998   OS << " template ";
999   TA.getAsTemplate().dump(OS);
1000 }
1001 
1002 void TextNodeDumper::VisitTemplateExpansionTemplateArgument(
1003     const TemplateArgument &TA) {
1004   if (TA.getAsTemplateOrTemplatePattern().getKind() ==
1005       TemplateName::UsingTemplate)
1006     OS << " using";
1007   OS << " template expansion ";
1008   TA.getAsTemplateOrTemplatePattern().dump(OS);
1009 }
1010 
1011 void TextNodeDumper::VisitExpressionTemplateArgument(const TemplateArgument &) {
1012   OS << " expr";
1013 }
1014 
1015 void TextNodeDumper::VisitPackTemplateArgument(const TemplateArgument &) {
1016   OS << " pack";
1017 }
1018 
1019 static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) {
1020   if (Node->path_empty())
1021     return;
1022 
1023   OS << " (";
1024   bool First = true;
1025   for (CastExpr::path_const_iterator I = Node->path_begin(),
1026                                      E = Node->path_end();
1027        I != E; ++I) {
1028     const CXXBaseSpecifier *Base = *I;
1029     if (!First)
1030       OS << " -> ";
1031 
1032     const auto *RD =
1033         cast<CXXRecordDecl>(Base->getType()->castAs<RecordType>()->getDecl());
1034 
1035     if (Base->isVirtual())
1036       OS << "virtual ";
1037     OS << RD->getName();
1038     First = false;
1039   }
1040 
1041   OS << ')';
1042 }
1043 
1044 void TextNodeDumper::VisitIfStmt(const IfStmt *Node) {
1045   if (Node->hasInitStorage())
1046     OS << " has_init";
1047   if (Node->hasVarStorage())
1048     OS << " has_var";
1049   if (Node->hasElseStorage())
1050     OS << " has_else";
1051   if (Node->isConstexpr())
1052     OS << " constexpr";
1053   if (Node->isConsteval()) {
1054     OS << " ";
1055     if (Node->isNegatedConsteval())
1056       OS << "!";
1057     OS << "consteval";
1058   }
1059 }
1060 
1061 void TextNodeDumper::VisitSwitchStmt(const SwitchStmt *Node) {
1062   if (Node->hasInitStorage())
1063     OS << " has_init";
1064   if (Node->hasVarStorage())
1065     OS << " has_var";
1066 }
1067 
1068 void TextNodeDumper::VisitWhileStmt(const WhileStmt *Node) {
1069   if (Node->hasVarStorage())
1070     OS << " has_var";
1071 }
1072 
1073 void TextNodeDumper::VisitLabelStmt(const LabelStmt *Node) {
1074   OS << " '" << Node->getName() << "'";
1075   if (Node->isSideEntry())
1076     OS << " side_entry";
1077 }
1078 
1079 void TextNodeDumper::VisitGotoStmt(const GotoStmt *Node) {
1080   OS << " '" << Node->getLabel()->getName() << "'";
1081   dumpPointer(Node->getLabel());
1082 }
1083 
1084 void TextNodeDumper::VisitCaseStmt(const CaseStmt *Node) {
1085   if (Node->caseStmtIsGNURange())
1086     OS << " gnu_range";
1087 }
1088 
1089 void clang::TextNodeDumper::VisitReturnStmt(const ReturnStmt *Node) {
1090   if (const VarDecl *Cand = Node->getNRVOCandidate()) {
1091     OS << " nrvo_candidate(";
1092     dumpBareDeclRef(Cand);
1093     OS << ")";
1094   }
1095 }
1096 
1097 void clang::TextNodeDumper::VisitCoawaitExpr(const CoawaitExpr *Node) {
1098   if (Node->isImplicit())
1099     OS << " implicit";
1100 }
1101 
1102 void clang::TextNodeDumper::VisitCoreturnStmt(const CoreturnStmt *Node) {
1103   if (Node->isImplicit())
1104     OS << " implicit";
1105 }
1106 
1107 void TextNodeDumper::VisitConstantExpr(const ConstantExpr *Node) {
1108   if (Node->hasAPValueResult())
1109     AddChild("value",
1110              [=] { Visit(Node->getAPValueResult(), Node->getType()); });
1111 }
1112 
1113 void TextNodeDumper::VisitCallExpr(const CallExpr *Node) {
1114   if (Node->usesADL())
1115     OS << " adl";
1116   if (Node->hasStoredFPFeatures())
1117     printFPOptions(Node->getFPFeatures());
1118 }
1119 
1120 void TextNodeDumper::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Node) {
1121   const char *OperatorSpelling = clang::getOperatorSpelling(Node->getOperator());
1122   if (OperatorSpelling)
1123     OS << " '" << OperatorSpelling << "'";
1124 
1125   VisitCallExpr(Node);
1126 }
1127 
1128 void TextNodeDumper::VisitCastExpr(const CastExpr *Node) {
1129   OS << " <";
1130   {
1131     ColorScope Color(OS, ShowColors, CastColor);
1132     OS << Node->getCastKindName();
1133   }
1134   dumpBasePath(OS, Node);
1135   OS << ">";
1136   if (Node->hasStoredFPFeatures())
1137     printFPOptions(Node->getFPFeatures());
1138 }
1139 
1140 void TextNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *Node) {
1141   VisitCastExpr(Node);
1142   if (Node->isPartOfExplicitCast())
1143     OS << " part_of_explicit_cast";
1144 }
1145 
1146 void TextNodeDumper::VisitDeclRefExpr(const DeclRefExpr *Node) {
1147   OS << " ";
1148   dumpBareDeclRef(Node->getDecl());
1149   dumpNestedNameSpecifier(Node->getQualifier());
1150   if (Node->getDecl() != Node->getFoundDecl()) {
1151     OS << " (";
1152     dumpBareDeclRef(Node->getFoundDecl());
1153     OS << ")";
1154   }
1155   switch (Node->isNonOdrUse()) {
1156   case NOUR_None: break;
1157   case NOUR_Unevaluated: OS << " non_odr_use_unevaluated"; break;
1158   case NOUR_Constant: OS << " non_odr_use_constant"; break;
1159   case NOUR_Discarded: OS << " non_odr_use_discarded"; break;
1160   }
1161   if (Node->refersToEnclosingVariableOrCapture())
1162     OS << " refers_to_enclosing_variable_or_capture";
1163   if (Node->isImmediateEscalating())
1164     OS << " immediate-escalating";
1165 }
1166 
1167 void clang::TextNodeDumper::VisitDependentScopeDeclRefExpr(
1168     const DependentScopeDeclRefExpr *Node) {
1169 
1170   dumpNestedNameSpecifier(Node->getQualifier());
1171 }
1172 
1173 void TextNodeDumper::VisitUnresolvedLookupExpr(
1174     const UnresolvedLookupExpr *Node) {
1175   OS << " (";
1176   if (!Node->requiresADL())
1177     OS << "no ";
1178   OS << "ADL) = '" << Node->getName() << '\'';
1179 
1180   UnresolvedLookupExpr::decls_iterator I = Node->decls_begin(),
1181                                        E = Node->decls_end();
1182   if (I == E)
1183     OS << " empty";
1184   for (; I != E; ++I)
1185     dumpPointer(*I);
1186 }
1187 
1188 void TextNodeDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) {
1189   {
1190     ColorScope Color(OS, ShowColors, DeclKindNameColor);
1191     OS << " " << Node->getDecl()->getDeclKindName() << "Decl";
1192   }
1193   OS << "='" << *Node->getDecl() << "'";
1194   dumpPointer(Node->getDecl());
1195   if (Node->isFreeIvar())
1196     OS << " isFreeIvar";
1197 }
1198 
1199 void TextNodeDumper::VisitSYCLUniqueStableNameExpr(
1200     const SYCLUniqueStableNameExpr *Node) {
1201   dumpType(Node->getTypeSourceInfo()->getType());
1202 }
1203 
1204 void TextNodeDumper::VisitPredefinedExpr(const PredefinedExpr *Node) {
1205   OS << " " << PredefinedExpr::getIdentKindName(Node->getIdentKind());
1206 }
1207 
1208 void TextNodeDumper::VisitCharacterLiteral(const CharacterLiteral *Node) {
1209   ColorScope Color(OS, ShowColors, ValueColor);
1210   OS << " " << Node->getValue();
1211 }
1212 
1213 void TextNodeDumper::VisitIntegerLiteral(const IntegerLiteral *Node) {
1214   bool isSigned = Node->getType()->isSignedIntegerType();
1215   ColorScope Color(OS, ShowColors, ValueColor);
1216   OS << " " << toString(Node->getValue(), 10, isSigned);
1217 }
1218 
1219 void TextNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *Node) {
1220   ColorScope Color(OS, ShowColors, ValueColor);
1221   OS << " " << Node->getValueAsString(/*Radix=*/10);
1222 }
1223 
1224 void TextNodeDumper::VisitFloatingLiteral(const FloatingLiteral *Node) {
1225   ColorScope Color(OS, ShowColors, ValueColor);
1226   OS << " " << Node->getValueAsApproximateDouble();
1227 }
1228 
1229 void TextNodeDumper::VisitStringLiteral(const StringLiteral *Str) {
1230   ColorScope Color(OS, ShowColors, ValueColor);
1231   OS << " ";
1232   Str->outputString(OS);
1233 }
1234 
1235 void TextNodeDumper::VisitInitListExpr(const InitListExpr *ILE) {
1236   if (auto *Field = ILE->getInitializedFieldInUnion()) {
1237     OS << " field ";
1238     dumpBareDeclRef(Field);
1239   }
1240 }
1241 
1242 void TextNodeDumper::VisitGenericSelectionExpr(const GenericSelectionExpr *E) {
1243   if (E->isResultDependent())
1244     OS << " result_dependent";
1245 }
1246 
1247 void TextNodeDumper::VisitUnaryOperator(const UnaryOperator *Node) {
1248   OS << " " << (Node->isPostfix() ? "postfix" : "prefix") << " '"
1249      << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
1250   if (!Node->canOverflow())
1251     OS << " cannot overflow";
1252   if (Node->hasStoredFPFeatures())
1253     printFPOptions(Node->getStoredFPFeatures());
1254 }
1255 
1256 void TextNodeDumper::VisitUnaryExprOrTypeTraitExpr(
1257     const UnaryExprOrTypeTraitExpr *Node) {
1258   OS << " " << getTraitSpelling(Node->getKind());
1259 
1260   if (Node->isArgumentType())
1261     dumpType(Node->getArgumentType());
1262 }
1263 
1264 void TextNodeDumper::VisitMemberExpr(const MemberExpr *Node) {
1265   OS << " " << (Node->isArrow() ? "->" : ".") << *Node->getMemberDecl();
1266   dumpPointer(Node->getMemberDecl());
1267   dumpNestedNameSpecifier(Node->getQualifier());
1268   switch (Node->isNonOdrUse()) {
1269   case NOUR_None: break;
1270   case NOUR_Unevaluated: OS << " non_odr_use_unevaluated"; break;
1271   case NOUR_Constant: OS << " non_odr_use_constant"; break;
1272   case NOUR_Discarded: OS << " non_odr_use_discarded"; break;
1273   }
1274 }
1275 
1276 void TextNodeDumper::VisitExtVectorElementExpr(
1277     const ExtVectorElementExpr *Node) {
1278   OS << " " << Node->getAccessor().getNameStart();
1279 }
1280 
1281 void TextNodeDumper::VisitBinaryOperator(const BinaryOperator *Node) {
1282   OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
1283   if (Node->hasStoredFPFeatures())
1284     printFPOptions(Node->getStoredFPFeatures());
1285 }
1286 
1287 void TextNodeDumper::VisitCompoundAssignOperator(
1288     const CompoundAssignOperator *Node) {
1289   OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode())
1290      << "' ComputeLHSTy=";
1291   dumpBareType(Node->getComputationLHSType());
1292   OS << " ComputeResultTy=";
1293   dumpBareType(Node->getComputationResultType());
1294   if (Node->hasStoredFPFeatures())
1295     printFPOptions(Node->getStoredFPFeatures());
1296 }
1297 
1298 void TextNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) {
1299   OS << " " << Node->getLabel()->getName();
1300   dumpPointer(Node->getLabel());
1301 }
1302 
1303 void TextNodeDumper::VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node) {
1304   OS << " " << Node->getCastName() << "<"
1305      << Node->getTypeAsWritten().getAsString() << ">"
1306      << " <" << Node->getCastKindName();
1307   dumpBasePath(OS, Node);
1308   OS << ">";
1309 }
1310 
1311 void TextNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node) {
1312   OS << " " << (Node->getValue() ? "true" : "false");
1313 }
1314 
1315 void TextNodeDumper::VisitCXXThisExpr(const CXXThisExpr *Node) {
1316   if (Node->isImplicit())
1317     OS << " implicit";
1318   OS << " this";
1319 }
1320 
1321 void TextNodeDumper::VisitCXXFunctionalCastExpr(
1322     const CXXFunctionalCastExpr *Node) {
1323   OS << " functional cast to " << Node->getTypeAsWritten().getAsString() << " <"
1324      << Node->getCastKindName() << ">";
1325   if (Node->hasStoredFPFeatures())
1326     printFPOptions(Node->getFPFeatures());
1327 }
1328 
1329 void TextNodeDumper::VisitCXXStaticCastExpr(const CXXStaticCastExpr *Node) {
1330   VisitCXXNamedCastExpr(Node);
1331   if (Node->hasStoredFPFeatures())
1332     printFPOptions(Node->getFPFeatures());
1333 }
1334 
1335 void TextNodeDumper::VisitCXXUnresolvedConstructExpr(
1336     const CXXUnresolvedConstructExpr *Node) {
1337   dumpType(Node->getTypeAsWritten());
1338   if (Node->isListInitialization())
1339     OS << " list";
1340 }
1341 
1342 void TextNodeDumper::VisitCXXConstructExpr(const CXXConstructExpr *Node) {
1343   CXXConstructorDecl *Ctor = Node->getConstructor();
1344   dumpType(Ctor->getType());
1345   if (Node->isElidable())
1346     OS << " elidable";
1347   if (Node->isListInitialization())
1348     OS << " list";
1349   if (Node->isStdInitListInitialization())
1350     OS << " std::initializer_list";
1351   if (Node->requiresZeroInitialization())
1352     OS << " zeroing";
1353   if (Node->isImmediateEscalating())
1354     OS << " immediate-escalating";
1355 }
1356 
1357 void TextNodeDumper::VisitCXXBindTemporaryExpr(
1358     const CXXBindTemporaryExpr *Node) {
1359   OS << " (CXXTemporary";
1360   dumpPointer(Node);
1361   OS << ")";
1362 }
1363 
1364 void TextNodeDumper::VisitCXXNewExpr(const CXXNewExpr *Node) {
1365   if (Node->isGlobalNew())
1366     OS << " global";
1367   if (Node->isArray())
1368     OS << " array";
1369   if (Node->getOperatorNew()) {
1370     OS << ' ';
1371     dumpBareDeclRef(Node->getOperatorNew());
1372   }
1373   // We could dump the deallocation function used in case of error, but it's
1374   // usually not that interesting.
1375 }
1376 
1377 void TextNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *Node) {
1378   if (Node->isGlobalDelete())
1379     OS << " global";
1380   if (Node->isArrayForm())
1381     OS << " array";
1382   if (Node->getOperatorDelete()) {
1383     OS << ' ';
1384     dumpBareDeclRef(Node->getOperatorDelete());
1385   }
1386 }
1387 
1388 void TextNodeDumper::VisitTypeTraitExpr(const TypeTraitExpr *Node) {
1389   OS << " " << getTraitSpelling(Node->getTrait());
1390 }
1391 
1392 void TextNodeDumper::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *Node) {
1393   OS << " " << getTraitSpelling(Node->getTrait());
1394 }
1395 
1396 void TextNodeDumper::VisitExpressionTraitExpr(const ExpressionTraitExpr *Node) {
1397   OS << " " << getTraitSpelling(Node->getTrait());
1398 }
1399 
1400 void TextNodeDumper::VisitMaterializeTemporaryExpr(
1401     const MaterializeTemporaryExpr *Node) {
1402   if (const ValueDecl *VD = Node->getExtendingDecl()) {
1403     OS << " extended by ";
1404     dumpBareDeclRef(VD);
1405   }
1406 }
1407 
1408 void TextNodeDumper::VisitExprWithCleanups(const ExprWithCleanups *Node) {
1409   for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i)
1410     dumpCleanupObject(Node->getObject(i));
1411 }
1412 
1413 void TextNodeDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) {
1414   dumpPointer(Node->getPack());
1415   dumpName(Node->getPack());
1416 }
1417 
1418 void TextNodeDumper::VisitCXXDependentScopeMemberExpr(
1419     const CXXDependentScopeMemberExpr *Node) {
1420   OS << " " << (Node->isArrow() ? "->" : ".") << Node->getMember();
1421 }
1422 
1423 void TextNodeDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) {
1424   OS << " selector=";
1425   Node->getSelector().print(OS);
1426   switch (Node->getReceiverKind()) {
1427   case ObjCMessageExpr::Instance:
1428     break;
1429 
1430   case ObjCMessageExpr::Class:
1431     OS << " class=";
1432     dumpBareType(Node->getClassReceiver());
1433     break;
1434 
1435   case ObjCMessageExpr::SuperInstance:
1436     OS << " super (instance)";
1437     break;
1438 
1439   case ObjCMessageExpr::SuperClass:
1440     OS << " super (class)";
1441     break;
1442   }
1443 }
1444 
1445 void TextNodeDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *Node) {
1446   if (auto *BoxingMethod = Node->getBoxingMethod()) {
1447     OS << " selector=";
1448     BoxingMethod->getSelector().print(OS);
1449   }
1450 }
1451 
1452 void TextNodeDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) {
1453   if (!Node->getCatchParamDecl())
1454     OS << " catch all";
1455 }
1456 
1457 void TextNodeDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *Node) {
1458   dumpType(Node->getEncodedType());
1459 }
1460 
1461 void TextNodeDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *Node) {
1462   OS << " ";
1463   Node->getSelector().print(OS);
1464 }
1465 
1466 void TextNodeDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *Node) {
1467   OS << ' ' << *Node->getProtocol();
1468 }
1469 
1470 void TextNodeDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node) {
1471   if (Node->isImplicitProperty()) {
1472     OS << " Kind=MethodRef Getter=\"";
1473     if (Node->getImplicitPropertyGetter())
1474       Node->getImplicitPropertyGetter()->getSelector().print(OS);
1475     else
1476       OS << "(null)";
1477 
1478     OS << "\" Setter=\"";
1479     if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter())
1480       Setter->getSelector().print(OS);
1481     else
1482       OS << "(null)";
1483     OS << "\"";
1484   } else {
1485     OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty()
1486        << '"';
1487   }
1488 
1489   if (Node->isSuperReceiver())
1490     OS << " super";
1491 
1492   OS << " Messaging=";
1493   if (Node->isMessagingGetter() && Node->isMessagingSetter())
1494     OS << "Getter&Setter";
1495   else if (Node->isMessagingGetter())
1496     OS << "Getter";
1497   else if (Node->isMessagingSetter())
1498     OS << "Setter";
1499 }
1500 
1501 void TextNodeDumper::VisitObjCSubscriptRefExpr(
1502     const ObjCSubscriptRefExpr *Node) {
1503   if (Node->isArraySubscriptRefExpr())
1504     OS << " Kind=ArraySubscript GetterForArray=\"";
1505   else
1506     OS << " Kind=DictionarySubscript GetterForDictionary=\"";
1507   if (Node->getAtIndexMethodDecl())
1508     Node->getAtIndexMethodDecl()->getSelector().print(OS);
1509   else
1510     OS << "(null)";
1511 
1512   if (Node->isArraySubscriptRefExpr())
1513     OS << "\" SetterForArray=\"";
1514   else
1515     OS << "\" SetterForDictionary=\"";
1516   if (Node->setAtIndexMethodDecl())
1517     Node->setAtIndexMethodDecl()->getSelector().print(OS);
1518   else
1519     OS << "(null)";
1520 }
1521 
1522 void TextNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node) {
1523   OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no");
1524 }
1525 
1526 void TextNodeDumper::VisitOMPIteratorExpr(const OMPIteratorExpr *Node) {
1527   OS << " ";
1528   for (unsigned I = 0, E = Node->numOfIterators(); I < E; ++I) {
1529     Visit(Node->getIteratorDecl(I));
1530     OS << " = ";
1531     const OMPIteratorExpr::IteratorRange Range = Node->getIteratorRange(I);
1532     OS << " begin ";
1533     Visit(Range.Begin);
1534     OS << " end ";
1535     Visit(Range.End);
1536     if (Range.Step) {
1537       OS << " step ";
1538       Visit(Range.Step);
1539     }
1540   }
1541 }
1542 
1543 void TextNodeDumper::VisitConceptSpecializationExpr(
1544     const ConceptSpecializationExpr *Node) {
1545   OS << " ";
1546   dumpBareDeclRef(Node->getFoundDecl());
1547 }
1548 
1549 void TextNodeDumper::VisitRequiresExpr(
1550     const RequiresExpr *Node) {
1551   if (!Node->isValueDependent())
1552     OS << (Node->isSatisfied() ? " satisfied" : " unsatisfied");
1553 }
1554 
1555 void TextNodeDumper::VisitRValueReferenceType(const ReferenceType *T) {
1556   if (T->isSpelledAsLValue())
1557     OS << " written as lvalue reference";
1558 }
1559 
1560 void TextNodeDumper::VisitArrayType(const ArrayType *T) {
1561   switch (T->getSizeModifier()) {
1562   case ArraySizeModifier::Normal:
1563     break;
1564   case ArraySizeModifier::Static:
1565     OS << " static";
1566     break;
1567   case ArraySizeModifier::Star:
1568     OS << " *";
1569     break;
1570   }
1571   OS << " " << T->getIndexTypeQualifiers().getAsString();
1572 }
1573 
1574 void TextNodeDumper::VisitConstantArrayType(const ConstantArrayType *T) {
1575   OS << " " << T->getSize();
1576   VisitArrayType(T);
1577 }
1578 
1579 void TextNodeDumper::VisitVariableArrayType(const VariableArrayType *T) {
1580   OS << " ";
1581   dumpSourceRange(T->getBracketsRange());
1582   VisitArrayType(T);
1583 }
1584 
1585 void TextNodeDumper::VisitDependentSizedArrayType(
1586     const DependentSizedArrayType *T) {
1587   VisitArrayType(T);
1588   OS << " ";
1589   dumpSourceRange(T->getBracketsRange());
1590 }
1591 
1592 void TextNodeDumper::VisitDependentSizedExtVectorType(
1593     const DependentSizedExtVectorType *T) {
1594   OS << " ";
1595   dumpLocation(T->getAttributeLoc());
1596 }
1597 
1598 void TextNodeDumper::VisitVectorType(const VectorType *T) {
1599   switch (T->getVectorKind()) {
1600   case VectorKind::Generic:
1601     break;
1602   case VectorKind::AltiVecVector:
1603     OS << " altivec";
1604     break;
1605   case VectorKind::AltiVecPixel:
1606     OS << " altivec pixel";
1607     break;
1608   case VectorKind::AltiVecBool:
1609     OS << " altivec bool";
1610     break;
1611   case VectorKind::Neon:
1612     OS << " neon";
1613     break;
1614   case VectorKind::NeonPoly:
1615     OS << " neon poly";
1616     break;
1617   case VectorKind::SveFixedLengthData:
1618     OS << " fixed-length sve data vector";
1619     break;
1620   case VectorKind::SveFixedLengthPredicate:
1621     OS << " fixed-length sve predicate vector";
1622     break;
1623   case VectorKind::RVVFixedLengthData:
1624     OS << " fixed-length rvv data vector";
1625     break;
1626   case VectorKind::RVVFixedLengthMask:
1627     OS << " fixed-length rvv mask vector";
1628     break;
1629   }
1630   OS << " " << T->getNumElements();
1631 }
1632 
1633 void TextNodeDumper::VisitFunctionType(const FunctionType *T) {
1634   auto EI = T->getExtInfo();
1635   if (EI.getNoReturn())
1636     OS << " noreturn";
1637   if (EI.getProducesResult())
1638     OS << " produces_result";
1639   if (EI.getHasRegParm())
1640     OS << " regparm " << EI.getRegParm();
1641   OS << " " << FunctionType::getNameForCallConv(EI.getCC());
1642 }
1643 
1644 void TextNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) {
1645   auto EPI = T->getExtProtoInfo();
1646   if (EPI.HasTrailingReturn)
1647     OS << " trailing_return";
1648   if (T->isConst())
1649     OS << " const";
1650   if (T->isVolatile())
1651     OS << " volatile";
1652   if (T->isRestrict())
1653     OS << " restrict";
1654   if (T->getExtProtoInfo().Variadic)
1655     OS << " variadic";
1656   switch (EPI.RefQualifier) {
1657   case RQ_None:
1658     break;
1659   case RQ_LValue:
1660     OS << " &";
1661     break;
1662   case RQ_RValue:
1663     OS << " &&";
1664     break;
1665   }
1666 
1667   switch (EPI.ExceptionSpec.Type) {
1668   case EST_None:
1669     break;
1670   case EST_DynamicNone:
1671     OS << " exceptionspec_dynamic_none";
1672     break;
1673   case EST_Dynamic:
1674     OS << " exceptionspec_dynamic";
1675     break;
1676   case EST_MSAny:
1677     OS << " exceptionspec_ms_any";
1678     break;
1679   case EST_NoThrow:
1680     OS << " exceptionspec_nothrow";
1681     break;
1682   case EST_BasicNoexcept:
1683     OS << " exceptionspec_basic_noexcept";
1684     break;
1685   case EST_DependentNoexcept:
1686     OS << " exceptionspec_dependent_noexcept";
1687     break;
1688   case EST_NoexceptFalse:
1689     OS << " exceptionspec_noexcept_false";
1690     break;
1691   case EST_NoexceptTrue:
1692     OS << " exceptionspec_noexcept_true";
1693     break;
1694   case EST_Unevaluated:
1695     OS << " exceptionspec_unevaluated";
1696     break;
1697   case EST_Uninstantiated:
1698     OS << " exceptionspec_uninstantiated";
1699     break;
1700   case EST_Unparsed:
1701     OS << " exceptionspec_unparsed";
1702     break;
1703   }
1704   if (!EPI.ExceptionSpec.Exceptions.empty()) {
1705     AddChild([=] {
1706       OS << "Exceptions:";
1707       for (unsigned I = 0, N = EPI.ExceptionSpec.Exceptions.size(); I != N;
1708            ++I) {
1709         if (I)
1710           OS << ",";
1711         dumpType(EPI.ExceptionSpec.Exceptions[I]);
1712       }
1713     });
1714   }
1715   if (EPI.ExceptionSpec.NoexceptExpr) {
1716     AddChild([=] {
1717       OS << "NoexceptExpr: ";
1718       Visit(EPI.ExceptionSpec.NoexceptExpr);
1719     });
1720   }
1721   dumpDeclRef(EPI.ExceptionSpec.SourceDecl, "ExceptionSourceDecl");
1722   dumpDeclRef(EPI.ExceptionSpec.SourceTemplate, "ExceptionSourceTemplate");
1723 
1724   // FIXME: Consumed parameters.
1725   VisitFunctionType(T);
1726 }
1727 
1728 void TextNodeDumper::VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
1729   dumpDeclRef(T->getDecl());
1730 }
1731 
1732 void TextNodeDumper::VisitUsingType(const UsingType *T) {
1733   dumpDeclRef(T->getFoundDecl());
1734   if (!T->typeMatchesDecl())
1735     OS << " divergent";
1736 }
1737 
1738 void TextNodeDumper::VisitTypedefType(const TypedefType *T) {
1739   dumpDeclRef(T->getDecl());
1740   if (!T->typeMatchesDecl())
1741     OS << " divergent";
1742 }
1743 
1744 void TextNodeDumper::VisitUnaryTransformType(const UnaryTransformType *T) {
1745   switch (T->getUTTKind()) {
1746 #define TRANSFORM_TYPE_TRAIT_DEF(Enum, Trait)                                  \
1747   case UnaryTransformType::Enum:                                               \
1748     OS << " " #Trait;                                                          \
1749     break;
1750 #include "clang/Basic/TransformTypeTraits.def"
1751   }
1752 }
1753 
1754 void TextNodeDumper::VisitTagType(const TagType *T) {
1755   dumpDeclRef(T->getDecl());
1756 }
1757 
1758 void TextNodeDumper::VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
1759   OS << " depth " << T->getDepth() << " index " << T->getIndex();
1760   if (T->isParameterPack())
1761     OS << " pack";
1762   dumpDeclRef(T->getDecl());
1763 }
1764 
1765 void TextNodeDumper::VisitSubstTemplateTypeParmType(
1766     const SubstTemplateTypeParmType *T) {
1767   dumpDeclRef(T->getAssociatedDecl());
1768   VisitTemplateTypeParmDecl(T->getReplacedParameter());
1769   if (auto PackIndex = T->getPackIndex())
1770     OS << " pack_index " << *PackIndex;
1771 }
1772 
1773 void TextNodeDumper::VisitSubstTemplateTypeParmPackType(
1774     const SubstTemplateTypeParmPackType *T) {
1775   dumpDeclRef(T->getAssociatedDecl());
1776   VisitTemplateTypeParmDecl(T->getReplacedParameter());
1777 }
1778 
1779 void TextNodeDumper::VisitAutoType(const AutoType *T) {
1780   if (T->isDecltypeAuto())
1781     OS << " decltype(auto)";
1782   if (!T->isDeduced())
1783     OS << " undeduced";
1784   if (T->isConstrained()) {
1785     dumpDeclRef(T->getTypeConstraintConcept());
1786     for (const auto &Arg : T->getTypeConstraintArguments())
1787       VisitTemplateArgument(Arg);
1788   }
1789 }
1790 
1791 void TextNodeDumper::VisitDeducedTemplateSpecializationType(
1792     const DeducedTemplateSpecializationType *T) {
1793   if (T->getTemplateName().getKind() == TemplateName::UsingTemplate)
1794     OS << " using";
1795 }
1796 
1797 void TextNodeDumper::VisitTemplateSpecializationType(
1798     const TemplateSpecializationType *T) {
1799   if (T->isTypeAlias())
1800     OS << " alias";
1801   if (T->getTemplateName().getKind() == TemplateName::UsingTemplate)
1802     OS << " using";
1803   OS << " ";
1804   T->getTemplateName().dump(OS);
1805 }
1806 
1807 void TextNodeDumper::VisitInjectedClassNameType(
1808     const InjectedClassNameType *T) {
1809   dumpDeclRef(T->getDecl());
1810 }
1811 
1812 void TextNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
1813   dumpDeclRef(T->getDecl());
1814 }
1815 
1816 void TextNodeDumper::VisitPackExpansionType(const PackExpansionType *T) {
1817   if (auto N = T->getNumExpansions())
1818     OS << " expansions " << *N;
1819 }
1820 
1821 void TextNodeDumper::VisitLabelDecl(const LabelDecl *D) { dumpName(D); }
1822 
1823 void TextNodeDumper::VisitTypedefDecl(const TypedefDecl *D) {
1824   dumpName(D);
1825   dumpType(D->getUnderlyingType());
1826   if (D->isModulePrivate())
1827     OS << " __module_private__";
1828 }
1829 
1830 void TextNodeDumper::VisitEnumDecl(const EnumDecl *D) {
1831   if (D->isScoped()) {
1832     if (D->isScopedUsingClassTag())
1833       OS << " class";
1834     else
1835       OS << " struct";
1836   }
1837   dumpName(D);
1838   if (D->isModulePrivate())
1839     OS << " __module_private__";
1840   if (D->isFixed())
1841     dumpType(D->getIntegerType());
1842 }
1843 
1844 void TextNodeDumper::VisitRecordDecl(const RecordDecl *D) {
1845   OS << ' ' << D->getKindName();
1846   dumpName(D);
1847   if (D->isModulePrivate())
1848     OS << " __module_private__";
1849   if (D->isCompleteDefinition())
1850     OS << " definition";
1851 }
1852 
1853 void TextNodeDumper::VisitEnumConstantDecl(const EnumConstantDecl *D) {
1854   dumpName(D);
1855   dumpType(D->getType());
1856 }
1857 
1858 void TextNodeDumper::VisitIndirectFieldDecl(const IndirectFieldDecl *D) {
1859   dumpName(D);
1860   dumpType(D->getType());
1861 
1862   for (const auto *Child : D->chain())
1863     dumpDeclRef(Child);
1864 }
1865 
1866 void TextNodeDumper::VisitFunctionDecl(const FunctionDecl *D) {
1867   dumpName(D);
1868   dumpType(D->getType());
1869   dumpTemplateSpecializationKind(D->getTemplateSpecializationKind());
1870 
1871   StorageClass SC = D->getStorageClass();
1872   if (SC != SC_None)
1873     OS << ' ' << VarDecl::getStorageClassSpecifierString(SC);
1874   if (D->isInlineSpecified())
1875     OS << " inline";
1876   if (D->isVirtualAsWritten())
1877     OS << " virtual";
1878   if (D->isModulePrivate())
1879     OS << " __module_private__";
1880 
1881   if (D->isPureVirtual())
1882     OS << " pure";
1883   if (D->isDefaulted()) {
1884     OS << " default";
1885     if (D->isDeleted())
1886       OS << "_delete";
1887   }
1888   if (D->isDeletedAsWritten())
1889     OS << " delete";
1890   if (D->isTrivial())
1891     OS << " trivial";
1892 
1893   if (D->isIneligibleOrNotSelected())
1894     OS << (isa<CXXDestructorDecl>(D) ? " not_selected" : " ineligible");
1895 
1896   if (const auto *FPT = D->getType()->getAs<FunctionProtoType>()) {
1897     FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
1898     switch (EPI.ExceptionSpec.Type) {
1899     default:
1900       break;
1901     case EST_Unevaluated:
1902       OS << " noexcept-unevaluated " << EPI.ExceptionSpec.SourceDecl;
1903       break;
1904     case EST_Uninstantiated:
1905       OS << " noexcept-uninstantiated " << EPI.ExceptionSpec.SourceTemplate;
1906       break;
1907     }
1908   }
1909 
1910   if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
1911     if (MD->size_overridden_methods() != 0) {
1912       auto dumpOverride = [=](const CXXMethodDecl *D) {
1913         SplitQualType T_split = D->getType().split();
1914         OS << D << " " << D->getParent()->getName() << "::" << D->getDeclName()
1915            << " '" << QualType::getAsString(T_split, PrintPolicy) << "'";
1916       };
1917 
1918       AddChild([=] {
1919         auto Overrides = MD->overridden_methods();
1920         OS << "Overrides: [ ";
1921         dumpOverride(*Overrides.begin());
1922         for (const auto *Override : llvm::drop_begin(Overrides)) {
1923           OS << ", ";
1924           dumpOverride(Override);
1925         }
1926         OS << " ]";
1927       });
1928     }
1929   }
1930 
1931   if (!D->isInlineSpecified() && D->isInlined()) {
1932     OS << " implicit-inline";
1933   }
1934   // Since NumParams comes from the FunctionProtoType of the FunctionDecl and
1935   // the Params are set later, it is possible for a dump during debugging to
1936   // encounter a FunctionDecl that has been created but hasn't been assigned
1937   // ParmVarDecls yet.
1938   if (!D->param_empty() && !D->param_begin())
1939     OS << " <<<NULL params x " << D->getNumParams() << ">>>";
1940 
1941   if (const auto *Instance = D->getInstantiatedFromMemberFunction()) {
1942     OS << " instantiated_from";
1943     dumpPointer(Instance);
1944   }
1945 }
1946 
1947 void TextNodeDumper::VisitLifetimeExtendedTemporaryDecl(
1948     const LifetimeExtendedTemporaryDecl *D) {
1949   OS << " extended by ";
1950   dumpBareDeclRef(D->getExtendingDecl());
1951   OS << " mangling ";
1952   {
1953     ColorScope Color(OS, ShowColors, ValueColor);
1954     OS << D->getManglingNumber();
1955   }
1956 }
1957 
1958 void TextNodeDumper::VisitFieldDecl(const FieldDecl *D) {
1959   dumpName(D);
1960   dumpType(D->getType());
1961   if (D->isMutable())
1962     OS << " mutable";
1963   if (D->isModulePrivate())
1964     OS << " __module_private__";
1965 }
1966 
1967 void TextNodeDumper::VisitVarDecl(const VarDecl *D) {
1968   dumpNestedNameSpecifier(D->getQualifier());
1969   dumpName(D);
1970   if (const auto *P = dyn_cast<ParmVarDecl>(D);
1971       P && P->isExplicitObjectParameter())
1972     OS << " this";
1973 
1974   dumpType(D->getType());
1975   dumpTemplateSpecializationKind(D->getTemplateSpecializationKind());
1976   StorageClass SC = D->getStorageClass();
1977   if (SC != SC_None)
1978     OS << ' ' << VarDecl::getStorageClassSpecifierString(SC);
1979   switch (D->getTLSKind()) {
1980   case VarDecl::TLS_None:
1981     break;
1982   case VarDecl::TLS_Static:
1983     OS << " tls";
1984     break;
1985   case VarDecl::TLS_Dynamic:
1986     OS << " tls_dynamic";
1987     break;
1988   }
1989   if (D->isModulePrivate())
1990     OS << " __module_private__";
1991   if (D->isNRVOVariable())
1992     OS << " nrvo";
1993   if (D->isInline())
1994     OS << " inline";
1995   if (D->isConstexpr())
1996     OS << " constexpr";
1997   if (D->hasInit()) {
1998     switch (D->getInitStyle()) {
1999     case VarDecl::CInit:
2000       OS << " cinit";
2001       break;
2002     case VarDecl::CallInit:
2003       OS << " callinit";
2004       break;
2005     case VarDecl::ListInit:
2006       OS << " listinit";
2007       break;
2008     case VarDecl::ParenListInit:
2009       OS << " parenlistinit";
2010     }
2011   }
2012   if (D->needsDestruction(D->getASTContext()))
2013     OS << " destroyed";
2014   if (D->isParameterPack())
2015     OS << " pack";
2016 
2017   if (D->hasInit()) {
2018     const Expr *E = D->getInit();
2019     // Only dump the value of constexpr VarDecls for now.
2020     if (E && !E->isValueDependent() && D->isConstexpr() &&
2021         !D->getType()->isDependentType()) {
2022       const APValue *Value = D->evaluateValue();
2023       if (Value)
2024         AddChild("value", [=] { Visit(*Value, E->getType()); });
2025     }
2026   }
2027 }
2028 
2029 void TextNodeDumper::VisitBindingDecl(const BindingDecl *D) {
2030   dumpName(D);
2031   dumpType(D->getType());
2032 }
2033 
2034 void TextNodeDumper::VisitCapturedDecl(const CapturedDecl *D) {
2035   if (D->isNothrow())
2036     OS << " nothrow";
2037 }
2038 
2039 void TextNodeDumper::VisitImportDecl(const ImportDecl *D) {
2040   OS << ' ' << D->getImportedModule()->getFullModuleName();
2041 
2042   for (Decl *InitD :
2043        D->getASTContext().getModuleInitializers(D->getImportedModule()))
2044     dumpDeclRef(InitD, "initializer");
2045 }
2046 
2047 void TextNodeDumper::VisitPragmaCommentDecl(const PragmaCommentDecl *D) {
2048   OS << ' ';
2049   switch (D->getCommentKind()) {
2050   case PCK_Unknown:
2051     llvm_unreachable("unexpected pragma comment kind");
2052   case PCK_Compiler:
2053     OS << "compiler";
2054     break;
2055   case PCK_ExeStr:
2056     OS << "exestr";
2057     break;
2058   case PCK_Lib:
2059     OS << "lib";
2060     break;
2061   case PCK_Linker:
2062     OS << "linker";
2063     break;
2064   case PCK_User:
2065     OS << "user";
2066     break;
2067   }
2068   StringRef Arg = D->getArg();
2069   if (!Arg.empty())
2070     OS << " \"" << Arg << "\"";
2071 }
2072 
2073 void TextNodeDumper::VisitPragmaDetectMismatchDecl(
2074     const PragmaDetectMismatchDecl *D) {
2075   OS << " \"" << D->getName() << "\" \"" << D->getValue() << "\"";
2076 }
2077 
2078 void TextNodeDumper::VisitOMPExecutableDirective(
2079     const OMPExecutableDirective *D) {
2080   if (D->isStandaloneDirective())
2081     OS << " openmp_standalone_directive";
2082 }
2083 
2084 void TextNodeDumper::VisitOMPDeclareReductionDecl(
2085     const OMPDeclareReductionDecl *D) {
2086   dumpName(D);
2087   dumpType(D->getType());
2088   OS << " combiner";
2089   dumpPointer(D->getCombiner());
2090   if (const auto *Initializer = D->getInitializer()) {
2091     OS << " initializer";
2092     dumpPointer(Initializer);
2093     switch (D->getInitializerKind()) {
2094     case OMPDeclareReductionInitKind::Direct:
2095       OS << " omp_priv = ";
2096       break;
2097     case OMPDeclareReductionInitKind::Copy:
2098       OS << " omp_priv ()";
2099       break;
2100     case OMPDeclareReductionInitKind::Call:
2101       break;
2102     }
2103   }
2104 }
2105 
2106 void TextNodeDumper::VisitOMPRequiresDecl(const OMPRequiresDecl *D) {
2107   for (const auto *C : D->clauselists()) {
2108     AddChild([=] {
2109       if (!C) {
2110         ColorScope Color(OS, ShowColors, NullColor);
2111         OS << "<<<NULL>>> OMPClause";
2112         return;
2113       }
2114       {
2115         ColorScope Color(OS, ShowColors, AttrColor);
2116         StringRef ClauseName(
2117             llvm::omp::getOpenMPClauseName(C->getClauseKind()));
2118         OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper()
2119            << ClauseName.drop_front() << "Clause";
2120       }
2121       dumpPointer(C);
2122       dumpSourceRange(SourceRange(C->getBeginLoc(), C->getEndLoc()));
2123     });
2124   }
2125 }
2126 
2127 void TextNodeDumper::VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) {
2128   dumpName(D);
2129   dumpType(D->getType());
2130 }
2131 
2132 void TextNodeDumper::VisitNamespaceDecl(const NamespaceDecl *D) {
2133   dumpName(D);
2134   if (D->isInline())
2135     OS << " inline";
2136   if (D->isNested())
2137     OS << " nested";
2138   if (!D->isOriginalNamespace())
2139     dumpDeclRef(D->getOriginalNamespace(), "original");
2140 }
2141 
2142 void TextNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
2143   OS << ' ';
2144   dumpBareDeclRef(D->getNominatedNamespace());
2145 }
2146 
2147 void TextNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
2148   dumpName(D);
2149   dumpDeclRef(D->getAliasedNamespace());
2150 }
2151 
2152 void TextNodeDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) {
2153   dumpName(D);
2154   dumpType(D->getUnderlyingType());
2155 }
2156 
2157 void TextNodeDumper::VisitTypeAliasTemplateDecl(
2158     const TypeAliasTemplateDecl *D) {
2159   dumpName(D);
2160 }
2161 
2162 void TextNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
2163   VisitRecordDecl(D);
2164   if (const auto *Instance = D->getInstantiatedFromMemberClass()) {
2165     OS << " instantiated_from";
2166     dumpPointer(Instance);
2167   }
2168   if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D))
2169     dumpTemplateSpecializationKind(CTSD->getSpecializationKind());
2170 
2171   dumpNestedNameSpecifier(D->getQualifier());
2172 
2173   if (!D->isCompleteDefinition())
2174     return;
2175 
2176   AddChild([=] {
2177     {
2178       ColorScope Color(OS, ShowColors, DeclKindNameColor);
2179       OS << "DefinitionData";
2180     }
2181 #define FLAG(fn, name)                                                         \
2182   if (D->fn())                                                                 \
2183     OS << " " #name;
2184     FLAG(isParsingBaseSpecifiers, parsing_base_specifiers);
2185 
2186     FLAG(isGenericLambda, generic);
2187     FLAG(isLambda, lambda);
2188 
2189     FLAG(isAnonymousStructOrUnion, is_anonymous);
2190     FLAG(canPassInRegisters, pass_in_registers);
2191     FLAG(isEmpty, empty);
2192     FLAG(isAggregate, aggregate);
2193     FLAG(isStandardLayout, standard_layout);
2194     FLAG(isTriviallyCopyable, trivially_copyable);
2195     FLAG(isPOD, pod);
2196     FLAG(isTrivial, trivial);
2197     FLAG(isPolymorphic, polymorphic);
2198     FLAG(isAbstract, abstract);
2199     FLAG(isLiteral, literal);
2200 
2201     FLAG(hasUserDeclaredConstructor, has_user_declared_ctor);
2202     FLAG(hasConstexprNonCopyMoveConstructor, has_constexpr_non_copy_move_ctor);
2203     FLAG(hasMutableFields, has_mutable_fields);
2204     FLAG(hasVariantMembers, has_variant_members);
2205     FLAG(allowConstDefaultInit, can_const_default_init);
2206 
2207     AddChild([=] {
2208       {
2209         ColorScope Color(OS, ShowColors, DeclKindNameColor);
2210         OS << "DefaultConstructor";
2211       }
2212       FLAG(hasDefaultConstructor, exists);
2213       FLAG(hasTrivialDefaultConstructor, trivial);
2214       FLAG(hasNonTrivialDefaultConstructor, non_trivial);
2215       FLAG(hasUserProvidedDefaultConstructor, user_provided);
2216       FLAG(hasConstexprDefaultConstructor, constexpr);
2217       FLAG(needsImplicitDefaultConstructor, needs_implicit);
2218       FLAG(defaultedDefaultConstructorIsConstexpr, defaulted_is_constexpr);
2219     });
2220 
2221     AddChild([=] {
2222       {
2223         ColorScope Color(OS, ShowColors, DeclKindNameColor);
2224         OS << "CopyConstructor";
2225       }
2226       FLAG(hasSimpleCopyConstructor, simple);
2227       FLAG(hasTrivialCopyConstructor, trivial);
2228       FLAG(hasNonTrivialCopyConstructor, non_trivial);
2229       FLAG(hasUserDeclaredCopyConstructor, user_declared);
2230       FLAG(hasCopyConstructorWithConstParam, has_const_param);
2231       FLAG(needsImplicitCopyConstructor, needs_implicit);
2232       FLAG(needsOverloadResolutionForCopyConstructor,
2233            needs_overload_resolution);
2234       if (!D->needsOverloadResolutionForCopyConstructor())
2235         FLAG(defaultedCopyConstructorIsDeleted, defaulted_is_deleted);
2236       FLAG(implicitCopyConstructorHasConstParam, implicit_has_const_param);
2237     });
2238 
2239     AddChild([=] {
2240       {
2241         ColorScope Color(OS, ShowColors, DeclKindNameColor);
2242         OS << "MoveConstructor";
2243       }
2244       FLAG(hasMoveConstructor, exists);
2245       FLAG(hasSimpleMoveConstructor, simple);
2246       FLAG(hasTrivialMoveConstructor, trivial);
2247       FLAG(hasNonTrivialMoveConstructor, non_trivial);
2248       FLAG(hasUserDeclaredMoveConstructor, user_declared);
2249       FLAG(needsImplicitMoveConstructor, needs_implicit);
2250       FLAG(needsOverloadResolutionForMoveConstructor,
2251            needs_overload_resolution);
2252       if (!D->needsOverloadResolutionForMoveConstructor())
2253         FLAG(defaultedMoveConstructorIsDeleted, defaulted_is_deleted);
2254     });
2255 
2256     AddChild([=] {
2257       {
2258         ColorScope Color(OS, ShowColors, DeclKindNameColor);
2259         OS << "CopyAssignment";
2260       }
2261       FLAG(hasSimpleCopyAssignment, simple);
2262       FLAG(hasTrivialCopyAssignment, trivial);
2263       FLAG(hasNonTrivialCopyAssignment, non_trivial);
2264       FLAG(hasCopyAssignmentWithConstParam, has_const_param);
2265       FLAG(hasUserDeclaredCopyAssignment, user_declared);
2266       FLAG(needsImplicitCopyAssignment, needs_implicit);
2267       FLAG(needsOverloadResolutionForCopyAssignment, needs_overload_resolution);
2268       FLAG(implicitCopyAssignmentHasConstParam, implicit_has_const_param);
2269     });
2270 
2271     AddChild([=] {
2272       {
2273         ColorScope Color(OS, ShowColors, DeclKindNameColor);
2274         OS << "MoveAssignment";
2275       }
2276       FLAG(hasMoveAssignment, exists);
2277       FLAG(hasSimpleMoveAssignment, simple);
2278       FLAG(hasTrivialMoveAssignment, trivial);
2279       FLAG(hasNonTrivialMoveAssignment, non_trivial);
2280       FLAG(hasUserDeclaredMoveAssignment, user_declared);
2281       FLAG(needsImplicitMoveAssignment, needs_implicit);
2282       FLAG(needsOverloadResolutionForMoveAssignment, needs_overload_resolution);
2283     });
2284 
2285     AddChild([=] {
2286       {
2287         ColorScope Color(OS, ShowColors, DeclKindNameColor);
2288         OS << "Destructor";
2289       }
2290       FLAG(hasSimpleDestructor, simple);
2291       FLAG(hasIrrelevantDestructor, irrelevant);
2292       FLAG(hasTrivialDestructor, trivial);
2293       FLAG(hasNonTrivialDestructor, non_trivial);
2294       FLAG(hasUserDeclaredDestructor, user_declared);
2295       FLAG(hasConstexprDestructor, constexpr);
2296       FLAG(needsImplicitDestructor, needs_implicit);
2297       FLAG(needsOverloadResolutionForDestructor, needs_overload_resolution);
2298       if (!D->needsOverloadResolutionForDestructor())
2299         FLAG(defaultedDestructorIsDeleted, defaulted_is_deleted);
2300     });
2301   });
2302 
2303   for (const auto &I : D->bases()) {
2304     AddChild([=] {
2305       if (I.isVirtual())
2306         OS << "virtual ";
2307       dumpAccessSpecifier(I.getAccessSpecifier());
2308       dumpType(I.getType());
2309       if (I.isPackExpansion())
2310         OS << "...";
2311     });
2312   }
2313 }
2314 
2315 void TextNodeDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
2316   dumpName(D);
2317 }
2318 
2319 void TextNodeDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
2320   dumpName(D);
2321 }
2322 
2323 void TextNodeDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
2324   dumpName(D);
2325 }
2326 
2327 void TextNodeDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) {
2328   dumpName(D);
2329 }
2330 
2331 void TextNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
2332   if (const auto *TC = D->getTypeConstraint()) {
2333     OS << " ";
2334     dumpBareDeclRef(TC->getNamedConcept());
2335     if (TC->getNamedConcept() != TC->getFoundDecl()) {
2336       OS << " (";
2337       dumpBareDeclRef(TC->getFoundDecl());
2338       OS << ")";
2339     }
2340   } else if (D->wasDeclaredWithTypename())
2341     OS << " typename";
2342   else
2343     OS << " class";
2344   OS << " depth " << D->getDepth() << " index " << D->getIndex();
2345   if (D->isParameterPack())
2346     OS << " ...";
2347   dumpName(D);
2348 }
2349 
2350 void TextNodeDumper::VisitNonTypeTemplateParmDecl(
2351     const NonTypeTemplateParmDecl *D) {
2352   dumpType(D->getType());
2353   OS << " depth " << D->getDepth() << " index " << D->getIndex();
2354   if (D->isParameterPack())
2355     OS << " ...";
2356   dumpName(D);
2357 }
2358 
2359 void TextNodeDumper::VisitTemplateTemplateParmDecl(
2360     const TemplateTemplateParmDecl *D) {
2361   OS << " depth " << D->getDepth() << " index " << D->getIndex();
2362   if (D->isParameterPack())
2363     OS << " ...";
2364   dumpName(D);
2365 }
2366 
2367 void TextNodeDumper::VisitUsingDecl(const UsingDecl *D) {
2368   OS << ' ';
2369   if (D->getQualifier())
2370     D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
2371   OS << D->getDeclName();
2372   dumpNestedNameSpecifier(D->getQualifier());
2373 }
2374 
2375 void TextNodeDumper::VisitUsingEnumDecl(const UsingEnumDecl *D) {
2376   OS << ' ';
2377   dumpBareDeclRef(D->getEnumDecl());
2378 }
2379 
2380 void TextNodeDumper::VisitUnresolvedUsingTypenameDecl(
2381     const UnresolvedUsingTypenameDecl *D) {
2382   OS << ' ';
2383   if (D->getQualifier())
2384     D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
2385   OS << D->getDeclName();
2386 }
2387 
2388 void TextNodeDumper::VisitUnresolvedUsingValueDecl(
2389     const UnresolvedUsingValueDecl *D) {
2390   OS << ' ';
2391   if (D->getQualifier())
2392     D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
2393   OS << D->getDeclName();
2394   dumpType(D->getType());
2395 }
2396 
2397 void TextNodeDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) {
2398   OS << ' ';
2399   dumpBareDeclRef(D->getTargetDecl());
2400 }
2401 
2402 void TextNodeDumper::VisitConstructorUsingShadowDecl(
2403     const ConstructorUsingShadowDecl *D) {
2404   if (D->constructsVirtualBase())
2405     OS << " virtual";
2406 
2407   AddChild([=] {
2408     OS << "target ";
2409     dumpBareDeclRef(D->getTargetDecl());
2410   });
2411 
2412   AddChild([=] {
2413     OS << "nominated ";
2414     dumpBareDeclRef(D->getNominatedBaseClass());
2415     OS << ' ';
2416     dumpBareDeclRef(D->getNominatedBaseClassShadowDecl());
2417   });
2418 
2419   AddChild([=] {
2420     OS << "constructed ";
2421     dumpBareDeclRef(D->getConstructedBaseClass());
2422     OS << ' ';
2423     dumpBareDeclRef(D->getConstructedBaseClassShadowDecl());
2424   });
2425 }
2426 
2427 void TextNodeDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
2428   switch (D->getLanguage()) {
2429   case LinkageSpecLanguageIDs::C:
2430     OS << " C";
2431     break;
2432   case LinkageSpecLanguageIDs::CXX:
2433     OS << " C++";
2434     break;
2435   }
2436 }
2437 
2438 void TextNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl *D) {
2439   OS << ' ';
2440   dumpAccessSpecifier(D->getAccess());
2441 }
2442 
2443 void TextNodeDumper::VisitFriendDecl(const FriendDecl *D) {
2444   if (TypeSourceInfo *T = D->getFriendType())
2445     dumpType(T->getType());
2446 }
2447 
2448 void TextNodeDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) {
2449   dumpName(D);
2450   dumpType(D->getType());
2451   if (D->getSynthesize())
2452     OS << " synthesize";
2453 
2454   switch (D->getAccessControl()) {
2455   case ObjCIvarDecl::None:
2456     OS << " none";
2457     break;
2458   case ObjCIvarDecl::Private:
2459     OS << " private";
2460     break;
2461   case ObjCIvarDecl::Protected:
2462     OS << " protected";
2463     break;
2464   case ObjCIvarDecl::Public:
2465     OS << " public";
2466     break;
2467   case ObjCIvarDecl::Package:
2468     OS << " package";
2469     break;
2470   }
2471 }
2472 
2473 void TextNodeDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
2474   if (D->isInstanceMethod())
2475     OS << " -";
2476   else
2477     OS << " +";
2478   dumpName(D);
2479   dumpType(D->getReturnType());
2480 
2481   if (D->isVariadic())
2482     OS << " variadic";
2483 }
2484 
2485 void TextNodeDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) {
2486   dumpName(D);
2487   switch (D->getVariance()) {
2488   case ObjCTypeParamVariance::Invariant:
2489     break;
2490 
2491   case ObjCTypeParamVariance::Covariant:
2492     OS << " covariant";
2493     break;
2494 
2495   case ObjCTypeParamVariance::Contravariant:
2496     OS << " contravariant";
2497     break;
2498   }
2499 
2500   if (D->hasExplicitBound())
2501     OS << " bounded";
2502   dumpType(D->getUnderlyingType());
2503 }
2504 
2505 void TextNodeDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
2506   dumpName(D);
2507   dumpDeclRef(D->getClassInterface());
2508   dumpDeclRef(D->getImplementation());
2509   for (const auto *P : D->protocols())
2510     dumpDeclRef(P);
2511 }
2512 
2513 void TextNodeDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
2514   dumpName(D);
2515   dumpDeclRef(D->getClassInterface());
2516   dumpDeclRef(D->getCategoryDecl());
2517 }
2518 
2519 void TextNodeDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
2520   dumpName(D);
2521 
2522   for (const auto *Child : D->protocols())
2523     dumpDeclRef(Child);
2524 }
2525 
2526 void TextNodeDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
2527   dumpName(D);
2528   dumpDeclRef(D->getSuperClass(), "super");
2529 
2530   dumpDeclRef(D->getImplementation());
2531   for (const auto *Child : D->protocols())
2532     dumpDeclRef(Child);
2533 }
2534 
2535 void TextNodeDumper::VisitObjCImplementationDecl(
2536     const ObjCImplementationDecl *D) {
2537   dumpName(D);
2538   dumpDeclRef(D->getSuperClass(), "super");
2539   dumpDeclRef(D->getClassInterface());
2540 }
2541 
2542 void TextNodeDumper::VisitObjCCompatibleAliasDecl(
2543     const ObjCCompatibleAliasDecl *D) {
2544   dumpName(D);
2545   dumpDeclRef(D->getClassInterface());
2546 }
2547 
2548 void TextNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
2549   dumpName(D);
2550   dumpType(D->getType());
2551 
2552   if (D->getPropertyImplementation() == ObjCPropertyDecl::Required)
2553     OS << " required";
2554   else if (D->getPropertyImplementation() == ObjCPropertyDecl::Optional)
2555     OS << " optional";
2556 
2557   ObjCPropertyAttribute::Kind Attrs = D->getPropertyAttributes();
2558   if (Attrs != ObjCPropertyAttribute::kind_noattr) {
2559     if (Attrs & ObjCPropertyAttribute::kind_readonly)
2560       OS << " readonly";
2561     if (Attrs & ObjCPropertyAttribute::kind_assign)
2562       OS << " assign";
2563     if (Attrs & ObjCPropertyAttribute::kind_readwrite)
2564       OS << " readwrite";
2565     if (Attrs & ObjCPropertyAttribute::kind_retain)
2566       OS << " retain";
2567     if (Attrs & ObjCPropertyAttribute::kind_copy)
2568       OS << " copy";
2569     if (Attrs & ObjCPropertyAttribute::kind_nonatomic)
2570       OS << " nonatomic";
2571     if (Attrs & ObjCPropertyAttribute::kind_atomic)
2572       OS << " atomic";
2573     if (Attrs & ObjCPropertyAttribute::kind_weak)
2574       OS << " weak";
2575     if (Attrs & ObjCPropertyAttribute::kind_strong)
2576       OS << " strong";
2577     if (Attrs & ObjCPropertyAttribute::kind_unsafe_unretained)
2578       OS << " unsafe_unretained";
2579     if (Attrs & ObjCPropertyAttribute::kind_class)
2580       OS << " class";
2581     if (Attrs & ObjCPropertyAttribute::kind_direct)
2582       OS << " direct";
2583     if (Attrs & ObjCPropertyAttribute::kind_getter)
2584       dumpDeclRef(D->getGetterMethodDecl(), "getter");
2585     if (Attrs & ObjCPropertyAttribute::kind_setter)
2586       dumpDeclRef(D->getSetterMethodDecl(), "setter");
2587   }
2588 }
2589 
2590 void TextNodeDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
2591   dumpName(D->getPropertyDecl());
2592   if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize)
2593     OS << " synthesize";
2594   else
2595     OS << " dynamic";
2596   dumpDeclRef(D->getPropertyDecl());
2597   dumpDeclRef(D->getPropertyIvarDecl());
2598 }
2599 
2600 void TextNodeDumper::VisitBlockDecl(const BlockDecl *D) {
2601   if (D->isVariadic())
2602     OS << " variadic";
2603 
2604   if (D->capturesCXXThis())
2605     OS << " captures_this";
2606 }
2607 
2608 void TextNodeDumper::VisitConceptDecl(const ConceptDecl *D) {
2609   dumpName(D);
2610 }
2611 
2612 void TextNodeDumper::VisitCompoundStmt(const CompoundStmt *S) {
2613   VisitStmt(S);
2614   if (S->hasStoredFPFeatures())
2615     printFPOptions(S->getStoredFPFeatures());
2616 }
2617 
2618 void TextNodeDumper::VisitHLSLBufferDecl(const HLSLBufferDecl *D) {
2619   if (D->isCBuffer())
2620     OS << " cbuffer";
2621   else
2622     OS << " tbuffer";
2623   dumpName(D);
2624 }
2625