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/SmallVector.h"
43 #include "llvm/ADT/StringRef.h"
45 using namespace clang;
52 NS_Attrs, NS_LazyChildren, NS_Children
58 Node(llvm::StringRef name) : Name(name), State(NS_Attrs) {}
60 bool isDoneWithAttrs() const { return State != NS_Attrs; }
63 template <class Impl> struct XMLDeclVisitor {
64 #define DISPATCH(NAME, CLASS) \
65 static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(D))
67 void dispatch(Decl *D) {
68 switch (D->getKind()) {
69 default: llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
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 default: llvm_unreachable("Type that isn't part of TypeNodes.inc!");
125 #define TYPE(DERIVED, BASE) \
126 case Type::DERIVED: \
127 DISPATCH(dispatch##DERIVED##TypeAttrs, DERIVED##Type); \
128 static_cast<Impl*>(this)->completeAttrs(); \
129 DISPATCH(dispatch##DERIVED##TypeChildren, DERIVED##Type); \
131 #define ABSTRACT_TYPE(DERIVED, BASE)
132 #include "clang/AST/TypeNodes.def"
136 #define TYPE(DERIVED, BASE) \
137 void dispatch##DERIVED##TypeAttrs(DERIVED##Type *T) { \
138 DISPATCH(dispatch##BASE##Attrs, BASE); \
139 DISPATCH(visit##DERIVED##TypeAttrs, DERIVED##Type); \
141 void visit##DERIVED##TypeAttrs(DERIVED##Type *T) {} \
142 void dispatch##DERIVED##TypeChildren(DERIVED##Type *T) { \
143 DISPATCH(dispatch##BASE##Children, BASE); \
144 DISPATCH(visit##DERIVED##TypeChildren, DERIVED##Type); \
146 void visit##DERIVED##TypeChildren(DERIVED##Type *T) {}
147 #include "clang/AST/TypeNodes.def"
149 void dispatchTypeAttrs(Type *T) {
150 DISPATCH(visitTypeAttrs, Type);
152 void visitTypeAttrs(Type *T) {}
154 void dispatchTypeChildren(Type *T) {
155 DISPATCH(visitTypeChildren, Type);
157 void visitTypeChildren(Type *T) {}
162 static llvm::StringRef getTypeKindName(Type *T) {
163 switch (T->getTypeClass()) {
164 #define TYPE(DERIVED, BASE) case Type::DERIVED: return #DERIVED "Type";
165 #define ABSTRACT_TYPE(DERIVED, BASE)
166 #include "clang/AST/TypeNodes.def"
169 llvm_unreachable("unknown type kind!");
170 return "unknown_type";
173 struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
174 public XMLTypeVisitor<XMLDumper> {
175 llvm::raw_ostream &out;
177 llvm::SmallVector<Node, 16> Stack;
179 explicit XMLDumper(llvm::raw_ostream &OS, ASTContext &context)
180 : out(OS), Context(context), Indent(0) {}
183 for (unsigned I = Indent; I; --I)
187 /// Push a new node on the stack.
188 void push(llvm::StringRef name) {
189 if (!Stack.empty()) {
190 assert(Stack.back().isDoneWithAttrs());
191 if (Stack.back().State == NS_LazyChildren) {
192 Stack.back().State = NS_Children;
198 Stack.push_back(Node(name));
202 /// Set the given attribute to the given value.
203 void set(llvm::StringRef attr, llvm::StringRef value) {
204 assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
205 out << ' ' << attr << '=' << '"' << value << '"'; // TODO: quotation
208 /// Finish attributes.
209 void completeAttrs() {
210 assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
211 Stack.back().State = NS_LazyChildren;
216 assert(!Stack.empty() && Stack.back().isDoneWithAttrs());
217 if (Stack.back().State == NS_LazyChildren) {
221 out << "</" << Stack.back().Name << ">\n";
223 if (Stack.size() > 1) Indent--;
227 //---- General utilities -------------------------------------------//
229 void setPointer(llvm::StringRef prop, const void *p) {
230 llvm::SmallString<10> buffer;
231 llvm::raw_svector_ostream os(buffer);
237 void setPointer(void *p) {
238 setPointer("ptr", p);
241 void setInteger(llvm::StringRef prop, const llvm::APSInt &v) {
242 set(prop, v.toString(10));
245 void setInteger(llvm::StringRef prop, unsigned n) {
246 llvm::SmallString<10> buffer;
247 llvm::raw_svector_ostream os(buffer);
253 void setFlag(llvm::StringRef prop, bool flag) {
254 if (flag) set(prop, "true");
257 void setName(DeclarationName Name) {
259 return set("name", "");
262 if (Name.isIdentifier())
263 return set("name", Name.getAsIdentifierInfo()->getName());
265 set("name", Name.getAsString());
268 class TemporaryContainer {
271 TemporaryContainer(XMLDumper &dumper, llvm::StringRef name)
274 Dumper.completeAttrs();
277 ~TemporaryContainer() {
282 void visitTemplateParameters(TemplateParameterList *L) {
283 push("template_parameters");
285 for (TemplateParameterList::iterator
286 I = L->begin(), E = L->end(); I != E; ++I)
291 void visitTemplateArguments(const TemplateArgumentList &L) {
292 push("template_arguments");
294 for (unsigned I = 0, E = L.size(); I != E; ++I)
299 /// Visits a reference to the given declaration.
300 void visitDeclRef(Decl *D) {
301 push(D->getDeclKindName());
302 setPointer("ref", D);
306 void visitDeclRef(llvm::StringRef Name, Decl *D) {
307 TemporaryContainer C(*this, Name);
308 if (D) visitDeclRef(D);
311 void dispatch(const TemplateArgument &A) {
312 switch (A.getKind()) {
313 case TemplateArgument::Null: {
314 TemporaryContainer C(*this, "null");
317 case TemplateArgument::Type: {
318 dispatch(A.getAsType());
321 case TemplateArgument::Template:
322 case TemplateArgument::TemplateExpansion:
326 case TemplateArgument::Declaration: {
327 visitDeclRef(A.getAsDecl());
330 case TemplateArgument::Integral: {
332 setInteger("value", *A.getAsIntegral());
337 case TemplateArgument::Expression: {
338 dispatch(A.getAsExpr());
341 case TemplateArgument::Pack: {
342 for (TemplateArgument::pack_iterator P = A.pack_begin(),
351 void dispatch(const TemplateArgumentLoc &A) {
352 dispatch(A.getArgument());
355 //---- Declarations ------------------------------------------------//
356 // Calls are made in this order:
357 // # Enter a new node.
360 // # In this phase, attributes are set on the node.
362 // visitNamedDeclAttrs(D)
364 // visitFieldDeclAttrs(D)
366 // # No more attributes after this point.
369 // # Create "header" child nodes, i.e. those which logically
370 // # belong to the declaration itself.
371 // visitDeclChildren(D)
372 // visitNamedDeclChildren(D)
374 // visitFieldDeclChildren(D)
376 // # Create nodes for the lexical children.
377 // visitDeclAsContext(D)
378 // visitNamedDeclAsContext(D)
380 // visitFieldDeclAsContext(D)
382 // # Finish the node.
384 void dispatch(Decl *D) {
385 push(D->getDeclKindName());
386 XMLDeclVisitor<XMLDumper>::dispatch(D);
389 void visitDeclAttrs(Decl *D) {
393 /// Visit all the lexical decls in the given context.
394 void visitDeclContext(DeclContext *DC) {
395 for (DeclContext::decl_iterator
396 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
399 // FIXME: point out visible declarations not in lexical context?
402 /// Set the "access" attribute on the current node according to the
404 void setAccess(AccessSpecifier AS) {
406 case AS_public: return set("access", "public");
407 case AS_protected: return set("access", "protected");
408 case AS_private: return set("access", "private");
409 case AS_none: llvm_unreachable("explicit forbidden access");
413 template <class T> void visitRedeclarableAttrs(T *D) {
414 if (T *Prev = D->getPreviousDeclaration())
415 setPointer("previous", Prev);
419 // TranslationUnitDecl
420 void visitTranslationUnitDeclAsContext(TranslationUnitDecl *D) {
425 void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) {
426 llvm::StringRef lang = "";
427 switch (D->getLanguage()) {
428 case LinkageSpecDecl::lang_c: lang = "C"; break;
429 case LinkageSpecDecl::lang_cxx: lang = "C++"; break;
433 void visitLinkageSpecDeclAsContext(LinkageSpecDecl *D) {
438 void visitNamespaceDeclAttrs(NamespaceDecl *D) {
439 setFlag("inline", D->isInline());
440 if (!D->isOriginalNamespace())
441 setPointer("original", D->getOriginalNamespace());
443 void visitNamespaceDeclAsContext(NamespaceDecl *D) {
448 void visitNamedDeclAttrs(NamedDecl *D) {
449 setName(D->getDeclName());
453 void visitValueDeclChildren(ValueDecl *D) {
454 dispatch(D->getType());
458 void visitDeclaratorDeclChildren(DeclaratorDecl *D) {
459 //dispatch(D->getTypeSourceInfo()->getTypeLoc());
463 void visitVarDeclAttrs(VarDecl *D) {
464 visitRedeclarableAttrs(D);
465 if (D->getStorageClass() != SC_None)
467 VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
468 setFlag("directinit", D->hasCXXDirectInitializer());
469 setFlag("nrvo", D->isNRVOVariable());
470 // TODO: instantiation, etc.
472 void visitVarDeclChildren(VarDecl *D) {
473 if (D->hasInit()) dispatch(D->getInit());
479 void visitFunctionDeclAttrs(FunctionDecl *D) {
480 visitRedeclarableAttrs(D);
481 setFlag("pure", D->isPure());
482 setFlag("trivial", D->isTrivial());
483 setFlag("returnzero", D->hasImplicitReturnZero());
484 setFlag("prototype", D->hasWrittenPrototype());
485 setFlag("deleted", D->isDeleted());
486 if (D->getStorageClass() != SC_None)
488 VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
489 setFlag("inline", D->isInlineSpecified());
490 // TODO: instantiation, etc.
492 void visitFunctionDeclChildren(FunctionDecl *D) {
493 for (FunctionDecl::param_iterator
494 I = D->param_begin(), E = D->param_end(); I != E; ++I)
496 if (D->isThisDeclarationADefinition())
497 dispatch(D->getBody());
501 // CXXConstructorDecl ?
502 // CXXDestructorDecl ?
503 // CXXConversionDecl ?
505 void dispatch(CXXCtorInitializer *Init) {
510 void visitFieldDeclAttrs(FieldDecl *D) {
511 setFlag("mutable", D->isMutable());
513 void visitFieldDeclChildren(FieldDecl *D) {
514 if (D->isBitField()) {
515 TemporaryContainer C(*this, "bitwidth");
516 dispatch(D->getBitWidth());
518 // TODO: C++0x member initializer
522 void visitEnumConstantDeclChildren(EnumConstantDecl *D) {
523 // value in any case?
524 if (D->getInitExpr()) dispatch(D->getInitExpr());
528 void visitIndirectFieldDeclChildren(IndirectFieldDecl *D) {
529 for (IndirectFieldDecl::chain_iterator
530 I = D->chain_begin(), E = D->chain_end(); I != E; ++I) {
531 NamedDecl *VD = const_cast<NamedDecl*>(*I);
532 push(isa<VarDecl>(VD) ? "variable" : "field");
533 setPointer("ptr", VD);
540 void visitTypeDeclAttrs(TypeDecl *D) {
541 setPointer("typeptr", D->getTypeForDecl());
545 void visitTypedefDeclAttrs(TypedefDecl *D) {
546 visitRedeclarableAttrs<TypedefNameDecl>(D);
548 void visitTypedefDeclChildren(TypedefDecl *D) {
549 dispatch(D->getTypeSourceInfo()->getTypeLoc());
553 void visitTypeAliasDeclAttrs(TypeAliasDecl *D) {
554 visitRedeclarableAttrs<TypedefNameDecl>(D);
556 void visitTypeAliasDeclChildren(TypeAliasDecl *D) {
557 dispatch(D->getTypeSourceInfo()->getTypeLoc());
561 void visitTagDeclAttrs(TagDecl *D) {
562 visitRedeclarableAttrs(D);
564 void visitTagDeclAsContext(TagDecl *D) {
569 void visitEnumDeclAttrs(EnumDecl *D) {
570 setFlag("scoped", D->isScoped());
571 setFlag("fixed", D->isFixed());
573 void visitEnumDeclChildren(EnumDecl *D) {
575 TemporaryContainer C(*this, "promotion_type");
576 dispatch(D->getPromotionType());
579 TemporaryContainer C(*this, "integer_type");
580 dispatch(D->getIntegerType());
586 void visitCXXRecordDeclChildren(CXXRecordDecl *D) {
587 if (!D->isThisDeclarationADefinition()) return;
589 for (CXXRecordDecl::base_class_iterator
590 I = D->bases_begin(), E = D->bases_end(); I != E; ++I) {
592 setAccess(I->getAccessSpecifier());
594 dispatch(I->getTypeSourceInfo()->getTypeLoc());
599 // ClassTemplateSpecializationDecl ?
601 // FileScopeAsmDecl ?
604 void visitBlockDeclAttrs(BlockDecl *D) {
605 setFlag("variadic", D->isVariadic());
607 void visitBlockDeclChildren(BlockDecl *D) {
608 for (FunctionDecl::param_iterator
609 I = D->param_begin(), E = D->param_end(); I != E; ++I)
611 dispatch(D->getBody());
615 void visitAccessSpecDeclAttrs(AccessSpecDecl *D) {
616 setAccess(D->getAccess());
620 void visitTemplateDeclChildren(TemplateDecl *D) {
621 visitTemplateParameters(D->getTemplateParameters());
622 dispatch(D->getTemplatedDecl());
625 // FunctionTemplateDecl
626 void visitFunctionTemplateDeclAttrs(FunctionTemplateDecl *D) {
627 visitRedeclarableAttrs(D);
629 void visitFunctionTemplateDeclChildren(FunctionTemplateDecl *D) {
630 // Mention all the specializations which don't have explicit
631 // declarations elsewhere.
632 for (FunctionTemplateDecl::spec_iterator
633 I = D->spec_begin(), E = D->spec_end(); I != E; ++I) {
634 FunctionTemplateSpecializationInfo *Info
635 = I->getTemplateSpecializationInfo();
637 bool Unknown = false;
638 switch (Info->getTemplateSpecializationKind()) {
639 case TSK_ImplicitInstantiation: Unknown = false; break;
640 case TSK_Undeclared: Unknown = true; break;
642 // These will be covered at their respective sites.
643 case TSK_ExplicitSpecialization: continue;
644 case TSK_ExplicitInstantiationDeclaration: continue;
645 case TSK_ExplicitInstantiationDefinition: continue;
648 TemporaryContainer C(*this,
649 Unknown ? "uninstantiated" : "instantiation");
650 visitTemplateArguments(*Info->TemplateArguments);
651 dispatch(Info->Function);
656 void visitClassTemplateDeclAttrs(ClassTemplateDecl *D) {
657 visitRedeclarableAttrs(D);
659 void visitClassTemplateDeclChildren(ClassTemplateDecl *D) {
660 // Mention all the specializations which don't have explicit
661 // declarations elsewhere.
662 for (ClassTemplateDecl::spec_iterator
663 I = D->spec_begin(), E = D->spec_end(); I != E; ++I) {
665 bool Unknown = false;
666 switch (I->getTemplateSpecializationKind()) {
667 case TSK_ImplicitInstantiation: Unknown = false; break;
668 case TSK_Undeclared: Unknown = true; break;
670 // These will be covered at their respective sites.
671 case TSK_ExplicitSpecialization: continue;
672 case TSK_ExplicitInstantiationDeclaration: continue;
673 case TSK_ExplicitInstantiationDefinition: continue;
676 TemporaryContainer C(*this,
677 Unknown ? "uninstantiated" : "instantiation");
678 visitTemplateArguments(I->getTemplateArgs());
683 // TemplateTypeParmDecl
684 void visitTemplateTypeParmDeclAttrs(TemplateTypeParmDecl *D) {
685 setInteger("depth", D->getDepth());
686 setInteger("index", D->getIndex());
688 void visitTemplateTypeParmDeclChildren(TemplateTypeParmDecl *D) {
689 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
690 dispatch(D->getDefaultArgumentInfo()->getTypeLoc());
694 // NonTypeTemplateParmDecl
695 void visitNonTypeTemplateParmDeclAttrs(NonTypeTemplateParmDecl *D) {
696 setInteger("depth", D->getDepth());
697 setInteger("index", D->getIndex());
699 void visitNonTypeTemplateParmDeclChildren(NonTypeTemplateParmDecl *D) {
700 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
701 dispatch(D->getDefaultArgument());
705 // TemplateTemplateParmDecl
706 void visitTemplateTemplateParmDeclAttrs(TemplateTemplateParmDecl *D) {
707 setInteger("depth", D->getDepth());
708 setInteger("index", D->getIndex());
710 void visitTemplateTemplateParmDeclChildren(TemplateTemplateParmDecl *D) {
711 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
712 dispatch(D->getDefaultArgument());
717 void visitFriendDeclChildren(FriendDecl *D) {
718 if (TypeSourceInfo *T = D->getFriendType())
719 dispatch(T->getTypeLoc());
721 dispatch(D->getFriendDecl());
724 // UsingDirectiveDecl ?
727 // NamespaceAliasDecl ?
728 // UnresolvedUsingValueDecl ?
729 // UnresolvedUsingTypenameDecl ?
730 // StaticAssertDecl ?
733 void visitObjCImplDeclChildren(ObjCImplDecl *D) {
734 visitDeclRef(D->getClassInterface());
736 void visitObjCImplDeclAsContext(ObjCImplDecl *D) {
741 void visitObjCClassDeclChildren(ObjCClassDecl *D) {
742 for (ObjCClassDecl::iterator I = D->begin(), E = D->end(); I != E; ++I)
743 visitDeclRef(I->getInterface());
747 void visitCategoryList(ObjCCategoryDecl *D) {
750 TemporaryContainer C(*this, "categories");
751 for (; D; D = D->getNextClassCategory())
754 void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) {
755 setPointer("typeptr", D->getTypeForDecl());
756 setFlag("forward_decl", D->isForwardDecl());
757 setFlag("implicit_interface", D->isImplicitInterfaceDecl());
759 void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) {
760 visitDeclRef("super", D->getSuperClass());
761 visitDeclRef("implementation", D->getImplementation());
762 if (D->protocol_begin() != D->protocol_end()) {
763 TemporaryContainer C(*this, "protocols");
764 for (ObjCInterfaceDecl::protocol_iterator
765 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
768 visitCategoryList(D->getCategoryList());
770 void visitObjCInterfaceDeclAsContext(ObjCInterfaceDecl *D) {
775 void visitObjCCategoryDeclAttrs(ObjCCategoryDecl *D) {
776 setFlag("extension", D->IsClassExtension());
777 setFlag("synth_bitfield", D->hasSynthBitfield());
779 void visitObjCCategoryDeclChildren(ObjCCategoryDecl *D) {
780 visitDeclRef("interface", D->getClassInterface());
781 visitDeclRef("implementation", D->getImplementation());
782 if (D->protocol_begin() != D->protocol_end()) {
783 TemporaryContainer C(*this, "protocols");
784 for (ObjCCategoryDecl::protocol_iterator
785 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
789 void visitObjCCategoryDeclAsContext(ObjCCategoryDecl *D) {
793 // ObjCCategoryImplDecl
794 void visitObjCCategoryImplDeclAttrs(ObjCCategoryImplDecl *D) {
795 set("identifier", D->getName());
797 void visitObjCCategoryImplDeclChildren(ObjCCategoryImplDecl *D) {
798 visitDeclRef(D->getCategoryDecl());
801 // ObjCImplementationDecl
802 void visitObjCImplementationDeclAttrs(ObjCImplementationDecl *D) {
803 setFlag("synth_bitfield", D->hasSynthBitfield());
804 set("identifier", D->getName());
806 void visitObjCImplementationDeclChildren(ObjCImplementationDecl *D) {
807 visitDeclRef("super", D->getSuperClass());
808 if (D->init_begin() != D->init_end()) {
809 TemporaryContainer C(*this, "initializers");
810 for (ObjCImplementationDecl::init_iterator
811 I = D->init_begin(), E = D->init_end(); I != E; ++I)
816 // ObjCForwardProtocolDecl
817 void visitObjCForwardProtocolDeclChildren(ObjCForwardProtocolDecl *D) {
818 for (ObjCForwardProtocolDecl::protocol_iterator
819 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
824 void visitObjCProtocolDeclAttrs(ObjCProtocolDecl *D) {
825 setFlag("forward_decl", D->isForwardDecl());
827 void visitObjCProtocolDeclChildren(ObjCProtocolDecl *D) {
828 if (D->protocol_begin() != D->protocol_end()) {
829 TemporaryContainer C(*this, "protocols");
830 for (ObjCInterfaceDecl::protocol_iterator
831 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
835 void visitObjCProtocolDeclAsContext(ObjCProtocolDecl *D) {
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());
849 void visitObjCMethodDeclChildren(ObjCMethodDecl *D) {
850 dispatch(D->getResultType());
851 for (ObjCMethodDecl::param_iterator
852 I = D->param_begin(), E = D->param_end(); I != E; ++I)
854 if (D->isThisDeclarationADefinition())
855 dispatch(D->getBody());
859 void setAccessControl(llvm::StringRef prop, ObjCIvarDecl::AccessControl AC) {
861 case ObjCIvarDecl::None: return set(prop, "none");
862 case ObjCIvarDecl::Private: return set(prop, "private");
863 case ObjCIvarDecl::Protected: return set(prop, "protected");
864 case ObjCIvarDecl::Public: return set(prop, "public");
865 case ObjCIvarDecl::Package: return set(prop, "package");
868 void visitObjCIvarDeclAttrs(ObjCIvarDecl *D) {
869 setFlag("synthesize", D->getSynthesize());
870 setAccessControl("access", D->getAccessControl());
873 // ObjCCompatibleAliasDecl
874 void visitObjCCompatibleAliasDeclChildren(ObjCCompatibleAliasDecl *D) {
875 visitDeclRef(D->getClassInterface());
878 // FIXME: ObjCPropertyDecl
879 // FIXME: ObjCPropertyImplDecl
881 //---- Types -----------------------------------------------------//
882 void dispatch(TypeLoc TL) {
883 dispatch(TL.getType()); // for now
886 void dispatch(QualType T) {
887 if (T.hasLocalQualifiers()) {
889 Qualifiers Qs = T.getLocalQualifiers();
890 setFlag("const", Qs.hasConst());
891 setFlag("volatile", Qs.hasVolatile());
892 setFlag("restrict", Qs.hasRestrict());
893 if (Qs.hasAddressSpace()) setInteger("addrspace", Qs.getAddressSpace());
894 if (Qs.hasObjCGCAttr()) {
895 switch (Qs.getObjCGCAttr()) {
896 case Qualifiers::Weak: set("gc", "weak"); break;
897 case Qualifiers::Strong: set("gc", "strong"); break;
898 case Qualifiers::GCNone: llvm_unreachable("explicit none");
903 dispatch(QualType(T.getTypePtr(), 0));
908 Type *Ty = const_cast<Type*>(T.getTypePtr());
909 push(getTypeKindName(Ty));
910 XMLTypeVisitor<XMLDumper>::dispatch(const_cast<Type*>(T.getTypePtr()));
914 void setCallingConv(CallingConv CC) {
916 case CC_Default: return;
917 case CC_C: return set("cc", "cdecl");
918 case CC_X86FastCall: return set("cc", "x86_fastcall");
919 case CC_X86StdCall: return set("cc", "x86_stdcall");
920 case CC_X86ThisCall: return set("cc", "x86_thiscall");
921 case CC_X86Pascal: return set("cc", "x86_pascal");
922 case CC_AAPCS: return set("cc", "aapcs");
923 case CC_AAPCS_VFP: return set("cc", "aapcs_vfp");
927 void visitTypeAttrs(Type *D) {
929 setFlag("dependent", D->isDependentType());
930 setFlag("variably_modified", D->isVariablyModifiedType());
932 setPointer("canonical", D->getCanonicalTypeInternal().getAsOpaquePtr());
935 void visitPointerTypeChildren(PointerType *T) {
936 dispatch(T->getPointeeType());
938 void visitReferenceTypeChildren(ReferenceType *T) {
939 dispatch(T->getPointeeType());
941 void visitObjCObjectPointerTypeChildren(ObjCObjectPointerType *T) {
942 dispatch(T->getPointeeType());
944 void visitBlockPointerTypeChildren(BlockPointerType *T) {
945 dispatch(T->getPointeeType());
948 // Types that just wrap declarations.
949 void visitTagTypeChildren(TagType *T) {
950 visitDeclRef(T->getDecl());
952 void visitTypedefTypeChildren(TypedefType *T) {
953 visitDeclRef(T->getDecl());
955 void visitObjCInterfaceTypeChildren(ObjCInterfaceType *T) {
956 visitDeclRef(T->getDecl());
958 void visitUnresolvedUsingTypeChildren(UnresolvedUsingType *T) {
959 visitDeclRef(T->getDecl());
961 void visitInjectedClassNameTypeChildren(InjectedClassNameType *T) {
962 visitDeclRef(T->getDecl());
965 void visitFunctionTypeAttrs(FunctionType *T) {
966 setFlag("noreturn", T->getNoReturnAttr());
967 setCallingConv(T->getCallConv());
968 if (T->getHasRegParm()) setInteger("regparm", T->getRegParmType());
970 void visitFunctionTypeChildren(FunctionType *T) {
971 dispatch(T->getResultType());
974 void visitFunctionProtoTypeAttrs(FunctionProtoType *T) {
975 setFlag("const", T->getTypeQuals() & Qualifiers::Const);
976 setFlag("volatile", T->getTypeQuals() & Qualifiers::Volatile);
977 setFlag("restrict", T->getTypeQuals() & Qualifiers::Restrict);
979 void visitFunctionProtoTypeChildren(FunctionProtoType *T) {
981 setFlag("variadic", T->isVariadic());
983 for (FunctionProtoType::arg_type_iterator
984 I = T->arg_type_begin(), E = T->arg_type_end(); I != E; ++I)
988 if (T->hasDynamicExceptionSpec()) {
989 push("exception_specifiers");
990 setFlag("any", T->getExceptionSpecType() == EST_MSAny);
992 for (FunctionProtoType::exception_iterator
993 I = T->exception_begin(), E = T->exception_end(); I != E; ++I)
997 // FIXME: noexcept specifier
1000 void visitTemplateSpecializationTypeChildren(TemplateSpecializationType *T) {
1001 if (const RecordType *RT = T->getAs<RecordType>())
1002 visitDeclRef(RT->getDecl());
1004 // TODO: TemplateName
1006 push("template_arguments");
1008 for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I)
1009 dispatch(T->getArg(I));
1013 //---- Statements ------------------------------------------------//
1014 void dispatch(Stmt *S) {
1015 // FIXME: this is not really XML at all
1018 Stack.back().State = NS_Children; // explicitly become non-lazy
1019 S->dump(out, Context.getSourceManager());
1026 void Decl::dumpXML() const {
1027 dumpXML(llvm::errs());
1030 void Decl::dumpXML(llvm::raw_ostream &out) const {
1031 XMLDumper(out, getASTContext()).dispatch(const_cast<Decl*>(this));
1034 #else /* ifndef NDEBUG */
1036 void Decl::dumpXML() const {}
1037 void Decl::dumpXML(llvm::raw_ostream &out) const {}