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