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