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