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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of clang/lib/AST/TextNodeDumper.cpp