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