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

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