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