1 //===--- DumpXML.cpp - Detailed XML dumping ---------------------*- C++ -*-===//
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) {
67 switch (D->getKind()) {
68 #define DECL(DERIVED, BASE) \
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); \
75 #define ABSTRACT_DECL(DECL)
76 #include "clang/AST/DeclNodes.inc"
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); \
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); \
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); \
95 void visit##DERIVED##DeclAsContext(DERIVED##Decl *D) {}
96 #include "clang/AST/DeclNodes.inc"
98 void dispatchDeclAttrs(Decl *D) {
99 DISPATCH(visitDeclAttrs, Decl);
101 void visitDeclAttrs(Decl *D) {}
103 void dispatchDeclChildren(Decl *D) {
104 DISPATCH(visitDeclChildren, Decl);
106 void visitDeclChildren(Decl *D) {}
108 void dispatchDeclAsContext(Decl *D) {
109 DISPATCH(visitDeclAsContext, Decl);
111 void visitDeclAsContext(Decl *D) {}
116 template <class Impl> struct XMLTypeVisitor {
117 #define DISPATCH(NAME, CLASS) \
118 static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(T))
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); \
128 #define ABSTRACT_TYPE(DERIVED, BASE)
129 #include "clang/AST/TypeNodes.def"
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); \
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); \
143 void visit##DERIVED##TypeChildren(DERIVED##Type *T) {}
144 #include "clang/AST/TypeNodes.def"
146 void dispatchTypeAttrs(Type *T) {
147 DISPATCH(visitTypeAttrs, Type);
149 void visitTypeAttrs(Type *T) {}
151 void dispatchTypeChildren(Type *T) {
152 DISPATCH(visitTypeChildren, Type);
154 void visitTypeChildren(Type *T) {}
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"
166 llvm_unreachable("unknown type kind!");
169 struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
170 public XMLTypeVisitor<XMLDumper> {
173 SmallVector<Node, 16> Stack;
175 explicit XMLDumper(raw_ostream &OS, ASTContext &context)
176 : out(OS), Context(context), Indent(0) {}
179 for (unsigned I = Indent; I; --I)
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;
194 Stack.push_back(Node(name));
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
204 /// Finish attributes.
205 void completeAttrs() {
206 assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
207 Stack.back().State = NS_LazyChildren;
212 assert(!Stack.empty() && Stack.back().isDoneWithAttrs());
213 if (Stack.back().State == NS_LazyChildren) {
217 out << "</" << Stack.back().Name << ">\n";
219 if (Stack.size() > 1) Indent--;
223 //---- General utilities -------------------------------------------//
225 void setPointer(StringRef prop, const void *p) {
226 SmallString<10> buffer;
227 llvm::raw_svector_ostream os(buffer);
233 void setPointer(void *p) {
234 setPointer("ptr", p);
237 void setInteger(StringRef prop, const llvm::APSInt &v) {
238 set(prop, v.toString(10));
241 void setInteger(StringRef prop, unsigned n) {
242 SmallString<10> buffer;
243 llvm::raw_svector_ostream os(buffer);
249 void setFlag(StringRef prop, bool flag) {
250 if (flag) set(prop, "true");
253 void setName(DeclarationName Name) {
255 return set("name", "");
258 if (Name.isIdentifier())
259 return set("name", Name.getAsIdentifierInfo()->getName());
261 set("name", Name.getAsString());
264 class TemporaryContainer {
267 TemporaryContainer(XMLDumper &dumper, StringRef name)
270 Dumper.completeAttrs();
273 ~TemporaryContainer() {
278 void visitTemplateParameters(TemplateParameterList *L) {
279 push("template_parameters");
281 for (TemplateParameterList::iterator
282 I = L->begin(), E = L->end(); I != E; ++I)
287 void visitTemplateArguments(const TemplateArgumentList &L) {
288 push("template_arguments");
290 for (unsigned I = 0, E = L.size(); I != E; ++I)
295 /// Visits a reference to the given declaration.
296 void visitDeclRef(Decl *D) {
297 push(D->getDeclKindName());
298 setPointer("ref", D);
302 void visitDeclRef(StringRef Name, Decl *D) {
303 TemporaryContainer C(*this, Name);
304 if (D) visitDeclRef(D);
307 void dispatch(const TemplateArgument &A) {
308 switch (A.getKind()) {
309 case TemplateArgument::Null: {
310 TemporaryContainer C(*this, "null");
313 case TemplateArgument::Type: {
314 dispatch(A.getAsType());
317 case TemplateArgument::Template:
318 case TemplateArgument::TemplateExpansion:
322 case TemplateArgument::Declaration: {
323 if (Decl *D = A.getAsDecl())
327 case TemplateArgument::Integral: {
329 setInteger("value", *A.getAsIntegral());
334 case TemplateArgument::Expression: {
335 dispatch(A.getAsExpr());
338 case TemplateArgument::Pack: {
339 for (TemplateArgument::pack_iterator P = A.pack_begin(),
348 void dispatch(const TemplateArgumentLoc &A) {
349 dispatch(A.getArgument());
352 //---- Declarations ------------------------------------------------//
353 // Calls are made in this order:
354 // # Enter a new node.
357 // # In this phase, attributes are set on the node.
359 // visitNamedDeclAttrs(D)
361 // visitFieldDeclAttrs(D)
363 // # No more attributes after this point.
366 // # Create "header" child nodes, i.e. those which logically
367 // # belong to the declaration itself.
368 // visitDeclChildren(D)
369 // visitNamedDeclChildren(D)
371 // visitFieldDeclChildren(D)
373 // # Create nodes for the lexical children.
374 // visitDeclAsContext(D)
375 // visitNamedDeclAsContext(D)
377 // visitFieldDeclAsContext(D)
379 // # Finish the node.
381 void dispatch(Decl *D) {
382 push(D->getDeclKindName());
383 XMLDeclVisitor<XMLDumper>::dispatch(D);
386 void visitDeclAttrs(Decl *D) {
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)
396 // FIXME: point out visible declarations not in lexical context?
399 /// Set the "access" attribute on the current node according to the
401 void setAccess(AccessSpecifier 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");
410 template <class T> void visitRedeclarableAttrs(T *D) {
411 if (T *Prev = D->getPreviousDecl())
412 setPointer("previous", Prev);
416 // TranslationUnitDecl
417 void visitTranslationUnitDeclAsContext(TranslationUnitDecl *D) {
422 void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) {
424 switch (D->getLanguage()) {
425 case LinkageSpecDecl::lang_c: lang = "C"; break;
426 case LinkageSpecDecl::lang_cxx: lang = "C++"; break;
430 void visitLinkageSpecDeclAsContext(LinkageSpecDecl *D) {
435 void visitNamespaceDeclAttrs(NamespaceDecl *D) {
436 setFlag("inline", D->isInline());
437 if (!D->isOriginalNamespace())
438 setPointer("original", D->getOriginalNamespace());
440 void visitNamespaceDeclAsContext(NamespaceDecl *D) {
445 void visitNamedDeclAttrs(NamedDecl *D) {
446 setName(D->getDeclName());
450 void visitValueDeclChildren(ValueDecl *D) {
451 dispatch(D->getType());
455 void visitDeclaratorDeclChildren(DeclaratorDecl *D) {
456 //dispatch(D->getTypeSourceInfo()->getTypeLoc());
460 void visitVarDeclAttrs(VarDecl *D) {
461 visitRedeclarableAttrs(D);
462 if (D->getStorageClass() != SC_None)
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;
471 set("initstyle", initStyle);
472 setFlag("nrvo", D->isNRVOVariable());
473 // TODO: instantiation, etc.
475 void visitVarDeclChildren(VarDecl *D) {
476 if (D->hasInit()) dispatch(D->getInit());
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)
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.
497 void visitFunctionDeclChildren(FunctionDecl *D) {
498 for (FunctionDecl::param_iterator
499 I = D->param_begin(), E = D->param_end(); I != E; ++I)
501 for (llvm::ArrayRef<NamedDecl*>::iterator
502 I = D->getDeclsInPrototypeScope().begin(), E = D->getDeclsInPrototypeScope().end();
505 if (D->doesThisDeclarationHaveABody())
506 dispatch(D->getBody());
510 // CXXConstructorDecl ?
511 // CXXDestructorDecl ?
512 // CXXConversionDecl ?
514 void dispatch(CXXCtorInitializer *Init) {
519 void visitFieldDeclAttrs(FieldDecl *D) {
520 setFlag("mutable", D->isMutable());
522 void visitFieldDeclChildren(FieldDecl *D) {
523 if (D->isBitField()) {
524 TemporaryContainer C(*this, "bitwidth");
525 dispatch(D->getBitWidth());
527 // TODO: C++0x member initializer
531 void visitEnumConstantDeclChildren(EnumConstantDecl *D) {
532 // value in any case?
533 if (D->getInitExpr()) dispatch(D->getInitExpr());
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);
549 void visitTypeDeclAttrs(TypeDecl *D) {
550 setPointer("typeptr", D->getTypeForDecl());
554 void visitTypedefDeclAttrs(TypedefDecl *D) {
555 visitRedeclarableAttrs<TypedefNameDecl>(D);
557 void visitTypedefDeclChildren(TypedefDecl *D) {
558 dispatch(D->getTypeSourceInfo()->getTypeLoc());
562 void visitTypeAliasDeclAttrs(TypeAliasDecl *D) {
563 visitRedeclarableAttrs<TypedefNameDecl>(D);
565 void visitTypeAliasDeclChildren(TypeAliasDecl *D) {
566 dispatch(D->getTypeSourceInfo()->getTypeLoc());
570 void visitTagDeclAttrs(TagDecl *D) {
571 visitRedeclarableAttrs(D);
573 void visitTagDeclAsContext(TagDecl *D) {
578 void visitEnumDeclAttrs(EnumDecl *D) {
579 setFlag("scoped", D->isScoped());
580 setFlag("fixed", D->isFixed());
582 void visitEnumDeclChildren(EnumDecl *D) {
584 TemporaryContainer C(*this, "promotion_type");
585 dispatch(D->getPromotionType());
588 TemporaryContainer C(*this, "integer_type");
589 dispatch(D->getIntegerType());
595 void visitCXXRecordDeclChildren(CXXRecordDecl *D) {
596 if (!D->isThisDeclarationADefinition()) return;
598 for (CXXRecordDecl::base_class_iterator
599 I = D->bases_begin(), E = D->bases_end(); I != E; ++I) {
601 setAccess(I->getAccessSpecifier());
603 dispatch(I->getTypeSourceInfo()->getTypeLoc());
608 // ClassTemplateSpecializationDecl ?
610 // FileScopeAsmDecl ?
613 void visitBlockDeclAttrs(BlockDecl *D) {
614 setFlag("variadic", D->isVariadic());
616 void visitBlockDeclChildren(BlockDecl *D) {
617 for (FunctionDecl::param_iterator
618 I = D->param_begin(), E = D->param_end(); I != E; ++I)
620 dispatch(D->getBody());
624 void visitAccessSpecDeclAttrs(AccessSpecDecl *D) {
625 setAccess(D->getAccess());
629 void visitTemplateDeclChildren(TemplateDecl *D) {
630 visitTemplateParameters(D->getTemplateParameters());
631 if (D->getTemplatedDecl())
632 dispatch(D->getTemplatedDecl());
635 // FunctionTemplateDecl
636 void visitFunctionTemplateDeclAttrs(FunctionTemplateDecl *D) {
637 visitRedeclarableAttrs(D);
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();
647 bool Unknown = false;
648 switch (Info->getTemplateSpecializationKind()) {
649 case TSK_ImplicitInstantiation: Unknown = false; break;
650 case TSK_Undeclared: Unknown = true; break;
652 // These will be covered at their respective sites.
653 case TSK_ExplicitSpecialization: continue;
654 case TSK_ExplicitInstantiationDeclaration: continue;
655 case TSK_ExplicitInstantiationDefinition: continue;
658 TemporaryContainer C(*this,
659 Unknown ? "uninstantiated" : "instantiation");
660 visitTemplateArguments(*Info->TemplateArguments);
661 dispatch(Info->Function);
666 void visitClassTemplateDeclAttrs(ClassTemplateDecl *D) {
667 visitRedeclarableAttrs(D);
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) {
675 bool Unknown = false;
676 switch (I->getTemplateSpecializationKind()) {
677 case TSK_ImplicitInstantiation: Unknown = false; break;
678 case TSK_Undeclared: Unknown = true; break;
680 // These will be covered at their respective sites.
681 case TSK_ExplicitSpecialization: continue;
682 case TSK_ExplicitInstantiationDeclaration: continue;
683 case TSK_ExplicitInstantiationDefinition: continue;
686 TemporaryContainer C(*this,
687 Unknown ? "uninstantiated" : "instantiation");
688 visitTemplateArguments(I->getTemplateArgs());
693 // TemplateTypeParmDecl
694 void visitTemplateTypeParmDeclAttrs(TemplateTypeParmDecl *D) {
695 setInteger("depth", D->getDepth());
696 setInteger("index", D->getIndex());
698 void visitTemplateTypeParmDeclChildren(TemplateTypeParmDecl *D) {
699 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
700 dispatch(D->getDefaultArgumentInfo()->getTypeLoc());
704 // NonTypeTemplateParmDecl
705 void visitNonTypeTemplateParmDeclAttrs(NonTypeTemplateParmDecl *D) {
706 setInteger("depth", D->getDepth());
707 setInteger("index", D->getIndex());
709 void visitNonTypeTemplateParmDeclChildren(NonTypeTemplateParmDecl *D) {
710 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
711 dispatch(D->getDefaultArgument());
715 // TemplateTemplateParmDecl
716 void visitTemplateTemplateParmDeclAttrs(TemplateTemplateParmDecl *D) {
717 setInteger("depth", D->getDepth());
718 setInteger("index", D->getIndex());
720 void visitTemplateTemplateParmDeclChildren(TemplateTemplateParmDecl *D) {
721 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
722 dispatch(D->getDefaultArgument());
727 void visitFriendDeclChildren(FriendDecl *D) {
728 if (TypeSourceInfo *T = D->getFriendType())
729 dispatch(T->getTypeLoc());
731 dispatch(D->getFriendDecl());
734 // UsingDirectiveDecl ?
737 // NamespaceAliasDecl ?
738 // UnresolvedUsingValueDecl ?
739 // UnresolvedUsingTypenameDecl ?
740 // StaticAssertDecl ?
743 void visitObjCImplDeclChildren(ObjCImplDecl *D) {
744 visitDeclRef(D->getClassInterface());
746 void visitObjCImplDeclAsContext(ObjCImplDecl *D) {
751 void visitCategoryList(ObjCCategoryDecl *D) {
754 TemporaryContainer C(*this, "categories");
755 for (; D; D = D->getNextClassCategory())
758 void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) {
759 setPointer("typeptr", D->getTypeForDecl());
760 setFlag("forward_decl", !D->isThisDeclarationADefinition());
761 setFlag("implicit_interface", D->isImplicitInterfaceDecl());
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)
772 visitCategoryList(D->getCategoryList());
774 void visitObjCInterfaceDeclAsContext(ObjCInterfaceDecl *D) {
779 void visitObjCCategoryDeclAttrs(ObjCCategoryDecl *D) {
780 setFlag("extension", D->IsClassExtension());
781 setFlag("synth_bitfield", D->hasSynthBitfield());
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)
793 void visitObjCCategoryDeclAsContext(ObjCCategoryDecl *D) {
797 // ObjCCategoryImplDecl
798 void visitObjCCategoryImplDeclAttrs(ObjCCategoryImplDecl *D) {
799 set("identifier", D->getName());
801 void visitObjCCategoryImplDeclChildren(ObjCCategoryImplDecl *D) {
802 visitDeclRef(D->getCategoryDecl());
805 // ObjCImplementationDecl
806 void visitObjCImplementationDeclAttrs(ObjCImplementationDecl *D) {
807 setFlag("synth_bitfield", D->hasSynthBitfield());
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("synthesized", D->isSynthesized());
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");
928 void visitTypeAttrs(Type *D) {
930 setFlag("dependent", D->isDependentType());
931 setFlag("variably_modified", D->isVariablyModifiedType());
933 setPointer("canonical", D->getCanonicalTypeInternal().getAsOpaquePtr());
936 void visitPointerTypeChildren(PointerType *T) {
937 dispatch(T->getPointeeType());
939 void visitReferenceTypeChildren(ReferenceType *T) {
940 dispatch(T->getPointeeType());
942 void visitObjCObjectPointerTypeChildren(ObjCObjectPointerType *T) {
943 dispatch(T->getPointeeType());
945 void visitBlockPointerTypeChildren(BlockPointerType *T) {
946 dispatch(T->getPointeeType());
949 // Types that just wrap declarations.
950 void visitTagTypeChildren(TagType *T) {
951 visitDeclRef(T->getDecl());
953 void visitTypedefTypeChildren(TypedefType *T) {
954 visitDeclRef(T->getDecl());
956 void visitObjCInterfaceTypeChildren(ObjCInterfaceType *T) {
957 visitDeclRef(T->getDecl());
959 void visitUnresolvedUsingTypeChildren(UnresolvedUsingType *T) {
960 visitDeclRef(T->getDecl());
962 void visitInjectedClassNameTypeChildren(InjectedClassNameType *T) {
963 visitDeclRef(T->getDecl());
966 void visitFunctionTypeAttrs(FunctionType *T) {
967 setFlag("noreturn", T->getNoReturnAttr());
968 setCallingConv(T->getCallConv());
969 if (T->getHasRegParm()) setInteger("regparm", T->getRegParmType());
971 void visitFunctionTypeChildren(FunctionType *T) {
972 dispatch(T->getResultType());
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);
980 void visitFunctionProtoTypeChildren(FunctionProtoType *T) {
982 setFlag("variadic", T->isVariadic());
984 for (FunctionProtoType::arg_type_iterator
985 I = T->arg_type_begin(), E = T->arg_type_end(); I != E; ++I)
989 if (T->hasDynamicExceptionSpec()) {
990 push("exception_specifiers");
991 setFlag("any", T->getExceptionSpecType() == EST_MSAny);
993 for (FunctionProtoType::exception_iterator
994 I = T->exception_begin(), E = T->exception_end(); I != E; ++I)
998 // FIXME: noexcept specifier
1001 void visitTemplateSpecializationTypeChildren(TemplateSpecializationType *T) {
1002 if (const RecordType *RT = T->getAs<RecordType>())
1003 visitDeclRef(RT->getDecl());
1005 // TODO: TemplateName
1007 push("template_arguments");
1009 for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I)
1010 dispatch(T->getArg(I));
1014 //---- Statements ------------------------------------------------//
1015 void dispatch(Stmt *S) {
1016 // FIXME: this is not really XML at all
1019 Stack.back().State = NS_Children; // explicitly become non-lazy
1020 S->dump(out, Context.getSourceManager());
1027 void Decl::dumpXML() const {
1028 dumpXML(llvm::errs());
1031 void Decl::dumpXML(raw_ostream &out) const {
1032 XMLDumper(out, getASTContext()).dispatch(const_cast<Decl*>(this));
1035 #else /* ifndef NDEBUG */
1037 void Decl::dumpXML() const {}
1038 void Decl::dumpXML(raw_ostream &out) const {}