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