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->getDeclName();
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::printFPOptions(FPOptionsOverride FPO) {
714#define OPTION(NAME, TYPE, WIDTH, PREVIOUS)                                    \
715  if (FPO.has##NAME##Override())                                               \
716    OS << " " #NAME "=" << FPO.get##NAME##Override();
717#include "clang/Basic/FPOptions.def"
718}
719
720void TextNodeDumper::visitTextComment(const comments::TextComment *C,
721                                      const comments::FullComment *) {
722  OS << " Text=\"" << C->getText() << "\"";
723}
724
725void TextNodeDumper::visitInlineCommandComment(
726    const comments::InlineCommandComment *C, const comments::FullComment *) {
727  OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
728  switch (C->getRenderKind()) {
729  case comments::InlineCommandComment::RenderNormal:
730    OS << " RenderNormal";
731    break;
732  case comments::InlineCommandComment::RenderBold:
733    OS << " RenderBold";
734    break;
735  case comments::InlineCommandComment::RenderMonospaced:
736    OS << " RenderMonospaced";
737    break;
738  case comments::InlineCommandComment::RenderEmphasized:
739    OS << " RenderEmphasized";
740    break;
741  case comments::InlineCommandComment::RenderAnchor:
742    OS << " RenderAnchor";
743    break;
744  }
745
746  for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
747    OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
748}
749
750void TextNodeDumper::visitHTMLStartTagComment(
751    const comments::HTMLStartTagComment *C, const comments::FullComment *) {
752  OS << " Name=\"" << C->getTagName() << "\"";
753  if (C->getNumAttrs() != 0) {
754    OS << " Attrs: ";
755    for (unsigned i = 0, e = C->getNumAttrs(); i != e; ++i) {
756      const comments::HTMLStartTagComment::Attribute &Attr = C->getAttr(i);
757      OS << " \"" << Attr.Name << "=\"" << Attr.Value << "\"";
758    }
759  }
760  if (C->isSelfClosing())
761    OS << " SelfClosing";
762}
763
764void TextNodeDumper::visitHTMLEndTagComment(
765    const comments::HTMLEndTagComment *C, const comments::FullComment *) {
766  OS << " Name=\"" << C->getTagName() << "\"";
767}
768
769void TextNodeDumper::visitBlockCommandComment(
770    const comments::BlockCommandComment *C, const comments::FullComment *) {
771  OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
772  for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
773    OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
774}
775
776void TextNodeDumper::visitParamCommandComment(
777    const comments::ParamCommandComment *C, const comments::FullComment *FC) {
778  OS << " "
779     << comments::ParamCommandComment::getDirectionAsString(C->getDirection());
780
781  if (C->isDirectionExplicit())
782    OS << " explicitly";
783  else
784    OS << " implicitly";
785
786  if (C->hasParamName()) {
787    if (C->isParamIndexValid())
788      OS << " Param=\"" << C->getParamName(FC) << "\"";
789    else
790      OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
791  }
792
793  if (C->isParamIndexValid() && !C->isVarArgParam())
794    OS << " ParamIndex=" << C->getParamIndex();
795}
796
797void TextNodeDumper::visitTParamCommandComment(
798    const comments::TParamCommandComment *C, const comments::FullComment *FC) {
799  if (C->hasParamName()) {
800    if (C->isPositionValid())
801      OS << " Param=\"" << C->getParamName(FC) << "\"";
802    else
803      OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
804  }
805
806  if (C->isPositionValid()) {
807    OS << " Position=<";
808    for (unsigned i = 0, e = C->getDepth(); i != e; ++i) {
809      OS << C->getIndex(i);
810      if (i != e - 1)
811        OS << ", ";
812    }
813    OS << ">";
814  }
815}
816
817void TextNodeDumper::visitVerbatimBlockComment(
818    const comments::VerbatimBlockComment *C, const comments::FullComment *) {
819  OS << " Name=\"" << getCommandName(C->getCommandID())
820     << "\""
821        " CloseName=\""
822     << C->getCloseName() << "\"";
823}
824
825void TextNodeDumper::visitVerbatimBlockLineComment(
826    const comments::VerbatimBlockLineComment *C,
827    const comments::FullComment *) {
828  OS << " Text=\"" << C->getText() << "\"";
829}
830
831void TextNodeDumper::visitVerbatimLineComment(
832    const comments::VerbatimLineComment *C, const comments::FullComment *) {
833  OS << " Text=\"" << C->getText() << "\"";
834}
835
836void TextNodeDumper::VisitNullTemplateArgument(const TemplateArgument &) {
837  OS << " null";
838}
839
840void TextNodeDumper::VisitTypeTemplateArgument(const TemplateArgument &TA) {
841  OS << " type";
842  dumpType(TA.getAsType());
843}
844
845void TextNodeDumper::VisitDeclarationTemplateArgument(
846    const TemplateArgument &TA) {
847  OS << " decl";
848  dumpDeclRef(TA.getAsDecl());
849}
850
851void TextNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument &) {
852  OS << " nullptr";
853}
854
855void TextNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) {
856  OS << " integral " << TA.getAsIntegral();
857}
858
859void TextNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) {
860  OS << " template ";
861  TA.getAsTemplate().dump(OS);
862}
863
864void TextNodeDumper::VisitTemplateExpansionTemplateArgument(
865    const TemplateArgument &TA) {
866  OS << " template expansion ";
867  TA.getAsTemplateOrTemplatePattern().dump(OS);
868}
869
870void TextNodeDumper::VisitExpressionTemplateArgument(const TemplateArgument &) {
871  OS << " expr";
872}
873
874void TextNodeDumper::VisitPackTemplateArgument(const TemplateArgument &) {
875  OS << " pack";
876}
877
878static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) {
879  if (Node->path_empty())
880    return;
881
882  OS << " (";
883  bool First = true;
884  for (CastExpr::path_const_iterator I = Node->path_begin(),
885                                     E = Node->path_end();
886       I != E; ++I) {
887    const CXXBaseSpecifier *Base = *I;
888    if (!First)
889      OS << " -> ";
890
891    const auto *RD =
892        cast<CXXRecordDecl>(Base->getType()->castAs<RecordType>()->getDecl());
893
894    if (Base->isVirtual())
895      OS << "virtual ";
896    OS << RD->getName();
897    First = false;
898  }
899
900  OS << ')';
901}
902
903void TextNodeDumper::VisitIfStmt(const IfStmt *Node) {
904  if (Node->hasInitStorage())
905    OS << " has_init";
906  if (Node->hasVarStorage())
907    OS << " has_var";
908  if (Node->hasElseStorage())
909    OS << " has_else";
910}
911
912void TextNodeDumper::VisitSwitchStmt(const SwitchStmt *Node) {
913  if (Node->hasInitStorage())
914    OS << " has_init";
915  if (Node->hasVarStorage())
916    OS << " has_var";
917}
918
919void TextNodeDumper::VisitWhileStmt(const WhileStmt *Node) {
920  if (Node->hasVarStorage())
921    OS << " has_var";
922}
923
924void TextNodeDumper::VisitLabelStmt(const LabelStmt *Node) {
925  OS << " '" << Node->getName() << "'";
926  if (Node->isSideEntry())
927    OS << " side_entry";
928}
929
930void TextNodeDumper::VisitGotoStmt(const GotoStmt *Node) {
931  OS << " '" << Node->getLabel()->getName() << "'";
932  dumpPointer(Node->getLabel());
933}
934
935void TextNodeDumper::VisitCaseStmt(const CaseStmt *Node) {
936  if (Node->caseStmtIsGNURange())
937    OS << " gnu_range";
938}
939
940void TextNodeDumper::VisitConstantExpr(const ConstantExpr *Node) {
941  if (Node->hasAPValueResult())
942    AddChild("value",
943             [=] { Visit(Node->getAPValueResult(), Node->getType()); });
944}
945
946void TextNodeDumper::VisitCallExpr(const CallExpr *Node) {
947  if (Node->usesADL())
948    OS << " adl";
949  if (Node->hasStoredFPFeatures())
950    printFPOptions(Node->getFPFeatures());
951}
952
953void TextNodeDumper::VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *Node) {
954  const char *OperatorSpelling = clang::getOperatorSpelling(Node->getOperator());
955  if (OperatorSpelling)
956    OS << " '" << OperatorSpelling << "'";
957
958  VisitCallExpr(Node);
959}
960
961void TextNodeDumper::VisitCastExpr(const CastExpr *Node) {
962  OS << " <";
963  {
964    ColorScope Color(OS, ShowColors, CastColor);
965    OS << Node->getCastKindName();
966  }
967  dumpBasePath(OS, Node);
968  OS << ">";
969  if (Node->hasStoredFPFeatures())
970    printFPOptions(Node->getFPFeatures());
971}
972
973void TextNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *Node) {
974  VisitCastExpr(Node);
975  if (Node->isPartOfExplicitCast())
976    OS << " part_of_explicit_cast";
977}
978
979void TextNodeDumper::VisitDeclRefExpr(const DeclRefExpr *Node) {
980  OS << " ";
981  dumpBareDeclRef(Node->getDecl());
982  if (Node->getDecl() != Node->getFoundDecl()) {
983    OS << " (";
984    dumpBareDeclRef(Node->getFoundDecl());
985    OS << ")";
986  }
987  switch (Node->isNonOdrUse()) {
988  case NOUR_None: break;
989  case NOUR_Unevaluated: OS << " non_odr_use_unevaluated"; break;
990  case NOUR_Constant: OS << " non_odr_use_constant"; break;
991  case NOUR_Discarded: OS << " non_odr_use_discarded"; break;
992  }
993}
994
995void TextNodeDumper::VisitUnresolvedLookupExpr(
996    const UnresolvedLookupExpr *Node) {
997  OS << " (";
998  if (!Node->requiresADL())
999    OS << "no ";
1000  OS << "ADL) = '" << Node->getName() << '\'';
1001
1002  UnresolvedLookupExpr::decls_iterator I = Node->decls_begin(),
1003                                       E = Node->decls_end();
1004  if (I == E)
1005    OS << " empty";
1006  for (; I != E; ++I)
1007    dumpPointer(*I);
1008}
1009
1010void TextNodeDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) {
1011  {
1012    ColorScope Color(OS, ShowColors, DeclKindNameColor);
1013    OS << " " << Node->getDecl()->getDeclKindName() << "Decl";
1014  }
1015  OS << "='" << *Node->getDecl() << "'";
1016  dumpPointer(Node->getDecl());
1017  if (Node->isFreeIvar())
1018    OS << " isFreeIvar";
1019}
1020
1021void TextNodeDumper::VisitPredefinedExpr(const PredefinedExpr *Node) {
1022  OS << " " << PredefinedExpr::getIdentKindName(Node->getIdentKind());
1023}
1024
1025void TextNodeDumper::VisitCharacterLiteral(const CharacterLiteral *Node) {
1026  ColorScope Color(OS, ShowColors, ValueColor);
1027  OS << " " << Node->getValue();
1028}
1029
1030void TextNodeDumper::VisitIntegerLiteral(const IntegerLiteral *Node) {
1031  bool isSigned = Node->getType()->isSignedIntegerType();
1032  ColorScope Color(OS, ShowColors, ValueColor);
1033  OS << " " << Node->getValue().toString(10, isSigned);
1034}
1035
1036void TextNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *Node) {
1037  ColorScope Color(OS, ShowColors, ValueColor);
1038  OS << " " << Node->getValueAsString(/*Radix=*/10);
1039}
1040
1041void TextNodeDumper::VisitFloatingLiteral(const FloatingLiteral *Node) {
1042  ColorScope Color(OS, ShowColors, ValueColor);
1043  OS << " " << Node->getValueAsApproximateDouble();
1044}
1045
1046void TextNodeDumper::VisitStringLiteral(const StringLiteral *Str) {
1047  ColorScope Color(OS, ShowColors, ValueColor);
1048  OS << " ";
1049  Str->outputString(OS);
1050}
1051
1052void TextNodeDumper::VisitInitListExpr(const InitListExpr *ILE) {
1053  if (auto *Field = ILE->getInitializedFieldInUnion()) {
1054    OS << " field ";
1055    dumpBareDeclRef(Field);
1056  }
1057}
1058
1059void TextNodeDumper::VisitGenericSelectionExpr(const GenericSelectionExpr *E) {
1060  if (E->isResultDependent())
1061    OS << " result_dependent";
1062}
1063
1064void TextNodeDumper::VisitUnaryOperator(const UnaryOperator *Node) {
1065  OS << " " << (Node->isPostfix() ? "postfix" : "prefix") << " '"
1066     << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
1067  if (!Node->canOverflow())
1068    OS << " cannot overflow";
1069  if (Node->hasStoredFPFeatures())
1070    printFPOptions(Node->getStoredFPFeatures());
1071}
1072
1073void TextNodeDumper::VisitUnaryExprOrTypeTraitExpr(
1074    const UnaryExprOrTypeTraitExpr *Node) {
1075  OS << " " << getTraitSpelling(Node->getKind());
1076
1077  if (Node->isArgumentType())
1078    dumpType(Node->getArgumentType());
1079}
1080
1081void TextNodeDumper::VisitMemberExpr(const MemberExpr *Node) {
1082  OS << " " << (Node->isArrow() ? "->" : ".") << *Node->getMemberDecl();
1083  dumpPointer(Node->getMemberDecl());
1084  switch (Node->isNonOdrUse()) {
1085  case NOUR_None: break;
1086  case NOUR_Unevaluated: OS << " non_odr_use_unevaluated"; break;
1087  case NOUR_Constant: OS << " non_odr_use_constant"; break;
1088  case NOUR_Discarded: OS << " non_odr_use_discarded"; break;
1089  }
1090}
1091
1092void TextNodeDumper::VisitExtVectorElementExpr(
1093    const ExtVectorElementExpr *Node) {
1094  OS << " " << Node->getAccessor().getNameStart();
1095}
1096
1097void TextNodeDumper::VisitBinaryOperator(const BinaryOperator *Node) {
1098  OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
1099  if (Node->hasStoredFPFeatures())
1100    printFPOptions(Node->getStoredFPFeatures());
1101}
1102
1103void TextNodeDumper::VisitCompoundAssignOperator(
1104    const CompoundAssignOperator *Node) {
1105  OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode())
1106     << "' ComputeLHSTy=";
1107  dumpBareType(Node->getComputationLHSType());
1108  OS << " ComputeResultTy=";
1109  dumpBareType(Node->getComputationResultType());
1110  if (Node->hasStoredFPFeatures())
1111    printFPOptions(Node->getStoredFPFeatures());
1112}
1113
1114void TextNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) {
1115  OS << " " << Node->getLabel()->getName();
1116  dumpPointer(Node->getLabel());
1117}
1118
1119void TextNodeDumper::VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node) {
1120  OS << " " << Node->getCastName() << "<"
1121     << Node->getTypeAsWritten().getAsString() << ">"
1122     << " <" << Node->getCastKindName();
1123  dumpBasePath(OS, Node);
1124  OS << ">";
1125}
1126
1127void TextNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node) {
1128  OS << " " << (Node->getValue() ? "true" : "false");
1129}
1130
1131void TextNodeDumper::VisitCXXThisExpr(const CXXThisExpr *Node) {
1132  if (Node->isImplicit())
1133    OS << " implicit";
1134  OS << " this";
1135}
1136
1137void TextNodeDumper::VisitCXXFunctionalCastExpr(
1138    const CXXFunctionalCastExpr *Node) {
1139  OS << " functional cast to " << Node->getTypeAsWritten().getAsString() << " <"
1140     << Node->getCastKindName() << ">";
1141  if (Node->hasStoredFPFeatures())
1142    printFPOptions(Node->getFPFeatures());
1143}
1144
1145void TextNodeDumper::VisitCXXStaticCastExpr(const CXXStaticCastExpr *Node) {
1146  VisitCXXNamedCastExpr(Node);
1147  if (Node->hasStoredFPFeatures())
1148    printFPOptions(Node->getFPFeatures());
1149}
1150
1151void TextNodeDumper::VisitCXXUnresolvedConstructExpr(
1152    const CXXUnresolvedConstructExpr *Node) {
1153  dumpType(Node->getTypeAsWritten());
1154  if (Node->isListInitialization())
1155    OS << " list";
1156}
1157
1158void TextNodeDumper::VisitCXXConstructExpr(const CXXConstructExpr *Node) {
1159  CXXConstructorDecl *Ctor = Node->getConstructor();
1160  dumpType(Ctor->getType());
1161  if (Node->isElidable())
1162    OS << " elidable";
1163  if (Node->isListInitialization())
1164    OS << " list";
1165  if (Node->isStdInitListInitialization())
1166    OS << " std::initializer_list";
1167  if (Node->requiresZeroInitialization())
1168    OS << " zeroing";
1169}
1170
1171void TextNodeDumper::VisitCXXBindTemporaryExpr(
1172    const CXXBindTemporaryExpr *Node) {
1173  OS << " (CXXTemporary";
1174  dumpPointer(Node);
1175  OS << ")";
1176}
1177
1178void TextNodeDumper::VisitCXXNewExpr(const CXXNewExpr *Node) {
1179  if (Node->isGlobalNew())
1180    OS << " global";
1181  if (Node->isArray())
1182    OS << " array";
1183  if (Node->getOperatorNew()) {
1184    OS << ' ';
1185    dumpBareDeclRef(Node->getOperatorNew());
1186  }
1187  // We could dump the deallocation function used in case of error, but it's
1188  // usually not that interesting.
1189}
1190
1191void TextNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *Node) {
1192  if (Node->isGlobalDelete())
1193    OS << " global";
1194  if (Node->isArrayForm())
1195    OS << " array";
1196  if (Node->getOperatorDelete()) {
1197    OS << ' ';
1198    dumpBareDeclRef(Node->getOperatorDelete());
1199  }
1200}
1201
1202void TextNodeDumper::VisitTypeTraitExpr(const TypeTraitExpr *Node) {
1203  OS << " " << getTraitSpelling(Node->getTrait());
1204}
1205
1206void TextNodeDumper::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *Node) {
1207  OS << " " << getTraitSpelling(Node->getTrait());
1208}
1209
1210void TextNodeDumper::VisitExpressionTraitExpr(const ExpressionTraitExpr *Node) {
1211  OS << " " << getTraitSpelling(Node->getTrait());
1212}
1213
1214void TextNodeDumper::VisitMaterializeTemporaryExpr(
1215    const MaterializeTemporaryExpr *Node) {
1216  if (const ValueDecl *VD = Node->getExtendingDecl()) {
1217    OS << " extended by ";
1218    dumpBareDeclRef(VD);
1219  }
1220}
1221
1222void TextNodeDumper::VisitExprWithCleanups(const ExprWithCleanups *Node) {
1223  for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i)
1224    dumpCleanupObject(Node->getObject(i));
1225}
1226
1227void TextNodeDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) {
1228  dumpPointer(Node->getPack());
1229  dumpName(Node->getPack());
1230}
1231
1232void TextNodeDumper::VisitCXXDependentScopeMemberExpr(
1233    const CXXDependentScopeMemberExpr *Node) {
1234  OS << " " << (Node->isArrow() ? "->" : ".") << Node->getMember();
1235}
1236
1237void TextNodeDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) {
1238  OS << " selector=";
1239  Node->getSelector().print(OS);
1240  switch (Node->getReceiverKind()) {
1241  case ObjCMessageExpr::Instance:
1242    break;
1243
1244  case ObjCMessageExpr::Class:
1245    OS << " class=";
1246    dumpBareType(Node->getClassReceiver());
1247    break;
1248
1249  case ObjCMessageExpr::SuperInstance:
1250    OS << " super (instance)";
1251    break;
1252
1253  case ObjCMessageExpr::SuperClass:
1254    OS << " super (class)";
1255    break;
1256  }
1257}
1258
1259void TextNodeDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *Node) {
1260  if (auto *BoxingMethod = Node->getBoxingMethod()) {
1261    OS << " selector=";
1262    BoxingMethod->getSelector().print(OS);
1263  }
1264}
1265
1266void TextNodeDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) {
1267  if (!Node->getCatchParamDecl())
1268    OS << " catch all";
1269}
1270
1271void TextNodeDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *Node) {
1272  dumpType(Node->getEncodedType());
1273}
1274
1275void TextNodeDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *Node) {
1276  OS << " ";
1277  Node->getSelector().print(OS);
1278}
1279
1280void TextNodeDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *Node) {
1281  OS << ' ' << *Node->getProtocol();
1282}
1283
1284void TextNodeDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node) {
1285  if (Node->isImplicitProperty()) {
1286    OS << " Kind=MethodRef Getter=\"";
1287    if (Node->getImplicitPropertyGetter())
1288      Node->getImplicitPropertyGetter()->getSelector().print(OS);
1289    else
1290      OS << "(null)";
1291
1292    OS << "\" Setter=\"";
1293    if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter())
1294      Setter->getSelector().print(OS);
1295    else
1296      OS << "(null)";
1297    OS << "\"";
1298  } else {
1299    OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty()
1300       << '"';
1301  }
1302
1303  if (Node->isSuperReceiver())
1304    OS << " super";
1305
1306  OS << " Messaging=";
1307  if (Node->isMessagingGetter() && Node->isMessagingSetter())
1308    OS << "Getter&Setter";
1309  else if (Node->isMessagingGetter())
1310    OS << "Getter";
1311  else if (Node->isMessagingSetter())
1312    OS << "Setter";
1313}
1314
1315void TextNodeDumper::VisitObjCSubscriptRefExpr(
1316    const ObjCSubscriptRefExpr *Node) {
1317  if (Node->isArraySubscriptRefExpr())
1318    OS << " Kind=ArraySubscript GetterForArray=\"";
1319  else
1320    OS << " Kind=DictionarySubscript GetterForDictionary=\"";
1321  if (Node->getAtIndexMethodDecl())
1322    Node->getAtIndexMethodDecl()->getSelector().print(OS);
1323  else
1324    OS << "(null)";
1325
1326  if (Node->isArraySubscriptRefExpr())
1327    OS << "\" SetterForArray=\"";
1328  else
1329    OS << "\" SetterForDictionary=\"";
1330  if (Node->setAtIndexMethodDecl())
1331    Node->setAtIndexMethodDecl()->getSelector().print(OS);
1332  else
1333    OS << "(null)";
1334}
1335
1336void TextNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node) {
1337  OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no");
1338}
1339
1340void TextNodeDumper::VisitOMPIteratorExpr(const OMPIteratorExpr *Node) {
1341  OS << " ";
1342  for (unsigned I = 0, E = Node->numOfIterators(); I < E; ++I) {
1343    Visit(Node->getIteratorDecl(I));
1344    OS << " = ";
1345    const OMPIteratorExpr::IteratorRange Range = Node->getIteratorRange(I);
1346    OS << " begin ";
1347    Visit(Range.Begin);
1348    OS << " end ";
1349    Visit(Range.End);
1350    if (Range.Step) {
1351      OS << " step ";
1352      Visit(Range.Step);
1353    }
1354  }
1355}
1356
1357void TextNodeDumper::VisitConceptSpecializationExpr(
1358    const ConceptSpecializationExpr *Node) {
1359  OS << " ";
1360  dumpBareDeclRef(Node->getFoundDecl());
1361}
1362
1363void TextNodeDumper::VisitRValueReferenceType(const ReferenceType *T) {
1364  if (T->isSpelledAsLValue())
1365    OS << " written as lvalue reference";
1366}
1367
1368void TextNodeDumper::VisitArrayType(const ArrayType *T) {
1369  switch (T->getSizeModifier()) {
1370  case ArrayType::Normal:
1371    break;
1372  case ArrayType::Static:
1373    OS << " static";
1374    break;
1375  case ArrayType::Star:
1376    OS << " *";
1377    break;
1378  }
1379  OS << " " << T->getIndexTypeQualifiers().getAsString();
1380}
1381
1382void TextNodeDumper::VisitConstantArrayType(const ConstantArrayType *T) {
1383  OS << " " << T->getSize();
1384  VisitArrayType(T);
1385}
1386
1387void TextNodeDumper::VisitVariableArrayType(const VariableArrayType *T) {
1388  OS << " ";
1389  dumpSourceRange(T->getBracketsRange());
1390  VisitArrayType(T);
1391}
1392
1393void TextNodeDumper::VisitDependentSizedArrayType(
1394    const DependentSizedArrayType *T) {
1395  VisitArrayType(T);
1396  OS << " ";
1397  dumpSourceRange(T->getBracketsRange());
1398}
1399
1400void TextNodeDumper::VisitDependentSizedExtVectorType(
1401    const DependentSizedExtVectorType *T) {
1402  OS << " ";
1403  dumpLocation(T->getAttributeLoc());
1404}
1405
1406void TextNodeDumper::VisitVectorType(const VectorType *T) {
1407  switch (T->getVectorKind()) {
1408  case VectorType::GenericVector:
1409    break;
1410  case VectorType::AltiVecVector:
1411    OS << " altivec";
1412    break;
1413  case VectorType::AltiVecPixel:
1414    OS << " altivec pixel";
1415    break;
1416  case VectorType::AltiVecBool:
1417    OS << " altivec bool";
1418    break;
1419  case VectorType::NeonVector:
1420    OS << " neon";
1421    break;
1422  case VectorType::NeonPolyVector:
1423    OS << " neon poly";
1424    break;
1425  case VectorType::SveFixedLengthDataVector:
1426    OS << " fixed-length sve data vector";
1427    break;
1428  case VectorType::SveFixedLengthPredicateVector:
1429    OS << " fixed-length sve predicate vector";
1430    break;
1431  }
1432  OS << " " << T->getNumElements();
1433}
1434
1435void TextNodeDumper::VisitFunctionType(const FunctionType *T) {
1436  auto EI = T->getExtInfo();
1437  if (EI.getNoReturn())
1438    OS << " noreturn";
1439  if (EI.getProducesResult())
1440    OS << " produces_result";
1441  if (EI.getHasRegParm())
1442    OS << " regparm " << EI.getRegParm();
1443  OS << " " << FunctionType::getNameForCallConv(EI.getCC());
1444}
1445
1446void TextNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) {
1447  auto EPI = T->getExtProtoInfo();
1448  if (EPI.HasTrailingReturn)
1449    OS << " trailing_return";
1450  if (T->isConst())
1451    OS << " const";
1452  if (T->isVolatile())
1453    OS << " volatile";
1454  if (T->isRestrict())
1455    OS << " restrict";
1456  if (T->getExtProtoInfo().Variadic)
1457    OS << " variadic";
1458  switch (EPI.RefQualifier) {
1459  case RQ_None:
1460    break;
1461  case RQ_LValue:
1462    OS << " &";
1463    break;
1464  case RQ_RValue:
1465    OS << " &&";
1466    break;
1467  }
1468  // FIXME: Exception specification.
1469  // FIXME: Consumed parameters.
1470  VisitFunctionType(T);
1471}
1472
1473void TextNodeDumper::VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
1474  dumpDeclRef(T->getDecl());
1475}
1476
1477void TextNodeDumper::VisitTypedefType(const TypedefType *T) {
1478  dumpDeclRef(T->getDecl());
1479}
1480
1481void TextNodeDumper::VisitUnaryTransformType(const UnaryTransformType *T) {
1482  switch (T->getUTTKind()) {
1483  case UnaryTransformType::EnumUnderlyingType:
1484    OS << " underlying_type";
1485    break;
1486  }
1487}
1488
1489void TextNodeDumper::VisitTagType(const TagType *T) {
1490  dumpDeclRef(T->getDecl());
1491}
1492
1493void TextNodeDumper::VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
1494  OS << " depth " << T->getDepth() << " index " << T->getIndex();
1495  if (T->isParameterPack())
1496    OS << " pack";
1497  dumpDeclRef(T->getDecl());
1498}
1499
1500void TextNodeDumper::VisitAutoType(const AutoType *T) {
1501  if (T->isDecltypeAuto())
1502    OS << " decltype(auto)";
1503  if (!T->isDeduced())
1504    OS << " undeduced";
1505  if (T->isConstrained()) {
1506    dumpDeclRef(T->getTypeConstraintConcept());
1507    for (const auto &Arg : T->getTypeConstraintArguments())
1508      VisitTemplateArgument(Arg);
1509  }
1510}
1511
1512void TextNodeDumper::VisitTemplateSpecializationType(
1513    const TemplateSpecializationType *T) {
1514  if (T->isTypeAlias())
1515    OS << " alias";
1516  OS << " ";
1517  T->getTemplateName().dump(OS);
1518}
1519
1520void TextNodeDumper::VisitInjectedClassNameType(
1521    const InjectedClassNameType *T) {
1522  dumpDeclRef(T->getDecl());
1523}
1524
1525void TextNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
1526  dumpDeclRef(T->getDecl());
1527}
1528
1529void TextNodeDumper::VisitPackExpansionType(const PackExpansionType *T) {
1530  if (auto N = T->getNumExpansions())
1531    OS << " expansions " << *N;
1532}
1533
1534void TextNodeDumper::VisitLabelDecl(const LabelDecl *D) { dumpName(D); }
1535
1536void TextNodeDumper::VisitTypedefDecl(const TypedefDecl *D) {
1537  dumpName(D);
1538  dumpType(D->getUnderlyingType());
1539  if (D->isModulePrivate())
1540    OS << " __module_private__";
1541}
1542
1543void TextNodeDumper::VisitEnumDecl(const EnumDecl *D) {
1544  if (D->isScoped()) {
1545    if (D->isScopedUsingClassTag())
1546      OS << " class";
1547    else
1548      OS << " struct";
1549  }
1550  dumpName(D);
1551  if (D->isModulePrivate())
1552    OS << " __module_private__";
1553  if (D->isFixed())
1554    dumpType(D->getIntegerType());
1555}
1556
1557void TextNodeDumper::VisitRecordDecl(const RecordDecl *D) {
1558  OS << ' ' << D->getKindName();
1559  dumpName(D);
1560  if (D->isModulePrivate())
1561    OS << " __module_private__";
1562  if (D->isCompleteDefinition())
1563    OS << " definition";
1564}
1565
1566void TextNodeDumper::VisitEnumConstantDecl(const EnumConstantDecl *D) {
1567  dumpName(D);
1568  dumpType(D->getType());
1569}
1570
1571void TextNodeDumper::VisitIndirectFieldDecl(const IndirectFieldDecl *D) {
1572  dumpName(D);
1573  dumpType(D->getType());
1574
1575  for (const auto *Child : D->chain())
1576    dumpDeclRef(Child);
1577}
1578
1579void TextNodeDumper::VisitFunctionDecl(const FunctionDecl *D) {
1580  dumpName(D);
1581  dumpType(D->getType());
1582
1583  StorageClass SC = D->getStorageClass();
1584  if (SC != SC_None)
1585    OS << ' ' << VarDecl::getStorageClassSpecifierString(SC);
1586  if (D->isInlineSpecified())
1587    OS << " inline";
1588  if (D->isVirtualAsWritten())
1589    OS << " virtual";
1590  if (D->isModulePrivate())
1591    OS << " __module_private__";
1592
1593  if (D->isPure())
1594    OS << " pure";
1595  if (D->isDefaulted()) {
1596    OS << " default";
1597    if (D->isDeleted())
1598      OS << "_delete";
1599  }
1600  if (D->isDeletedAsWritten())
1601    OS << " delete";
1602  if (D->isTrivial())
1603    OS << " trivial";
1604
1605  if (const auto *FPT = D->getType()->getAs<FunctionProtoType>()) {
1606    FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
1607    switch (EPI.ExceptionSpec.Type) {
1608    default:
1609      break;
1610    case EST_Unevaluated:
1611      OS << " noexcept-unevaluated " << EPI.ExceptionSpec.SourceDecl;
1612      break;
1613    case EST_Uninstantiated:
1614      OS << " noexcept-uninstantiated " << EPI.ExceptionSpec.SourceTemplate;
1615      break;
1616    }
1617  }
1618
1619  if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
1620    if (MD->size_overridden_methods() != 0) {
1621      auto dumpOverride = [=](const CXXMethodDecl *D) {
1622        SplitQualType T_split = D->getType().split();
1623        OS << D << " " << D->getParent()->getName() << "::" << D->getDeclName()
1624           << " '" << QualType::getAsString(T_split, PrintPolicy) << "'";
1625      };
1626
1627      AddChild([=] {
1628        auto Overrides = MD->overridden_methods();
1629        OS << "Overrides: [ ";
1630        dumpOverride(*Overrides.begin());
1631        for (const auto *Override :
1632             llvm::make_range(Overrides.begin() + 1, Overrides.end())) {
1633          OS << ", ";
1634          dumpOverride(Override);
1635        }
1636        OS << " ]";
1637      });
1638    }
1639  }
1640
1641  // Since NumParams comes from the FunctionProtoType of the FunctionDecl and
1642  // the Params are set later, it is possible for a dump during debugging to
1643  // encounter a FunctionDecl that has been created but hasn't been assigned
1644  // ParmVarDecls yet.
1645  if (!D->param_empty() && !D->param_begin())
1646    OS << " <<<NULL params x " << D->getNumParams() << ">>>";
1647}
1648
1649void TextNodeDumper::VisitLifetimeExtendedTemporaryDecl(
1650    const LifetimeExtendedTemporaryDecl *D) {
1651  OS << " extended by ";
1652  dumpBareDeclRef(D->getExtendingDecl());
1653  OS << " mangling ";
1654  {
1655    ColorScope Color(OS, ShowColors, ValueColor);
1656    OS << D->getManglingNumber();
1657  }
1658}
1659
1660void TextNodeDumper::VisitFieldDecl(const FieldDecl *D) {
1661  dumpName(D);
1662  dumpType(D->getType());
1663  if (D->isMutable())
1664    OS << " mutable";
1665  if (D->isModulePrivate())
1666    OS << " __module_private__";
1667}
1668
1669void TextNodeDumper::VisitVarDecl(const VarDecl *D) {
1670  dumpName(D);
1671  dumpType(D->getType());
1672  StorageClass SC = D->getStorageClass();
1673  if (SC != SC_None)
1674    OS << ' ' << VarDecl::getStorageClassSpecifierString(SC);
1675  switch (D->getTLSKind()) {
1676  case VarDecl::TLS_None:
1677    break;
1678  case VarDecl::TLS_Static:
1679    OS << " tls";
1680    break;
1681  case VarDecl::TLS_Dynamic:
1682    OS << " tls_dynamic";
1683    break;
1684  }
1685  if (D->isModulePrivate())
1686    OS << " __module_private__";
1687  if (D->isNRVOVariable())
1688    OS << " nrvo";
1689  if (D->isInline())
1690    OS << " inline";
1691  if (D->isConstexpr())
1692    OS << " constexpr";
1693  if (D->hasInit()) {
1694    switch (D->getInitStyle()) {
1695    case VarDecl::CInit:
1696      OS << " cinit";
1697      break;
1698    case VarDecl::CallInit:
1699      OS << " callinit";
1700      break;
1701    case VarDecl::ListInit:
1702      OS << " listinit";
1703      break;
1704    }
1705  }
1706  if (D->needsDestruction(D->getASTContext()))
1707    OS << " destroyed";
1708  if (D->isParameterPack())
1709    OS << " pack";
1710
1711  if (D->hasInit()) {
1712    const Expr *E = D->getInit();
1713    // Only dump the value of constexpr VarDecls for now.
1714    if (E && !E->isValueDependent() && D->isConstexpr()) {
1715      const APValue *Value = D->evaluateValue();
1716      if (Value)
1717        AddChild("value", [=] { Visit(*Value, E->getType()); });
1718    }
1719  }
1720}
1721
1722void TextNodeDumper::VisitBindingDecl(const BindingDecl *D) {
1723  dumpName(D);
1724  dumpType(D->getType());
1725}
1726
1727void TextNodeDumper::VisitCapturedDecl(const CapturedDecl *D) {
1728  if (D->isNothrow())
1729    OS << " nothrow";
1730}
1731
1732void TextNodeDumper::VisitImportDecl(const ImportDecl *D) {
1733  OS << ' ' << D->getImportedModule()->getFullModuleName();
1734
1735  for (Decl *InitD :
1736       D->getASTContext().getModuleInitializers(D->getImportedModule()))
1737    dumpDeclRef(InitD, "initializer");
1738}
1739
1740void TextNodeDumper::VisitPragmaCommentDecl(const PragmaCommentDecl *D) {
1741  OS << ' ';
1742  switch (D->getCommentKind()) {
1743  case PCK_Unknown:
1744    llvm_unreachable("unexpected pragma comment kind");
1745  case PCK_Compiler:
1746    OS << "compiler";
1747    break;
1748  case PCK_ExeStr:
1749    OS << "exestr";
1750    break;
1751  case PCK_Lib:
1752    OS << "lib";
1753    break;
1754  case PCK_Linker:
1755    OS << "linker";
1756    break;
1757  case PCK_User:
1758    OS << "user";
1759    break;
1760  }
1761  StringRef Arg = D->getArg();
1762  if (!Arg.empty())
1763    OS << " \"" << Arg << "\"";
1764}
1765
1766void TextNodeDumper::VisitPragmaDetectMismatchDecl(
1767    const PragmaDetectMismatchDecl *D) {
1768  OS << " \"" << D->getName() << "\" \"" << D->getValue() << "\"";
1769}
1770
1771void TextNodeDumper::VisitOMPExecutableDirective(
1772    const OMPExecutableDirective *D) {
1773  if (D->isStandaloneDirective())
1774    OS << " openmp_standalone_directive";
1775}
1776
1777void TextNodeDumper::VisitOMPDeclareReductionDecl(
1778    const OMPDeclareReductionDecl *D) {
1779  dumpName(D);
1780  dumpType(D->getType());
1781  OS << " combiner";
1782  dumpPointer(D->getCombiner());
1783  if (const auto *Initializer = D->getInitializer()) {
1784    OS << " initializer";
1785    dumpPointer(Initializer);
1786    switch (D->getInitializerKind()) {
1787    case OMPDeclareReductionDecl::DirectInit:
1788      OS << " omp_priv = ";
1789      break;
1790    case OMPDeclareReductionDecl::CopyInit:
1791      OS << " omp_priv ()";
1792      break;
1793    case OMPDeclareReductionDecl::CallInit:
1794      break;
1795    }
1796  }
1797}
1798
1799void TextNodeDumper::VisitOMPRequiresDecl(const OMPRequiresDecl *D) {
1800  for (const auto *C : D->clauselists()) {
1801    AddChild([=] {
1802      if (!C) {
1803        ColorScope Color(OS, ShowColors, NullColor);
1804        OS << "<<<NULL>>> OMPClause";
1805        return;
1806      }
1807      {
1808        ColorScope Color(OS, ShowColors, AttrColor);
1809        StringRef ClauseName(
1810            llvm::omp::getOpenMPClauseName(C->getClauseKind()));
1811        OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper()
1812           << ClauseName.drop_front() << "Clause";
1813      }
1814      dumpPointer(C);
1815      dumpSourceRange(SourceRange(C->getBeginLoc(), C->getEndLoc()));
1816    });
1817  }
1818}
1819
1820void TextNodeDumper::VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) {
1821  dumpName(D);
1822  dumpType(D->getType());
1823}
1824
1825void TextNodeDumper::VisitNamespaceDecl(const NamespaceDecl *D) {
1826  dumpName(D);
1827  if (D->isInline())
1828    OS << " inline";
1829  if (!D->isOriginalNamespace())
1830    dumpDeclRef(D->getOriginalNamespace(), "original");
1831}
1832
1833void TextNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
1834  OS << ' ';
1835  dumpBareDeclRef(D->getNominatedNamespace());
1836}
1837
1838void TextNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
1839  dumpName(D);
1840  dumpDeclRef(D->getAliasedNamespace());
1841}
1842
1843void TextNodeDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) {
1844  dumpName(D);
1845  dumpType(D->getUnderlyingType());
1846}
1847
1848void TextNodeDumper::VisitTypeAliasTemplateDecl(
1849    const TypeAliasTemplateDecl *D) {
1850  dumpName(D);
1851}
1852
1853void TextNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
1854  VisitRecordDecl(D);
1855  if (!D->isCompleteDefinition())
1856    return;
1857
1858  AddChild([=] {
1859    {
1860      ColorScope Color(OS, ShowColors, DeclKindNameColor);
1861      OS << "DefinitionData";
1862    }
1863#define FLAG(fn, name)                                                         \
1864  if (D->fn())                                                                 \
1865    OS << " " #name;
1866    FLAG(isParsingBaseSpecifiers, parsing_base_specifiers);
1867
1868    FLAG(isGenericLambda, generic);
1869    FLAG(isLambda, lambda);
1870
1871    FLAG(isAnonymousStructOrUnion, is_anonymous);
1872    FLAG(canPassInRegisters, pass_in_registers);
1873    FLAG(isEmpty, empty);
1874    FLAG(isAggregate, aggregate);
1875    FLAG(isStandardLayout, standard_layout);
1876    FLAG(isTriviallyCopyable, trivially_copyable);
1877    FLAG(isPOD, pod);
1878    FLAG(isTrivial, trivial);
1879    FLAG(isPolymorphic, polymorphic);
1880    FLAG(isAbstract, abstract);
1881    FLAG(isLiteral, literal);
1882
1883    FLAG(hasUserDeclaredConstructor, has_user_declared_ctor);
1884    FLAG(hasConstexprNonCopyMoveConstructor, has_constexpr_non_copy_move_ctor);
1885    FLAG(hasMutableFields, has_mutable_fields);
1886    FLAG(hasVariantMembers, has_variant_members);
1887    FLAG(allowConstDefaultInit, can_const_default_init);
1888
1889    AddChild([=] {
1890      {
1891        ColorScope Color(OS, ShowColors, DeclKindNameColor);
1892        OS << "DefaultConstructor";
1893      }
1894      FLAG(hasDefaultConstructor, exists);
1895      FLAG(hasTrivialDefaultConstructor, trivial);
1896      FLAG(hasNonTrivialDefaultConstructor, non_trivial);
1897      FLAG(hasUserProvidedDefaultConstructor, user_provided);
1898      FLAG(hasConstexprDefaultConstructor, constexpr);
1899      FLAG(needsImplicitDefaultConstructor, needs_implicit);
1900      FLAG(defaultedDefaultConstructorIsConstexpr, defaulted_is_constexpr);
1901    });
1902
1903    AddChild([=] {
1904      {
1905        ColorScope Color(OS, ShowColors, DeclKindNameColor);
1906        OS << "CopyConstructor";
1907      }
1908      FLAG(hasSimpleCopyConstructor, simple);
1909      FLAG(hasTrivialCopyConstructor, trivial);
1910      FLAG(hasNonTrivialCopyConstructor, non_trivial);
1911      FLAG(hasUserDeclaredCopyConstructor, user_declared);
1912      FLAG(hasCopyConstructorWithConstParam, has_const_param);
1913      FLAG(needsImplicitCopyConstructor, needs_implicit);
1914      FLAG(needsOverloadResolutionForCopyConstructor,
1915           needs_overload_resolution);
1916      if (!D->needsOverloadResolutionForCopyConstructor())
1917        FLAG(defaultedCopyConstructorIsDeleted, defaulted_is_deleted);
1918      FLAG(implicitCopyConstructorHasConstParam, implicit_has_const_param);
1919    });
1920
1921    AddChild([=] {
1922      {
1923        ColorScope Color(OS, ShowColors, DeclKindNameColor);
1924        OS << "MoveConstructor";
1925      }
1926      FLAG(hasMoveConstructor, exists);
1927      FLAG(hasSimpleMoveConstructor, simple);
1928      FLAG(hasTrivialMoveConstructor, trivial);
1929      FLAG(hasNonTrivialMoveConstructor, non_trivial);
1930      FLAG(hasUserDeclaredMoveConstructor, user_declared);
1931      FLAG(needsImplicitMoveConstructor, needs_implicit);
1932      FLAG(needsOverloadResolutionForMoveConstructor,
1933           needs_overload_resolution);
1934      if (!D->needsOverloadResolutionForMoveConstructor())
1935        FLAG(defaultedMoveConstructorIsDeleted, defaulted_is_deleted);
1936    });
1937
1938    AddChild([=] {
1939      {
1940        ColorScope Color(OS, ShowColors, DeclKindNameColor);
1941        OS << "CopyAssignment";
1942      }
1943      FLAG(hasSimpleCopyAssignment, simple);
1944      FLAG(hasTrivialCopyAssignment, trivial);
1945      FLAG(hasNonTrivialCopyAssignment, non_trivial);
1946      FLAG(hasCopyAssignmentWithConstParam, has_const_param);
1947      FLAG(hasUserDeclaredCopyAssignment, user_declared);
1948      FLAG(needsImplicitCopyAssignment, needs_implicit);
1949      FLAG(needsOverloadResolutionForCopyAssignment, needs_overload_resolution);
1950      FLAG(implicitCopyAssignmentHasConstParam, implicit_has_const_param);
1951    });
1952
1953    AddChild([=] {
1954      {
1955        ColorScope Color(OS, ShowColors, DeclKindNameColor);
1956        OS << "MoveAssignment";
1957      }
1958      FLAG(hasMoveAssignment, exists);
1959      FLAG(hasSimpleMoveAssignment, simple);
1960      FLAG(hasTrivialMoveAssignment, trivial);
1961      FLAG(hasNonTrivialMoveAssignment, non_trivial);
1962      FLAG(hasUserDeclaredMoveAssignment, user_declared);
1963      FLAG(needsImplicitMoveAssignment, needs_implicit);
1964      FLAG(needsOverloadResolutionForMoveAssignment, needs_overload_resolution);
1965    });
1966
1967    AddChild([=] {
1968      {
1969        ColorScope Color(OS, ShowColors, DeclKindNameColor);
1970        OS << "Destructor";
1971      }
1972      FLAG(hasSimpleDestructor, simple);
1973      FLAG(hasIrrelevantDestructor, irrelevant);
1974      FLAG(hasTrivialDestructor, trivial);
1975      FLAG(hasNonTrivialDestructor, non_trivial);
1976      FLAG(hasUserDeclaredDestructor, user_declared);
1977      FLAG(hasConstexprDestructor, constexpr);
1978      FLAG(needsImplicitDestructor, needs_implicit);
1979      FLAG(needsOverloadResolutionForDestructor, needs_overload_resolution);
1980      if (!D->needsOverloadResolutionForDestructor())
1981        FLAG(defaultedDestructorIsDeleted, defaulted_is_deleted);
1982    });
1983  });
1984
1985  for (const auto &I : D->bases()) {
1986    AddChild([=] {
1987      if (I.isVirtual())
1988        OS << "virtual ";
1989      dumpAccessSpecifier(I.getAccessSpecifier());
1990      dumpType(I.getType());
1991      if (I.isPackExpansion())
1992        OS << "...";
1993    });
1994  }
1995}
1996
1997void TextNodeDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
1998  dumpName(D);
1999}
2000
2001void TextNodeDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
2002  dumpName(D);
2003}
2004
2005void TextNodeDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
2006  dumpName(D);
2007}
2008
2009void TextNodeDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) {
2010  dumpName(D);
2011}
2012
2013void TextNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
2014  if (const auto *TC = D->getTypeConstraint()) {
2015    OS << " ";
2016    dumpBareDeclRef(TC->getNamedConcept());
2017    if (TC->getNamedConcept() != TC->getFoundDecl()) {
2018      OS << " (";
2019      dumpBareDeclRef(TC->getFoundDecl());
2020      OS << ")";
2021    }
2022  } else if (D->wasDeclaredWithTypename())
2023    OS << " typename";
2024  else
2025    OS << " class";
2026  OS << " depth " << D->getDepth() << " index " << D->getIndex();
2027  if (D->isParameterPack())
2028    OS << " ...";
2029  dumpName(D);
2030}
2031
2032void TextNodeDumper::VisitNonTypeTemplateParmDecl(
2033    const NonTypeTemplateParmDecl *D) {
2034  dumpType(D->getType());
2035  OS << " depth " << D->getDepth() << " index " << D->getIndex();
2036  if (D->isParameterPack())
2037    OS << " ...";
2038  dumpName(D);
2039}
2040
2041void TextNodeDumper::VisitTemplateTemplateParmDecl(
2042    const TemplateTemplateParmDecl *D) {
2043  OS << " depth " << D->getDepth() << " index " << D->getIndex();
2044  if (D->isParameterPack())
2045    OS << " ...";
2046  dumpName(D);
2047}
2048
2049void TextNodeDumper::VisitUsingDecl(const UsingDecl *D) {
2050  OS << ' ';
2051  if (D->getQualifier())
2052    D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
2053  OS << D->getDeclName();
2054}
2055
2056void TextNodeDumper::VisitUnresolvedUsingTypenameDecl(
2057    const UnresolvedUsingTypenameDecl *D) {
2058  OS << ' ';
2059  if (D->getQualifier())
2060    D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
2061  OS << D->getDeclName();
2062}
2063
2064void TextNodeDumper::VisitUnresolvedUsingValueDecl(
2065    const UnresolvedUsingValueDecl *D) {
2066  OS << ' ';
2067  if (D->getQualifier())
2068    D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
2069  OS << D->getDeclName();
2070  dumpType(D->getType());
2071}
2072
2073void TextNodeDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) {
2074  OS << ' ';
2075  dumpBareDeclRef(D->getTargetDecl());
2076}
2077
2078void TextNodeDumper::VisitConstructorUsingShadowDecl(
2079    const ConstructorUsingShadowDecl *D) {
2080  if (D->constructsVirtualBase())
2081    OS << " virtual";
2082
2083  AddChild([=] {
2084    OS << "target ";
2085    dumpBareDeclRef(D->getTargetDecl());
2086  });
2087
2088  AddChild([=] {
2089    OS << "nominated ";
2090    dumpBareDeclRef(D->getNominatedBaseClass());
2091    OS << ' ';
2092    dumpBareDeclRef(D->getNominatedBaseClassShadowDecl());
2093  });
2094
2095  AddChild([=] {
2096    OS << "constructed ";
2097    dumpBareDeclRef(D->getConstructedBaseClass());
2098    OS << ' ';
2099    dumpBareDeclRef(D->getConstructedBaseClassShadowDecl());
2100  });
2101}
2102
2103void TextNodeDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
2104  switch (D->getLanguage()) {
2105  case LinkageSpecDecl::lang_c:
2106    OS << " C";
2107    break;
2108  case LinkageSpecDecl::lang_cxx:
2109    OS << " C++";
2110    break;
2111  }
2112}
2113
2114void TextNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl *D) {
2115  OS << ' ';
2116  dumpAccessSpecifier(D->getAccess());
2117}
2118
2119void TextNodeDumper::VisitFriendDecl(const FriendDecl *D) {
2120  if (TypeSourceInfo *T = D->getFriendType())
2121    dumpType(T->getType());
2122}
2123
2124void TextNodeDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) {
2125  dumpName(D);
2126  dumpType(D->getType());
2127  if (D->getSynthesize())
2128    OS << " synthesize";
2129
2130  switch (D->getAccessControl()) {
2131  case ObjCIvarDecl::None:
2132    OS << " none";
2133    break;
2134  case ObjCIvarDecl::Private:
2135    OS << " private";
2136    break;
2137  case ObjCIvarDecl::Protected:
2138    OS << " protected";
2139    break;
2140  case ObjCIvarDecl::Public:
2141    OS << " public";
2142    break;
2143  case ObjCIvarDecl::Package:
2144    OS << " package";
2145    break;
2146  }
2147}
2148
2149void TextNodeDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
2150  if (D->isInstanceMethod())
2151    OS << " -";
2152  else
2153    OS << " +";
2154  dumpName(D);
2155  dumpType(D->getReturnType());
2156
2157  if (D->isVariadic())
2158    OS << " variadic";
2159}
2160
2161void TextNodeDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) {
2162  dumpName(D);
2163  switch (D->getVariance()) {
2164  case ObjCTypeParamVariance::Invariant:
2165    break;
2166
2167  case ObjCTypeParamVariance::Covariant:
2168    OS << " covariant";
2169    break;
2170
2171  case ObjCTypeParamVariance::Contravariant:
2172    OS << " contravariant";
2173    break;
2174  }
2175
2176  if (D->hasExplicitBound())
2177    OS << " bounded";
2178  dumpType(D->getUnderlyingType());
2179}
2180
2181void TextNodeDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
2182  dumpName(D);
2183  dumpDeclRef(D->getClassInterface());
2184  dumpDeclRef(D->getImplementation());
2185  for (const auto *P : D->protocols())
2186    dumpDeclRef(P);
2187}
2188
2189void TextNodeDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
2190  dumpName(D);
2191  dumpDeclRef(D->getClassInterface());
2192  dumpDeclRef(D->getCategoryDecl());
2193}
2194
2195void TextNodeDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
2196  dumpName(D);
2197
2198  for (const auto *Child : D->protocols())
2199    dumpDeclRef(Child);
2200}
2201
2202void TextNodeDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
2203  dumpName(D);
2204  dumpDeclRef(D->getSuperClass(), "super");
2205
2206  dumpDeclRef(D->getImplementation());
2207  for (const auto *Child : D->protocols())
2208    dumpDeclRef(Child);
2209}
2210
2211void TextNodeDumper::VisitObjCImplementationDecl(
2212    const ObjCImplementationDecl *D) {
2213  dumpName(D);
2214  dumpDeclRef(D->getSuperClass(), "super");
2215  dumpDeclRef(D->getClassInterface());
2216}
2217
2218void TextNodeDumper::VisitObjCCompatibleAliasDecl(
2219    const ObjCCompatibleAliasDecl *D) {
2220  dumpName(D);
2221  dumpDeclRef(D->getClassInterface());
2222}
2223
2224void TextNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
2225  dumpName(D);
2226  dumpType(D->getType());
2227
2228  if (D->getPropertyImplementation() == ObjCPropertyDecl::Required)
2229    OS << " required";
2230  else if (D->getPropertyImplementation() == ObjCPropertyDecl::Optional)
2231    OS << " optional";
2232
2233  ObjCPropertyAttribute::Kind Attrs = D->getPropertyAttributes();
2234  if (Attrs != ObjCPropertyAttribute::kind_noattr) {
2235    if (Attrs & ObjCPropertyAttribute::kind_readonly)
2236      OS << " readonly";
2237    if (Attrs & ObjCPropertyAttribute::kind_assign)
2238      OS << " assign";
2239    if (Attrs & ObjCPropertyAttribute::kind_readwrite)
2240      OS << " readwrite";
2241    if (Attrs & ObjCPropertyAttribute::kind_retain)
2242      OS << " retain";
2243    if (Attrs & ObjCPropertyAttribute::kind_copy)
2244      OS << " copy";
2245    if (Attrs & ObjCPropertyAttribute::kind_nonatomic)
2246      OS << " nonatomic";
2247    if (Attrs & ObjCPropertyAttribute::kind_atomic)
2248      OS << " atomic";
2249    if (Attrs & ObjCPropertyAttribute::kind_weak)
2250      OS << " weak";
2251    if (Attrs & ObjCPropertyAttribute::kind_strong)
2252      OS << " strong";
2253    if (Attrs & ObjCPropertyAttribute::kind_unsafe_unretained)
2254      OS << " unsafe_unretained";
2255    if (Attrs & ObjCPropertyAttribute::kind_class)
2256      OS << " class";
2257    if (Attrs & ObjCPropertyAttribute::kind_direct)
2258      OS << " direct";
2259    if (Attrs & ObjCPropertyAttribute::kind_getter)
2260      dumpDeclRef(D->getGetterMethodDecl(), "getter");
2261    if (Attrs & ObjCPropertyAttribute::kind_setter)
2262      dumpDeclRef(D->getSetterMethodDecl(), "setter");
2263  }
2264}
2265
2266void TextNodeDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
2267  dumpName(D->getPropertyDecl());
2268  if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize)
2269    OS << " synthesize";
2270  else
2271    OS << " dynamic";
2272  dumpDeclRef(D->getPropertyDecl());
2273  dumpDeclRef(D->getPropertyIvarDecl());
2274}
2275
2276void TextNodeDumper::VisitBlockDecl(const BlockDecl *D) {
2277  if (D->isVariadic())
2278    OS << " variadic";
2279
2280  if (D->capturesCXXThis())
2281    OS << " captures_this";
2282}
2283
2284void TextNodeDumper::VisitConceptDecl(const ConceptDecl *D) {
2285  dumpName(D);
2286}
2287