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