1 //===--- TextNodeDumper.cpp - Printing of AST nodes -----------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements AST dumping of components of individual AST nodes.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "clang/AST/TextNodeDumper.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
20 using namespace clang;
21
dumpPreviousDeclImpl(raw_ostream & OS,...)22 static void dumpPreviousDeclImpl(raw_ostream &OS, ...) {}
23
24 template <typename T>
dumpPreviousDeclImpl(raw_ostream & OS,const Mergeable<T> * D)25 static void dumpPreviousDeclImpl(raw_ostream &OS, const Mergeable<T> *D) {
26 const T *First = D->getFirstDecl();
27 if (First != D)
28 OS << " first " << First;
29 }
30
31 template <typename T>
dumpPreviousDeclImpl(raw_ostream & OS,const Redeclarable<T> * D)32 static void dumpPreviousDeclImpl(raw_ostream &OS, const Redeclarable<T> *D) {
33 const T *Prev = D->getPreviousDecl();
34 if (Prev)
35 OS << " prev " << Prev;
36 }
37
38 /// Dump the previous declaration in the redeclaration chain for a declaration,
39 /// if any.
dumpPreviousDecl(raw_ostream & OS,const Decl * D)40 static void dumpPreviousDecl(raw_ostream &OS, const Decl *D) {
41 switch (D->getKind()) {
42 #define DECL(DERIVED, BASE) \
43 case Decl::DERIVED: \
44 return dumpPreviousDeclImpl(OS, cast<DERIVED##Decl>(D));
45 #define ABSTRACT_DECL(DECL)
46 #include "clang/AST/DeclNodes.inc"
47 }
48 llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
49 }
50
TextNodeDumper(raw_ostream & OS,bool ShowColors,const SourceManager * SM,const PrintingPolicy & PrintPolicy,const comments::CommandTraits * Traits)51 TextNodeDumper::TextNodeDumper(raw_ostream &OS, bool ShowColors,
52 const SourceManager *SM,
53 const PrintingPolicy &PrintPolicy,
54 const comments::CommandTraits *Traits)
55 : TextTreeStructure(OS, ShowColors), OS(OS), ShowColors(ShowColors), SM(SM),
56 PrintPolicy(PrintPolicy), Traits(Traits) {}
57
Visit(const comments::Comment * C,const comments::FullComment * FC)58 void TextNodeDumper::Visit(const comments::Comment *C,
59 const comments::FullComment *FC) {
60 if (!C) {
61 ColorScope Color(OS, ShowColors, NullColor);
62 OS << "<<<NULL>>>";
63 return;
64 }
65
66 {
67 ColorScope Color(OS, ShowColors, CommentColor);
68 OS << C->getCommentKindName();
69 }
70 dumpPointer(C);
71 dumpSourceRange(C->getSourceRange());
72
73 ConstCommentVisitor<TextNodeDumper, void,
74 const comments::FullComment *>::visit(C, FC);
75 }
76
Visit(const Attr * A)77 void TextNodeDumper::Visit(const Attr *A) {
78 {
79 ColorScope Color(OS, ShowColors, AttrColor);
80
81 switch (A->getKind()) {
82 #define ATTR(X) \
83 case attr::X: \
84 OS << #X; \
85 break;
86 #include "clang/Basic/AttrList.inc"
87 }
88 OS << "Attr";
89 }
90 dumpPointer(A);
91 dumpSourceRange(A->getRange());
92 if (A->isInherited())
93 OS << " Inherited";
94 if (A->isImplicit())
95 OS << " Implicit";
96
97 ConstAttrVisitor<TextNodeDumper>::Visit(A);
98 }
99
Visit(const TemplateArgument & TA,SourceRange R,const Decl * From,StringRef Label)100 void TextNodeDumper::Visit(const TemplateArgument &TA, SourceRange R,
101 const Decl *From, StringRef Label) {
102 OS << "TemplateArgument";
103 if (R.isValid())
104 dumpSourceRange(R);
105
106 if (From)
107 dumpDeclRef(From, Label);
108
109 ConstTemplateArgumentVisitor<TextNodeDumper>::Visit(TA);
110 }
111
Visit(const Stmt * Node)112 void TextNodeDumper::Visit(const Stmt *Node) {
113 if (!Node) {
114 ColorScope Color(OS, ShowColors, NullColor);
115 OS << "<<<NULL>>>";
116 return;
117 }
118 {
119 ColorScope Color(OS, ShowColors, StmtColor);
120 OS << Node->getStmtClassName();
121 }
122 dumpPointer(Node);
123 dumpSourceRange(Node->getSourceRange());
124
125 if (const auto *E = dyn_cast<Expr>(Node)) {
126 dumpType(E->getType());
127
128 {
129 ColorScope Color(OS, ShowColors, ValueKindColor);
130 switch (E->getValueKind()) {
131 case VK_RValue:
132 break;
133 case VK_LValue:
134 OS << " lvalue";
135 break;
136 case VK_XValue:
137 OS << " xvalue";
138 break;
139 }
140 }
141
142 {
143 ColorScope Color(OS, ShowColors, ObjectKindColor);
144 switch (E->getObjectKind()) {
145 case OK_Ordinary:
146 break;
147 case OK_BitField:
148 OS << " bitfield";
149 break;
150 case OK_ObjCProperty:
151 OS << " objcproperty";
152 break;
153 case OK_ObjCSubscript:
154 OS << " objcsubscript";
155 break;
156 case OK_VectorComponent:
157 OS << " vectorcomponent";
158 break;
159 }
160 }
161 }
162
163 ConstStmtVisitor<TextNodeDumper>::Visit(Node);
164 }
165
Visit(const Type * T)166 void TextNodeDumper::Visit(const Type *T) {
167 if (!T) {
168 ColorScope Color(OS, ShowColors, NullColor);
169 OS << "<<<NULL>>>";
170 return;
171 }
172 if (isa<LocInfoType>(T)) {
173 {
174 ColorScope Color(OS, ShowColors, TypeColor);
175 OS << "LocInfo Type";
176 }
177 dumpPointer(T);
178 return;
179 }
180
181 {
182 ColorScope Color(OS, ShowColors, TypeColor);
183 OS << T->getTypeClassName() << "Type";
184 }
185 dumpPointer(T);
186 OS << " ";
187 dumpBareType(QualType(T, 0), false);
188
189 QualType SingleStepDesugar =
190 T->getLocallyUnqualifiedSingleStepDesugaredType();
191 if (SingleStepDesugar != QualType(T, 0))
192 OS << " sugar";
193
194 if (T->isDependentType())
195 OS << " dependent";
196 else if (T->isInstantiationDependentType())
197 OS << " instantiation_dependent";
198
199 if (T->isVariablyModifiedType())
200 OS << " variably_modified";
201 if (T->containsUnexpandedParameterPack())
202 OS << " contains_unexpanded_pack";
203 if (T->isFromAST())
204 OS << " imported";
205
206 TypeVisitor<TextNodeDumper>::Visit(T);
207 }
208
Visit(QualType T)209 void TextNodeDumper::Visit(QualType T) {
210 OS << "QualType";
211 dumpPointer(T.getAsOpaquePtr());
212 OS << " ";
213 dumpBareType(T, false);
214 OS << " " << T.split().Quals.getAsString();
215 }
216
Visit(const Decl * D)217 void TextNodeDumper::Visit(const Decl *D) {
218 if (!D) {
219 ColorScope Color(OS, ShowColors, NullColor);
220 OS << "<<<NULL>>>";
221 return;
222 }
223
224 {
225 ColorScope Color(OS, ShowColors, DeclKindNameColor);
226 OS << D->getDeclKindName() << "Decl";
227 }
228 dumpPointer(D);
229 if (D->getLexicalDeclContext() != D->getDeclContext())
230 OS << " parent " << cast<Decl>(D->getDeclContext());
231 dumpPreviousDecl(OS, D);
232 dumpSourceRange(D->getSourceRange());
233 OS << ' ';
234 dumpLocation(D->getLocation());
235 if (D->isFromASTFile())
236 OS << " imported";
237 if (Module *M = D->getOwningModule())
238 OS << " in " << M->getFullModuleName();
239 if (auto *ND = dyn_cast<NamedDecl>(D))
240 for (Module *M : D->getASTContext().getModulesWithMergedDefinition(
241 const_cast<NamedDecl *>(ND)))
242 AddChild([=] { OS << "also in " << M->getFullModuleName(); });
243 if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
244 if (ND->isHidden())
245 OS << " hidden";
246 if (D->isImplicit())
247 OS << " implicit";
248
249 if (D->isUsed())
250 OS << " used";
251 else if (D->isThisDeclarationReferenced())
252 OS << " referenced";
253
254 if (D->isInvalidDecl())
255 OS << " invalid";
256 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
257 if (FD->isConstexpr())
258 OS << " constexpr";
259 }
260
Visit(const CXXCtorInitializer * Init)261 void TextNodeDumper::Visit(const CXXCtorInitializer *Init) {
262 OS << "CXXCtorInitializer";
263 if (Init->isAnyMemberInitializer()) {
264 OS << ' ';
265 dumpBareDeclRef(Init->getAnyMember());
266 } else if (Init->isBaseInitializer()) {
267 dumpType(QualType(Init->getBaseClass(), 0));
268 } else if (Init->isDelegatingInitializer()) {
269 dumpType(Init->getTypeSourceInfo()->getType());
270 } else {
271 llvm_unreachable("Unknown initializer type");
272 }
273 }
274
Visit(const BlockDecl::Capture & C)275 void TextNodeDumper::Visit(const BlockDecl::Capture &C) {
276 OS << "capture";
277 if (C.isByRef())
278 OS << " byref";
279 if (C.isNested())
280 OS << " nested";
281 if (C.getVariable()) {
282 OS << ' ';
283 dumpBareDeclRef(C.getVariable());
284 }
285 }
286
Visit(const OMPClause * C)287 void TextNodeDumper::Visit(const OMPClause *C) {
288 if (!C) {
289 ColorScope Color(OS, ShowColors, NullColor);
290 OS << "<<<NULL>>> OMPClause";
291 return;
292 }
293 {
294 ColorScope Color(OS, ShowColors, AttrColor);
295 StringRef ClauseName(getOpenMPClauseName(C->getClauseKind()));
296 OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper()
297 << ClauseName.drop_front() << "Clause";
298 }
299 dumpPointer(C);
300 dumpSourceRange(SourceRange(C->getBeginLoc(), C->getEndLoc()));
301 if (C->isImplicit())
302 OS << " <implicit>";
303 }
304
dumpPointer(const void * Ptr)305 void TextNodeDumper::dumpPointer(const void *Ptr) {
306 ColorScope Color(OS, ShowColors, AddressColor);
307 OS << ' ' << Ptr;
308 }
309
dumpLocation(SourceLocation Loc)310 void TextNodeDumper::dumpLocation(SourceLocation Loc) {
311 if (!SM)
312 return;
313
314 ColorScope Color(OS, ShowColors, LocationColor);
315 SourceLocation SpellingLoc = SM->getSpellingLoc(Loc);
316
317 // The general format we print out is filename:line:col, but we drop pieces
318 // that haven't changed since the last loc printed.
319 PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc);
320
321 if (PLoc.isInvalid()) {
322 OS << "<invalid sloc>";
323 return;
324 }
325
326 if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) {
327 OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':'
328 << PLoc.getColumn();
329 LastLocFilename = PLoc.getFilename();
330 LastLocLine = PLoc.getLine();
331 } else if (PLoc.getLine() != LastLocLine) {
332 OS << "line" << ':' << PLoc.getLine() << ':' << PLoc.getColumn();
333 LastLocLine = PLoc.getLine();
334 } else {
335 OS << "col" << ':' << PLoc.getColumn();
336 }
337 }
338
dumpSourceRange(SourceRange R)339 void TextNodeDumper::dumpSourceRange(SourceRange R) {
340 // Can't translate locations if a SourceManager isn't available.
341 if (!SM)
342 return;
343
344 OS << " <";
345 dumpLocation(R.getBegin());
346 if (R.getBegin() != R.getEnd()) {
347 OS << ", ";
348 dumpLocation(R.getEnd());
349 }
350 OS << ">";
351
352 // <t2.c:123:421[blah], t2.c:412:321>
353 }
354
dumpBareType(QualType T,bool Desugar)355 void TextNodeDumper::dumpBareType(QualType T, bool Desugar) {
356 ColorScope Color(OS, ShowColors, TypeColor);
357
358 SplitQualType T_split = T.split();
359 OS << "'" << QualType::getAsString(T_split, PrintPolicy) << "'";
360
361 if (Desugar && !T.isNull()) {
362 // If the type is sugared, also dump a (shallow) desugared type.
363 SplitQualType D_split = T.getSplitDesugaredType();
364 if (T_split != D_split)
365 OS << ":'" << QualType::getAsString(D_split, PrintPolicy) << "'";
366 }
367 }
368
dumpType(QualType T)369 void TextNodeDumper::dumpType(QualType T) {
370 OS << ' ';
371 dumpBareType(T);
372 }
373
dumpBareDeclRef(const Decl * D)374 void TextNodeDumper::dumpBareDeclRef(const Decl *D) {
375 if (!D) {
376 ColorScope Color(OS, ShowColors, NullColor);
377 OS << "<<<NULL>>>";
378 return;
379 }
380
381 {
382 ColorScope Color(OS, ShowColors, DeclKindNameColor);
383 OS << D->getDeclKindName();
384 }
385 dumpPointer(D);
386
387 if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
388 ColorScope Color(OS, ShowColors, DeclNameColor);
389 OS << " '" << ND->getDeclName() << '\'';
390 }
391
392 if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
393 dumpType(VD->getType());
394 }
395
dumpName(const NamedDecl * ND)396 void TextNodeDumper::dumpName(const NamedDecl *ND) {
397 if (ND->getDeclName()) {
398 ColorScope Color(OS, ShowColors, DeclNameColor);
399 OS << ' ' << ND->getNameAsString();
400 }
401 }
402
dumpAccessSpecifier(AccessSpecifier AS)403 void TextNodeDumper::dumpAccessSpecifier(AccessSpecifier AS) {
404 switch (AS) {
405 case AS_none:
406 break;
407 case AS_public:
408 OS << "public";
409 break;
410 case AS_protected:
411 OS << "protected";
412 break;
413 case AS_private:
414 OS << "private";
415 break;
416 }
417 }
418
dumpCXXTemporary(const CXXTemporary * Temporary)419 void TextNodeDumper::dumpCXXTemporary(const CXXTemporary *Temporary) {
420 OS << "(CXXTemporary";
421 dumpPointer(Temporary);
422 OS << ")";
423 }
424
dumpDeclRef(const Decl * D,StringRef Label)425 void TextNodeDumper::dumpDeclRef(const Decl *D, StringRef Label) {
426 if (!D)
427 return;
428
429 AddChild([=] {
430 if (!Label.empty())
431 OS << Label << ' ';
432 dumpBareDeclRef(D);
433 });
434 }
435
getCommandName(unsigned CommandID)436 const char *TextNodeDumper::getCommandName(unsigned CommandID) {
437 if (Traits)
438 return Traits->getCommandInfo(CommandID)->Name;
439 const comments::CommandInfo *Info =
440 comments::CommandTraits::getBuiltinCommandInfo(CommandID);
441 if (Info)
442 return Info->Name;
443 return "<not a builtin command>";
444 }
445
visitTextComment(const comments::TextComment * C,const comments::FullComment *)446 void TextNodeDumper::visitTextComment(const comments::TextComment *C,
447 const comments::FullComment *) {
448 OS << " Text=\"" << C->getText() << "\"";
449 }
450
visitInlineCommandComment(const comments::InlineCommandComment * C,const comments::FullComment *)451 void TextNodeDumper::visitInlineCommandComment(
452 const comments::InlineCommandComment *C, const comments::FullComment *) {
453 OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
454 switch (C->getRenderKind()) {
455 case comments::InlineCommandComment::RenderNormal:
456 OS << " RenderNormal";
457 break;
458 case comments::InlineCommandComment::RenderBold:
459 OS << " RenderBold";
460 break;
461 case comments::InlineCommandComment::RenderMonospaced:
462 OS << " RenderMonospaced";
463 break;
464 case comments::InlineCommandComment::RenderEmphasized:
465 OS << " RenderEmphasized";
466 break;
467 }
468
469 for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
470 OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
471 }
472
visitHTMLStartTagComment(const comments::HTMLStartTagComment * C,const comments::FullComment *)473 void TextNodeDumper::visitHTMLStartTagComment(
474 const comments::HTMLStartTagComment *C, const comments::FullComment *) {
475 OS << " Name=\"" << C->getTagName() << "\"";
476 if (C->getNumAttrs() != 0) {
477 OS << " Attrs: ";
478 for (unsigned i = 0, e = C->getNumAttrs(); i != e; ++i) {
479 const comments::HTMLStartTagComment::Attribute &Attr = C->getAttr(i);
480 OS << " \"" << Attr.Name << "=\"" << Attr.Value << "\"";
481 }
482 }
483 if (C->isSelfClosing())
484 OS << " SelfClosing";
485 }
486
visitHTMLEndTagComment(const comments::HTMLEndTagComment * C,const comments::FullComment *)487 void TextNodeDumper::visitHTMLEndTagComment(
488 const comments::HTMLEndTagComment *C, const comments::FullComment *) {
489 OS << " Name=\"" << C->getTagName() << "\"";
490 }
491
visitBlockCommandComment(const comments::BlockCommandComment * C,const comments::FullComment *)492 void TextNodeDumper::visitBlockCommandComment(
493 const comments::BlockCommandComment *C, const comments::FullComment *) {
494 OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
495 for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
496 OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
497 }
498
visitParamCommandComment(const comments::ParamCommandComment * C,const comments::FullComment * FC)499 void TextNodeDumper::visitParamCommandComment(
500 const comments::ParamCommandComment *C, const comments::FullComment *FC) {
501 OS << " "
502 << comments::ParamCommandComment::getDirectionAsString(C->getDirection());
503
504 if (C->isDirectionExplicit())
505 OS << " explicitly";
506 else
507 OS << " implicitly";
508
509 if (C->hasParamName()) {
510 if (C->isParamIndexValid())
511 OS << " Param=\"" << C->getParamName(FC) << "\"";
512 else
513 OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
514 }
515
516 if (C->isParamIndexValid() && !C->isVarArgParam())
517 OS << " ParamIndex=" << C->getParamIndex();
518 }
519
visitTParamCommandComment(const comments::TParamCommandComment * C,const comments::FullComment * FC)520 void TextNodeDumper::visitTParamCommandComment(
521 const comments::TParamCommandComment *C, const comments::FullComment *FC) {
522 if (C->hasParamName()) {
523 if (C->isPositionValid())
524 OS << " Param=\"" << C->getParamName(FC) << "\"";
525 else
526 OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
527 }
528
529 if (C->isPositionValid()) {
530 OS << " Position=<";
531 for (unsigned i = 0, e = C->getDepth(); i != e; ++i) {
532 OS << C->getIndex(i);
533 if (i != e - 1)
534 OS << ", ";
535 }
536 OS << ">";
537 }
538 }
539
visitVerbatimBlockComment(const comments::VerbatimBlockComment * C,const comments::FullComment *)540 void TextNodeDumper::visitVerbatimBlockComment(
541 const comments::VerbatimBlockComment *C, const comments::FullComment *) {
542 OS << " Name=\"" << getCommandName(C->getCommandID())
543 << "\""
544 " CloseName=\""
545 << C->getCloseName() << "\"";
546 }
547
visitVerbatimBlockLineComment(const comments::VerbatimBlockLineComment * C,const comments::FullComment *)548 void TextNodeDumper::visitVerbatimBlockLineComment(
549 const comments::VerbatimBlockLineComment *C,
550 const comments::FullComment *) {
551 OS << " Text=\"" << C->getText() << "\"";
552 }
553
visitVerbatimLineComment(const comments::VerbatimLineComment * C,const comments::FullComment *)554 void TextNodeDumper::visitVerbatimLineComment(
555 const comments::VerbatimLineComment *C, const comments::FullComment *) {
556 OS << " Text=\"" << C->getText() << "\"";
557 }
558
VisitNullTemplateArgument(const TemplateArgument &)559 void TextNodeDumper::VisitNullTemplateArgument(const TemplateArgument &) {
560 OS << " null";
561 }
562
VisitTypeTemplateArgument(const TemplateArgument & TA)563 void TextNodeDumper::VisitTypeTemplateArgument(const TemplateArgument &TA) {
564 OS << " type";
565 dumpType(TA.getAsType());
566 }
567
VisitDeclarationTemplateArgument(const TemplateArgument & TA)568 void TextNodeDumper::VisitDeclarationTemplateArgument(
569 const TemplateArgument &TA) {
570 OS << " decl";
571 dumpDeclRef(TA.getAsDecl());
572 }
573
VisitNullPtrTemplateArgument(const TemplateArgument &)574 void TextNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument &) {
575 OS << " nullptr";
576 }
577
VisitIntegralTemplateArgument(const TemplateArgument & TA)578 void TextNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) {
579 OS << " integral " << TA.getAsIntegral();
580 }
581
VisitTemplateTemplateArgument(const TemplateArgument & TA)582 void TextNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) {
583 OS << " template ";
584 TA.getAsTemplate().dump(OS);
585 }
586
VisitTemplateExpansionTemplateArgument(const TemplateArgument & TA)587 void TextNodeDumper::VisitTemplateExpansionTemplateArgument(
588 const TemplateArgument &TA) {
589 OS << " template expansion ";
590 TA.getAsTemplateOrTemplatePattern().dump(OS);
591 }
592
VisitExpressionTemplateArgument(const TemplateArgument &)593 void TextNodeDumper::VisitExpressionTemplateArgument(const TemplateArgument &) {
594 OS << " expr";
595 }
596
VisitPackTemplateArgument(const TemplateArgument &)597 void TextNodeDumper::VisitPackTemplateArgument(const TemplateArgument &) {
598 OS << " pack";
599 }
600
dumpBasePath(raw_ostream & OS,const CastExpr * Node)601 static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) {
602 if (Node->path_empty())
603 return;
604
605 OS << " (";
606 bool First = true;
607 for (CastExpr::path_const_iterator I = Node->path_begin(),
608 E = Node->path_end();
609 I != E; ++I) {
610 const CXXBaseSpecifier *Base = *I;
611 if (!First)
612 OS << " -> ";
613
614 const CXXRecordDecl *RD =
615 cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
616
617 if (Base->isVirtual())
618 OS << "virtual ";
619 OS << RD->getName();
620 First = false;
621 }
622
623 OS << ')';
624 }
625
VisitIfStmt(const IfStmt * Node)626 void TextNodeDumper::VisitIfStmt(const IfStmt *Node) {
627 if (Node->hasInitStorage())
628 OS << " has_init";
629 if (Node->hasVarStorage())
630 OS << " has_var";
631 if (Node->hasElseStorage())
632 OS << " has_else";
633 }
634
VisitSwitchStmt(const SwitchStmt * Node)635 void TextNodeDumper::VisitSwitchStmt(const SwitchStmt *Node) {
636 if (Node->hasInitStorage())
637 OS << " has_init";
638 if (Node->hasVarStorage())
639 OS << " has_var";
640 }
641
VisitWhileStmt(const WhileStmt * Node)642 void TextNodeDumper::VisitWhileStmt(const WhileStmt *Node) {
643 if (Node->hasVarStorage())
644 OS << " has_var";
645 }
646
VisitLabelStmt(const LabelStmt * Node)647 void TextNodeDumper::VisitLabelStmt(const LabelStmt *Node) {
648 OS << " '" << Node->getName() << "'";
649 }
650
VisitGotoStmt(const GotoStmt * Node)651 void TextNodeDumper::VisitGotoStmt(const GotoStmt *Node) {
652 OS << " '" << Node->getLabel()->getName() << "'";
653 dumpPointer(Node->getLabel());
654 }
655
VisitCaseStmt(const CaseStmt * Node)656 void TextNodeDumper::VisitCaseStmt(const CaseStmt *Node) {
657 if (Node->caseStmtIsGNURange())
658 OS << " gnu_range";
659 }
660
VisitCallExpr(const CallExpr * Node)661 void TextNodeDumper::VisitCallExpr(const CallExpr *Node) {
662 if (Node->usesADL())
663 OS << " adl";
664 }
665
VisitCastExpr(const CastExpr * Node)666 void TextNodeDumper::VisitCastExpr(const CastExpr *Node) {
667 OS << " <";
668 {
669 ColorScope Color(OS, ShowColors, CastColor);
670 OS << Node->getCastKindName();
671 }
672 dumpBasePath(OS, Node);
673 OS << ">";
674 }
675
VisitImplicitCastExpr(const ImplicitCastExpr * Node)676 void TextNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *Node) {
677 VisitCastExpr(Node);
678 if (Node->isPartOfExplicitCast())
679 OS << " part_of_explicit_cast";
680 }
681
VisitDeclRefExpr(const DeclRefExpr * Node)682 void TextNodeDumper::VisitDeclRefExpr(const DeclRefExpr *Node) {
683 OS << " ";
684 dumpBareDeclRef(Node->getDecl());
685 if (Node->getDecl() != Node->getFoundDecl()) {
686 OS << " (";
687 dumpBareDeclRef(Node->getFoundDecl());
688 OS << ")";
689 }
690 }
691
VisitUnresolvedLookupExpr(const UnresolvedLookupExpr * Node)692 void TextNodeDumper::VisitUnresolvedLookupExpr(
693 const UnresolvedLookupExpr *Node) {
694 OS << " (";
695 if (!Node->requiresADL())
696 OS << "no ";
697 OS << "ADL) = '" << Node->getName() << '\'';
698
699 UnresolvedLookupExpr::decls_iterator I = Node->decls_begin(),
700 E = Node->decls_end();
701 if (I == E)
702 OS << " empty";
703 for (; I != E; ++I)
704 dumpPointer(*I);
705 }
706
VisitObjCIvarRefExpr(const ObjCIvarRefExpr * Node)707 void TextNodeDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) {
708 {
709 ColorScope Color(OS, ShowColors, DeclKindNameColor);
710 OS << " " << Node->getDecl()->getDeclKindName() << "Decl";
711 }
712 OS << "='" << *Node->getDecl() << "'";
713 dumpPointer(Node->getDecl());
714 if (Node->isFreeIvar())
715 OS << " isFreeIvar";
716 }
717
VisitPredefinedExpr(const PredefinedExpr * Node)718 void TextNodeDumper::VisitPredefinedExpr(const PredefinedExpr *Node) {
719 OS << " " << PredefinedExpr::getIdentKindName(Node->getIdentKind());
720 }
721
VisitCharacterLiteral(const CharacterLiteral * Node)722 void TextNodeDumper::VisitCharacterLiteral(const CharacterLiteral *Node) {
723 ColorScope Color(OS, ShowColors, ValueColor);
724 OS << " " << Node->getValue();
725 }
726
VisitIntegerLiteral(const IntegerLiteral * Node)727 void TextNodeDumper::VisitIntegerLiteral(const IntegerLiteral *Node) {
728 bool isSigned = Node->getType()->isSignedIntegerType();
729 ColorScope Color(OS, ShowColors, ValueColor);
730 OS << " " << Node->getValue().toString(10, isSigned);
731 }
732
VisitFixedPointLiteral(const FixedPointLiteral * Node)733 void TextNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *Node) {
734 ColorScope Color(OS, ShowColors, ValueColor);
735 OS << " " << Node->getValueAsString(/*Radix=*/10);
736 }
737
VisitFloatingLiteral(const FloatingLiteral * Node)738 void TextNodeDumper::VisitFloatingLiteral(const FloatingLiteral *Node) {
739 ColorScope Color(OS, ShowColors, ValueColor);
740 OS << " " << Node->getValueAsApproximateDouble();
741 }
742
VisitStringLiteral(const StringLiteral * Str)743 void TextNodeDumper::VisitStringLiteral(const StringLiteral *Str) {
744 ColorScope Color(OS, ShowColors, ValueColor);
745 OS << " ";
746 Str->outputString(OS);
747 }
748
VisitInitListExpr(const InitListExpr * ILE)749 void TextNodeDumper::VisitInitListExpr(const InitListExpr *ILE) {
750 if (auto *Field = ILE->getInitializedFieldInUnion()) {
751 OS << " field ";
752 dumpBareDeclRef(Field);
753 }
754 }
755
VisitUnaryOperator(const UnaryOperator * Node)756 void TextNodeDumper::VisitUnaryOperator(const UnaryOperator *Node) {
757 OS << " " << (Node->isPostfix() ? "postfix" : "prefix") << " '"
758 << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
759 if (!Node->canOverflow())
760 OS << " cannot overflow";
761 }
762
VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr * Node)763 void TextNodeDumper::VisitUnaryExprOrTypeTraitExpr(
764 const UnaryExprOrTypeTraitExpr *Node) {
765 switch (Node->getKind()) {
766 case UETT_SizeOf:
767 OS << " sizeof";
768 break;
769 case UETT_AlignOf:
770 OS << " alignof";
771 break;
772 case UETT_VecStep:
773 OS << " vec_step";
774 break;
775 case UETT_OpenMPRequiredSimdAlign:
776 OS << " __builtin_omp_required_simd_align";
777 break;
778 case UETT_PreferredAlignOf:
779 OS << " __alignof";
780 break;
781 }
782 if (Node->isArgumentType())
783 dumpType(Node->getArgumentType());
784 }
785
VisitMemberExpr(const MemberExpr * Node)786 void TextNodeDumper::VisitMemberExpr(const MemberExpr *Node) {
787 OS << " " << (Node->isArrow() ? "->" : ".") << *Node->getMemberDecl();
788 dumpPointer(Node->getMemberDecl());
789 }
790
VisitExtVectorElementExpr(const ExtVectorElementExpr * Node)791 void TextNodeDumper::VisitExtVectorElementExpr(
792 const ExtVectorElementExpr *Node) {
793 OS << " " << Node->getAccessor().getNameStart();
794 }
795
VisitBinaryOperator(const BinaryOperator * Node)796 void TextNodeDumper::VisitBinaryOperator(const BinaryOperator *Node) {
797 OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
798 }
799
VisitCompoundAssignOperator(const CompoundAssignOperator * Node)800 void TextNodeDumper::VisitCompoundAssignOperator(
801 const CompoundAssignOperator *Node) {
802 OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode())
803 << "' ComputeLHSTy=";
804 dumpBareType(Node->getComputationLHSType());
805 OS << " ComputeResultTy=";
806 dumpBareType(Node->getComputationResultType());
807 }
808
VisitAddrLabelExpr(const AddrLabelExpr * Node)809 void TextNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) {
810 OS << " " << Node->getLabel()->getName();
811 dumpPointer(Node->getLabel());
812 }
813
VisitCXXNamedCastExpr(const CXXNamedCastExpr * Node)814 void TextNodeDumper::VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node) {
815 OS << " " << Node->getCastName() << "<"
816 << Node->getTypeAsWritten().getAsString() << ">"
817 << " <" << Node->getCastKindName();
818 dumpBasePath(OS, Node);
819 OS << ">";
820 }
821
VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr * Node)822 void TextNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node) {
823 OS << " " << (Node->getValue() ? "true" : "false");
824 }
825
VisitCXXThisExpr(const CXXThisExpr * Node)826 void TextNodeDumper::VisitCXXThisExpr(const CXXThisExpr *Node) {
827 OS << " this";
828 }
829
VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr * Node)830 void TextNodeDumper::VisitCXXFunctionalCastExpr(
831 const CXXFunctionalCastExpr *Node) {
832 OS << " functional cast to " << Node->getTypeAsWritten().getAsString() << " <"
833 << Node->getCastKindName() << ">";
834 }
835
VisitCXXUnresolvedConstructExpr(const CXXUnresolvedConstructExpr * Node)836 void TextNodeDumper::VisitCXXUnresolvedConstructExpr(
837 const CXXUnresolvedConstructExpr *Node) {
838 dumpType(Node->getTypeAsWritten());
839 if (Node->isListInitialization())
840 OS << " list";
841 }
842
VisitCXXConstructExpr(const CXXConstructExpr * Node)843 void TextNodeDumper::VisitCXXConstructExpr(const CXXConstructExpr *Node) {
844 CXXConstructorDecl *Ctor = Node->getConstructor();
845 dumpType(Ctor->getType());
846 if (Node->isElidable())
847 OS << " elidable";
848 if (Node->isListInitialization())
849 OS << " list";
850 if (Node->isStdInitListInitialization())
851 OS << " std::initializer_list";
852 if (Node->requiresZeroInitialization())
853 OS << " zeroing";
854 }
855
VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr * Node)856 void TextNodeDumper::VisitCXXBindTemporaryExpr(
857 const CXXBindTemporaryExpr *Node) {
858 OS << " ";
859 dumpCXXTemporary(Node->getTemporary());
860 }
861
VisitCXXNewExpr(const CXXNewExpr * Node)862 void TextNodeDumper::VisitCXXNewExpr(const CXXNewExpr *Node) {
863 if (Node->isGlobalNew())
864 OS << " global";
865 if (Node->isArray())
866 OS << " array";
867 if (Node->getOperatorNew()) {
868 OS << ' ';
869 dumpBareDeclRef(Node->getOperatorNew());
870 }
871 // We could dump the deallocation function used in case of error, but it's
872 // usually not that interesting.
873 }
874
VisitCXXDeleteExpr(const CXXDeleteExpr * Node)875 void TextNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *Node) {
876 if (Node->isGlobalDelete())
877 OS << " global";
878 if (Node->isArrayForm())
879 OS << " array";
880 if (Node->getOperatorDelete()) {
881 OS << ' ';
882 dumpBareDeclRef(Node->getOperatorDelete());
883 }
884 }
885
VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr * Node)886 void TextNodeDumper::VisitMaterializeTemporaryExpr(
887 const MaterializeTemporaryExpr *Node) {
888 if (const ValueDecl *VD = Node->getExtendingDecl()) {
889 OS << " extended by ";
890 dumpBareDeclRef(VD);
891 }
892 }
893
VisitExprWithCleanups(const ExprWithCleanups * Node)894 void TextNodeDumper::VisitExprWithCleanups(const ExprWithCleanups *Node) {
895 for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i)
896 dumpDeclRef(Node->getObject(i), "cleanup");
897 }
898
VisitSizeOfPackExpr(const SizeOfPackExpr * Node)899 void TextNodeDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) {
900 dumpPointer(Node->getPack());
901 dumpName(Node->getPack());
902 }
903
VisitCXXDependentScopeMemberExpr(const CXXDependentScopeMemberExpr * Node)904 void TextNodeDumper::VisitCXXDependentScopeMemberExpr(
905 const CXXDependentScopeMemberExpr *Node) {
906 OS << " " << (Node->isArrow() ? "->" : ".") << Node->getMember();
907 }
908
VisitObjCMessageExpr(const ObjCMessageExpr * Node)909 void TextNodeDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) {
910 OS << " selector=";
911 Node->getSelector().print(OS);
912 switch (Node->getReceiverKind()) {
913 case ObjCMessageExpr::Instance:
914 break;
915
916 case ObjCMessageExpr::Class:
917 OS << " class=";
918 dumpBareType(Node->getClassReceiver());
919 break;
920
921 case ObjCMessageExpr::SuperInstance:
922 OS << " super (instance)";
923 break;
924
925 case ObjCMessageExpr::SuperClass:
926 OS << " super (class)";
927 break;
928 }
929 }
930
VisitObjCBoxedExpr(const ObjCBoxedExpr * Node)931 void TextNodeDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *Node) {
932 if (auto *BoxingMethod = Node->getBoxingMethod()) {
933 OS << " selector=";
934 BoxingMethod->getSelector().print(OS);
935 }
936 }
937
VisitObjCAtCatchStmt(const ObjCAtCatchStmt * Node)938 void TextNodeDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) {
939 if (!Node->getCatchParamDecl())
940 OS << " catch all";
941 }
942
VisitObjCEncodeExpr(const ObjCEncodeExpr * Node)943 void TextNodeDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *Node) {
944 dumpType(Node->getEncodedType());
945 }
946
VisitObjCSelectorExpr(const ObjCSelectorExpr * Node)947 void TextNodeDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *Node) {
948 OS << " ";
949 Node->getSelector().print(OS);
950 }
951
VisitObjCProtocolExpr(const ObjCProtocolExpr * Node)952 void TextNodeDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *Node) {
953 OS << ' ' << *Node->getProtocol();
954 }
955
VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr * Node)956 void TextNodeDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node) {
957 if (Node->isImplicitProperty()) {
958 OS << " Kind=MethodRef Getter=\"";
959 if (Node->getImplicitPropertyGetter())
960 Node->getImplicitPropertyGetter()->getSelector().print(OS);
961 else
962 OS << "(null)";
963
964 OS << "\" Setter=\"";
965 if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter())
966 Setter->getSelector().print(OS);
967 else
968 OS << "(null)";
969 OS << "\"";
970 } else {
971 OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty()
972 << '"';
973 }
974
975 if (Node->isSuperReceiver())
976 OS << " super";
977
978 OS << " Messaging=";
979 if (Node->isMessagingGetter() && Node->isMessagingSetter())
980 OS << "Getter&Setter";
981 else if (Node->isMessagingGetter())
982 OS << "Getter";
983 else if (Node->isMessagingSetter())
984 OS << "Setter";
985 }
986
VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr * Node)987 void TextNodeDumper::VisitObjCSubscriptRefExpr(
988 const ObjCSubscriptRefExpr *Node) {
989 if (Node->isArraySubscriptRefExpr())
990 OS << " Kind=ArraySubscript GetterForArray=\"";
991 else
992 OS << " Kind=DictionarySubscript GetterForDictionary=\"";
993 if (Node->getAtIndexMethodDecl())
994 Node->getAtIndexMethodDecl()->getSelector().print(OS);
995 else
996 OS << "(null)";
997
998 if (Node->isArraySubscriptRefExpr())
999 OS << "\" SetterForArray=\"";
1000 else
1001 OS << "\" SetterForDictionary=\"";
1002 if (Node->setAtIndexMethodDecl())
1003 Node->setAtIndexMethodDecl()->getSelector().print(OS);
1004 else
1005 OS << "(null)";
1006 }
1007
VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr * Node)1008 void TextNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node) {
1009 OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no");
1010 }
1011
VisitRValueReferenceType(const ReferenceType * T)1012 void TextNodeDumper::VisitRValueReferenceType(const ReferenceType *T) {
1013 if (T->isSpelledAsLValue())
1014 OS << " written as lvalue reference";
1015 }
1016
VisitArrayType(const ArrayType * T)1017 void TextNodeDumper::VisitArrayType(const ArrayType *T) {
1018 switch (T->getSizeModifier()) {
1019 case ArrayType::Normal:
1020 break;
1021 case ArrayType::Static:
1022 OS << " static";
1023 break;
1024 case ArrayType::Star:
1025 OS << " *";
1026 break;
1027 }
1028 OS << " " << T->getIndexTypeQualifiers().getAsString();
1029 }
1030
VisitConstantArrayType(const ConstantArrayType * T)1031 void TextNodeDumper::VisitConstantArrayType(const ConstantArrayType *T) {
1032 OS << " " << T->getSize();
1033 VisitArrayType(T);
1034 }
1035
VisitVariableArrayType(const VariableArrayType * T)1036 void TextNodeDumper::VisitVariableArrayType(const VariableArrayType *T) {
1037 OS << " ";
1038 dumpSourceRange(T->getBracketsRange());
1039 VisitArrayType(T);
1040 }
1041
VisitDependentSizedArrayType(const DependentSizedArrayType * T)1042 void TextNodeDumper::VisitDependentSizedArrayType(
1043 const DependentSizedArrayType *T) {
1044 VisitArrayType(T);
1045 OS << " ";
1046 dumpSourceRange(T->getBracketsRange());
1047 }
1048
VisitDependentSizedExtVectorType(const DependentSizedExtVectorType * T)1049 void TextNodeDumper::VisitDependentSizedExtVectorType(
1050 const DependentSizedExtVectorType *T) {
1051 OS << " ";
1052 dumpLocation(T->getAttributeLoc());
1053 }
1054
VisitVectorType(const VectorType * T)1055 void TextNodeDumper::VisitVectorType(const VectorType *T) {
1056 switch (T->getVectorKind()) {
1057 case VectorType::GenericVector:
1058 break;
1059 case VectorType::AltiVecVector:
1060 OS << " altivec";
1061 break;
1062 case VectorType::AltiVecPixel:
1063 OS << " altivec pixel";
1064 break;
1065 case VectorType::AltiVecBool:
1066 OS << " altivec bool";
1067 break;
1068 case VectorType::NeonVector:
1069 OS << " neon";
1070 break;
1071 case VectorType::NeonPolyVector:
1072 OS << " neon poly";
1073 break;
1074 }
1075 OS << " " << T->getNumElements();
1076 }
1077
VisitFunctionType(const FunctionType * T)1078 void TextNodeDumper::VisitFunctionType(const FunctionType *T) {
1079 auto EI = T->getExtInfo();
1080 if (EI.getNoReturn())
1081 OS << " noreturn";
1082 if (EI.getProducesResult())
1083 OS << " produces_result";
1084 if (EI.getHasRegParm())
1085 OS << " regparm " << EI.getRegParm();
1086 OS << " " << FunctionType::getNameForCallConv(EI.getCC());
1087 }
1088
VisitFunctionProtoType(const FunctionProtoType * T)1089 void TextNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) {
1090 auto EPI = T->getExtProtoInfo();
1091 if (EPI.HasTrailingReturn)
1092 OS << " trailing_return";
1093 if (T->isConst())
1094 OS << " const";
1095 if (T->isVolatile())
1096 OS << " volatile";
1097 if (T->isRestrict())
1098 OS << " restrict";
1099 switch (EPI.RefQualifier) {
1100 case RQ_None:
1101 break;
1102 case RQ_LValue:
1103 OS << " &";
1104 break;
1105 case RQ_RValue:
1106 OS << " &&";
1107 break;
1108 }
1109 // FIXME: Exception specification.
1110 // FIXME: Consumed parameters.
1111 VisitFunctionType(T);
1112 }
1113
VisitUnresolvedUsingType(const UnresolvedUsingType * T)1114 void TextNodeDumper::VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
1115 dumpDeclRef(T->getDecl());
1116 }
1117
VisitTypedefType(const TypedefType * T)1118 void TextNodeDumper::VisitTypedefType(const TypedefType *T) {
1119 dumpDeclRef(T->getDecl());
1120 }
1121
VisitUnaryTransformType(const UnaryTransformType * T)1122 void TextNodeDumper::VisitUnaryTransformType(const UnaryTransformType *T) {
1123 switch (T->getUTTKind()) {
1124 case UnaryTransformType::EnumUnderlyingType:
1125 OS << " underlying_type";
1126 break;
1127 }
1128 }
1129
VisitTagType(const TagType * T)1130 void TextNodeDumper::VisitTagType(const TagType *T) {
1131 dumpDeclRef(T->getDecl());
1132 }
1133
VisitTemplateTypeParmType(const TemplateTypeParmType * T)1134 void TextNodeDumper::VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
1135 OS << " depth " << T->getDepth() << " index " << T->getIndex();
1136 if (T->isParameterPack())
1137 OS << " pack";
1138 dumpDeclRef(T->getDecl());
1139 }
1140
VisitAutoType(const AutoType * T)1141 void TextNodeDumper::VisitAutoType(const AutoType *T) {
1142 if (T->isDecltypeAuto())
1143 OS << " decltype(auto)";
1144 if (!T->isDeduced())
1145 OS << " undeduced";
1146 }
1147
VisitTemplateSpecializationType(const TemplateSpecializationType * T)1148 void TextNodeDumper::VisitTemplateSpecializationType(
1149 const TemplateSpecializationType *T) {
1150 if (T->isTypeAlias())
1151 OS << " alias";
1152 OS << " ";
1153 T->getTemplateName().dump(OS);
1154 }
1155
VisitInjectedClassNameType(const InjectedClassNameType * T)1156 void TextNodeDumper::VisitInjectedClassNameType(
1157 const InjectedClassNameType *T) {
1158 dumpDeclRef(T->getDecl());
1159 }
1160
VisitObjCInterfaceType(const ObjCInterfaceType * T)1161 void TextNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
1162 dumpDeclRef(T->getDecl());
1163 }
1164
VisitPackExpansionType(const PackExpansionType * T)1165 void TextNodeDumper::VisitPackExpansionType(const PackExpansionType *T) {
1166 if (auto N = T->getNumExpansions())
1167 OS << " expansions " << *N;
1168 }
1169