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