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