1 //===--- DumpXML.cpp - Detailed XML dumping -------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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.
13 // There is no guarantee of stability for this format.
15 //===----------------------------------------------------------------------===//
17 // Only pay for this in code size in assertions-enabled builds.
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"
43 using namespace clang;
50 NS_Attrs, NS_LazyChildren, NS_Children
56 Node(StringRef name) : Name(name), State(NS_Attrs) {}
58 bool isDoneWithAttrs() const { return State != NS_Attrs; }
61 template <class Impl> struct XMLDeclVisitor {
62 #define DISPATCH(NAME, CLASS) \
63 static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(D))
65 void dispatch(Decl *D) {
67 static_cast<Impl*>(this)->set("used", "1");
68 switch (D->getKind()) {
69 #define DECL(DERIVED, BASE) \
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); \
76 #define ABSTRACT_DECL(DECL)
77 #include "clang/AST/DeclNodes.inc"
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); \
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); \
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); \
96 void visit##DERIVED##DeclAsContext(DERIVED##Decl *D) {}
97 #include "clang/AST/DeclNodes.inc"
99 void dispatchDeclAttrs(Decl *D) {
100 DISPATCH(visitDeclAttrs, Decl);
102 void visitDeclAttrs(Decl *D) {}
104 void dispatchDeclChildren(Decl *D) {
105 DISPATCH(visitDeclChildren, Decl);
107 void visitDeclChildren(Decl *D) {}
109 void dispatchDeclAsContext(Decl *D) {
110 DISPATCH(visitDeclAsContext, Decl);
112 void visitDeclAsContext(Decl *D) {}
117 template <class Impl> struct XMLTypeVisitor {
118 #define DISPATCH(NAME, CLASS) \
119 static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(T))
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); \
129 #define ABSTRACT_TYPE(DERIVED, BASE)
130 #include "clang/AST/TypeNodes.def"
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); \
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); \
144 void visit##DERIVED##TypeChildren(DERIVED##Type *T) {}
145 #include "clang/AST/TypeNodes.def"
147 void dispatchTypeAttrs(Type *T) {
148 DISPATCH(visitTypeAttrs, Type);
150 void visitTypeAttrs(Type *T) {}
152 void dispatchTypeChildren(Type *T) {
153 DISPATCH(visitTypeChildren, Type);
155 void visitTypeChildren(Type *T) {}
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"
167 llvm_unreachable("unknown type kind!");
170 struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
171 public XMLTypeVisitor<XMLDumper> {
174 SmallVector<Node, 16> Stack;
176 explicit XMLDumper(raw_ostream &OS, ASTContext &context)
177 : out(OS), Context(context), Indent(0) {}
180 for (unsigned I = Indent; I; --I)
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;
195 Stack.push_back(Node(name));
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
205 /// Finish attributes.
206 void completeAttrs() {
207 assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
208 Stack.back().State = NS_LazyChildren;
213 assert(!Stack.empty() && Stack.back().isDoneWithAttrs());
214 if (Stack.back().State == NS_LazyChildren) {
218 out << "</" << Stack.back().Name << ">\n";
220 if (Stack.size() > 1) Indent--;
224 //---- General utilities -------------------------------------------//
226 void setPointer(StringRef prop, const void *p) {
227 SmallString<10> buffer;
228 llvm::raw_svector_ostream os(buffer);
234 void setPointer(void *p) {
235 setPointer("ptr", p);
238 void setInteger(StringRef prop, const llvm::APSInt &v) {
239 set(prop, v.toString(10));
242 void setInteger(StringRef prop, unsigned n) {
243 SmallString<10> buffer;
244 llvm::raw_svector_ostream os(buffer);
250 void setFlag(StringRef prop, bool flag) {
251 if (flag) set(prop, "true");
254 void setName(DeclarationName Name) {
256 return set("name", "");
259 if (Name.isIdentifier())
260 return set("name", Name.getAsIdentifierInfo()->getName());
262 set("name", Name.getAsString());
265 class TemporaryContainer {
268 TemporaryContainer(XMLDumper &dumper, StringRef name)
271 Dumper.completeAttrs();
274 ~TemporaryContainer() {
279 void visitTemplateParameters(TemplateParameterList *L) {
280 push("template_parameters");
282 for (TemplateParameterList::iterator
283 I = L->begin(), E = L->end(); I != E; ++I)
288 void visitTemplateArguments(const TemplateArgumentList &L) {
289 push("template_arguments");
291 for (unsigned I = 0, E = L.size(); I != E; ++I)
296 /// Visits a reference to the given declaration.
297 void visitDeclRef(Decl *D) {
298 push(D->getDeclKindName());
299 setPointer("ref", D);
303 void visitDeclRef(StringRef Name, Decl *D) {
304 TemporaryContainer C(*this, Name);
305 if (D) visitDeclRef(D);
308 void dispatch(const TemplateArgument &A) {
309 switch (A.getKind()) {
310 case TemplateArgument::Null: {
311 TemporaryContainer C(*this, "null");
314 case TemplateArgument::Type: {
315 dispatch(A.getAsType());
318 case TemplateArgument::Template:
319 case TemplateArgument::TemplateExpansion:
320 case TemplateArgument::NullPtr:
324 case TemplateArgument::Declaration: {
325 visitDeclRef(A.getAsDecl());
328 case TemplateArgument::Integral: {
330 setInteger("value", A.getAsIntegral());
335 case TemplateArgument::Expression: {
336 dispatch(A.getAsExpr());
339 case TemplateArgument::Pack: {
340 for (TemplateArgument::pack_iterator P = A.pack_begin(),
349 void dispatch(const TemplateArgumentLoc &A) {
350 dispatch(A.getArgument());
353 //---- Declarations ------------------------------------------------//
354 // Calls are made in this order:
355 // # Enter a new node.
358 // # In this phase, attributes are set on the node.
360 // visitNamedDeclAttrs(D)
362 // visitFieldDeclAttrs(D)
364 // # No more attributes after this point.
367 // # Create "header" child nodes, i.e. those which logically
368 // # belong to the declaration itself.
369 // visitDeclChildren(D)
370 // visitNamedDeclChildren(D)
372 // visitFieldDeclChildren(D)
374 // # Create nodes for the lexical children.
375 // visitDeclAsContext(D)
376 // visitNamedDeclAsContext(D)
378 // visitFieldDeclAsContext(D)
380 // # Finish the node.
382 void dispatch(Decl *D) {
383 push(D->getDeclKindName());
384 XMLDeclVisitor<XMLDumper>::dispatch(D);
387 void visitDeclAttrs(Decl *D) {
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)
397 // FIXME: point out visible declarations not in lexical context?
400 /// Set the "access" attribute on the current node according to the
402 void setAccess(AccessSpecifier 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");
411 template <class T> void visitRedeclarableAttrs(T *D) {
412 if (T *Prev = D->getPreviousDecl())
413 setPointer("previous", Prev);
417 // TranslationUnitDecl
418 void visitTranslationUnitDeclAsContext(TranslationUnitDecl *D) {
423 void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) {
425 switch (D->getLanguage()) {
426 case LinkageSpecDecl::lang_c: lang = "C"; break;
427 case LinkageSpecDecl::lang_cxx: lang = "C++"; break;
431 void visitLinkageSpecDeclAsContext(LinkageSpecDecl *D) {
436 void visitNamespaceDeclAttrs(NamespaceDecl *D) {
437 setFlag("inline", D->isInline());
438 if (!D->isOriginalNamespace())
439 setPointer("original", D->getOriginalNamespace());
441 void visitNamespaceDeclAsContext(NamespaceDecl *D) {
446 void visitNamedDeclAttrs(NamedDecl *D) {
447 setName(D->getDeclName());
451 void visitValueDeclChildren(ValueDecl *D) {
452 dispatch(D->getType());
456 void visitDeclaratorDeclChildren(DeclaratorDecl *D) {
457 //dispatch(D->getTypeSourceInfo()->getTypeLoc());
461 void visitVarDeclAttrs(VarDecl *D) {
462 visitRedeclarableAttrs(D);
463 if (D->getStorageClass() != SC_None)
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;
472 set("initstyle", initStyle);
473 setFlag("nrvo", D->isNRVOVariable());
474 // TODO: instantiation, etc.
476 void visitVarDeclChildren(VarDecl *D) {
477 if (D->hasInit()) dispatch(D->getInit());
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)
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.
498 void visitFunctionDeclChildren(FunctionDecl *D) {
499 for (FunctionDecl::param_iterator
500 I = D->param_begin(), E = D->param_end(); I != E; ++I)
502 for (ArrayRef<NamedDecl *>::iterator I = D->getDeclsInPrototypeScope().begin(),
503 E = D->getDeclsInPrototypeScope().end();
506 if (D->doesThisDeclarationHaveABody())
507 dispatch(D->getBody());
511 // CXXConstructorDecl ?
512 // CXXDestructorDecl ?
513 // CXXConversionDecl ?
515 void dispatch(CXXCtorInitializer *Init) {
520 void visitFieldDeclAttrs(FieldDecl *D) {
521 setFlag("mutable", D->isMutable());
523 void visitFieldDeclChildren(FieldDecl *D) {
524 if (D->isBitField()) {
525 TemporaryContainer C(*this, "bitwidth");
526 dispatch(D->getBitWidth());
528 // TODO: C++0x member initializer
532 void visitEnumConstantDeclChildren(EnumConstantDecl *D) {
533 // value in any case?
534 if (D->getInitExpr()) dispatch(D->getInitExpr());
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);
550 void visitTypeDeclAttrs(TypeDecl *D) {
551 setPointer("typeptr", D->getTypeForDecl());
555 void visitTypedefDeclAttrs(TypedefDecl *D) {
556 visitRedeclarableAttrs<TypedefNameDecl>(D);
558 void visitTypedefDeclChildren(TypedefDecl *D) {
559 dispatch(D->getTypeSourceInfo()->getTypeLoc());
563 void visitTypeAliasDeclAttrs(TypeAliasDecl *D) {
564 visitRedeclarableAttrs<TypedefNameDecl>(D);
566 void visitTypeAliasDeclChildren(TypeAliasDecl *D) {
567 dispatch(D->getTypeSourceInfo()->getTypeLoc());
571 void visitTagDeclAttrs(TagDecl *D) {
572 visitRedeclarableAttrs(D);
574 void visitTagDeclAsContext(TagDecl *D) {
579 void visitEnumDeclAttrs(EnumDecl *D) {
580 setFlag("scoped", D->isScoped());
581 setFlag("fixed", D->isFixed());
583 void visitEnumDeclChildren(EnumDecl *D) {
585 TemporaryContainer C(*this, "promotion_type");
586 dispatch(D->getPromotionType());
589 TemporaryContainer C(*this, "integer_type");
590 dispatch(D->getIntegerType());
596 void visitCXXRecordDeclChildren(CXXRecordDecl *D) {
597 if (!D->isThisDeclarationADefinition()) return;
599 for (CXXRecordDecl::base_class_iterator
600 I = D->bases_begin(), E = D->bases_end(); I != E; ++I) {
602 setAccess(I->getAccessSpecifier());
604 dispatch(I->getTypeSourceInfo()->getTypeLoc());
609 // ClassTemplateSpecializationDecl ?
611 // FileScopeAsmDecl ?
614 void visitBlockDeclAttrs(BlockDecl *D) {
615 setFlag("variadic", D->isVariadic());
617 void visitBlockDeclChildren(BlockDecl *D) {
618 for (FunctionDecl::param_iterator
619 I = D->param_begin(), E = D->param_end(); I != E; ++I)
621 dispatch(D->getBody());
625 void visitAccessSpecDeclAttrs(AccessSpecDecl *D) {
626 setAccess(D->getAccess());
630 void visitTemplateDeclChildren(TemplateDecl *D) {
631 visitTemplateParameters(D->getTemplateParameters());
632 if (D->getTemplatedDecl())
633 dispatch(D->getTemplatedDecl());
636 // FunctionTemplateDecl
637 void visitFunctionTemplateDeclAttrs(FunctionTemplateDecl *D) {
638 visitRedeclarableAttrs(D);
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();
648 bool Unknown = false;
649 switch (Info->getTemplateSpecializationKind()) {
650 case TSK_ImplicitInstantiation: Unknown = false; break;
651 case TSK_Undeclared: Unknown = true; break;
653 // These will be covered at their respective sites.
654 case TSK_ExplicitSpecialization: continue;
655 case TSK_ExplicitInstantiationDeclaration: continue;
656 case TSK_ExplicitInstantiationDefinition: continue;
659 TemporaryContainer C(*this,
660 Unknown ? "uninstantiated" : "instantiation");
661 visitTemplateArguments(*Info->TemplateArguments);
662 dispatch(Info->Function);
667 void visitClassTemplateDeclAttrs(ClassTemplateDecl *D) {
668 visitRedeclarableAttrs(D);
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) {
676 bool Unknown = false;
677 switch (I->getTemplateSpecializationKind()) {
678 case TSK_ImplicitInstantiation: Unknown = false; break;
679 case TSK_Undeclared: Unknown = true; break;
681 // These will be covered at their respective sites.
682 case TSK_ExplicitSpecialization: continue;
683 case TSK_ExplicitInstantiationDeclaration: continue;
684 case TSK_ExplicitInstantiationDefinition: continue;
687 TemporaryContainer C(*this,
688 Unknown ? "uninstantiated" : "instantiation");
689 visitTemplateArguments(I->getTemplateArgs());
694 // TemplateTypeParmDecl
695 void visitTemplateTypeParmDeclAttrs(TemplateTypeParmDecl *D) {
696 setInteger("depth", D->getDepth());
697 setInteger("index", D->getIndex());
699 void visitTemplateTypeParmDeclChildren(TemplateTypeParmDecl *D) {
700 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
701 dispatch(D->getDefaultArgumentInfo()->getTypeLoc());
705 // NonTypeTemplateParmDecl
706 void visitNonTypeTemplateParmDeclAttrs(NonTypeTemplateParmDecl *D) {
707 setInteger("depth", D->getDepth());
708 setInteger("index", D->getIndex());
710 void visitNonTypeTemplateParmDeclChildren(NonTypeTemplateParmDecl *D) {
711 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
712 dispatch(D->getDefaultArgument());
716 // TemplateTemplateParmDecl
717 void visitTemplateTemplateParmDeclAttrs(TemplateTemplateParmDecl *D) {
718 setInteger("depth", D->getDepth());
719 setInteger("index", D->getIndex());
721 void visitTemplateTemplateParmDeclChildren(TemplateTemplateParmDecl *D) {
722 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
723 dispatch(D->getDefaultArgument());
728 void visitFriendDeclChildren(FriendDecl *D) {
729 if (TypeSourceInfo *T = D->getFriendType())
730 dispatch(T->getTypeLoc());
732 dispatch(D->getFriendDecl());
735 // UsingDirectiveDecl ?
738 // NamespaceAliasDecl ?
739 // UnresolvedUsingValueDecl ?
740 // UnresolvedUsingTypenameDecl ?
741 // StaticAssertDecl ?
744 void visitObjCImplDeclChildren(ObjCImplDecl *D) {
745 visitDeclRef(D->getClassInterface());
747 void visitObjCImplDeclAsContext(ObjCImplDecl *D) {
751 void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) {
752 setPointer("typeptr", D->getTypeForDecl());
753 setFlag("forward_decl", !D->isThisDeclarationADefinition());
754 setFlag("implicit_interface", D->isImplicitInterfaceDecl());
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)
766 if (!D->visible_categories_empty()) {
767 TemporaryContainer C(*this, "categories");
769 for (ObjCInterfaceDecl::visible_categories_iterator
770 Cat = D->visible_categories_begin(),
771 CatEnd = D->visible_categories_end();
772 Cat != CatEnd; ++Cat) {
777 void visitObjCInterfaceDeclAsContext(ObjCInterfaceDecl *D) {
782 void visitObjCCategoryDeclAttrs(ObjCCategoryDecl *D) {
783 setFlag("extension", D->IsClassExtension());
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)
795 void visitObjCCategoryDeclAsContext(ObjCCategoryDecl *D) {
799 // ObjCCategoryImplDecl
800 void visitObjCCategoryImplDeclAttrs(ObjCCategoryImplDecl *D) {
801 set("identifier", D->getName());
803 void visitObjCCategoryImplDeclChildren(ObjCCategoryImplDecl *D) {
804 visitDeclRef(D->getCategoryDecl());
807 // ObjCImplementationDecl
808 void visitObjCImplementationDeclAttrs(ObjCImplementationDecl *D) {
809 set("identifier", D->getName());
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)
822 void visitObjCProtocolDeclChildren(ObjCProtocolDecl *D) {
823 if (!D->isThisDeclarationADefinition())
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)
833 void visitObjCProtocolDeclAsContext(ObjCProtocolDecl *D) {
834 if (!D->isThisDeclarationADefinition())
841 void visitObjCMethodDeclAttrs(ObjCMethodDecl *D) {
843 // implementation control?
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());
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)
856 if (D->isThisDeclarationADefinition())
857 dispatch(D->getBody());
861 void setAccessControl(StringRef prop, ObjCIvarDecl::AccessControl 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");
870 void visitObjCIvarDeclAttrs(ObjCIvarDecl *D) {
871 setFlag("synthesize", D->getSynthesize());
872 setAccessControl("access", D->getAccessControl());
875 // ObjCCompatibleAliasDecl
876 void visitObjCCompatibleAliasDeclChildren(ObjCCompatibleAliasDecl *D) {
877 visitDeclRef(D->getClassInterface());
880 // FIXME: ObjCPropertyDecl
881 // FIXME: ObjCPropertyImplDecl
883 //---- Types -----------------------------------------------------//
884 void dispatch(TypeLoc TL) {
885 dispatch(TL.getType()); // for now
888 void dispatch(QualType T) {
889 if (T.hasLocalQualifiers()) {
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");
905 dispatch(QualType(T.getTypePtr(), 0));
910 Type *Ty = const_cast<Type*>(T.getTypePtr());
911 push(getTypeKindName(Ty));
912 XMLTypeVisitor<XMLDumper>::dispatch(const_cast<Type*>(T.getTypePtr()));
916 void setCallingConv(CallingConv 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");
931 void visitTypeAttrs(Type *D) {
933 setFlag("dependent", D->isDependentType());
934 setFlag("variably_modified", D->isVariablyModifiedType());
936 setPointer("canonical", D->getCanonicalTypeInternal().getAsOpaquePtr());
939 void visitPointerTypeChildren(PointerType *T) {
940 dispatch(T->getPointeeType());
942 void visitReferenceTypeChildren(ReferenceType *T) {
943 dispatch(T->getPointeeType());
945 void visitObjCObjectPointerTypeChildren(ObjCObjectPointerType *T) {
946 dispatch(T->getPointeeType());
948 void visitBlockPointerTypeChildren(BlockPointerType *T) {
949 dispatch(T->getPointeeType());
952 // Types that just wrap declarations.
953 void visitTagTypeChildren(TagType *T) {
954 visitDeclRef(T->getDecl());
956 void visitTypedefTypeChildren(TypedefType *T) {
957 visitDeclRef(T->getDecl());
959 void visitObjCInterfaceTypeChildren(ObjCInterfaceType *T) {
960 visitDeclRef(T->getDecl());
962 void visitUnresolvedUsingTypeChildren(UnresolvedUsingType *T) {
963 visitDeclRef(T->getDecl());
965 void visitInjectedClassNameTypeChildren(InjectedClassNameType *T) {
966 visitDeclRef(T->getDecl());
969 void visitFunctionTypeAttrs(FunctionType *T) {
970 setFlag("noreturn", T->getNoReturnAttr());
971 setCallingConv(T->getCallConv());
972 if (T->getHasRegParm()) setInteger("regparm", T->getRegParmType());
974 void visitFunctionTypeChildren(FunctionType *T) {
975 dispatch(T->getResultType());
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;
993 void visitFunctionProtoTypeChildren(FunctionProtoType *T) {
995 setFlag("variadic", T->isVariadic());
997 for (FunctionProtoType::arg_type_iterator
998 I = T->arg_type_begin(), E = T->arg_type_end(); I != E; ++I)
1002 if (T->hasDynamicExceptionSpec()) {
1003 push("exception_specifiers");
1004 setFlag("any", T->getExceptionSpecType() == EST_MSAny);
1006 for (FunctionProtoType::exception_iterator
1007 I = T->exception_begin(), E = T->exception_end(); I != E; ++I)
1011 // FIXME: noexcept specifier
1014 void visitTemplateSpecializationTypeChildren(TemplateSpecializationType *T) {
1015 if (const RecordType *RT = T->getAs<RecordType>())
1016 visitDeclRef(RT->getDecl());
1018 // TODO: TemplateName
1020 push("template_arguments");
1022 for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I)
1023 dispatch(T->getArg(I));
1027 //---- Statements ------------------------------------------------//
1028 void dispatch(Stmt *S) {
1029 // FIXME: this is not really XML at all
1032 Stack.back().State = NS_Children; // explicitly become non-lazy
1033 S->dump(out, Context.getSourceManager());
1040 void Decl::dumpXML() const {
1041 dumpXML(llvm::errs());
1044 void Decl::dumpXML(raw_ostream &out) const {
1045 XMLDumper(out, getASTContext()).dispatch(const_cast<Decl*>(this));
1048 #else /* ifndef NDEBUG */
1050 void Decl::dumpXML() const {}
1051 void Decl::dumpXML(raw_ostream &out) const {}