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