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