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