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