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/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"
44 using namespace clang;
51 NS_Attrs, NS_LazyChildren, NS_Children
57 Node(StringRef name) : Name(name), State(NS_Attrs) {}
59 bool isDoneWithAttrs() const { return State != NS_Attrs; }
62 template <class Impl> struct XMLDeclVisitor {
63 #define DISPATCH(NAME, CLASS) \
64 static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(D))
66 void dispatch(Decl *D) {
68 static_cast<Impl*>(this)->set("used", "1");
69 switch (D->getKind()) {
70 #define DECL(DERIVED, BASE) \
72 DISPATCH(dispatch##DERIVED##DeclAttrs, DERIVED##Decl); \
73 static_cast<Impl*>(this)->completeAttrs(); \
74 DISPATCH(dispatch##DERIVED##DeclChildren, DERIVED##Decl); \
75 DISPATCH(dispatch##DERIVED##DeclAsContext, DERIVED##Decl); \
77 #define ABSTRACT_DECL(DECL)
78 #include "clang/AST/DeclNodes.inc"
82 #define DECL(DERIVED, BASE) \
83 void dispatch##DERIVED##DeclAttrs(DERIVED##Decl *D) { \
84 DISPATCH(dispatch##BASE##Attrs, BASE); \
85 DISPATCH(visit##DERIVED##DeclAttrs, DERIVED##Decl); \
87 void visit##DERIVED##DeclAttrs(DERIVED##Decl *D) {} \
88 void dispatch##DERIVED##DeclChildren(DERIVED##Decl *D) { \
89 DISPATCH(dispatch##BASE##Children, BASE); \
90 DISPATCH(visit##DERIVED##DeclChildren, DERIVED##Decl); \
92 void visit##DERIVED##DeclChildren(DERIVED##Decl *D) {} \
93 void dispatch##DERIVED##DeclAsContext(DERIVED##Decl *D) { \
94 DISPATCH(dispatch##BASE##AsContext, BASE); \
95 DISPATCH(visit##DERIVED##DeclAsContext, DERIVED##Decl); \
97 void visit##DERIVED##DeclAsContext(DERIVED##Decl *D) {}
98 #include "clang/AST/DeclNodes.inc"
100 void dispatchDeclAttrs(Decl *D) {
101 DISPATCH(visitDeclAttrs, Decl);
103 void visitDeclAttrs(Decl *D) {}
105 void dispatchDeclChildren(Decl *D) {
106 DISPATCH(visitDeclChildren, Decl);
108 void visitDeclChildren(Decl *D) {}
110 void dispatchDeclAsContext(Decl *D) {
111 DISPATCH(visitDeclAsContext, Decl);
113 void visitDeclAsContext(Decl *D) {}
118 template <class Impl> struct XMLTypeVisitor {
119 #define DISPATCH(NAME, CLASS) \
120 static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(T))
122 void dispatch(Type *T) {
123 switch (T->getTypeClass()) {
124 #define TYPE(DERIVED, BASE) \
125 case Type::DERIVED: \
126 DISPATCH(dispatch##DERIVED##TypeAttrs, DERIVED##Type); \
127 static_cast<Impl*>(this)->completeAttrs(); \
128 DISPATCH(dispatch##DERIVED##TypeChildren, DERIVED##Type); \
130 #define ABSTRACT_TYPE(DERIVED, BASE)
131 #include "clang/AST/TypeNodes.def"
135 #define TYPE(DERIVED, BASE) \
136 void dispatch##DERIVED##TypeAttrs(DERIVED##Type *T) { \
137 DISPATCH(dispatch##BASE##Attrs, BASE); \
138 DISPATCH(visit##DERIVED##TypeAttrs, DERIVED##Type); \
140 void visit##DERIVED##TypeAttrs(DERIVED##Type *T) {} \
141 void dispatch##DERIVED##TypeChildren(DERIVED##Type *T) { \
142 DISPATCH(dispatch##BASE##Children, BASE); \
143 DISPATCH(visit##DERIVED##TypeChildren, DERIVED##Type); \
145 void visit##DERIVED##TypeChildren(DERIVED##Type *T) {}
146 #include "clang/AST/TypeNodes.def"
148 void dispatchTypeAttrs(Type *T) {
149 DISPATCH(visitTypeAttrs, Type);
151 void visitTypeAttrs(Type *T) {}
153 void dispatchTypeChildren(Type *T) {
154 DISPATCH(visitTypeChildren, Type);
156 void visitTypeChildren(Type *T) {}
161 static StringRef getTypeKindName(Type *T) {
162 switch (T->getTypeClass()) {
163 #define TYPE(DERIVED, BASE) case Type::DERIVED: return #DERIVED "Type";
164 #define ABSTRACT_TYPE(DERIVED, BASE)
165 #include "clang/AST/TypeNodes.def"
168 llvm_unreachable("unknown type kind!");
171 struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
172 public XMLTypeVisitor<XMLDumper> {
175 SmallVector<Node, 16> Stack;
177 explicit XMLDumper(raw_ostream &OS, ASTContext &context)
178 : out(OS), Context(context), Indent(0) {}
181 for (unsigned I = Indent; I; --I)
185 /// Push a new node on the stack.
186 void push(StringRef name) {
187 if (!Stack.empty()) {
188 assert(Stack.back().isDoneWithAttrs());
189 if (Stack.back().State == NS_LazyChildren) {
190 Stack.back().State = NS_Children;
196 Stack.push_back(Node(name));
200 /// Set the given attribute to the given value.
201 void set(StringRef attr, StringRef value) {
202 assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
203 out << ' ' << attr << '=' << '"' << value << '"'; // TODO: quotation
206 /// Finish attributes.
207 void completeAttrs() {
208 assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
209 Stack.back().State = NS_LazyChildren;
214 assert(!Stack.empty() && Stack.back().isDoneWithAttrs());
215 if (Stack.back().State == NS_LazyChildren) {
219 out << "</" << Stack.back().Name << ">\n";
221 if (Stack.size() > 1) Indent--;
225 //---- General utilities -------------------------------------------//
227 void setPointer(StringRef prop, const void *p) {
228 SmallString<10> buffer;
229 llvm::raw_svector_ostream os(buffer);
235 void setPointer(void *p) {
236 setPointer("ptr", p);
239 void setInteger(StringRef prop, const llvm::APSInt &v) {
240 set(prop, v.toString(10));
243 void setInteger(StringRef prop, unsigned n) {
244 SmallString<10> buffer;
245 llvm::raw_svector_ostream os(buffer);
251 void setFlag(StringRef prop, bool flag) {
252 if (flag) set(prop, "true");
255 void setName(DeclarationName Name) {
257 return set("name", "");
260 if (Name.isIdentifier())
261 return set("name", Name.getAsIdentifierInfo()->getName());
263 set("name", Name.getAsString());
266 class TemporaryContainer {
269 TemporaryContainer(XMLDumper &dumper, StringRef name)
272 Dumper.completeAttrs();
275 ~TemporaryContainer() {
280 void visitTemplateParameters(TemplateParameterList *L) {
281 push("template_parameters");
283 for (TemplateParameterList::iterator
284 I = L->begin(), E = L->end(); I != E; ++I)
289 void visitTemplateArguments(const TemplateArgumentList &L) {
290 push("template_arguments");
292 for (unsigned I = 0, E = L.size(); I != E; ++I)
297 /// Visits a reference to the given declaration.
298 void visitDeclRef(Decl *D) {
299 push(D->getDeclKindName());
300 setPointer("ref", D);
304 void visitDeclRef(StringRef Name, Decl *D) {
305 TemporaryContainer C(*this, Name);
306 if (D) visitDeclRef(D);
309 void dispatch(const TemplateArgument &A) {
310 switch (A.getKind()) {
311 case TemplateArgument::Null: {
312 TemporaryContainer C(*this, "null");
315 case TemplateArgument::Type: {
316 dispatch(A.getAsType());
319 case TemplateArgument::Template:
320 case TemplateArgument::TemplateExpansion:
321 case TemplateArgument::NullPtr:
325 case TemplateArgument::Declaration: {
326 visitDeclRef(A.getAsDecl());
329 case TemplateArgument::Integral: {
331 setInteger("value", A.getAsIntegral());
336 case TemplateArgument::Expression: {
337 dispatch(A.getAsExpr());
340 case TemplateArgument::Pack: {
341 for (TemplateArgument::pack_iterator P = A.pack_begin(),
350 void dispatch(const TemplateArgumentLoc &A) {
351 dispatch(A.getArgument());
354 //---- Declarations ------------------------------------------------//
355 // Calls are made in this order:
356 // # Enter a new node.
359 // # In this phase, attributes are set on the node.
361 // visitNamedDeclAttrs(D)
363 // visitFieldDeclAttrs(D)
365 // # No more attributes after this point.
368 // # Create "header" child nodes, i.e. those which logically
369 // # belong to the declaration itself.
370 // visitDeclChildren(D)
371 // visitNamedDeclChildren(D)
373 // visitFieldDeclChildren(D)
375 // # Create nodes for the lexical children.
376 // visitDeclAsContext(D)
377 // visitNamedDeclAsContext(D)
379 // visitFieldDeclAsContext(D)
381 // # Finish the node.
383 void dispatch(Decl *D) {
384 push(D->getDeclKindName());
385 XMLDeclVisitor<XMLDumper>::dispatch(D);
388 void visitDeclAttrs(Decl *D) {
392 /// Visit all the lexical decls in the given context.
393 void visitDeclContext(DeclContext *DC) {
394 for (DeclContext::decl_iterator
395 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
398 // FIXME: point out visible declarations not in lexical context?
401 /// Set the "access" attribute on the current node according to the
403 void setAccess(AccessSpecifier AS) {
405 case AS_public: return set("access", "public");
406 case AS_protected: return set("access", "protected");
407 case AS_private: return set("access", "private");
408 case AS_none: llvm_unreachable("explicit forbidden access");
412 template <class T> void visitRedeclarableAttrs(T *D) {
413 if (T *Prev = D->getPreviousDecl())
414 setPointer("previous", Prev);
418 // TranslationUnitDecl
419 void visitTranslationUnitDeclAsContext(TranslationUnitDecl *D) {
424 void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) {
426 switch (D->getLanguage()) {
427 case LinkageSpecDecl::lang_c: lang = "C"; break;
428 case LinkageSpecDecl::lang_cxx: lang = "C++"; break;
432 void visitLinkageSpecDeclAsContext(LinkageSpecDecl *D) {
437 void visitNamespaceDeclAttrs(NamespaceDecl *D) {
438 setFlag("inline", D->isInline());
439 if (!D->isOriginalNamespace())
440 setPointer("original", D->getOriginalNamespace());
442 void visitNamespaceDeclAsContext(NamespaceDecl *D) {
447 void visitNamedDeclAttrs(NamedDecl *D) {
448 setName(D->getDeclName());
452 void visitValueDeclChildren(ValueDecl *D) {
453 dispatch(D->getType());
457 void visitDeclaratorDeclChildren(DeclaratorDecl *D) {
458 //dispatch(D->getTypeSourceInfo()->getTypeLoc());
462 void visitVarDeclAttrs(VarDecl *D) {
463 visitRedeclarableAttrs(D);
464 if (D->getStorageClass() != SC_None)
466 VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
467 StringRef initStyle = "";
468 switch (D->getInitStyle()) {
469 case VarDecl::CInit: initStyle = "c"; break;
470 case VarDecl::CallInit: initStyle = "call"; break;
471 case VarDecl::ListInit: initStyle = "list"; break;
473 set("initstyle", initStyle);
474 setFlag("nrvo", D->isNRVOVariable());
475 // TODO: instantiation, etc.
477 void visitVarDeclChildren(VarDecl *D) {
478 if (D->hasInit()) dispatch(D->getInit());
484 void visitFunctionDeclAttrs(FunctionDecl *D) {
485 visitRedeclarableAttrs(D);
486 setFlag("pure", D->isPure());
487 setFlag("trivial", D->isTrivial());
488 setFlag("returnzero", D->hasImplicitReturnZero());
489 setFlag("prototype", D->hasWrittenPrototype());
490 setFlag("deleted", D->isDeletedAsWritten());
491 if (D->getStorageClass() != SC_None)
493 VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
494 setFlag("inline", D->isInlineSpecified());
495 if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>())
496 set("asmlabel", ALA->getLabel());
497 // TODO: instantiation, etc.
499 void visitFunctionDeclChildren(FunctionDecl *D) {
500 for (FunctionDecl::param_iterator
501 I = D->param_begin(), E = D->param_end(); I != E; ++I)
503 for (llvm::ArrayRef<NamedDecl*>::iterator
504 I = D->getDeclsInPrototypeScope().begin(), E = D->getDeclsInPrototypeScope().end();
507 if (D->doesThisDeclarationHaveABody())
508 dispatch(D->getBody());
512 // CXXConstructorDecl ?
513 // CXXDestructorDecl ?
514 // CXXConversionDecl ?
516 void dispatch(CXXCtorInitializer *Init) {
521 void visitFieldDeclAttrs(FieldDecl *D) {
522 setFlag("mutable", D->isMutable());
524 void visitFieldDeclChildren(FieldDecl *D) {
525 if (D->isBitField()) {
526 TemporaryContainer C(*this, "bitwidth");
527 dispatch(D->getBitWidth());
529 // TODO: C++0x member initializer
533 void visitEnumConstantDeclChildren(EnumConstantDecl *D) {
534 // value in any case?
535 if (D->getInitExpr()) dispatch(D->getInitExpr());
539 void visitIndirectFieldDeclChildren(IndirectFieldDecl *D) {
540 for (IndirectFieldDecl::chain_iterator
541 I = D->chain_begin(), E = D->chain_end(); I != E; ++I) {
542 NamedDecl *VD = const_cast<NamedDecl*>(*I);
543 push(isa<VarDecl>(VD) ? "variable" : "field");
544 setPointer("ptr", VD);
551 void visitTypeDeclAttrs(TypeDecl *D) {
552 setPointer("typeptr", D->getTypeForDecl());
556 void visitTypedefDeclAttrs(TypedefDecl *D) {
557 visitRedeclarableAttrs<TypedefNameDecl>(D);
559 void visitTypedefDeclChildren(TypedefDecl *D) {
560 dispatch(D->getTypeSourceInfo()->getTypeLoc());
564 void visitTypeAliasDeclAttrs(TypeAliasDecl *D) {
565 visitRedeclarableAttrs<TypedefNameDecl>(D);
567 void visitTypeAliasDeclChildren(TypeAliasDecl *D) {
568 dispatch(D->getTypeSourceInfo()->getTypeLoc());
572 void visitTagDeclAttrs(TagDecl *D) {
573 visitRedeclarableAttrs(D);
575 void visitTagDeclAsContext(TagDecl *D) {
580 void visitEnumDeclAttrs(EnumDecl *D) {
581 setFlag("scoped", D->isScoped());
582 setFlag("fixed", D->isFixed());
584 void visitEnumDeclChildren(EnumDecl *D) {
586 TemporaryContainer C(*this, "promotion_type");
587 dispatch(D->getPromotionType());
590 TemporaryContainer C(*this, "integer_type");
591 dispatch(D->getIntegerType());
597 void visitCXXRecordDeclChildren(CXXRecordDecl *D) {
598 if (!D->isThisDeclarationADefinition()) return;
600 for (CXXRecordDecl::base_class_iterator
601 I = D->bases_begin(), E = D->bases_end(); I != E; ++I) {
603 setAccess(I->getAccessSpecifier());
605 dispatch(I->getTypeSourceInfo()->getTypeLoc());
610 // ClassTemplateSpecializationDecl ?
612 // FileScopeAsmDecl ?
615 void visitBlockDeclAttrs(BlockDecl *D) {
616 setFlag("variadic", D->isVariadic());
618 void visitBlockDeclChildren(BlockDecl *D) {
619 for (FunctionDecl::param_iterator
620 I = D->param_begin(), E = D->param_end(); I != E; ++I)
622 dispatch(D->getBody());
626 void visitAccessSpecDeclAttrs(AccessSpecDecl *D) {
627 setAccess(D->getAccess());
631 void visitTemplateDeclChildren(TemplateDecl *D) {
632 visitTemplateParameters(D->getTemplateParameters());
633 if (D->getTemplatedDecl())
634 dispatch(D->getTemplatedDecl());
637 // FunctionTemplateDecl
638 void visitFunctionTemplateDeclAttrs(FunctionTemplateDecl *D) {
639 visitRedeclarableAttrs(D);
641 void visitFunctionTemplateDeclChildren(FunctionTemplateDecl *D) {
642 // Mention all the specializations which don't have explicit
643 // declarations elsewhere.
644 for (FunctionTemplateDecl::spec_iterator
645 I = D->spec_begin(), E = D->spec_end(); I != E; ++I) {
646 FunctionTemplateSpecializationInfo *Info
647 = I->getTemplateSpecializationInfo();
649 bool Unknown = false;
650 switch (Info->getTemplateSpecializationKind()) {
651 case TSK_ImplicitInstantiation: Unknown = false; break;
652 case TSK_Undeclared: Unknown = true; break;
654 // These will be covered at their respective sites.
655 case TSK_ExplicitSpecialization: continue;
656 case TSK_ExplicitInstantiationDeclaration: continue;
657 case TSK_ExplicitInstantiationDefinition: continue;
660 TemporaryContainer C(*this,
661 Unknown ? "uninstantiated" : "instantiation");
662 visitTemplateArguments(*Info->TemplateArguments);
663 dispatch(Info->Function);
668 void visitClassTemplateDeclAttrs(ClassTemplateDecl *D) {
669 visitRedeclarableAttrs(D);
671 void visitClassTemplateDeclChildren(ClassTemplateDecl *D) {
672 // Mention all the specializations which don't have explicit
673 // declarations elsewhere.
674 for (ClassTemplateDecl::spec_iterator
675 I = D->spec_begin(), E = D->spec_end(); I != E; ++I) {
677 bool Unknown = false;
678 switch (I->getTemplateSpecializationKind()) {
679 case TSK_ImplicitInstantiation: Unknown = false; break;
680 case TSK_Undeclared: Unknown = true; break;
682 // These will be covered at their respective sites.
683 case TSK_ExplicitSpecialization: continue;
684 case TSK_ExplicitInstantiationDeclaration: continue;
685 case TSK_ExplicitInstantiationDefinition: continue;
688 TemporaryContainer C(*this,
689 Unknown ? "uninstantiated" : "instantiation");
690 visitTemplateArguments(I->getTemplateArgs());
695 // TemplateTypeParmDecl
696 void visitTemplateTypeParmDeclAttrs(TemplateTypeParmDecl *D) {
697 setInteger("depth", D->getDepth());
698 setInteger("index", D->getIndex());
700 void visitTemplateTypeParmDeclChildren(TemplateTypeParmDecl *D) {
701 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
702 dispatch(D->getDefaultArgumentInfo()->getTypeLoc());
706 // NonTypeTemplateParmDecl
707 void visitNonTypeTemplateParmDeclAttrs(NonTypeTemplateParmDecl *D) {
708 setInteger("depth", D->getDepth());
709 setInteger("index", D->getIndex());
711 void visitNonTypeTemplateParmDeclChildren(NonTypeTemplateParmDecl *D) {
712 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
713 dispatch(D->getDefaultArgument());
717 // TemplateTemplateParmDecl
718 void visitTemplateTemplateParmDeclAttrs(TemplateTemplateParmDecl *D) {
719 setInteger("depth", D->getDepth());
720 setInteger("index", D->getIndex());
722 void visitTemplateTemplateParmDeclChildren(TemplateTemplateParmDecl *D) {
723 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
724 dispatch(D->getDefaultArgument());
729 void visitFriendDeclChildren(FriendDecl *D) {
730 if (TypeSourceInfo *T = D->getFriendType())
731 dispatch(T->getTypeLoc());
733 dispatch(D->getFriendDecl());
736 // UsingDirectiveDecl ?
739 // NamespaceAliasDecl ?
740 // UnresolvedUsingValueDecl ?
741 // UnresolvedUsingTypenameDecl ?
742 // StaticAssertDecl ?
745 void visitObjCImplDeclChildren(ObjCImplDecl *D) {
746 visitDeclRef(D->getClassInterface());
748 void visitObjCImplDeclAsContext(ObjCImplDecl *D) {
753 void visitCategoryList(ObjCCategoryDecl *D) {
756 TemporaryContainer C(*this, "categories");
757 for (; D; D = D->getNextClassCategory())
760 void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) {
761 setPointer("typeptr", D->getTypeForDecl());
762 setFlag("forward_decl", !D->isThisDeclarationADefinition());
763 setFlag("implicit_interface", D->isImplicitInterfaceDecl());
765 void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) {
766 visitDeclRef("super", D->getSuperClass());
767 visitDeclRef("implementation", D->getImplementation());
768 if (D->protocol_begin() != D->protocol_end()) {
769 TemporaryContainer C(*this, "protocols");
770 for (ObjCInterfaceDecl::protocol_iterator
771 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
774 visitCategoryList(D->getCategoryList());
776 void visitObjCInterfaceDeclAsContext(ObjCInterfaceDecl *D) {
781 void visitObjCCategoryDeclAttrs(ObjCCategoryDecl *D) {
782 setFlag("extension", D->IsClassExtension());
784 void visitObjCCategoryDeclChildren(ObjCCategoryDecl *D) {
785 visitDeclRef("interface", D->getClassInterface());
786 visitDeclRef("implementation", D->getImplementation());
787 if (D->protocol_begin() != D->protocol_end()) {
788 TemporaryContainer C(*this, "protocols");
789 for (ObjCCategoryDecl::protocol_iterator
790 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
794 void visitObjCCategoryDeclAsContext(ObjCCategoryDecl *D) {
798 // ObjCCategoryImplDecl
799 void visitObjCCategoryImplDeclAttrs(ObjCCategoryImplDecl *D) {
800 set("identifier", D->getName());
802 void visitObjCCategoryImplDeclChildren(ObjCCategoryImplDecl *D) {
803 visitDeclRef(D->getCategoryDecl());
806 // ObjCImplementationDecl
807 void visitObjCImplementationDeclAttrs(ObjCImplementationDecl *D) {
808 set("identifier", D->getName());
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)
821 void visitObjCProtocolDeclChildren(ObjCProtocolDecl *D) {
822 if (!D->isThisDeclarationADefinition())
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)
832 void visitObjCProtocolDeclAsContext(ObjCProtocolDecl *D) {
833 if (!D->isThisDeclarationADefinition())
840 void visitObjCMethodDeclAttrs(ObjCMethodDecl *D) {
842 // implementation control?
844 setFlag("instance", D->isInstanceMethod());
845 setFlag("variadic", D->isVariadic());
846 setFlag("property_accessor", D->isPropertyAccessor());
847 setFlag("defined", D->isDefined());
848 setFlag("related_result_type", D->hasRelatedResultType());
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)
855 if (D->isThisDeclarationADefinition())
856 dispatch(D->getBody());
860 void setAccessControl(StringRef prop, ObjCIvarDecl::AccessControl 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");
869 void visitObjCIvarDeclAttrs(ObjCIvarDecl *D) {
870 setFlag("synthesize", D->getSynthesize());
871 setAccessControl("access", D->getAccessControl());
874 // ObjCCompatibleAliasDecl
875 void visitObjCCompatibleAliasDeclChildren(ObjCCompatibleAliasDecl *D) {
876 visitDeclRef(D->getClassInterface());
879 // FIXME: ObjCPropertyDecl
880 // FIXME: ObjCPropertyImplDecl
882 //---- Types -----------------------------------------------------//
883 void dispatch(TypeLoc TL) {
884 dispatch(TL.getType()); // for now
887 void dispatch(QualType T) {
888 if (T.hasLocalQualifiers()) {
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");
904 dispatch(QualType(T.getTypePtr(), 0));
909 Type *Ty = const_cast<Type*>(T.getTypePtr());
910 push(getTypeKindName(Ty));
911 XMLTypeVisitor<XMLDumper>::dispatch(const_cast<Type*>(T.getTypePtr()));
915 void setCallingConv(CallingConv 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 case CC_PnaclCall: return set("cc", "pnaclcall");
929 void visitTypeAttrs(Type *D) {
931 setFlag("dependent", D->isDependentType());
932 setFlag("variably_modified", D->isVariablyModifiedType());
934 setPointer("canonical", D->getCanonicalTypeInternal().getAsOpaquePtr());
937 void visitPointerTypeChildren(PointerType *T) {
938 dispatch(T->getPointeeType());
940 void visitReferenceTypeChildren(ReferenceType *T) {
941 dispatch(T->getPointeeType());
943 void visitObjCObjectPointerTypeChildren(ObjCObjectPointerType *T) {
944 dispatch(T->getPointeeType());
946 void visitBlockPointerTypeChildren(BlockPointerType *T) {
947 dispatch(T->getPointeeType());
950 // Types that just wrap declarations.
951 void visitTagTypeChildren(TagType *T) {
952 visitDeclRef(T->getDecl());
954 void visitTypedefTypeChildren(TypedefType *T) {
955 visitDeclRef(T->getDecl());
957 void visitObjCInterfaceTypeChildren(ObjCInterfaceType *T) {
958 visitDeclRef(T->getDecl());
960 void visitUnresolvedUsingTypeChildren(UnresolvedUsingType *T) {
961 visitDeclRef(T->getDecl());
963 void visitInjectedClassNameTypeChildren(InjectedClassNameType *T) {
964 visitDeclRef(T->getDecl());
967 void visitFunctionTypeAttrs(FunctionType *T) {
968 setFlag("noreturn", T->getNoReturnAttr());
969 setCallingConv(T->getCallConv());
970 if (T->getHasRegParm()) setInteger("regparm", T->getRegParmType());
972 void visitFunctionTypeChildren(FunctionType *T) {
973 dispatch(T->getResultType());
976 void visitFunctionProtoTypeAttrs(FunctionProtoType *T) {
977 setFlag("const", T->isConst());
978 setFlag("volatile", T->isVolatile());
979 setFlag("restrict", T->isRestrict());
980 switch (T->getExceptionSpecType()) {
981 case EST_None: break;
982 case EST_DynamicNone: set("exception_spec", "throw()"); break;
983 case EST_Dynamic: set("exception_spec", "throw(T)"); break;
984 case EST_MSAny: set("exception_spec", "throw(...)"); break;
985 case EST_BasicNoexcept: set("exception_spec", "noexcept"); break;
986 case EST_ComputedNoexcept: set("exception_spec", "noexcept(expr)"); break;
987 case EST_Unevaluated: set("exception_spec", "unevaluated"); break;
988 case EST_Uninstantiated: set("exception_spec", "uninstantiated"); break;
991 void visitFunctionProtoTypeChildren(FunctionProtoType *T) {
993 setFlag("variadic", T->isVariadic());
995 for (FunctionProtoType::arg_type_iterator
996 I = T->arg_type_begin(), E = T->arg_type_end(); I != E; ++I)
1000 if (T->hasDynamicExceptionSpec()) {
1001 push("exception_specifiers");
1002 setFlag("any", T->getExceptionSpecType() == EST_MSAny);
1004 for (FunctionProtoType::exception_iterator
1005 I = T->exception_begin(), E = T->exception_end(); I != E; ++I)
1009 // FIXME: noexcept specifier
1012 void visitTemplateSpecializationTypeChildren(TemplateSpecializationType *T) {
1013 if (const RecordType *RT = T->getAs<RecordType>())
1014 visitDeclRef(RT->getDecl());
1016 // TODO: TemplateName
1018 push("template_arguments");
1020 for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I)
1021 dispatch(T->getArg(I));
1025 //---- Statements ------------------------------------------------//
1026 void dispatch(Stmt *S) {
1027 // FIXME: this is not really XML at all
1030 Stack.back().State = NS_Children; // explicitly become non-lazy
1031 S->dump(out, Context.getSourceManager());
1038 void Decl::dumpXML() const {
1039 dumpXML(llvm::errs());
1042 void Decl::dumpXML(raw_ostream &out) const {
1043 XMLDumper(out, getASTContext()).dispatch(const_cast<Decl*>(this));
1046 #else /* ifndef NDEBUG */
1048 void Decl::dumpXML() const {}
1049 void Decl::dumpXML(raw_ostream &out) const {}