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