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