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