1 //===--- DumpXML.cpp - Detailed XML dumping -------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the Decl::dumpXML() method, a debugging tool to 11 // print a detailed graph of an AST in an unspecified XML format. 12 // 13 // There is no guarantee of stability for this format. 14 // 15 //===----------------------------------------------------------------------===// 16 17 // Only pay for this in code size in assertions-enabled builds. 18 19 #include "clang/AST/ASTContext.h" 20 #include "clang/AST/Attr.h" 21 #include "clang/AST/Decl.h" 22 #include "clang/AST/DeclCXX.h" 23 #include "clang/AST/DeclFriend.h" 24 #include "clang/AST/DeclObjC.h" 25 #include "clang/AST/DeclTemplate.h" 26 #include "clang/AST/DeclVisitor.h" 27 #include "clang/AST/Expr.h" 28 #include "clang/AST/ExprCXX.h" 29 #include "clang/AST/ExprObjC.h" 30 #include "clang/AST/NestedNameSpecifier.h" 31 #include "clang/AST/Stmt.h" 32 #include "clang/AST/StmtCXX.h" 33 #include "clang/AST/StmtObjC.h" 34 #include "clang/AST/StmtVisitor.h" 35 #include "clang/AST/TemplateBase.h" 36 #include "clang/AST/TemplateName.h" 37 #include "clang/AST/Type.h" 38 #include "clang/AST/TypeLoc.h" 39 #include "clang/AST/TypeLocVisitor.h" 40 #include "clang/AST/TypeVisitor.h" 41 #include "llvm/ADT/SmallString.h" 42 43 using namespace clang; 44 45 #ifndef NDEBUG 46 47 namespace { 48 49 enum NodeState { 50 NS_Attrs, NS_LazyChildren, NS_Children 51 }; 52 53 struct Node { 54 StringRef Name; 55 NodeState State; 56 Node(StringRef name) : Name(name), State(NS_Attrs) {} 57 58 bool isDoneWithAttrs() const { return State != NS_Attrs; } 59 }; 60 61 template <class Impl> struct XMLDeclVisitor { 62 #define DISPATCH(NAME, CLASS) \ 63 static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(D)) 64 65 void dispatch(Decl *D) { 66 if (D->isUsed()) 67 static_cast<Impl*>(this)->set("used", "1"); 68 switch (D->getKind()) { 69 #define DECL(DERIVED, BASE) \ 70 case Decl::DERIVED: \ 71 DISPATCH(dispatch##DERIVED##DeclAttrs, DERIVED##Decl); \ 72 static_cast<Impl*>(this)->completeAttrs(); \ 73 DISPATCH(dispatch##DERIVED##DeclChildren, DERIVED##Decl); \ 74 DISPATCH(dispatch##DERIVED##DeclAsContext, DERIVED##Decl); \ 75 break; 76 #define ABSTRACT_DECL(DECL) 77 #include "clang/AST/DeclNodes.inc" 78 } 79 } 80 81 #define DECL(DERIVED, BASE) \ 82 void dispatch##DERIVED##DeclAttrs(DERIVED##Decl *D) { \ 83 DISPATCH(dispatch##BASE##Attrs, BASE); \ 84 DISPATCH(visit##DERIVED##DeclAttrs, DERIVED##Decl); \ 85 } \ 86 void visit##DERIVED##DeclAttrs(DERIVED##Decl *D) {} \ 87 void dispatch##DERIVED##DeclChildren(DERIVED##Decl *D) { \ 88 DISPATCH(dispatch##BASE##Children, BASE); \ 89 DISPATCH(visit##DERIVED##DeclChildren, DERIVED##Decl); \ 90 } \ 91 void visit##DERIVED##DeclChildren(DERIVED##Decl *D) {} \ 92 void dispatch##DERIVED##DeclAsContext(DERIVED##Decl *D) { \ 93 DISPATCH(dispatch##BASE##AsContext, BASE); \ 94 DISPATCH(visit##DERIVED##DeclAsContext, DERIVED##Decl); \ 95 } \ 96 void visit##DERIVED##DeclAsContext(DERIVED##Decl *D) {} 97 #include "clang/AST/DeclNodes.inc" 98 99 void dispatchDeclAttrs(Decl *D) { 100 DISPATCH(visitDeclAttrs, Decl); 101 } 102 void visitDeclAttrs(Decl *D) {} 103 104 void dispatchDeclChildren(Decl *D) { 105 DISPATCH(visitDeclChildren, Decl); 106 } 107 void visitDeclChildren(Decl *D) {} 108 109 void dispatchDeclAsContext(Decl *D) { 110 DISPATCH(visitDeclAsContext, Decl); 111 } 112 void visitDeclAsContext(Decl *D) {} 113 114 #undef DISPATCH 115 }; 116 117 template <class Impl> struct XMLTypeVisitor { 118 #define DISPATCH(NAME, CLASS) \ 119 static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(T)) 120 121 void dispatch(Type *T) { 122 switch (T->getTypeClass()) { 123 #define TYPE(DERIVED, BASE) \ 124 case Type::DERIVED: \ 125 DISPATCH(dispatch##DERIVED##TypeAttrs, DERIVED##Type); \ 126 static_cast<Impl*>(this)->completeAttrs(); \ 127 DISPATCH(dispatch##DERIVED##TypeChildren, DERIVED##Type); \ 128 break; 129 #define ABSTRACT_TYPE(DERIVED, BASE) 130 #include "clang/AST/TypeNodes.def" 131 } 132 } 133 134 #define TYPE(DERIVED, BASE) \ 135 void dispatch##DERIVED##TypeAttrs(DERIVED##Type *T) { \ 136 DISPATCH(dispatch##BASE##Attrs, BASE); \ 137 DISPATCH(visit##DERIVED##TypeAttrs, DERIVED##Type); \ 138 } \ 139 void visit##DERIVED##TypeAttrs(DERIVED##Type *T) {} \ 140 void dispatch##DERIVED##TypeChildren(DERIVED##Type *T) { \ 141 DISPATCH(dispatch##BASE##Children, BASE); \ 142 DISPATCH(visit##DERIVED##TypeChildren, DERIVED##Type); \ 143 } \ 144 void visit##DERIVED##TypeChildren(DERIVED##Type *T) {} 145 #include "clang/AST/TypeNodes.def" 146 147 void dispatchTypeAttrs(Type *T) { 148 DISPATCH(visitTypeAttrs, Type); 149 } 150 void visitTypeAttrs(Type *T) {} 151 152 void dispatchTypeChildren(Type *T) { 153 DISPATCH(visitTypeChildren, Type); 154 } 155 void visitTypeChildren(Type *T) {} 156 157 #undef DISPATCH 158 }; 159 160 static StringRef getTypeKindName(Type *T) { 161 switch (T->getTypeClass()) { 162 #define TYPE(DERIVED, BASE) case Type::DERIVED: return #DERIVED "Type"; 163 #define ABSTRACT_TYPE(DERIVED, BASE) 164 #include "clang/AST/TypeNodes.def" 165 } 166 167 llvm_unreachable("unknown type kind!"); 168 } 169 170 struct XMLDumper : public XMLDeclVisitor<XMLDumper>, 171 public XMLTypeVisitor<XMLDumper> { 172 raw_ostream &out; 173 ASTContext &Context; 174 SmallVector<Node, 16> Stack; 175 unsigned Indent; 176 explicit XMLDumper(raw_ostream &OS, ASTContext &context) 177 : out(OS), Context(context), Indent(0) {} 178 179 void indent() { 180 for (unsigned I = Indent; I; --I) 181 out << ' '; 182 } 183 184 /// Push a new node on the stack. 185 void push(StringRef name) { 186 if (!Stack.empty()) { 187 assert(Stack.back().isDoneWithAttrs()); 188 if (Stack.back().State == NS_LazyChildren) { 189 Stack.back().State = NS_Children; 190 out << ">\n"; 191 } 192 Indent++; 193 indent(); 194 } 195 Stack.push_back(Node(name)); 196 out << '<' << name; 197 } 198 199 /// Set the given attribute to the given value. 200 void set(StringRef attr, StringRef value) { 201 assert(!Stack.empty() && !Stack.back().isDoneWithAttrs()); 202 out << ' ' << attr << '=' << '"' << value << '"'; // TODO: quotation 203 } 204 205 /// Finish attributes. 206 void completeAttrs() { 207 assert(!Stack.empty() && !Stack.back().isDoneWithAttrs()); 208 Stack.back().State = NS_LazyChildren; 209 } 210 211 /// Pop a node. 212 void pop() { 213 assert(!Stack.empty() && Stack.back().isDoneWithAttrs()); 214 if (Stack.back().State == NS_LazyChildren) { 215 out << "/>\n"; 216 } else { 217 indent(); 218 out << "</" << Stack.back().Name << ">\n"; 219 } 220 if (Stack.size() > 1) Indent--; 221 Stack.pop_back(); 222 } 223 224 //---- General utilities -------------------------------------------// 225 226 void setPointer(StringRef prop, const void *p) { 227 SmallString<10> buffer; 228 llvm::raw_svector_ostream os(buffer); 229 os << p; 230 os.flush(); 231 set(prop, buffer); 232 } 233 234 void setPointer(void *p) { 235 setPointer("ptr", p); 236 } 237 238 void setInteger(StringRef prop, const llvm::APSInt &v) { 239 set(prop, v.toString(10)); 240 } 241 242 void setInteger(StringRef prop, unsigned n) { 243 SmallString<10> buffer; 244 llvm::raw_svector_ostream os(buffer); 245 os << n; 246 os.flush(); 247 set(prop, buffer); 248 } 249 250 void setFlag(StringRef prop, bool flag) { 251 if (flag) set(prop, "true"); 252 } 253 254 void setName(DeclarationName Name) { 255 if (!Name) 256 return set("name", ""); 257 258 // Common case. 259 if (Name.isIdentifier()) 260 return set("name", Name.getAsIdentifierInfo()->getName()); 261 262 set("name", Name.getAsString()); 263 } 264 265 class TemporaryContainer { 266 XMLDumper &Dumper; 267 public: 268 TemporaryContainer(XMLDumper &dumper, StringRef name) 269 : Dumper(dumper) { 270 Dumper.push(name); 271 Dumper.completeAttrs(); 272 } 273 274 ~TemporaryContainer() { 275 Dumper.pop(); 276 } 277 }; 278 279 void visitTemplateParameters(TemplateParameterList *L) { 280 push("template_parameters"); 281 completeAttrs(); 282 for (TemplateParameterList::iterator 283 I = L->begin(), E = L->end(); I != E; ++I) 284 dispatch(*I); 285 pop(); 286 } 287 288 void visitTemplateArguments(const TemplateArgumentList &L) { 289 push("template_arguments"); 290 completeAttrs(); 291 for (unsigned I = 0, E = L.size(); I != E; ++I) 292 dispatch(L[I]); 293 pop(); 294 } 295 296 /// Visits a reference to the given declaration. 297 void visitDeclRef(Decl *D) { 298 push(D->getDeclKindName()); 299 setPointer("ref", D); 300 completeAttrs(); 301 pop(); 302 } 303 void visitDeclRef(StringRef Name, Decl *D) { 304 TemporaryContainer C(*this, Name); 305 if (D) visitDeclRef(D); 306 } 307 308 void dispatch(const TemplateArgument &A) { 309 switch (A.getKind()) { 310 case TemplateArgument::Null: { 311 TemporaryContainer C(*this, "null"); 312 break; 313 } 314 case TemplateArgument::Type: { 315 dispatch(A.getAsType()); 316 break; 317 } 318 case TemplateArgument::Template: 319 case TemplateArgument::TemplateExpansion: 320 case TemplateArgument::NullPtr: 321 // FIXME: Implement! 322 break; 323 324 case TemplateArgument::Declaration: { 325 visitDeclRef(A.getAsDecl()); 326 break; 327 } 328 case TemplateArgument::Integral: { 329 push("integer"); 330 setInteger("value", A.getAsIntegral()); 331 completeAttrs(); 332 pop(); 333 break; 334 } 335 case TemplateArgument::Expression: { 336 dispatch(A.getAsExpr()); 337 break; 338 } 339 case TemplateArgument::Pack: { 340 for (TemplateArgument::pack_iterator P = A.pack_begin(), 341 PEnd = A.pack_end(); 342 P != PEnd; ++P) 343 dispatch(*P); 344 break; 345 } 346 } 347 } 348 349 void dispatch(const TemplateArgumentLoc &A) { 350 dispatch(A.getArgument()); 351 } 352 353 //---- Declarations ------------------------------------------------// 354 // Calls are made in this order: 355 // # Enter a new node. 356 // push("FieldDecl") 357 // 358 // # In this phase, attributes are set on the node. 359 // visitDeclAttrs(D) 360 // visitNamedDeclAttrs(D) 361 // ... 362 // visitFieldDeclAttrs(D) 363 // 364 // # No more attributes after this point. 365 // completeAttrs() 366 // 367 // # Create "header" child nodes, i.e. those which logically 368 // # belong to the declaration itself. 369 // visitDeclChildren(D) 370 // visitNamedDeclChildren(D) 371 // ... 372 // visitFieldDeclChildren(D) 373 // 374 // # Create nodes for the lexical children. 375 // visitDeclAsContext(D) 376 // visitNamedDeclAsContext(D) 377 // ... 378 // visitFieldDeclAsContext(D) 379 // 380 // # Finish the node. 381 // pop(); 382 void dispatch(Decl *D) { 383 push(D->getDeclKindName()); 384 XMLDeclVisitor<XMLDumper>::dispatch(D); 385 pop(); 386 } 387 void visitDeclAttrs(Decl *D) { 388 setPointer(D); 389 } 390 391 /// Visit all the lexical decls in the given context. 392 void visitDeclContext(DeclContext *DC) { 393 for (DeclContext::decl_iterator 394 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) 395 dispatch(*I); 396 397 // FIXME: point out visible declarations not in lexical context? 398 } 399 400 /// Set the "access" attribute on the current node according to the 401 /// given specifier. 402 void setAccess(AccessSpecifier AS) { 403 switch (AS) { 404 case AS_public: return set("access", "public"); 405 case AS_protected: return set("access", "protected"); 406 case AS_private: return set("access", "private"); 407 case AS_none: llvm_unreachable("explicit forbidden access"); 408 } 409 } 410 411 template <class T> void visitRedeclarableAttrs(T *D) { 412 if (T *Prev = D->getPreviousDecl()) 413 setPointer("previous", Prev); 414 } 415 416 417 // TranslationUnitDecl 418 void visitTranslationUnitDeclAsContext(TranslationUnitDecl *D) { 419 visitDeclContext(D); 420 } 421 422 // LinkageSpecDecl 423 void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) { 424 StringRef lang = ""; 425 switch (D->getLanguage()) { 426 case LinkageSpecDecl::lang_c: lang = "C"; break; 427 case LinkageSpecDecl::lang_cxx: lang = "C++"; break; 428 } 429 set("lang", lang); 430 } 431 void visitLinkageSpecDeclAsContext(LinkageSpecDecl *D) { 432 visitDeclContext(D); 433 } 434 435 // NamespaceDecl 436 void visitNamespaceDeclAttrs(NamespaceDecl *D) { 437 setFlag("inline", D->isInline()); 438 if (!D->isOriginalNamespace()) 439 setPointer("original", D->getOriginalNamespace()); 440 } 441 void visitNamespaceDeclAsContext(NamespaceDecl *D) { 442 visitDeclContext(D); 443 } 444 445 // NamedDecl 446 void visitNamedDeclAttrs(NamedDecl *D) { 447 setName(D->getDeclName()); 448 } 449 450 // ValueDecl 451 void visitValueDeclChildren(ValueDecl *D) { 452 dispatch(D->getType()); 453 } 454 455 // DeclaratorDecl 456 void visitDeclaratorDeclChildren(DeclaratorDecl *D) { 457 //dispatch(D->getTypeSourceInfo()->getTypeLoc()); 458 } 459 460 // VarDecl 461 void visitVarDeclAttrs(VarDecl *D) { 462 visitRedeclarableAttrs(D); 463 if (D->getStorageClass() != SC_None) 464 set("storage", 465 VarDecl::getStorageClassSpecifierString(D->getStorageClass())); 466 StringRef initStyle = ""; 467 switch (D->getInitStyle()) { 468 case VarDecl::CInit: initStyle = "c"; break; 469 case VarDecl::CallInit: initStyle = "call"; break; 470 case VarDecl::ListInit: initStyle = "list"; break; 471 } 472 set("initstyle", initStyle); 473 setFlag("nrvo", D->isNRVOVariable()); 474 // TODO: instantiation, etc. 475 } 476 void visitVarDeclChildren(VarDecl *D) { 477 if (D->hasInit()) dispatch(D->getInit()); 478 } 479 480 // ParmVarDecl? 481 482 // FunctionDecl 483 void visitFunctionDeclAttrs(FunctionDecl *D) { 484 visitRedeclarableAttrs(D); 485 setFlag("pure", D->isPure()); 486 setFlag("trivial", D->isTrivial()); 487 setFlag("returnzero", D->hasImplicitReturnZero()); 488 setFlag("prototype", D->hasWrittenPrototype()); 489 setFlag("deleted", D->isDeletedAsWritten()); 490 if (D->getStorageClass() != SC_None) 491 set("storage", 492 VarDecl::getStorageClassSpecifierString(D->getStorageClass())); 493 setFlag("inline", D->isInlineSpecified()); 494 if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) 495 set("asmlabel", ALA->getLabel()); 496 // TODO: instantiation, etc. 497 } 498 void visitFunctionDeclChildren(FunctionDecl *D) { 499 for (FunctionDecl::param_iterator 500 I = D->param_begin(), E = D->param_end(); I != E; ++I) 501 dispatch(*I); 502 for (ArrayRef<NamedDecl *>::iterator I = D->getDeclsInPrototypeScope().begin(), 503 E = D->getDeclsInPrototypeScope().end(); 504 I != E; ++I) 505 dispatch(*I); 506 if (D->doesThisDeclarationHaveABody()) 507 dispatch(D->getBody()); 508 } 509 510 // CXXMethodDecl ? 511 // CXXConstructorDecl ? 512 // CXXDestructorDecl ? 513 // CXXConversionDecl ? 514 515 void dispatch(CXXCtorInitializer *Init) { 516 // TODO 517 } 518 519 // FieldDecl 520 void visitFieldDeclAttrs(FieldDecl *D) { 521 setFlag("mutable", D->isMutable()); 522 } 523 void visitFieldDeclChildren(FieldDecl *D) { 524 if (D->isBitField()) { 525 TemporaryContainer C(*this, "bitwidth"); 526 dispatch(D->getBitWidth()); 527 } 528 // TODO: C++0x member initializer 529 } 530 531 // EnumConstantDecl 532 void visitEnumConstantDeclChildren(EnumConstantDecl *D) { 533 // value in any case? 534 if (D->getInitExpr()) dispatch(D->getInitExpr()); 535 } 536 537 // IndirectFieldDecl 538 void visitIndirectFieldDeclChildren(IndirectFieldDecl *D) { 539 for (IndirectFieldDecl::chain_iterator 540 I = D->chain_begin(), E = D->chain_end(); I != E; ++I) { 541 NamedDecl *VD = const_cast<NamedDecl*>(*I); 542 push(isa<VarDecl>(VD) ? "variable" : "field"); 543 setPointer("ptr", VD); 544 completeAttrs(); 545 pop(); 546 } 547 } 548 549 // TypeDecl 550 void visitTypeDeclAttrs(TypeDecl *D) { 551 setPointer("typeptr", D->getTypeForDecl()); 552 } 553 554 // TypedefDecl 555 void visitTypedefDeclAttrs(TypedefDecl *D) { 556 visitRedeclarableAttrs<TypedefNameDecl>(D); 557 } 558 void visitTypedefDeclChildren(TypedefDecl *D) { 559 dispatch(D->getTypeSourceInfo()->getTypeLoc()); 560 } 561 562 // TypeAliasDecl 563 void visitTypeAliasDeclAttrs(TypeAliasDecl *D) { 564 visitRedeclarableAttrs<TypedefNameDecl>(D); 565 } 566 void visitTypeAliasDeclChildren(TypeAliasDecl *D) { 567 dispatch(D->getTypeSourceInfo()->getTypeLoc()); 568 } 569 570 // TagDecl 571 void visitTagDeclAttrs(TagDecl *D) { 572 visitRedeclarableAttrs(D); 573 } 574 void visitTagDeclAsContext(TagDecl *D) { 575 visitDeclContext(D); 576 } 577 578 // EnumDecl 579 void visitEnumDeclAttrs(EnumDecl *D) { 580 setFlag("scoped", D->isScoped()); 581 setFlag("fixed", D->isFixed()); 582 } 583 void visitEnumDeclChildren(EnumDecl *D) { 584 { 585 TemporaryContainer C(*this, "promotion_type"); 586 dispatch(D->getPromotionType()); 587 } 588 { 589 TemporaryContainer C(*this, "integer_type"); 590 dispatch(D->getIntegerType()); 591 } 592 } 593 594 // RecordDecl ? 595 596 void visitCXXRecordDeclChildren(CXXRecordDecl *D) { 597 if (!D->isThisDeclarationADefinition()) return; 598 599 for (CXXRecordDecl::base_class_iterator 600 I = D->bases_begin(), E = D->bases_end(); I != E; ++I) { 601 push("base"); 602 setAccess(I->getAccessSpecifier()); 603 completeAttrs(); 604 dispatch(I->getTypeSourceInfo()->getTypeLoc()); 605 pop(); 606 } 607 } 608 609 // ClassTemplateSpecializationDecl ? 610 611 // FileScopeAsmDecl ? 612 613 // BlockDecl 614 void visitBlockDeclAttrs(BlockDecl *D) { 615 setFlag("variadic", D->isVariadic()); 616 } 617 void visitBlockDeclChildren(BlockDecl *D) { 618 for (FunctionDecl::param_iterator 619 I = D->param_begin(), E = D->param_end(); I != E; ++I) 620 dispatch(*I); 621 dispatch(D->getBody()); 622 } 623 624 // AccessSpecDecl 625 void visitAccessSpecDeclAttrs(AccessSpecDecl *D) { 626 setAccess(D->getAccess()); 627 } 628 629 // TemplateDecl 630 void visitTemplateDeclChildren(TemplateDecl *D) { 631 visitTemplateParameters(D->getTemplateParameters()); 632 if (D->getTemplatedDecl()) 633 dispatch(D->getTemplatedDecl()); 634 } 635 636 // FunctionTemplateDecl 637 void visitFunctionTemplateDeclAttrs(FunctionTemplateDecl *D) { 638 visitRedeclarableAttrs(D); 639 } 640 void visitFunctionTemplateDeclChildren(FunctionTemplateDecl *D) { 641 // Mention all the specializations which don't have explicit 642 // declarations elsewhere. 643 for (FunctionTemplateDecl::spec_iterator 644 I = D->spec_begin(), E = D->spec_end(); I != E; ++I) { 645 FunctionTemplateSpecializationInfo *Info 646 = I->getTemplateSpecializationInfo(); 647 648 bool Unknown = false; 649 switch (Info->getTemplateSpecializationKind()) { 650 case TSK_ImplicitInstantiation: Unknown = false; break; 651 case TSK_Undeclared: Unknown = true; break; 652 653 // These will be covered at their respective sites. 654 case TSK_ExplicitSpecialization: continue; 655 case TSK_ExplicitInstantiationDeclaration: continue; 656 case TSK_ExplicitInstantiationDefinition: continue; 657 } 658 659 TemporaryContainer C(*this, 660 Unknown ? "uninstantiated" : "instantiation"); 661 visitTemplateArguments(*Info->TemplateArguments); 662 dispatch(Info->Function); 663 } 664 } 665 666 // ClasTemplateDecl 667 void visitClassTemplateDeclAttrs(ClassTemplateDecl *D) { 668 visitRedeclarableAttrs(D); 669 } 670 void visitClassTemplateDeclChildren(ClassTemplateDecl *D) { 671 // Mention all the specializations which don't have explicit 672 // declarations elsewhere. 673 for (ClassTemplateDecl::spec_iterator 674 I = D->spec_begin(), E = D->spec_end(); I != E; ++I) { 675 676 bool Unknown = false; 677 switch (I->getTemplateSpecializationKind()) { 678 case TSK_ImplicitInstantiation: Unknown = false; break; 679 case TSK_Undeclared: Unknown = true; break; 680 681 // These will be covered at their respective sites. 682 case TSK_ExplicitSpecialization: continue; 683 case TSK_ExplicitInstantiationDeclaration: continue; 684 case TSK_ExplicitInstantiationDefinition: continue; 685 } 686 687 TemporaryContainer C(*this, 688 Unknown ? "uninstantiated" : "instantiation"); 689 visitTemplateArguments(I->getTemplateArgs()); 690 dispatch(*I); 691 } 692 } 693 694 // TemplateTypeParmDecl 695 void visitTemplateTypeParmDeclAttrs(TemplateTypeParmDecl *D) { 696 setInteger("depth", D->getDepth()); 697 setInteger("index", D->getIndex()); 698 } 699 void visitTemplateTypeParmDeclChildren(TemplateTypeParmDecl *D) { 700 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) 701 dispatch(D->getDefaultArgumentInfo()->getTypeLoc()); 702 // parameter pack? 703 } 704 705 // NonTypeTemplateParmDecl 706 void visitNonTypeTemplateParmDeclAttrs(NonTypeTemplateParmDecl *D) { 707 setInteger("depth", D->getDepth()); 708 setInteger("index", D->getIndex()); 709 } 710 void visitNonTypeTemplateParmDeclChildren(NonTypeTemplateParmDecl *D) { 711 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) 712 dispatch(D->getDefaultArgument()); 713 // parameter pack? 714 } 715 716 // TemplateTemplateParmDecl 717 void visitTemplateTemplateParmDeclAttrs(TemplateTemplateParmDecl *D) { 718 setInteger("depth", D->getDepth()); 719 setInteger("index", D->getIndex()); 720 } 721 void visitTemplateTemplateParmDeclChildren(TemplateTemplateParmDecl *D) { 722 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) 723 dispatch(D->getDefaultArgument()); 724 // parameter pack? 725 } 726 727 // FriendDecl 728 void visitFriendDeclChildren(FriendDecl *D) { 729 if (TypeSourceInfo *T = D->getFriendType()) 730 dispatch(T->getTypeLoc()); 731 else 732 dispatch(D->getFriendDecl()); 733 } 734 735 // UsingDirectiveDecl ? 736 // UsingDecl ? 737 // UsingShadowDecl ? 738 // NamespaceAliasDecl ? 739 // UnresolvedUsingValueDecl ? 740 // UnresolvedUsingTypenameDecl ? 741 // StaticAssertDecl ? 742 743 // ObjCImplDecl 744 void visitObjCImplDeclChildren(ObjCImplDecl *D) { 745 visitDeclRef(D->getClassInterface()); 746 } 747 void visitObjCImplDeclAsContext(ObjCImplDecl *D) { 748 visitDeclContext(D); 749 } 750 751 void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) { 752 setPointer("typeptr", D->getTypeForDecl()); 753 setFlag("forward_decl", !D->isThisDeclarationADefinition()); 754 setFlag("implicit_interface", D->isImplicitInterfaceDecl()); 755 } 756 void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) { 757 visitDeclRef("super", D->getSuperClass()); 758 visitDeclRef("implementation", D->getImplementation()); 759 if (D->protocol_begin() != D->protocol_end()) { 760 TemporaryContainer C(*this, "protocols"); 761 for (ObjCInterfaceDecl::protocol_iterator 762 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) 763 visitDeclRef(*I); 764 } 765 766 if (!D->visible_categories_empty()) { 767 TemporaryContainer C(*this, "categories"); 768 769 for (ObjCInterfaceDecl::visible_categories_iterator 770 Cat = D->visible_categories_begin(), 771 CatEnd = D->visible_categories_end(); 772 Cat != CatEnd; ++Cat) { 773 visitDeclRef(*Cat); 774 } 775 } 776 } 777 void visitObjCInterfaceDeclAsContext(ObjCInterfaceDecl *D) { 778 visitDeclContext(D); 779 } 780 781 // ObjCCategoryDecl 782 void visitObjCCategoryDeclAttrs(ObjCCategoryDecl *D) { 783 setFlag("extension", D->IsClassExtension()); 784 } 785 void visitObjCCategoryDeclChildren(ObjCCategoryDecl *D) { 786 visitDeclRef("interface", D->getClassInterface()); 787 visitDeclRef("implementation", D->getImplementation()); 788 if (D->protocol_begin() != D->protocol_end()) { 789 TemporaryContainer C(*this, "protocols"); 790 for (ObjCCategoryDecl::protocol_iterator 791 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) 792 visitDeclRef(*I); 793 } 794 } 795 void visitObjCCategoryDeclAsContext(ObjCCategoryDecl *D) { 796 visitDeclContext(D); 797 } 798 799 // ObjCCategoryImplDecl 800 void visitObjCCategoryImplDeclAttrs(ObjCCategoryImplDecl *D) { 801 set("identifier", D->getName()); 802 } 803 void visitObjCCategoryImplDeclChildren(ObjCCategoryImplDecl *D) { 804 visitDeclRef(D->getCategoryDecl()); 805 } 806 807 // ObjCImplementationDecl 808 void visitObjCImplementationDeclAttrs(ObjCImplementationDecl *D) { 809 set("identifier", D->getName()); 810 } 811 void visitObjCImplementationDeclChildren(ObjCImplementationDecl *D) { 812 visitDeclRef("super", D->getSuperClass()); 813 if (D->init_begin() != D->init_end()) { 814 TemporaryContainer C(*this, "initializers"); 815 for (ObjCImplementationDecl::init_iterator 816 I = D->init_begin(), E = D->init_end(); I != E; ++I) 817 dispatch(*I); 818 } 819 } 820 821 // ObjCProtocolDecl 822 void visitObjCProtocolDeclChildren(ObjCProtocolDecl *D) { 823 if (!D->isThisDeclarationADefinition()) 824 return; 825 826 if (D->protocol_begin() != D->protocol_end()) { 827 TemporaryContainer C(*this, "protocols"); 828 for (ObjCInterfaceDecl::protocol_iterator 829 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) 830 visitDeclRef(*I); 831 } 832 } 833 void visitObjCProtocolDeclAsContext(ObjCProtocolDecl *D) { 834 if (!D->isThisDeclarationADefinition()) 835 return; 836 837 visitDeclContext(D); 838 } 839 840 // ObjCMethodDecl 841 void visitObjCMethodDeclAttrs(ObjCMethodDecl *D) { 842 // decl qualifier? 843 // implementation control? 844 845 setFlag("instance", D->isInstanceMethod()); 846 setFlag("variadic", D->isVariadic()); 847 setFlag("property_accessor", D->isPropertyAccessor()); 848 setFlag("defined", D->isDefined()); 849 setFlag("related_result_type", D->hasRelatedResultType()); 850 } 851 void visitObjCMethodDeclChildren(ObjCMethodDecl *D) { 852 dispatch(D->getResultType()); 853 for (ObjCMethodDecl::param_iterator 854 I = D->param_begin(), E = D->param_end(); I != E; ++I) 855 dispatch(*I); 856 if (D->isThisDeclarationADefinition()) 857 dispatch(D->getBody()); 858 } 859 860 // ObjCIvarDecl 861 void setAccessControl(StringRef prop, ObjCIvarDecl::AccessControl AC) { 862 switch (AC) { 863 case ObjCIvarDecl::None: return set(prop, "none"); 864 case ObjCIvarDecl::Private: return set(prop, "private"); 865 case ObjCIvarDecl::Protected: return set(prop, "protected"); 866 case ObjCIvarDecl::Public: return set(prop, "public"); 867 case ObjCIvarDecl::Package: return set(prop, "package"); 868 } 869 } 870 void visitObjCIvarDeclAttrs(ObjCIvarDecl *D) { 871 setFlag("synthesize", D->getSynthesize()); 872 setAccessControl("access", D->getAccessControl()); 873 } 874 875 // ObjCCompatibleAliasDecl 876 void visitObjCCompatibleAliasDeclChildren(ObjCCompatibleAliasDecl *D) { 877 visitDeclRef(D->getClassInterface()); 878 } 879 880 // FIXME: ObjCPropertyDecl 881 // FIXME: ObjCPropertyImplDecl 882 883 //---- Types -----------------------------------------------------// 884 void dispatch(TypeLoc TL) { 885 dispatch(TL.getType()); // for now 886 } 887 888 void dispatch(QualType T) { 889 if (T.hasLocalQualifiers()) { 890 push("QualType"); 891 Qualifiers Qs = T.getLocalQualifiers(); 892 setFlag("const", Qs.hasConst()); 893 setFlag("volatile", Qs.hasVolatile()); 894 setFlag("restrict", Qs.hasRestrict()); 895 if (Qs.hasAddressSpace()) setInteger("addrspace", Qs.getAddressSpace()); 896 if (Qs.hasObjCGCAttr()) { 897 switch (Qs.getObjCGCAttr()) { 898 case Qualifiers::Weak: set("gc", "weak"); break; 899 case Qualifiers::Strong: set("gc", "strong"); break; 900 case Qualifiers::GCNone: llvm_unreachable("explicit none"); 901 } 902 } 903 904 completeAttrs(); 905 dispatch(QualType(T.getTypePtr(), 0)); 906 pop(); 907 return; 908 } 909 910 Type *Ty = const_cast<Type*>(T.getTypePtr()); 911 push(getTypeKindName(Ty)); 912 XMLTypeVisitor<XMLDumper>::dispatch(const_cast<Type*>(T.getTypePtr())); 913 pop(); 914 } 915 916 void setCallingConv(CallingConv CC) { 917 switch (CC) { 918 case CC_Default: return; 919 case CC_C: return set("cc", "cdecl"); 920 case CC_X86FastCall: return set("cc", "x86_fastcall"); 921 case CC_X86StdCall: return set("cc", "x86_stdcall"); 922 case CC_X86ThisCall: return set("cc", "x86_thiscall"); 923 case CC_X86Pascal: return set("cc", "x86_pascal"); 924 case CC_AAPCS: return set("cc", "aapcs"); 925 case CC_AAPCS_VFP: return set("cc", "aapcs_vfp"); 926 case CC_PnaclCall: return set("cc", "pnaclcall"); 927 case CC_IntelOclBicc: return set("cc", "intel_ocl_bicc"); 928 } 929 } 930 931 void visitTypeAttrs(Type *D) { 932 setPointer(D); 933 setFlag("dependent", D->isDependentType()); 934 setFlag("variably_modified", D->isVariablyModifiedType()); 935 936 setPointer("canonical", D->getCanonicalTypeInternal().getAsOpaquePtr()); 937 } 938 939 void visitPointerTypeChildren(PointerType *T) { 940 dispatch(T->getPointeeType()); 941 } 942 void visitReferenceTypeChildren(ReferenceType *T) { 943 dispatch(T->getPointeeType()); 944 } 945 void visitObjCObjectPointerTypeChildren(ObjCObjectPointerType *T) { 946 dispatch(T->getPointeeType()); 947 } 948 void visitBlockPointerTypeChildren(BlockPointerType *T) { 949 dispatch(T->getPointeeType()); 950 } 951 952 // Types that just wrap declarations. 953 void visitTagTypeChildren(TagType *T) { 954 visitDeclRef(T->getDecl()); 955 } 956 void visitTypedefTypeChildren(TypedefType *T) { 957 visitDeclRef(T->getDecl()); 958 } 959 void visitObjCInterfaceTypeChildren(ObjCInterfaceType *T) { 960 visitDeclRef(T->getDecl()); 961 } 962 void visitUnresolvedUsingTypeChildren(UnresolvedUsingType *T) { 963 visitDeclRef(T->getDecl()); 964 } 965 void visitInjectedClassNameTypeChildren(InjectedClassNameType *T) { 966 visitDeclRef(T->getDecl()); 967 } 968 969 void visitFunctionTypeAttrs(FunctionType *T) { 970 setFlag("noreturn", T->getNoReturnAttr()); 971 setCallingConv(T->getCallConv()); 972 if (T->getHasRegParm()) setInteger("regparm", T->getRegParmType()); 973 } 974 void visitFunctionTypeChildren(FunctionType *T) { 975 dispatch(T->getResultType()); 976 } 977 978 void visitFunctionProtoTypeAttrs(FunctionProtoType *T) { 979 setFlag("const", T->isConst()); 980 setFlag("volatile", T->isVolatile()); 981 setFlag("restrict", T->isRestrict()); 982 switch (T->getExceptionSpecType()) { 983 case EST_None: break; 984 case EST_DynamicNone: set("exception_spec", "throw()"); break; 985 case EST_Dynamic: set("exception_spec", "throw(T)"); break; 986 case EST_MSAny: set("exception_spec", "throw(...)"); break; 987 case EST_BasicNoexcept: set("exception_spec", "noexcept"); break; 988 case EST_ComputedNoexcept: set("exception_spec", "noexcept(expr)"); break; 989 case EST_Unevaluated: set("exception_spec", "unevaluated"); break; 990 case EST_Uninstantiated: set("exception_spec", "uninstantiated"); break; 991 } 992 } 993 void visitFunctionProtoTypeChildren(FunctionProtoType *T) { 994 push("parameters"); 995 setFlag("variadic", T->isVariadic()); 996 completeAttrs(); 997 for (FunctionProtoType::arg_type_iterator 998 I = T->arg_type_begin(), E = T->arg_type_end(); I != E; ++I) 999 dispatch(*I); 1000 pop(); 1001 1002 if (T->hasDynamicExceptionSpec()) { 1003 push("exception_specifiers"); 1004 setFlag("any", T->getExceptionSpecType() == EST_MSAny); 1005 completeAttrs(); 1006 for (FunctionProtoType::exception_iterator 1007 I = T->exception_begin(), E = T->exception_end(); I != E; ++I) 1008 dispatch(*I); 1009 pop(); 1010 } 1011 // FIXME: noexcept specifier 1012 } 1013 1014 void visitTemplateSpecializationTypeChildren(TemplateSpecializationType *T) { 1015 if (const RecordType *RT = T->getAs<RecordType>()) 1016 visitDeclRef(RT->getDecl()); 1017 1018 // TODO: TemplateName 1019 1020 push("template_arguments"); 1021 completeAttrs(); 1022 for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I) 1023 dispatch(T->getArg(I)); 1024 pop(); 1025 } 1026 1027 //---- Statements ------------------------------------------------// 1028 void dispatch(Stmt *S) { 1029 // FIXME: this is not really XML at all 1030 push("Stmt"); 1031 out << ">\n"; 1032 Stack.back().State = NS_Children; // explicitly become non-lazy 1033 S->dump(out, Context.getSourceManager()); 1034 out << '\n'; 1035 pop(); 1036 } 1037 }; 1038 } 1039 1040 void Decl::dumpXML() const { 1041 dumpXML(llvm::errs()); 1042 } 1043 1044 void Decl::dumpXML(raw_ostream &out) const { 1045 XMLDumper(out, getASTContext()).dispatch(const_cast<Decl*>(this)); 1046 } 1047 1048 #else /* ifndef NDEBUG */ 1049 1050 void Decl::dumpXML() const {} 1051 void Decl::dumpXML(raw_ostream &out) const {} 1052 1053 #endif 1054