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