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