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