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