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