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