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