blob: 1998cfaec044f118c6af5332a78c4c2af38b40fa [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
Roman Lebedevb5700602019-03-20 16:32:36 +0000124 if (Node->isOMPStructuredBlock())
125 OS << " openmp_structured_block";
126
Stephen Kelly07b76d22019-01-12 16:53:27 +0000127 if (const auto *E = dyn_cast<Expr>(Node)) {
128 dumpType(E->getType());
129
130 {
131 ColorScope Color(OS, ShowColors, ValueKindColor);
132 switch (E->getValueKind()) {
133 case VK_RValue:
134 break;
135 case VK_LValue:
136 OS << " lvalue";
137 break;
138 case VK_XValue:
139 OS << " xvalue";
140 break;
141 }
142 }
143
144 {
145 ColorScope Color(OS, ShowColors, ObjectKindColor);
146 switch (E->getObjectKind()) {
147 case OK_Ordinary:
148 break;
149 case OK_BitField:
150 OS << " bitfield";
151 break;
152 case OK_ObjCProperty:
153 OS << " objcproperty";
154 break;
155 case OK_ObjCSubscript:
156 OS << " objcsubscript";
157 break;
158 case OK_VectorComponent:
159 OS << " vectorcomponent";
160 break;
161 }
162 }
163 }
164
165 ConstStmtVisitor<TextNodeDumper>::Visit(Node);
166}
167
Stephen Kelly449fa762019-01-14 20:11:02 +0000168void TextNodeDumper::Visit(const Type *T) {
169 if (!T) {
170 ColorScope Color(OS, ShowColors, NullColor);
171 OS << "<<<NULL>>>";
172 return;
173 }
174 if (isa<LocInfoType>(T)) {
175 {
176 ColorScope Color(OS, ShowColors, TypeColor);
177 OS << "LocInfo Type";
178 }
179 dumpPointer(T);
180 return;
181 }
182
183 {
184 ColorScope Color(OS, ShowColors, TypeColor);
185 OS << T->getTypeClassName() << "Type";
186 }
187 dumpPointer(T);
188 OS << " ";
189 dumpBareType(QualType(T, 0), false);
190
191 QualType SingleStepDesugar =
192 T->getLocallyUnqualifiedSingleStepDesugaredType();
193 if (SingleStepDesugar != QualType(T, 0))
194 OS << " sugar";
195
196 if (T->isDependentType())
197 OS << " dependent";
198 else if (T->isInstantiationDependentType())
199 OS << " instantiation_dependent";
200
201 if (T->isVariablyModifiedType())
202 OS << " variably_modified";
203 if (T->containsUnexpandedParameterPack())
204 OS << " contains_unexpanded_pack";
205 if (T->isFromAST())
206 OS << " imported";
Stephen Kellyf08ca202019-01-15 09:30:00 +0000207
208 TypeVisitor<TextNodeDumper>::Visit(T);
Stephen Kelly449fa762019-01-14 20:11:02 +0000209}
210
Stephen Kelly58c65042019-01-14 20:15:29 +0000211void TextNodeDumper::Visit(QualType T) {
212 OS << "QualType";
213 dumpPointer(T.getAsOpaquePtr());
214 OS << " ";
215 dumpBareType(T, false);
216 OS << " " << T.split().Quals.getAsString();
217}
218
Stephen Kellyd83fe892019-01-15 09:35:52 +0000219void TextNodeDumper::Visit(const Decl *D) {
220 if (!D) {
221 ColorScope Color(OS, ShowColors, NullColor);
222 OS << "<<<NULL>>>";
223 return;
224 }
225
226 {
227 ColorScope Color(OS, ShowColors, DeclKindNameColor);
228 OS << D->getDeclKindName() << "Decl";
229 }
230 dumpPointer(D);
231 if (D->getLexicalDeclContext() != D->getDeclContext())
232 OS << " parent " << cast<Decl>(D->getDeclContext());
233 dumpPreviousDecl(OS, D);
234 dumpSourceRange(D->getSourceRange());
235 OS << ' ';
236 dumpLocation(D->getLocation());
237 if (D->isFromASTFile())
238 OS << " imported";
239 if (Module *M = D->getOwningModule())
240 OS << " in " << M->getFullModuleName();
241 if (auto *ND = dyn_cast<NamedDecl>(D))
242 for (Module *M : D->getASTContext().getModulesWithMergedDefinition(
243 const_cast<NamedDecl *>(ND)))
244 AddChild([=] { OS << "also in " << M->getFullModuleName(); });
245 if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
246 if (ND->isHidden())
247 OS << " hidden";
248 if (D->isImplicit())
249 OS << " implicit";
250
251 if (D->isUsed())
252 OS << " used";
253 else if (D->isThisDeclarationReferenced())
254 OS << " referenced";
255
256 if (D->isInvalidDecl())
257 OS << " invalid";
Gauthier Harnisch796ed032019-06-14 08:56:20 +0000258 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
259 if (FD->isConstexprSpecified())
Stephen Kellyd83fe892019-01-15 09:35:52 +0000260 OS << " constexpr";
Gauthier Harnisch796ed032019-06-14 08:56:20 +0000261 if (FD->isConsteval())
262 OS << " consteval";
263 }
Stephen Kelly25f18bf2019-01-19 09:05:55 +0000264
265 if (!isa<FunctionDecl>(*D)) {
266 const auto *MD = dyn_cast<ObjCMethodDecl>(D);
267 if (!MD || !MD->isThisDeclarationADefinition()) {
268 const auto *DC = dyn_cast<DeclContext>(D);
269 if (DC && DC->hasExternalLexicalStorage()) {
270 ColorScope Color(OS, ShowColors, UndeserializedColor);
271 OS << " <undeserialized declarations>";
272 }
273 }
274 }
Stephen Kellyb6318c92019-01-30 19:32:48 +0000275
276 ConstDeclVisitor<TextNodeDumper>::Visit(D);
Stephen Kellyd83fe892019-01-15 09:35:52 +0000277}
278
Stephen Kelly0e050fa2019-01-15 20:17:33 +0000279void TextNodeDumper::Visit(const CXXCtorInitializer *Init) {
280 OS << "CXXCtorInitializer";
281 if (Init->isAnyMemberInitializer()) {
282 OS << ' ';
283 dumpBareDeclRef(Init->getAnyMember());
284 } else if (Init->isBaseInitializer()) {
285 dumpType(QualType(Init->getBaseClass(), 0));
286 } else if (Init->isDelegatingInitializer()) {
287 dumpType(Init->getTypeSourceInfo()->getType());
288 } else {
289 llvm_unreachable("Unknown initializer type");
290 }
291}
292
Stephen Kellyfbf424e2019-01-15 20:41:37 +0000293void TextNodeDumper::Visit(const BlockDecl::Capture &C) {
294 OS << "capture";
295 if (C.isByRef())
296 OS << " byref";
297 if (C.isNested())
298 OS << " nested";
299 if (C.getVariable()) {
300 OS << ' ';
301 dumpBareDeclRef(C.getVariable());
302 }
303}
304
Stephen Kelly3cdd1a72019-01-15 20:31:31 +0000305void TextNodeDumper::Visit(const OMPClause *C) {
306 if (!C) {
307 ColorScope Color(OS, ShowColors, NullColor);
308 OS << "<<<NULL>>> OMPClause";
309 return;
310 }
311 {
312 ColorScope Color(OS, ShowColors, AttrColor);
313 StringRef ClauseName(getOpenMPClauseName(C->getClauseKind()));
314 OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper()
315 << ClauseName.drop_front() << "Clause";
316 }
317 dumpPointer(C);
318 dumpSourceRange(SourceRange(C->getBeginLoc(), C->getEndLoc()));
319 if (C->isImplicit())
320 OS << " <implicit>";
321}
322
Stephen Kellyfbf40f42019-01-29 22:22:55 +0000323void TextNodeDumper::Visit(const GenericSelectionExpr::ConstAssociation &A) {
324 const TypeSourceInfo *TSI = A.getTypeSourceInfo();
325 if (TSI) {
326 OS << "case ";
327 dumpType(TSI->getType());
328 } else {
329 OS << "default";
330 }
331
332 if (A.isSelected())
333 OS << " selected";
334}
335
Stephen Kellyd8744a72018-12-05 21:12:39 +0000336void TextNodeDumper::dumpPointer(const void *Ptr) {
337 ColorScope Color(OS, ShowColors, AddressColor);
338 OS << ' ' << Ptr;
339}
340
341void TextNodeDumper::dumpLocation(SourceLocation Loc) {
342 if (!SM)
343 return;
344
345 ColorScope Color(OS, ShowColors, LocationColor);
346 SourceLocation SpellingLoc = SM->getSpellingLoc(Loc);
347
348 // The general format we print out is filename:line:col, but we drop pieces
349 // that haven't changed since the last loc printed.
350 PresumedLoc PLoc = SM->getPresumedLoc(SpellingLoc);
351
352 if (PLoc.isInvalid()) {
353 OS << "<invalid sloc>";
354 return;
355 }
356
357 if (strcmp(PLoc.getFilename(), LastLocFilename) != 0) {
358 OS << PLoc.getFilename() << ':' << PLoc.getLine() << ':'
359 << PLoc.getColumn();
360 LastLocFilename = PLoc.getFilename();
361 LastLocLine = PLoc.getLine();
362 } else if (PLoc.getLine() != LastLocLine) {
363 OS << "line" << ':' << PLoc.getLine() << ':' << PLoc.getColumn();
364 LastLocLine = PLoc.getLine();
365 } else {
366 OS << "col" << ':' << PLoc.getColumn();
367 }
368}
369
370void TextNodeDumper::dumpSourceRange(SourceRange R) {
371 // Can't translate locations if a SourceManager isn't available.
372 if (!SM)
373 return;
374
375 OS << " <";
376 dumpLocation(R.getBegin());
377 if (R.getBegin() != R.getEnd()) {
378 OS << ", ";
379 dumpLocation(R.getEnd());
380 }
381 OS << ">";
382
383 // <t2.c:123:421[blah], t2.c:412:321>
384}
385
386void TextNodeDumper::dumpBareType(QualType T, bool Desugar) {
387 ColorScope Color(OS, ShowColors, TypeColor);
388
389 SplitQualType T_split = T.split();
390 OS << "'" << QualType::getAsString(T_split, PrintPolicy) << "'";
391
392 if (Desugar && !T.isNull()) {
393 // If the type is sugared, also dump a (shallow) desugared type.
394 SplitQualType D_split = T.getSplitDesugaredType();
395 if (T_split != D_split)
396 OS << ":'" << QualType::getAsString(D_split, PrintPolicy) << "'";
397 }
398}
399
400void TextNodeDumper::dumpType(QualType T) {
401 OS << ' ';
402 dumpBareType(T);
403}
404
405void TextNodeDumper::dumpBareDeclRef(const Decl *D) {
406 if (!D) {
407 ColorScope Color(OS, ShowColors, NullColor);
408 OS << "<<<NULL>>>";
409 return;
410 }
411
412 {
413 ColorScope Color(OS, ShowColors, DeclKindNameColor);
414 OS << D->getDeclKindName();
415 }
416 dumpPointer(D);
417
418 if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
419 ColorScope Color(OS, ShowColors, DeclNameColor);
420 OS << " '" << ND->getDeclName() << '\'';
421 }
422
423 if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
424 dumpType(VD->getType());
425}
426
427void TextNodeDumper::dumpName(const NamedDecl *ND) {
428 if (ND->getDeclName()) {
429 ColorScope Color(OS, ShowColors, DeclNameColor);
430 OS << ' ' << ND->getNameAsString();
431 }
432}
433
434void TextNodeDumper::dumpAccessSpecifier(AccessSpecifier AS) {
435 switch (AS) {
436 case AS_none:
437 break;
438 case AS_public:
439 OS << "public";
440 break;
441 case AS_protected:
442 OS << "protected";
443 break;
444 case AS_private:
445 OS << "private";
446 break;
447 }
448}
449
450void TextNodeDumper::dumpCXXTemporary(const CXXTemporary *Temporary) {
451 OS << "(CXXTemporary";
452 dumpPointer(Temporary);
453 OS << ")";
454}
Stephen Kellye26a88a2018-12-09 13:30:17 +0000455
Stephen Kelly9bc90a22019-01-12 15:45:05 +0000456void TextNodeDumper::dumpDeclRef(const Decl *D, StringRef Label) {
Stephen Kellyd186dbc2019-01-08 23:11:24 +0000457 if (!D)
458 return;
459
Stephen Kelly12243212019-01-10 20:58:21 +0000460 AddChild([=] {
Stephen Kelly9bc90a22019-01-12 15:45:05 +0000461 if (!Label.empty())
Stephen Kellyd186dbc2019-01-08 23:11:24 +0000462 OS << Label << ' ';
463 dumpBareDeclRef(D);
464 });
465}
466
Stephen Kellye26a88a2018-12-09 13:30:17 +0000467const char *TextNodeDumper::getCommandName(unsigned CommandID) {
468 if (Traits)
469 return Traits->getCommandInfo(CommandID)->Name;
470 const comments::CommandInfo *Info =
471 comments::CommandTraits::getBuiltinCommandInfo(CommandID);
472 if (Info)
473 return Info->Name;
474 return "<not a builtin command>";
475}
476
477void TextNodeDumper::visitTextComment(const comments::TextComment *C,
478 const comments::FullComment *) {
479 OS << " Text=\"" << C->getText() << "\"";
480}
481
482void TextNodeDumper::visitInlineCommandComment(
483 const comments::InlineCommandComment *C, const comments::FullComment *) {
484 OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
485 switch (C->getRenderKind()) {
486 case comments::InlineCommandComment::RenderNormal:
487 OS << " RenderNormal";
488 break;
489 case comments::InlineCommandComment::RenderBold:
490 OS << " RenderBold";
491 break;
492 case comments::InlineCommandComment::RenderMonospaced:
493 OS << " RenderMonospaced";
494 break;
495 case comments::InlineCommandComment::RenderEmphasized:
496 OS << " RenderEmphasized";
497 break;
498 }
499
500 for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
501 OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
502}
503
504void TextNodeDumper::visitHTMLStartTagComment(
505 const comments::HTMLStartTagComment *C, const comments::FullComment *) {
506 OS << " Name=\"" << C->getTagName() << "\"";
507 if (C->getNumAttrs() != 0) {
508 OS << " Attrs: ";
509 for (unsigned i = 0, e = C->getNumAttrs(); i != e; ++i) {
510 const comments::HTMLStartTagComment::Attribute &Attr = C->getAttr(i);
511 OS << " \"" << Attr.Name << "=\"" << Attr.Value << "\"";
512 }
513 }
514 if (C->isSelfClosing())
515 OS << " SelfClosing";
516}
517
518void TextNodeDumper::visitHTMLEndTagComment(
519 const comments::HTMLEndTagComment *C, const comments::FullComment *) {
520 OS << " Name=\"" << C->getTagName() << "\"";
521}
522
523void TextNodeDumper::visitBlockCommandComment(
524 const comments::BlockCommandComment *C, const comments::FullComment *) {
525 OS << " Name=\"" << getCommandName(C->getCommandID()) << "\"";
526 for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i)
527 OS << " Arg[" << i << "]=\"" << C->getArgText(i) << "\"";
528}
529
530void TextNodeDumper::visitParamCommandComment(
531 const comments::ParamCommandComment *C, const comments::FullComment *FC) {
532 OS << " "
533 << comments::ParamCommandComment::getDirectionAsString(C->getDirection());
534
535 if (C->isDirectionExplicit())
536 OS << " explicitly";
537 else
538 OS << " implicitly";
539
540 if (C->hasParamName()) {
541 if (C->isParamIndexValid())
542 OS << " Param=\"" << C->getParamName(FC) << "\"";
543 else
544 OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
545 }
546
547 if (C->isParamIndexValid() && !C->isVarArgParam())
548 OS << " ParamIndex=" << C->getParamIndex();
549}
550
551void TextNodeDumper::visitTParamCommandComment(
552 const comments::TParamCommandComment *C, const comments::FullComment *FC) {
553 if (C->hasParamName()) {
554 if (C->isPositionValid())
555 OS << " Param=\"" << C->getParamName(FC) << "\"";
556 else
557 OS << " Param=\"" << C->getParamNameAsWritten() << "\"";
558 }
559
560 if (C->isPositionValid()) {
561 OS << " Position=<";
562 for (unsigned i = 0, e = C->getDepth(); i != e; ++i) {
563 OS << C->getIndex(i);
564 if (i != e - 1)
565 OS << ", ";
566 }
567 OS << ">";
568 }
569}
570
571void TextNodeDumper::visitVerbatimBlockComment(
572 const comments::VerbatimBlockComment *C, const comments::FullComment *) {
573 OS << " Name=\"" << getCommandName(C->getCommandID())
574 << "\""
575 " CloseName=\""
576 << C->getCloseName() << "\"";
577}
578
579void TextNodeDumper::visitVerbatimBlockLineComment(
580 const comments::VerbatimBlockLineComment *C,
581 const comments::FullComment *) {
582 OS << " Text=\"" << C->getText() << "\"";
583}
584
585void TextNodeDumper::visitVerbatimLineComment(
586 const comments::VerbatimLineComment *C, const comments::FullComment *) {
587 OS << " Text=\"" << C->getText() << "\"";
588}
Stephen Kelly63a6f3a2019-01-12 16:35:37 +0000589
590void TextNodeDumper::VisitNullTemplateArgument(const TemplateArgument &) {
591 OS << " null";
592}
593
594void TextNodeDumper::VisitTypeTemplateArgument(const TemplateArgument &TA) {
595 OS << " type";
596 dumpType(TA.getAsType());
597}
598
599void TextNodeDumper::VisitDeclarationTemplateArgument(
600 const TemplateArgument &TA) {
601 OS << " decl";
602 dumpDeclRef(TA.getAsDecl());
603}
604
605void TextNodeDumper::VisitNullPtrTemplateArgument(const TemplateArgument &) {
606 OS << " nullptr";
607}
608
609void TextNodeDumper::VisitIntegralTemplateArgument(const TemplateArgument &TA) {
610 OS << " integral " << TA.getAsIntegral();
611}
612
613void TextNodeDumper::VisitTemplateTemplateArgument(const TemplateArgument &TA) {
614 OS << " template ";
615 TA.getAsTemplate().dump(OS);
616}
617
618void TextNodeDumper::VisitTemplateExpansionTemplateArgument(
619 const TemplateArgument &TA) {
620 OS << " template expansion ";
621 TA.getAsTemplateOrTemplatePattern().dump(OS);
622}
623
624void TextNodeDumper::VisitExpressionTemplateArgument(const TemplateArgument &) {
625 OS << " expr";
626}
627
628void TextNodeDumper::VisitPackTemplateArgument(const TemplateArgument &) {
629 OS << " pack";
630}
Stephen Kelly07b76d22019-01-12 16:53:27 +0000631
632static void dumpBasePath(raw_ostream &OS, const CastExpr *Node) {
633 if (Node->path_empty())
634 return;
635
636 OS << " (";
637 bool First = true;
638 for (CastExpr::path_const_iterator I = Node->path_begin(),
639 E = Node->path_end();
640 I != E; ++I) {
641 const CXXBaseSpecifier *Base = *I;
642 if (!First)
643 OS << " -> ";
644
645 const CXXRecordDecl *RD =
646 cast<CXXRecordDecl>(Base->getType()->getAs<RecordType>()->getDecl());
647
648 if (Base->isVirtual())
649 OS << "virtual ";
650 OS << RD->getName();
651 First = false;
652 }
653
654 OS << ')';
655}
656
657void TextNodeDumper::VisitIfStmt(const IfStmt *Node) {
658 if (Node->hasInitStorage())
659 OS << " has_init";
660 if (Node->hasVarStorage())
661 OS << " has_var";
662 if (Node->hasElseStorage())
663 OS << " has_else";
664}
665
666void TextNodeDumper::VisitSwitchStmt(const SwitchStmt *Node) {
667 if (Node->hasInitStorage())
668 OS << " has_init";
669 if (Node->hasVarStorage())
670 OS << " has_var";
671}
672
673void TextNodeDumper::VisitWhileStmt(const WhileStmt *Node) {
674 if (Node->hasVarStorage())
675 OS << " has_var";
676}
677
678void TextNodeDumper::VisitLabelStmt(const LabelStmt *Node) {
679 OS << " '" << Node->getName() << "'";
680}
681
682void TextNodeDumper::VisitGotoStmt(const GotoStmt *Node) {
683 OS << " '" << Node->getLabel()->getName() << "'";
684 dumpPointer(Node->getLabel());
685}
686
687void TextNodeDumper::VisitCaseStmt(const CaseStmt *Node) {
688 if (Node->caseStmtIsGNURange())
689 OS << " gnu_range";
690}
691
692void TextNodeDumper::VisitCallExpr(const CallExpr *Node) {
693 if (Node->usesADL())
694 OS << " adl";
695}
696
697void TextNodeDumper::VisitCastExpr(const CastExpr *Node) {
698 OS << " <";
699 {
700 ColorScope Color(OS, ShowColors, CastColor);
701 OS << Node->getCastKindName();
702 }
703 dumpBasePath(OS, Node);
704 OS << ">";
705}
706
707void TextNodeDumper::VisitImplicitCastExpr(const ImplicitCastExpr *Node) {
708 VisitCastExpr(Node);
709 if (Node->isPartOfExplicitCast())
710 OS << " part_of_explicit_cast";
711}
712
713void TextNodeDumper::VisitDeclRefExpr(const DeclRefExpr *Node) {
714 OS << " ";
715 dumpBareDeclRef(Node->getDecl());
716 if (Node->getDecl() != Node->getFoundDecl()) {
717 OS << " (";
718 dumpBareDeclRef(Node->getFoundDecl());
719 OS << ")";
720 }
Richard Smith715f7a12019-06-11 17:50:32 +0000721 switch (Node->isNonOdrUse()) {
722 case NOUR_None: break;
723 case NOUR_Unevaluated: OS << " non_odr_use_unevaluated"; break;
724 case NOUR_Constant: OS << " non_odr_use_constant"; break;
725 case NOUR_Discarded: OS << " non_odr_use_discarded"; break;
726 }
Stephen Kelly07b76d22019-01-12 16:53:27 +0000727}
728
729void TextNodeDumper::VisitUnresolvedLookupExpr(
730 const UnresolvedLookupExpr *Node) {
731 OS << " (";
732 if (!Node->requiresADL())
733 OS << "no ";
734 OS << "ADL) = '" << Node->getName() << '\'';
735
736 UnresolvedLookupExpr::decls_iterator I = Node->decls_begin(),
737 E = Node->decls_end();
738 if (I == E)
739 OS << " empty";
740 for (; I != E; ++I)
741 dumpPointer(*I);
742}
743
744void TextNodeDumper::VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node) {
745 {
746 ColorScope Color(OS, ShowColors, DeclKindNameColor);
747 OS << " " << Node->getDecl()->getDeclKindName() << "Decl";
748 }
749 OS << "='" << *Node->getDecl() << "'";
750 dumpPointer(Node->getDecl());
751 if (Node->isFreeIvar())
752 OS << " isFreeIvar";
753}
754
755void TextNodeDumper::VisitPredefinedExpr(const PredefinedExpr *Node) {
756 OS << " " << PredefinedExpr::getIdentKindName(Node->getIdentKind());
757}
758
759void TextNodeDumper::VisitCharacterLiteral(const CharacterLiteral *Node) {
760 ColorScope Color(OS, ShowColors, ValueColor);
761 OS << " " << Node->getValue();
762}
763
764void TextNodeDumper::VisitIntegerLiteral(const IntegerLiteral *Node) {
765 bool isSigned = Node->getType()->isSignedIntegerType();
766 ColorScope Color(OS, ShowColors, ValueColor);
767 OS << " " << Node->getValue().toString(10, isSigned);
768}
769
770void TextNodeDumper::VisitFixedPointLiteral(const FixedPointLiteral *Node) {
771 ColorScope Color(OS, ShowColors, ValueColor);
772 OS << " " << Node->getValueAsString(/*Radix=*/10);
773}
774
775void TextNodeDumper::VisitFloatingLiteral(const FloatingLiteral *Node) {
776 ColorScope Color(OS, ShowColors, ValueColor);
777 OS << " " << Node->getValueAsApproximateDouble();
778}
779
780void TextNodeDumper::VisitStringLiteral(const StringLiteral *Str) {
781 ColorScope Color(OS, ShowColors, ValueColor);
782 OS << " ";
783 Str->outputString(OS);
784}
785
786void TextNodeDumper::VisitInitListExpr(const InitListExpr *ILE) {
787 if (auto *Field = ILE->getInitializedFieldInUnion()) {
788 OS << " field ";
789 dumpBareDeclRef(Field);
790 }
791}
792
Stephen Kellyaecce852019-01-29 22:58:28 +0000793void TextNodeDumper::VisitGenericSelectionExpr(const GenericSelectionExpr *E) {
794 if (E->isResultDependent())
795 OS << " result_dependent";
796}
797
Stephen Kelly07b76d22019-01-12 16:53:27 +0000798void TextNodeDumper::VisitUnaryOperator(const UnaryOperator *Node) {
799 OS << " " << (Node->isPostfix() ? "postfix" : "prefix") << " '"
800 << UnaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
801 if (!Node->canOverflow())
802 OS << " cannot overflow";
803}
804
805void TextNodeDumper::VisitUnaryExprOrTypeTraitExpr(
806 const UnaryExprOrTypeTraitExpr *Node) {
807 switch (Node->getKind()) {
808 case UETT_SizeOf:
809 OS << " sizeof";
810 break;
811 case UETT_AlignOf:
812 OS << " alignof";
813 break;
814 case UETT_VecStep:
815 OS << " vec_step";
816 break;
817 case UETT_OpenMPRequiredSimdAlign:
818 OS << " __builtin_omp_required_simd_align";
819 break;
820 case UETT_PreferredAlignOf:
821 OS << " __alignof";
822 break;
823 }
824 if (Node->isArgumentType())
825 dumpType(Node->getArgumentType());
826}
827
828void TextNodeDumper::VisitMemberExpr(const MemberExpr *Node) {
829 OS << " " << (Node->isArrow() ? "->" : ".") << *Node->getMemberDecl();
830 dumpPointer(Node->getMemberDecl());
Richard Smith1bbad592019-06-11 17:50:36 +0000831 switch (Node->isNonOdrUse()) {
832 case NOUR_None: break;
833 case NOUR_Unevaluated: OS << " non_odr_use_unevaluated"; break;
834 case NOUR_Constant: OS << " non_odr_use_constant"; break;
835 case NOUR_Discarded: OS << " non_odr_use_discarded"; break;
836 }
Stephen Kelly07b76d22019-01-12 16:53:27 +0000837}
838
839void TextNodeDumper::VisitExtVectorElementExpr(
840 const ExtVectorElementExpr *Node) {
841 OS << " " << Node->getAccessor().getNameStart();
842}
843
844void TextNodeDumper::VisitBinaryOperator(const BinaryOperator *Node) {
845 OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "'";
846}
847
848void TextNodeDumper::VisitCompoundAssignOperator(
849 const CompoundAssignOperator *Node) {
850 OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode())
851 << "' ComputeLHSTy=";
852 dumpBareType(Node->getComputationLHSType());
853 OS << " ComputeResultTy=";
854 dumpBareType(Node->getComputationResultType());
855}
856
857void TextNodeDumper::VisitAddrLabelExpr(const AddrLabelExpr *Node) {
858 OS << " " << Node->getLabel()->getName();
859 dumpPointer(Node->getLabel());
860}
861
862void TextNodeDumper::VisitCXXNamedCastExpr(const CXXNamedCastExpr *Node) {
863 OS << " " << Node->getCastName() << "<"
864 << Node->getTypeAsWritten().getAsString() << ">"
865 << " <" << Node->getCastKindName();
866 dumpBasePath(OS, Node);
867 OS << ">";
868}
869
870void TextNodeDumper::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *Node) {
871 OS << " " << (Node->getValue() ? "true" : "false");
872}
873
874void TextNodeDumper::VisitCXXThisExpr(const CXXThisExpr *Node) {
Bruno Ricci64bebe92019-02-03 18:20:27 +0000875 if (Node->isImplicit())
876 OS << " implicit";
Stephen Kelly07b76d22019-01-12 16:53:27 +0000877 OS << " this";
878}
879
880void TextNodeDumper::VisitCXXFunctionalCastExpr(
881 const CXXFunctionalCastExpr *Node) {
882 OS << " functional cast to " << Node->getTypeAsWritten().getAsString() << " <"
883 << Node->getCastKindName() << ">";
884}
885
886void TextNodeDumper::VisitCXXUnresolvedConstructExpr(
887 const CXXUnresolvedConstructExpr *Node) {
888 dumpType(Node->getTypeAsWritten());
889 if (Node->isListInitialization())
890 OS << " list";
891}
892
893void TextNodeDumper::VisitCXXConstructExpr(const CXXConstructExpr *Node) {
894 CXXConstructorDecl *Ctor = Node->getConstructor();
895 dumpType(Ctor->getType());
896 if (Node->isElidable())
897 OS << " elidable";
898 if (Node->isListInitialization())
899 OS << " list";
900 if (Node->isStdInitListInitialization())
901 OS << " std::initializer_list";
902 if (Node->requiresZeroInitialization())
903 OS << " zeroing";
904}
905
906void TextNodeDumper::VisitCXXBindTemporaryExpr(
907 const CXXBindTemporaryExpr *Node) {
908 OS << " ";
909 dumpCXXTemporary(Node->getTemporary());
910}
911
912void TextNodeDumper::VisitCXXNewExpr(const CXXNewExpr *Node) {
913 if (Node->isGlobalNew())
914 OS << " global";
915 if (Node->isArray())
916 OS << " array";
917 if (Node->getOperatorNew()) {
918 OS << ' ';
919 dumpBareDeclRef(Node->getOperatorNew());
920 }
921 // We could dump the deallocation function used in case of error, but it's
922 // usually not that interesting.
923}
924
925void TextNodeDumper::VisitCXXDeleteExpr(const CXXDeleteExpr *Node) {
926 if (Node->isGlobalDelete())
927 OS << " global";
928 if (Node->isArrayForm())
929 OS << " array";
930 if (Node->getOperatorDelete()) {
931 OS << ' ';
932 dumpBareDeclRef(Node->getOperatorDelete());
933 }
934}
935
936void TextNodeDumper::VisitMaterializeTemporaryExpr(
937 const MaterializeTemporaryExpr *Node) {
938 if (const ValueDecl *VD = Node->getExtendingDecl()) {
939 OS << " extended by ";
940 dumpBareDeclRef(VD);
941 }
942}
943
944void TextNodeDumper::VisitExprWithCleanups(const ExprWithCleanups *Node) {
945 for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i)
946 dumpDeclRef(Node->getObject(i), "cleanup");
947}
948
949void TextNodeDumper::VisitSizeOfPackExpr(const SizeOfPackExpr *Node) {
950 dumpPointer(Node->getPack());
951 dumpName(Node->getPack());
952}
953
954void TextNodeDumper::VisitCXXDependentScopeMemberExpr(
955 const CXXDependentScopeMemberExpr *Node) {
956 OS << " " << (Node->isArrow() ? "->" : ".") << Node->getMember();
957}
958
959void TextNodeDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) {
960 OS << " selector=";
961 Node->getSelector().print(OS);
962 switch (Node->getReceiverKind()) {
963 case ObjCMessageExpr::Instance:
964 break;
965
966 case ObjCMessageExpr::Class:
967 OS << " class=";
968 dumpBareType(Node->getClassReceiver());
969 break;
970
971 case ObjCMessageExpr::SuperInstance:
972 OS << " super (instance)";
973 break;
974
975 case ObjCMessageExpr::SuperClass:
976 OS << " super (class)";
977 break;
978 }
979}
980
981void TextNodeDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *Node) {
982 if (auto *BoxingMethod = Node->getBoxingMethod()) {
983 OS << " selector=";
984 BoxingMethod->getSelector().print(OS);
985 }
986}
987
988void TextNodeDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) {
989 if (!Node->getCatchParamDecl())
990 OS << " catch all";
991}
992
993void TextNodeDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *Node) {
994 dumpType(Node->getEncodedType());
995}
996
997void TextNodeDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *Node) {
998 OS << " ";
999 Node->getSelector().print(OS);
1000}
1001
1002void TextNodeDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *Node) {
1003 OS << ' ' << *Node->getProtocol();
1004}
1005
1006void TextNodeDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node) {
1007 if (Node->isImplicitProperty()) {
1008 OS << " Kind=MethodRef Getter=\"";
1009 if (Node->getImplicitPropertyGetter())
1010 Node->getImplicitPropertyGetter()->getSelector().print(OS);
1011 else
1012 OS << "(null)";
1013
1014 OS << "\" Setter=\"";
1015 if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter())
1016 Setter->getSelector().print(OS);
1017 else
1018 OS << "(null)";
1019 OS << "\"";
1020 } else {
1021 OS << " Kind=PropertyRef Property=\"" << *Node->getExplicitProperty()
1022 << '"';
1023 }
1024
1025 if (Node->isSuperReceiver())
1026 OS << " super";
1027
1028 OS << " Messaging=";
1029 if (Node->isMessagingGetter() && Node->isMessagingSetter())
1030 OS << "Getter&Setter";
1031 else if (Node->isMessagingGetter())
1032 OS << "Getter";
1033 else if (Node->isMessagingSetter())
1034 OS << "Setter";
1035}
1036
1037void TextNodeDumper::VisitObjCSubscriptRefExpr(
1038 const ObjCSubscriptRefExpr *Node) {
1039 if (Node->isArraySubscriptRefExpr())
1040 OS << " Kind=ArraySubscript GetterForArray=\"";
1041 else
1042 OS << " Kind=DictionarySubscript GetterForDictionary=\"";
1043 if (Node->getAtIndexMethodDecl())
1044 Node->getAtIndexMethodDecl()->getSelector().print(OS);
1045 else
1046 OS << "(null)";
1047
1048 if (Node->isArraySubscriptRefExpr())
1049 OS << "\" SetterForArray=\"";
1050 else
1051 OS << "\" SetterForDictionary=\"";
1052 if (Node->setAtIndexMethodDecl())
1053 Node->setAtIndexMethodDecl()->getSelector().print(OS);
1054 else
1055 OS << "(null)";
1056}
1057
1058void TextNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node) {
1059 OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no");
1060}
Stephen Kellyf08ca202019-01-15 09:30:00 +00001061
1062void TextNodeDumper::VisitRValueReferenceType(const ReferenceType *T) {
1063 if (T->isSpelledAsLValue())
1064 OS << " written as lvalue reference";
1065}
1066
1067void TextNodeDumper::VisitArrayType(const ArrayType *T) {
1068 switch (T->getSizeModifier()) {
1069 case ArrayType::Normal:
1070 break;
1071 case ArrayType::Static:
1072 OS << " static";
1073 break;
1074 case ArrayType::Star:
1075 OS << " *";
1076 break;
1077 }
1078 OS << " " << T->getIndexTypeQualifiers().getAsString();
1079}
1080
1081void TextNodeDumper::VisitConstantArrayType(const ConstantArrayType *T) {
1082 OS << " " << T->getSize();
1083 VisitArrayType(T);
1084}
1085
1086void TextNodeDumper::VisitVariableArrayType(const VariableArrayType *T) {
1087 OS << " ";
1088 dumpSourceRange(T->getBracketsRange());
1089 VisitArrayType(T);
1090}
1091
1092void TextNodeDumper::VisitDependentSizedArrayType(
1093 const DependentSizedArrayType *T) {
1094 VisitArrayType(T);
1095 OS << " ";
1096 dumpSourceRange(T->getBracketsRange());
1097}
1098
1099void TextNodeDumper::VisitDependentSizedExtVectorType(
1100 const DependentSizedExtVectorType *T) {
1101 OS << " ";
1102 dumpLocation(T->getAttributeLoc());
1103}
1104
1105void TextNodeDumper::VisitVectorType(const VectorType *T) {
1106 switch (T->getVectorKind()) {
1107 case VectorType::GenericVector:
1108 break;
1109 case VectorType::AltiVecVector:
1110 OS << " altivec";
1111 break;
1112 case VectorType::AltiVecPixel:
1113 OS << " altivec pixel";
1114 break;
1115 case VectorType::AltiVecBool:
1116 OS << " altivec bool";
1117 break;
1118 case VectorType::NeonVector:
1119 OS << " neon";
1120 break;
1121 case VectorType::NeonPolyVector:
1122 OS << " neon poly";
1123 break;
1124 }
1125 OS << " " << T->getNumElements();
1126}
1127
1128void TextNodeDumper::VisitFunctionType(const FunctionType *T) {
1129 auto EI = T->getExtInfo();
1130 if (EI.getNoReturn())
1131 OS << " noreturn";
1132 if (EI.getProducesResult())
1133 OS << " produces_result";
1134 if (EI.getHasRegParm())
1135 OS << " regparm " << EI.getRegParm();
1136 OS << " " << FunctionType::getNameForCallConv(EI.getCC());
1137}
1138
1139void TextNodeDumper::VisitFunctionProtoType(const FunctionProtoType *T) {
1140 auto EPI = T->getExtProtoInfo();
1141 if (EPI.HasTrailingReturn)
1142 OS << " trailing_return";
1143 if (T->isConst())
1144 OS << " const";
1145 if (T->isVolatile())
1146 OS << " volatile";
1147 if (T->isRestrict())
1148 OS << " restrict";
Stephen Kelly149119d2019-01-18 21:38:30 +00001149 if (T->getExtProtoInfo().Variadic)
1150 OS << " variadic";
Stephen Kellyf08ca202019-01-15 09:30:00 +00001151 switch (EPI.RefQualifier) {
1152 case RQ_None:
1153 break;
1154 case RQ_LValue:
1155 OS << " &";
1156 break;
1157 case RQ_RValue:
1158 OS << " &&";
1159 break;
1160 }
1161 // FIXME: Exception specification.
1162 // FIXME: Consumed parameters.
1163 VisitFunctionType(T);
1164}
1165
1166void TextNodeDumper::VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
1167 dumpDeclRef(T->getDecl());
1168}
1169
1170void TextNodeDumper::VisitTypedefType(const TypedefType *T) {
1171 dumpDeclRef(T->getDecl());
1172}
1173
1174void TextNodeDumper::VisitUnaryTransformType(const UnaryTransformType *T) {
1175 switch (T->getUTTKind()) {
1176 case UnaryTransformType::EnumUnderlyingType:
1177 OS << " underlying_type";
1178 break;
1179 }
1180}
1181
1182void TextNodeDumper::VisitTagType(const TagType *T) {
1183 dumpDeclRef(T->getDecl());
1184}
1185
1186void TextNodeDumper::VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
1187 OS << " depth " << T->getDepth() << " index " << T->getIndex();
1188 if (T->isParameterPack())
1189 OS << " pack";
1190 dumpDeclRef(T->getDecl());
1191}
1192
1193void TextNodeDumper::VisitAutoType(const AutoType *T) {
1194 if (T->isDecltypeAuto())
1195 OS << " decltype(auto)";
1196 if (!T->isDeduced())
1197 OS << " undeduced";
1198}
1199
1200void TextNodeDumper::VisitTemplateSpecializationType(
1201 const TemplateSpecializationType *T) {
1202 if (T->isTypeAlias())
1203 OS << " alias";
1204 OS << " ";
1205 T->getTemplateName().dump(OS);
1206}
1207
1208void TextNodeDumper::VisitInjectedClassNameType(
1209 const InjectedClassNameType *T) {
1210 dumpDeclRef(T->getDecl());
1211}
1212
1213void TextNodeDumper::VisitObjCInterfaceType(const ObjCInterfaceType *T) {
1214 dumpDeclRef(T->getDecl());
1215}
1216
1217void TextNodeDumper::VisitPackExpansionType(const PackExpansionType *T) {
1218 if (auto N = T->getNumExpansions())
1219 OS << " expansions " << *N;
1220}
Stephen Kellyb6318c92019-01-30 19:32:48 +00001221
1222void TextNodeDumper::VisitLabelDecl(const LabelDecl *D) { dumpName(D); }
1223
1224void TextNodeDumper::VisitTypedefDecl(const TypedefDecl *D) {
1225 dumpName(D);
1226 dumpType(D->getUnderlyingType());
1227 if (D->isModulePrivate())
1228 OS << " __module_private__";
1229}
1230
1231void TextNodeDumper::VisitEnumDecl(const EnumDecl *D) {
1232 if (D->isScoped()) {
1233 if (D->isScopedUsingClassTag())
1234 OS << " class";
1235 else
1236 OS << " struct";
1237 }
1238 dumpName(D);
1239 if (D->isModulePrivate())
1240 OS << " __module_private__";
1241 if (D->isFixed())
1242 dumpType(D->getIntegerType());
1243}
1244
1245void TextNodeDumper::VisitRecordDecl(const RecordDecl *D) {
1246 OS << ' ' << D->getKindName();
1247 dumpName(D);
1248 if (D->isModulePrivate())
1249 OS << " __module_private__";
1250 if (D->isCompleteDefinition())
1251 OS << " definition";
1252}
1253
1254void TextNodeDumper::VisitEnumConstantDecl(const EnumConstantDecl *D) {
1255 dumpName(D);
1256 dumpType(D->getType());
1257}
1258
1259void TextNodeDumper::VisitIndirectFieldDecl(const IndirectFieldDecl *D) {
1260 dumpName(D);
1261 dumpType(D->getType());
1262
1263 for (const auto *Child : D->chain())
1264 dumpDeclRef(Child);
1265}
1266
1267void TextNodeDumper::VisitFunctionDecl(const FunctionDecl *D) {
1268 dumpName(D);
1269 dumpType(D->getType());
1270
1271 StorageClass SC = D->getStorageClass();
1272 if (SC != SC_None)
1273 OS << ' ' << VarDecl::getStorageClassSpecifierString(SC);
1274 if (D->isInlineSpecified())
1275 OS << " inline";
1276 if (D->isVirtualAsWritten())
1277 OS << " virtual";
1278 if (D->isModulePrivate())
1279 OS << " __module_private__";
1280
1281 if (D->isPure())
1282 OS << " pure";
1283 if (D->isDefaulted()) {
1284 OS << " default";
1285 if (D->isDeleted())
1286 OS << "_delete";
1287 }
1288 if (D->isDeletedAsWritten())
1289 OS << " delete";
1290 if (D->isTrivial())
1291 OS << " trivial";
1292
1293 if (const auto *FPT = D->getType()->getAs<FunctionProtoType>()) {
1294 FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
1295 switch (EPI.ExceptionSpec.Type) {
1296 default:
1297 break;
1298 case EST_Unevaluated:
1299 OS << " noexcept-unevaluated " << EPI.ExceptionSpec.SourceDecl;
1300 break;
1301 case EST_Uninstantiated:
1302 OS << " noexcept-uninstantiated " << EPI.ExceptionSpec.SourceTemplate;
1303 break;
1304 }
1305 }
1306
1307 if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
1308 if (MD->size_overridden_methods() != 0) {
1309 auto dumpOverride = [=](const CXXMethodDecl *D) {
1310 SplitQualType T_split = D->getType().split();
1311 OS << D << " " << D->getParent()->getName()
1312 << "::" << D->getNameAsString() << " '"
1313 << QualType::getAsString(T_split, PrintPolicy) << "'";
1314 };
1315
1316 AddChild([=] {
1317 auto Overrides = MD->overridden_methods();
1318 OS << "Overrides: [ ";
1319 dumpOverride(*Overrides.begin());
1320 for (const auto *Override :
1321 llvm::make_range(Overrides.begin() + 1, Overrides.end())) {
1322 OS << ", ";
1323 dumpOverride(Override);
1324 }
1325 OS << " ]";
1326 });
1327 }
1328 }
1329
1330 // Since NumParams comes from the FunctionProtoType of the FunctionDecl and
1331 // the Params are set later, it is possible for a dump during debugging to
1332 // encounter a FunctionDecl that has been created but hasn't been assigned
1333 // ParmVarDecls yet.
1334 if (!D->param_empty() && !D->param_begin())
1335 OS << " <<<NULL params x " << D->getNumParams() << ">>>";
1336}
1337
1338void TextNodeDumper::VisitFieldDecl(const FieldDecl *D) {
1339 dumpName(D);
1340 dumpType(D->getType());
1341 if (D->isMutable())
1342 OS << " mutable";
1343 if (D->isModulePrivate())
1344 OS << " __module_private__";
1345}
1346
1347void TextNodeDumper::VisitVarDecl(const VarDecl *D) {
1348 dumpName(D);
1349 dumpType(D->getType());
1350 StorageClass SC = D->getStorageClass();
1351 if (SC != SC_None)
1352 OS << ' ' << VarDecl::getStorageClassSpecifierString(SC);
1353 switch (D->getTLSKind()) {
1354 case VarDecl::TLS_None:
1355 break;
1356 case VarDecl::TLS_Static:
1357 OS << " tls";
1358 break;
1359 case VarDecl::TLS_Dynamic:
1360 OS << " tls_dynamic";
1361 break;
1362 }
1363 if (D->isModulePrivate())
1364 OS << " __module_private__";
1365 if (D->isNRVOVariable())
1366 OS << " nrvo";
1367 if (D->isInline())
1368 OS << " inline";
1369 if (D->isConstexpr())
1370 OS << " constexpr";
1371 if (D->hasInit()) {
1372 switch (D->getInitStyle()) {
1373 case VarDecl::CInit:
1374 OS << " cinit";
1375 break;
1376 case VarDecl::CallInit:
1377 OS << " callinit";
1378 break;
1379 case VarDecl::ListInit:
1380 OS << " listinit";
1381 break;
1382 }
1383 }
Richard Smithb2997f52019-05-21 20:10:50 +00001384 if (D->isParameterPack())
1385 OS << " pack";
Stephen Kellyb6318c92019-01-30 19:32:48 +00001386}
1387
1388void TextNodeDumper::VisitBindingDecl(const BindingDecl *D) {
1389 dumpName(D);
1390 dumpType(D->getType());
1391}
1392
1393void TextNodeDumper::VisitCapturedDecl(const CapturedDecl *D) {
1394 if (D->isNothrow())
1395 OS << " nothrow";
1396}
1397
1398void TextNodeDumper::VisitImportDecl(const ImportDecl *D) {
1399 OS << ' ' << D->getImportedModule()->getFullModuleName();
Richard Smith520a37f2019-02-05 23:37:13 +00001400
1401 for (Decl *InitD :
1402 D->getASTContext().getModuleInitializers(D->getImportedModule()))
1403 dumpDeclRef(InitD, "initializer");
Stephen Kellyb6318c92019-01-30 19:32:48 +00001404}
1405
1406void TextNodeDumper::VisitPragmaCommentDecl(const PragmaCommentDecl *D) {
1407 OS << ' ';
1408 switch (D->getCommentKind()) {
1409 case PCK_Unknown:
1410 llvm_unreachable("unexpected pragma comment kind");
1411 case PCK_Compiler:
1412 OS << "compiler";
1413 break;
1414 case PCK_ExeStr:
1415 OS << "exestr";
1416 break;
1417 case PCK_Lib:
1418 OS << "lib";
1419 break;
1420 case PCK_Linker:
1421 OS << "linker";
1422 break;
1423 case PCK_User:
1424 OS << "user";
1425 break;
1426 }
1427 StringRef Arg = D->getArg();
1428 if (!Arg.empty())
1429 OS << " \"" << Arg << "\"";
1430}
1431
1432void TextNodeDumper::VisitPragmaDetectMismatchDecl(
1433 const PragmaDetectMismatchDecl *D) {
1434 OS << " \"" << D->getName() << "\" \"" << D->getValue() << "\"";
1435}
1436
Roman Lebedevb5700602019-03-20 16:32:36 +00001437void TextNodeDumper::VisitOMPExecutableDirective(
1438 const OMPExecutableDirective *D) {
1439 if (D->isStandaloneDirective())
1440 OS << " openmp_standalone_directive";
1441}
1442
Stephen Kellyb6318c92019-01-30 19:32:48 +00001443void TextNodeDumper::VisitOMPDeclareReductionDecl(
1444 const OMPDeclareReductionDecl *D) {
1445 dumpName(D);
1446 dumpType(D->getType());
1447 OS << " combiner";
1448 dumpPointer(D->getCombiner());
1449 if (const auto *Initializer = D->getInitializer()) {
1450 OS << " initializer";
1451 dumpPointer(Initializer);
1452 switch (D->getInitializerKind()) {
1453 case OMPDeclareReductionDecl::DirectInit:
1454 OS << " omp_priv = ";
1455 break;
1456 case OMPDeclareReductionDecl::CopyInit:
1457 OS << " omp_priv ()";
1458 break;
1459 case OMPDeclareReductionDecl::CallInit:
1460 break;
1461 }
1462 }
1463}
1464
1465void TextNodeDumper::VisitOMPRequiresDecl(const OMPRequiresDecl *D) {
1466 for (const auto *C : D->clauselists()) {
1467 AddChild([=] {
1468 if (!C) {
1469 ColorScope Color(OS, ShowColors, NullColor);
1470 OS << "<<<NULL>>> OMPClause";
1471 return;
1472 }
1473 {
1474 ColorScope Color(OS, ShowColors, AttrColor);
1475 StringRef ClauseName(getOpenMPClauseName(C->getClauseKind()));
1476 OS << "OMP" << ClauseName.substr(/*Start=*/0, /*N=*/1).upper()
1477 << ClauseName.drop_front() << "Clause";
1478 }
1479 dumpPointer(C);
1480 dumpSourceRange(SourceRange(C->getBeginLoc(), C->getEndLoc()));
1481 });
1482 }
1483}
1484
1485void TextNodeDumper::VisitOMPCapturedExprDecl(const OMPCapturedExprDecl *D) {
1486 dumpName(D);
1487 dumpType(D->getType());
1488}
1489
1490void TextNodeDumper::VisitNamespaceDecl(const NamespaceDecl *D) {
1491 dumpName(D);
1492 if (D->isInline())
1493 OS << " inline";
1494 if (!D->isOriginalNamespace())
1495 dumpDeclRef(D->getOriginalNamespace(), "original");
1496}
1497
1498void TextNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
1499 OS << ' ';
1500 dumpBareDeclRef(D->getNominatedNamespace());
1501}
1502
1503void TextNodeDumper::VisitNamespaceAliasDecl(const NamespaceAliasDecl *D) {
1504 dumpName(D);
1505 dumpDeclRef(D->getAliasedNamespace());
1506}
1507
1508void TextNodeDumper::VisitTypeAliasDecl(const TypeAliasDecl *D) {
1509 dumpName(D);
1510 dumpType(D->getUnderlyingType());
1511}
1512
1513void TextNodeDumper::VisitTypeAliasTemplateDecl(
1514 const TypeAliasTemplateDecl *D) {
1515 dumpName(D);
1516}
1517
1518void TextNodeDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) {
1519 VisitRecordDecl(D);
1520 if (!D->isCompleteDefinition())
1521 return;
1522
1523 AddChild([=] {
1524 {
1525 ColorScope Color(OS, ShowColors, DeclKindNameColor);
1526 OS << "DefinitionData";
1527 }
1528#define FLAG(fn, name) \
1529 if (D->fn()) \
1530 OS << " " #name;
1531 FLAG(isParsingBaseSpecifiers, parsing_base_specifiers);
1532
1533 FLAG(isGenericLambda, generic);
1534 FLAG(isLambda, lambda);
1535
1536 FLAG(canPassInRegisters, pass_in_registers);
1537 FLAG(isEmpty, empty);
1538 FLAG(isAggregate, aggregate);
1539 FLAG(isStandardLayout, standard_layout);
1540 FLAG(isTriviallyCopyable, trivially_copyable);
1541 FLAG(isPOD, pod);
1542 FLAG(isTrivial, trivial);
1543 FLAG(isPolymorphic, polymorphic);
1544 FLAG(isAbstract, abstract);
1545 FLAG(isLiteral, literal);
1546
1547 FLAG(hasUserDeclaredConstructor, has_user_declared_ctor);
1548 FLAG(hasConstexprNonCopyMoveConstructor, has_constexpr_non_copy_move_ctor);
1549 FLAG(hasMutableFields, has_mutable_fields);
1550 FLAG(hasVariantMembers, has_variant_members);
1551 FLAG(allowConstDefaultInit, can_const_default_init);
1552
1553 AddChild([=] {
1554 {
1555 ColorScope Color(OS, ShowColors, DeclKindNameColor);
1556 OS << "DefaultConstructor";
1557 }
1558 FLAG(hasDefaultConstructor, exists);
1559 FLAG(hasTrivialDefaultConstructor, trivial);
1560 FLAG(hasNonTrivialDefaultConstructor, non_trivial);
1561 FLAG(hasUserProvidedDefaultConstructor, user_provided);
1562 FLAG(hasConstexprDefaultConstructor, constexpr);
1563 FLAG(needsImplicitDefaultConstructor, needs_implicit);
1564 FLAG(defaultedDefaultConstructorIsConstexpr, defaulted_is_constexpr);
1565 });
1566
1567 AddChild([=] {
1568 {
1569 ColorScope Color(OS, ShowColors, DeclKindNameColor);
1570 OS << "CopyConstructor";
1571 }
1572 FLAG(hasSimpleCopyConstructor, simple);
1573 FLAG(hasTrivialCopyConstructor, trivial);
1574 FLAG(hasNonTrivialCopyConstructor, non_trivial);
1575 FLAG(hasUserDeclaredCopyConstructor, user_declared);
1576 FLAG(hasCopyConstructorWithConstParam, has_const_param);
1577 FLAG(needsImplicitCopyConstructor, needs_implicit);
1578 FLAG(needsOverloadResolutionForCopyConstructor,
1579 needs_overload_resolution);
1580 if (!D->needsOverloadResolutionForCopyConstructor())
1581 FLAG(defaultedCopyConstructorIsDeleted, defaulted_is_deleted);
1582 FLAG(implicitCopyConstructorHasConstParam, implicit_has_const_param);
1583 });
1584
1585 AddChild([=] {
1586 {
1587 ColorScope Color(OS, ShowColors, DeclKindNameColor);
1588 OS << "MoveConstructor";
1589 }
1590 FLAG(hasMoveConstructor, exists);
1591 FLAG(hasSimpleMoveConstructor, simple);
1592 FLAG(hasTrivialMoveConstructor, trivial);
1593 FLAG(hasNonTrivialMoveConstructor, non_trivial);
1594 FLAG(hasUserDeclaredMoveConstructor, user_declared);
1595 FLAG(needsImplicitMoveConstructor, needs_implicit);
1596 FLAG(needsOverloadResolutionForMoveConstructor,
1597 needs_overload_resolution);
1598 if (!D->needsOverloadResolutionForMoveConstructor())
1599 FLAG(defaultedMoveConstructorIsDeleted, defaulted_is_deleted);
1600 });
1601
1602 AddChild([=] {
1603 {
1604 ColorScope Color(OS, ShowColors, DeclKindNameColor);
1605 OS << "CopyAssignment";
1606 }
1607 FLAG(hasTrivialCopyAssignment, trivial);
1608 FLAG(hasNonTrivialCopyAssignment, non_trivial);
1609 FLAG(hasCopyAssignmentWithConstParam, has_const_param);
1610 FLAG(hasUserDeclaredCopyAssignment, user_declared);
1611 FLAG(needsImplicitCopyAssignment, needs_implicit);
1612 FLAG(needsOverloadResolutionForCopyAssignment, needs_overload_resolution);
1613 FLAG(implicitCopyAssignmentHasConstParam, implicit_has_const_param);
1614 });
1615
1616 AddChild([=] {
1617 {
1618 ColorScope Color(OS, ShowColors, DeclKindNameColor);
1619 OS << "MoveAssignment";
1620 }
1621 FLAG(hasMoveAssignment, exists);
1622 FLAG(hasSimpleMoveAssignment, simple);
1623 FLAG(hasTrivialMoveAssignment, trivial);
1624 FLAG(hasNonTrivialMoveAssignment, non_trivial);
1625 FLAG(hasUserDeclaredMoveAssignment, user_declared);
1626 FLAG(needsImplicitMoveAssignment, needs_implicit);
1627 FLAG(needsOverloadResolutionForMoveAssignment, needs_overload_resolution);
1628 });
1629
1630 AddChild([=] {
1631 {
1632 ColorScope Color(OS, ShowColors, DeclKindNameColor);
1633 OS << "Destructor";
1634 }
1635 FLAG(hasSimpleDestructor, simple);
1636 FLAG(hasIrrelevantDestructor, irrelevant);
1637 FLAG(hasTrivialDestructor, trivial);
1638 FLAG(hasNonTrivialDestructor, non_trivial);
1639 FLAG(hasUserDeclaredDestructor, user_declared);
1640 FLAG(needsImplicitDestructor, needs_implicit);
1641 FLAG(needsOverloadResolutionForDestructor, needs_overload_resolution);
1642 if (!D->needsOverloadResolutionForDestructor())
1643 FLAG(defaultedDestructorIsDeleted, defaulted_is_deleted);
1644 });
1645 });
1646
1647 for (const auto &I : D->bases()) {
1648 AddChild([=] {
1649 if (I.isVirtual())
1650 OS << "virtual ";
1651 dumpAccessSpecifier(I.getAccessSpecifier());
1652 dumpType(I.getType());
1653 if (I.isPackExpansion())
1654 OS << "...";
1655 });
1656 }
1657}
1658
1659void TextNodeDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
1660 dumpName(D);
1661}
1662
1663void TextNodeDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) {
1664 dumpName(D);
1665}
1666
1667void TextNodeDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) {
1668 dumpName(D);
1669}
1670
1671void TextNodeDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) {
1672 dumpName(D);
1673}
1674
1675void TextNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
1676 if (D->wasDeclaredWithTypename())
1677 OS << " typename";
1678 else
1679 OS << " class";
1680 OS << " depth " << D->getDepth() << " index " << D->getIndex();
1681 if (D->isParameterPack())
1682 OS << " ...";
1683 dumpName(D);
1684}
1685
1686void TextNodeDumper::VisitNonTypeTemplateParmDecl(
1687 const NonTypeTemplateParmDecl *D) {
1688 dumpType(D->getType());
1689 OS << " depth " << D->getDepth() << " index " << D->getIndex();
1690 if (D->isParameterPack())
1691 OS << " ...";
1692 dumpName(D);
1693}
1694
1695void TextNodeDumper::VisitTemplateTemplateParmDecl(
1696 const TemplateTemplateParmDecl *D) {
1697 OS << " depth " << D->getDepth() << " index " << D->getIndex();
1698 if (D->isParameterPack())
1699 OS << " ...";
1700 dumpName(D);
1701}
1702
1703void TextNodeDumper::VisitUsingDecl(const UsingDecl *D) {
1704 OS << ' ';
1705 if (D->getQualifier())
1706 D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
1707 OS << D->getNameAsString();
1708}
1709
1710void TextNodeDumper::VisitUnresolvedUsingTypenameDecl(
1711 const UnresolvedUsingTypenameDecl *D) {
1712 OS << ' ';
1713 if (D->getQualifier())
1714 D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
1715 OS << D->getNameAsString();
1716}
1717
1718void TextNodeDumper::VisitUnresolvedUsingValueDecl(
1719 const UnresolvedUsingValueDecl *D) {
1720 OS << ' ';
1721 if (D->getQualifier())
1722 D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy());
1723 OS << D->getNameAsString();
1724 dumpType(D->getType());
1725}
1726
1727void TextNodeDumper::VisitUsingShadowDecl(const UsingShadowDecl *D) {
1728 OS << ' ';
1729 dumpBareDeclRef(D->getTargetDecl());
1730}
1731
1732void TextNodeDumper::VisitConstructorUsingShadowDecl(
1733 const ConstructorUsingShadowDecl *D) {
1734 if (D->constructsVirtualBase())
1735 OS << " virtual";
1736
1737 AddChild([=] {
1738 OS << "target ";
1739 dumpBareDeclRef(D->getTargetDecl());
1740 });
1741
1742 AddChild([=] {
1743 OS << "nominated ";
1744 dumpBareDeclRef(D->getNominatedBaseClass());
1745 OS << ' ';
1746 dumpBareDeclRef(D->getNominatedBaseClassShadowDecl());
1747 });
1748
1749 AddChild([=] {
1750 OS << "constructed ";
1751 dumpBareDeclRef(D->getConstructedBaseClass());
1752 OS << ' ';
1753 dumpBareDeclRef(D->getConstructedBaseClassShadowDecl());
1754 });
1755}
1756
1757void TextNodeDumper::VisitLinkageSpecDecl(const LinkageSpecDecl *D) {
1758 switch (D->getLanguage()) {
1759 case LinkageSpecDecl::lang_c:
1760 OS << " C";
1761 break;
1762 case LinkageSpecDecl::lang_cxx:
1763 OS << " C++";
1764 break;
1765 }
1766}
1767
1768void TextNodeDumper::VisitAccessSpecDecl(const AccessSpecDecl *D) {
1769 OS << ' ';
1770 dumpAccessSpecifier(D->getAccess());
1771}
1772
1773void TextNodeDumper::VisitFriendDecl(const FriendDecl *D) {
1774 if (TypeSourceInfo *T = D->getFriendType())
1775 dumpType(T->getType());
1776}
1777
1778void TextNodeDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) {
1779 dumpName(D);
1780 dumpType(D->getType());
1781 if (D->getSynthesize())
1782 OS << " synthesize";
1783
1784 switch (D->getAccessControl()) {
1785 case ObjCIvarDecl::None:
1786 OS << " none";
1787 break;
1788 case ObjCIvarDecl::Private:
1789 OS << " private";
1790 break;
1791 case ObjCIvarDecl::Protected:
1792 OS << " protected";
1793 break;
1794 case ObjCIvarDecl::Public:
1795 OS << " public";
1796 break;
1797 case ObjCIvarDecl::Package:
1798 OS << " package";
1799 break;
1800 }
1801}
1802
1803void TextNodeDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) {
1804 if (D->isInstanceMethod())
1805 OS << " -";
1806 else
1807 OS << " +";
1808 dumpName(D);
1809 dumpType(D->getReturnType());
1810
1811 if (D->isVariadic())
1812 OS << " variadic";
1813}
1814
1815void TextNodeDumper::VisitObjCTypeParamDecl(const ObjCTypeParamDecl *D) {
1816 dumpName(D);
1817 switch (D->getVariance()) {
1818 case ObjCTypeParamVariance::Invariant:
1819 break;
1820
1821 case ObjCTypeParamVariance::Covariant:
1822 OS << " covariant";
1823 break;
1824
1825 case ObjCTypeParamVariance::Contravariant:
1826 OS << " contravariant";
1827 break;
1828 }
1829
1830 if (D->hasExplicitBound())
1831 OS << " bounded";
1832 dumpType(D->getUnderlyingType());
1833}
1834
1835void TextNodeDumper::VisitObjCCategoryDecl(const ObjCCategoryDecl *D) {
1836 dumpName(D);
1837 dumpDeclRef(D->getClassInterface());
1838 dumpDeclRef(D->getImplementation());
1839 for (const auto *P : D->protocols())
1840 dumpDeclRef(P);
1841}
1842
1843void TextNodeDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) {
1844 dumpName(D);
1845 dumpDeclRef(D->getClassInterface());
1846 dumpDeclRef(D->getCategoryDecl());
1847}
1848
1849void TextNodeDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) {
1850 dumpName(D);
1851
1852 for (const auto *Child : D->protocols())
1853 dumpDeclRef(Child);
1854}
1855
1856void TextNodeDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) {
1857 dumpName(D);
1858 dumpDeclRef(D->getSuperClass(), "super");
1859
1860 dumpDeclRef(D->getImplementation());
1861 for (const auto *Child : D->protocols())
1862 dumpDeclRef(Child);
1863}
1864
1865void TextNodeDumper::VisitObjCImplementationDecl(
1866 const ObjCImplementationDecl *D) {
1867 dumpName(D);
1868 dumpDeclRef(D->getSuperClass(), "super");
1869 dumpDeclRef(D->getClassInterface());
1870}
1871
1872void TextNodeDumper::VisitObjCCompatibleAliasDecl(
1873 const ObjCCompatibleAliasDecl *D) {
1874 dumpName(D);
1875 dumpDeclRef(D->getClassInterface());
1876}
1877
1878void TextNodeDumper::VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
1879 dumpName(D);
1880 dumpType(D->getType());
1881
1882 if (D->getPropertyImplementation() == ObjCPropertyDecl::Required)
1883 OS << " required";
1884 else if (D->getPropertyImplementation() == ObjCPropertyDecl::Optional)
1885 OS << " optional";
1886
1887 ObjCPropertyDecl::PropertyAttributeKind Attrs = D->getPropertyAttributes();
1888 if (Attrs != ObjCPropertyDecl::OBJC_PR_noattr) {
1889 if (Attrs & ObjCPropertyDecl::OBJC_PR_readonly)
1890 OS << " readonly";
1891 if (Attrs & ObjCPropertyDecl::OBJC_PR_assign)
1892 OS << " assign";
1893 if (Attrs & ObjCPropertyDecl::OBJC_PR_readwrite)
1894 OS << " readwrite";
1895 if (Attrs & ObjCPropertyDecl::OBJC_PR_retain)
1896 OS << " retain";
1897 if (Attrs & ObjCPropertyDecl::OBJC_PR_copy)
1898 OS << " copy";
1899 if (Attrs & ObjCPropertyDecl::OBJC_PR_nonatomic)
1900 OS << " nonatomic";
1901 if (Attrs & ObjCPropertyDecl::OBJC_PR_atomic)
1902 OS << " atomic";
1903 if (Attrs & ObjCPropertyDecl::OBJC_PR_weak)
1904 OS << " weak";
1905 if (Attrs & ObjCPropertyDecl::OBJC_PR_strong)
1906 OS << " strong";
1907 if (Attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained)
1908 OS << " unsafe_unretained";
1909 if (Attrs & ObjCPropertyDecl::OBJC_PR_class)
1910 OS << " class";
1911 if (Attrs & ObjCPropertyDecl::OBJC_PR_getter)
1912 dumpDeclRef(D->getGetterMethodDecl(), "getter");
1913 if (Attrs & ObjCPropertyDecl::OBJC_PR_setter)
1914 dumpDeclRef(D->getSetterMethodDecl(), "setter");
1915 }
1916}
1917
1918void TextNodeDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) {
1919 dumpName(D->getPropertyDecl());
1920 if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize)
1921 OS << " synthesize";
1922 else
1923 OS << " dynamic";
1924 dumpDeclRef(D->getPropertyDecl());
1925 dumpDeclRef(D->getPropertyIvarDecl());
1926}
1927
1928void TextNodeDumper::VisitBlockDecl(const BlockDecl *D) {
1929 if (D->isVariadic())
1930 OS << " variadic";
1931
1932 if (D->capturesCXXThis())
1933 OS << " captures_this";
1934}