diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/AST/DumpXML.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/AST/DumpXML.cpp | 1040 |
1 files changed, 1040 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp b/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp new file mode 100644 index 0000000..4c7cd8a --- /dev/null +++ b/contrib/llvm/tools/clang/lib/AST/DumpXML.cpp @@ -0,0 +1,1040 @@ +//===--- DumpXML.cpp - Detailed XML dumping ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the Decl::dumpXML() method, a debugging tool to +// print a detailed graph of an AST in an unspecified XML format. +// +// There is no guarantee of stability for this format. +// +//===----------------------------------------------------------------------===// + +// Only pay for this in code size in assertions-enabled builds. + +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclFriend.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclVisitor.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" +#include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtVisitor.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/TemplateName.h" +#include "clang/AST/Type.h" +#include "clang/AST/TypeLoc.h" +#include "clang/AST/TypeLocVisitor.h" +#include "clang/AST/TypeVisitor.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" +#include "llvm/ADT/SmallString.h" + +using namespace clang; + +#ifndef NDEBUG + +namespace { + +enum NodeState { + NS_Attrs, NS_LazyChildren, NS_Children +}; + +struct Node { + StringRef Name; + NodeState State; + Node(StringRef name) : Name(name), State(NS_Attrs) {} + + bool isDoneWithAttrs() const { return State != NS_Attrs; } +}; + +template <class Impl> struct XMLDeclVisitor { +#define DISPATCH(NAME, CLASS) \ + static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(D)) + + void dispatch(Decl *D) { + switch (D->getKind()) { +#define DECL(DERIVED, BASE) \ + case Decl::DERIVED: \ + DISPATCH(dispatch##DERIVED##DeclAttrs, DERIVED##Decl); \ + static_cast<Impl*>(this)->completeAttrs(); \ + DISPATCH(dispatch##DERIVED##DeclChildren, DERIVED##Decl); \ + DISPATCH(dispatch##DERIVED##DeclAsContext, DERIVED##Decl); \ + break; +#define ABSTRACT_DECL(DECL) +#include "clang/AST/DeclNodes.inc" + } + } + +#define DECL(DERIVED, BASE) \ + void dispatch##DERIVED##DeclAttrs(DERIVED##Decl *D) { \ + DISPATCH(dispatch##BASE##Attrs, BASE); \ + DISPATCH(visit##DERIVED##DeclAttrs, DERIVED##Decl); \ + } \ + void visit##DERIVED##DeclAttrs(DERIVED##Decl *D) {} \ + void dispatch##DERIVED##DeclChildren(DERIVED##Decl *D) { \ + DISPATCH(dispatch##BASE##Children, BASE); \ + DISPATCH(visit##DERIVED##DeclChildren, DERIVED##Decl); \ + } \ + void visit##DERIVED##DeclChildren(DERIVED##Decl *D) {} \ + void dispatch##DERIVED##DeclAsContext(DERIVED##Decl *D) { \ + DISPATCH(dispatch##BASE##AsContext, BASE); \ + DISPATCH(visit##DERIVED##DeclAsContext, DERIVED##Decl); \ + } \ + void visit##DERIVED##DeclAsContext(DERIVED##Decl *D) {} +#include "clang/AST/DeclNodes.inc" + + void dispatchDeclAttrs(Decl *D) { + DISPATCH(visitDeclAttrs, Decl); + } + void visitDeclAttrs(Decl *D) {} + + void dispatchDeclChildren(Decl *D) { + DISPATCH(visitDeclChildren, Decl); + } + void visitDeclChildren(Decl *D) {} + + void dispatchDeclAsContext(Decl *D) { + DISPATCH(visitDeclAsContext, Decl); + } + void visitDeclAsContext(Decl *D) {} + +#undef DISPATCH +}; + +template <class Impl> struct XMLTypeVisitor { +#define DISPATCH(NAME, CLASS) \ + static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(T)) + + void dispatch(Type *T) { + switch (T->getTypeClass()) { +#define TYPE(DERIVED, BASE) \ + case Type::DERIVED: \ + DISPATCH(dispatch##DERIVED##TypeAttrs, DERIVED##Type); \ + static_cast<Impl*>(this)->completeAttrs(); \ + DISPATCH(dispatch##DERIVED##TypeChildren, DERIVED##Type); \ + break; +#define ABSTRACT_TYPE(DERIVED, BASE) +#include "clang/AST/TypeNodes.def" + } + } + +#define TYPE(DERIVED, BASE) \ + void dispatch##DERIVED##TypeAttrs(DERIVED##Type *T) { \ + DISPATCH(dispatch##BASE##Attrs, BASE); \ + DISPATCH(visit##DERIVED##TypeAttrs, DERIVED##Type); \ + } \ + void visit##DERIVED##TypeAttrs(DERIVED##Type *T) {} \ + void dispatch##DERIVED##TypeChildren(DERIVED##Type *T) { \ + DISPATCH(dispatch##BASE##Children, BASE); \ + DISPATCH(visit##DERIVED##TypeChildren, DERIVED##Type); \ + } \ + void visit##DERIVED##TypeChildren(DERIVED##Type *T) {} +#include "clang/AST/TypeNodes.def" + + void dispatchTypeAttrs(Type *T) { + DISPATCH(visitTypeAttrs, Type); + } + void visitTypeAttrs(Type *T) {} + + void dispatchTypeChildren(Type *T) { + DISPATCH(visitTypeChildren, Type); + } + void visitTypeChildren(Type *T) {} + +#undef DISPATCH +}; + +static StringRef getTypeKindName(Type *T) { + switch (T->getTypeClass()) { +#define TYPE(DERIVED, BASE) case Type::DERIVED: return #DERIVED "Type"; +#define ABSTRACT_TYPE(DERIVED, BASE) +#include "clang/AST/TypeNodes.def" + } + + llvm_unreachable("unknown type kind!"); +} + +struct XMLDumper : public XMLDeclVisitor<XMLDumper>, + public XMLTypeVisitor<XMLDumper> { + raw_ostream &out; + ASTContext &Context; + SmallVector<Node, 16> Stack; + unsigned Indent; + explicit XMLDumper(raw_ostream &OS, ASTContext &context) + : out(OS), Context(context), Indent(0) {} + + void indent() { + for (unsigned I = Indent; I; --I) + out << ' '; + } + + /// Push a new node on the stack. + void push(StringRef name) { + if (!Stack.empty()) { + assert(Stack.back().isDoneWithAttrs()); + if (Stack.back().State == NS_LazyChildren) { + Stack.back().State = NS_Children; + out << ">\n"; + } + Indent++; + indent(); + } + Stack.push_back(Node(name)); + out << '<' << name; + } + + /// Set the given attribute to the given value. + void set(StringRef attr, StringRef value) { + assert(!Stack.empty() && !Stack.back().isDoneWithAttrs()); + out << ' ' << attr << '=' << '"' << value << '"'; // TODO: quotation + } + + /// Finish attributes. + void completeAttrs() { + assert(!Stack.empty() && !Stack.back().isDoneWithAttrs()); + Stack.back().State = NS_LazyChildren; + } + + /// Pop a node. + void pop() { + assert(!Stack.empty() && Stack.back().isDoneWithAttrs()); + if (Stack.back().State == NS_LazyChildren) { + out << "/>\n"; + } else { + indent(); + out << "</" << Stack.back().Name << ">\n"; + } + if (Stack.size() > 1) Indent--; + Stack.pop_back(); + } + + //---- General utilities -------------------------------------------// + + void setPointer(StringRef prop, const void *p) { + SmallString<10> buffer; + llvm::raw_svector_ostream os(buffer); + os << p; + os.flush(); + set(prop, buffer); + } + + void setPointer(void *p) { + setPointer("ptr", p); + } + + void setInteger(StringRef prop, const llvm::APSInt &v) { + set(prop, v.toString(10)); + } + + void setInteger(StringRef prop, unsigned n) { + SmallString<10> buffer; + llvm::raw_svector_ostream os(buffer); + os << n; + os.flush(); + set(prop, buffer); + } + + void setFlag(StringRef prop, bool flag) { + if (flag) set(prop, "true"); + } + + void setName(DeclarationName Name) { + if (!Name) + return set("name", ""); + + // Common case. + if (Name.isIdentifier()) + return set("name", Name.getAsIdentifierInfo()->getName()); + + set("name", Name.getAsString()); + } + + class TemporaryContainer { + XMLDumper &Dumper; + public: + TemporaryContainer(XMLDumper &dumper, StringRef name) + : Dumper(dumper) { + Dumper.push(name); + Dumper.completeAttrs(); + } + + ~TemporaryContainer() { + Dumper.pop(); + } + }; + + void visitTemplateParameters(TemplateParameterList *L) { + push("template_parameters"); + completeAttrs(); + for (TemplateParameterList::iterator + I = L->begin(), E = L->end(); I != E; ++I) + dispatch(*I); + pop(); + } + + void visitTemplateArguments(const TemplateArgumentList &L) { + push("template_arguments"); + completeAttrs(); + for (unsigned I = 0, E = L.size(); I != E; ++I) + dispatch(L[I]); + pop(); + } + + /// Visits a reference to the given declaration. + void visitDeclRef(Decl *D) { + push(D->getDeclKindName()); + setPointer("ref", D); + completeAttrs(); + pop(); + } + void visitDeclRef(StringRef Name, Decl *D) { + TemporaryContainer C(*this, Name); + if (D) visitDeclRef(D); + } + + void dispatch(const TemplateArgument &A) { + switch (A.getKind()) { + case TemplateArgument::Null: { + TemporaryContainer C(*this, "null"); + break; + } + case TemplateArgument::Type: { + dispatch(A.getAsType()); + break; + } + case TemplateArgument::Template: + case TemplateArgument::TemplateExpansion: + // FIXME: Implement! + break; + + case TemplateArgument::Declaration: { + if (Decl *D = A.getAsDecl()) + visitDeclRef(D); + break; + } + case TemplateArgument::Integral: { + push("integer"); + setInteger("value", *A.getAsIntegral()); + completeAttrs(); + pop(); + break; + } + case TemplateArgument::Expression: { + dispatch(A.getAsExpr()); + break; + } + case TemplateArgument::Pack: { + for (TemplateArgument::pack_iterator P = A.pack_begin(), + PEnd = A.pack_end(); + P != PEnd; ++P) + dispatch(*P); + break; + } + } + } + + void dispatch(const TemplateArgumentLoc &A) { + dispatch(A.getArgument()); + } + + //---- Declarations ------------------------------------------------// + // Calls are made in this order: + // # Enter a new node. + // push("FieldDecl") + // + // # In this phase, attributes are set on the node. + // visitDeclAttrs(D) + // visitNamedDeclAttrs(D) + // ... + // visitFieldDeclAttrs(D) + // + // # No more attributes after this point. + // completeAttrs() + // + // # Create "header" child nodes, i.e. those which logically + // # belong to the declaration itself. + // visitDeclChildren(D) + // visitNamedDeclChildren(D) + // ... + // visitFieldDeclChildren(D) + // + // # Create nodes for the lexical children. + // visitDeclAsContext(D) + // visitNamedDeclAsContext(D) + // ... + // visitFieldDeclAsContext(D) + // + // # Finish the node. + // pop(); + void dispatch(Decl *D) { + push(D->getDeclKindName()); + XMLDeclVisitor<XMLDumper>::dispatch(D); + pop(); + } + void visitDeclAttrs(Decl *D) { + setPointer(D); + } + + /// Visit all the lexical decls in the given context. + void visitDeclContext(DeclContext *DC) { + for (DeclContext::decl_iterator + I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) + dispatch(*I); + + // FIXME: point out visible declarations not in lexical context? + } + + /// Set the "access" attribute on the current node according to the + /// given specifier. + void setAccess(AccessSpecifier AS) { + switch (AS) { + case AS_public: return set("access", "public"); + case AS_protected: return set("access", "protected"); + case AS_private: return set("access", "private"); + case AS_none: llvm_unreachable("explicit forbidden access"); + } + } + + template <class T> void visitRedeclarableAttrs(T *D) { + if (T *Prev = D->getPreviousDecl()) + setPointer("previous", Prev); + } + + + // TranslationUnitDecl + void visitTranslationUnitDeclAsContext(TranslationUnitDecl *D) { + visitDeclContext(D); + } + + // LinkageSpecDecl + void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) { + StringRef lang = ""; + switch (D->getLanguage()) { + case LinkageSpecDecl::lang_c: lang = "C"; break; + case LinkageSpecDecl::lang_cxx: lang = "C++"; break; + } + set("lang", lang); + } + void visitLinkageSpecDeclAsContext(LinkageSpecDecl *D) { + visitDeclContext(D); + } + + // NamespaceDecl + void visitNamespaceDeclAttrs(NamespaceDecl *D) { + setFlag("inline", D->isInline()); + if (!D->isOriginalNamespace()) + setPointer("original", D->getOriginalNamespace()); + } + void visitNamespaceDeclAsContext(NamespaceDecl *D) { + visitDeclContext(D); + } + + // NamedDecl + void visitNamedDeclAttrs(NamedDecl *D) { + setName(D->getDeclName()); + } + + // ValueDecl + void visitValueDeclChildren(ValueDecl *D) { + dispatch(D->getType()); + } + + // DeclaratorDecl + void visitDeclaratorDeclChildren(DeclaratorDecl *D) { + //dispatch(D->getTypeSourceInfo()->getTypeLoc()); + } + + // VarDecl + void visitVarDeclAttrs(VarDecl *D) { + visitRedeclarableAttrs(D); + if (D->getStorageClass() != SC_None) + set("storage", + VarDecl::getStorageClassSpecifierString(D->getStorageClass())); + StringRef initStyle = ""; + switch (D->getInitStyle()) { + case VarDecl::CInit: initStyle = "c"; break; + case VarDecl::CallInit: initStyle = "call"; break; + case VarDecl::ListInit: initStyle = "list"; break; + } + set("initstyle", initStyle); + setFlag("nrvo", D->isNRVOVariable()); + // TODO: instantiation, etc. + } + void visitVarDeclChildren(VarDecl *D) { + if (D->hasInit()) dispatch(D->getInit()); + } + + // ParmVarDecl? + + // FunctionDecl + void visitFunctionDeclAttrs(FunctionDecl *D) { + visitRedeclarableAttrs(D); + setFlag("pure", D->isPure()); + setFlag("trivial", D->isTrivial()); + setFlag("returnzero", D->hasImplicitReturnZero()); + setFlag("prototype", D->hasWrittenPrototype()); + setFlag("deleted", D->isDeletedAsWritten()); + if (D->getStorageClass() != SC_None) + set("storage", + VarDecl::getStorageClassSpecifierString(D->getStorageClass())); + setFlag("inline", D->isInlineSpecified()); + if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) + set("asmlabel", ALA->getLabel()); + // TODO: instantiation, etc. + } + void visitFunctionDeclChildren(FunctionDecl *D) { + for (FunctionDecl::param_iterator + I = D->param_begin(), E = D->param_end(); I != E; ++I) + dispatch(*I); + for (llvm::ArrayRef<NamedDecl*>::iterator + I = D->getDeclsInPrototypeScope().begin(), E = D->getDeclsInPrototypeScope().end(); + I != E; ++I) + dispatch(*I); + if (D->doesThisDeclarationHaveABody()) + dispatch(D->getBody()); + } + + // CXXMethodDecl ? + // CXXConstructorDecl ? + // CXXDestructorDecl ? + // CXXConversionDecl ? + + void dispatch(CXXCtorInitializer *Init) { + // TODO + } + + // FieldDecl + void visitFieldDeclAttrs(FieldDecl *D) { + setFlag("mutable", D->isMutable()); + } + void visitFieldDeclChildren(FieldDecl *D) { + if (D->isBitField()) { + TemporaryContainer C(*this, "bitwidth"); + dispatch(D->getBitWidth()); + } + // TODO: C++0x member initializer + } + + // EnumConstantDecl + void visitEnumConstantDeclChildren(EnumConstantDecl *D) { + // value in any case? + if (D->getInitExpr()) dispatch(D->getInitExpr()); + } + + // IndirectFieldDecl + void visitIndirectFieldDeclChildren(IndirectFieldDecl *D) { + for (IndirectFieldDecl::chain_iterator + I = D->chain_begin(), E = D->chain_end(); I != E; ++I) { + NamedDecl *VD = const_cast<NamedDecl*>(*I); + push(isa<VarDecl>(VD) ? "variable" : "field"); + setPointer("ptr", VD); + completeAttrs(); + pop(); + } + } + + // TypeDecl + void visitTypeDeclAttrs(TypeDecl *D) { + setPointer("typeptr", D->getTypeForDecl()); + } + + // TypedefDecl + void visitTypedefDeclAttrs(TypedefDecl *D) { + visitRedeclarableAttrs<TypedefNameDecl>(D); + } + void visitTypedefDeclChildren(TypedefDecl *D) { + dispatch(D->getTypeSourceInfo()->getTypeLoc()); + } + + // TypeAliasDecl + void visitTypeAliasDeclAttrs(TypeAliasDecl *D) { + visitRedeclarableAttrs<TypedefNameDecl>(D); + } + void visitTypeAliasDeclChildren(TypeAliasDecl *D) { + dispatch(D->getTypeSourceInfo()->getTypeLoc()); + } + + // TagDecl + void visitTagDeclAttrs(TagDecl *D) { + visitRedeclarableAttrs(D); + } + void visitTagDeclAsContext(TagDecl *D) { + visitDeclContext(D); + } + + // EnumDecl + void visitEnumDeclAttrs(EnumDecl *D) { + setFlag("scoped", D->isScoped()); + setFlag("fixed", D->isFixed()); + } + void visitEnumDeclChildren(EnumDecl *D) { + { + TemporaryContainer C(*this, "promotion_type"); + dispatch(D->getPromotionType()); + } + { + TemporaryContainer C(*this, "integer_type"); + dispatch(D->getIntegerType()); + } + } + + // RecordDecl ? + + void visitCXXRecordDeclChildren(CXXRecordDecl *D) { + if (!D->isThisDeclarationADefinition()) return; + + for (CXXRecordDecl::base_class_iterator + I = D->bases_begin(), E = D->bases_end(); I != E; ++I) { + push("base"); + setAccess(I->getAccessSpecifier()); + completeAttrs(); + dispatch(I->getTypeSourceInfo()->getTypeLoc()); + pop(); + } + } + + // ClassTemplateSpecializationDecl ? + + // FileScopeAsmDecl ? + + // BlockDecl + void visitBlockDeclAttrs(BlockDecl *D) { + setFlag("variadic", D->isVariadic()); + } + void visitBlockDeclChildren(BlockDecl *D) { + for (FunctionDecl::param_iterator + I = D->param_begin(), E = D->param_end(); I != E; ++I) + dispatch(*I); + dispatch(D->getBody()); + } + + // AccessSpecDecl + void visitAccessSpecDeclAttrs(AccessSpecDecl *D) { + setAccess(D->getAccess()); + } + + // TemplateDecl + void visitTemplateDeclChildren(TemplateDecl *D) { + visitTemplateParameters(D->getTemplateParameters()); + if (D->getTemplatedDecl()) + dispatch(D->getTemplatedDecl()); + } + + // FunctionTemplateDecl + void visitFunctionTemplateDeclAttrs(FunctionTemplateDecl *D) { + visitRedeclarableAttrs(D); + } + void visitFunctionTemplateDeclChildren(FunctionTemplateDecl *D) { + // Mention all the specializations which don't have explicit + // declarations elsewhere. + for (FunctionTemplateDecl::spec_iterator + I = D->spec_begin(), E = D->spec_end(); I != E; ++I) { + FunctionTemplateSpecializationInfo *Info + = I->getTemplateSpecializationInfo(); + + bool Unknown = false; + switch (Info->getTemplateSpecializationKind()) { + case TSK_ImplicitInstantiation: Unknown = false; break; + case TSK_Undeclared: Unknown = true; break; + + // These will be covered at their respective sites. + case TSK_ExplicitSpecialization: continue; + case TSK_ExplicitInstantiationDeclaration: continue; + case TSK_ExplicitInstantiationDefinition: continue; + } + + TemporaryContainer C(*this, + Unknown ? "uninstantiated" : "instantiation"); + visitTemplateArguments(*Info->TemplateArguments); + dispatch(Info->Function); + } + } + + // ClasTemplateDecl + void visitClassTemplateDeclAttrs(ClassTemplateDecl *D) { + visitRedeclarableAttrs(D); + } + void visitClassTemplateDeclChildren(ClassTemplateDecl *D) { + // Mention all the specializations which don't have explicit + // declarations elsewhere. + for (ClassTemplateDecl::spec_iterator + I = D->spec_begin(), E = D->spec_end(); I != E; ++I) { + + bool Unknown = false; + switch (I->getTemplateSpecializationKind()) { + case TSK_ImplicitInstantiation: Unknown = false; break; + case TSK_Undeclared: Unknown = true; break; + + // These will be covered at their respective sites. + case TSK_ExplicitSpecialization: continue; + case TSK_ExplicitInstantiationDeclaration: continue; + case TSK_ExplicitInstantiationDefinition: continue; + } + + TemporaryContainer C(*this, + Unknown ? "uninstantiated" : "instantiation"); + visitTemplateArguments(I->getTemplateArgs()); + dispatch(*I); + } + } + + // TemplateTypeParmDecl + void visitTemplateTypeParmDeclAttrs(TemplateTypeParmDecl *D) { + setInteger("depth", D->getDepth()); + setInteger("index", D->getIndex()); + } + void visitTemplateTypeParmDeclChildren(TemplateTypeParmDecl *D) { + if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) + dispatch(D->getDefaultArgumentInfo()->getTypeLoc()); + // parameter pack? + } + + // NonTypeTemplateParmDecl + void visitNonTypeTemplateParmDeclAttrs(NonTypeTemplateParmDecl *D) { + setInteger("depth", D->getDepth()); + setInteger("index", D->getIndex()); + } + void visitNonTypeTemplateParmDeclChildren(NonTypeTemplateParmDecl *D) { + if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) + dispatch(D->getDefaultArgument()); + // parameter pack? + } + + // TemplateTemplateParmDecl + void visitTemplateTemplateParmDeclAttrs(TemplateTemplateParmDecl *D) { + setInteger("depth", D->getDepth()); + setInteger("index", D->getIndex()); + } + void visitTemplateTemplateParmDeclChildren(TemplateTemplateParmDecl *D) { + if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) + dispatch(D->getDefaultArgument()); + // parameter pack? + } + + // FriendDecl + void visitFriendDeclChildren(FriendDecl *D) { + if (TypeSourceInfo *T = D->getFriendType()) + dispatch(T->getTypeLoc()); + else + dispatch(D->getFriendDecl()); + } + + // UsingDirectiveDecl ? + // UsingDecl ? + // UsingShadowDecl ? + // NamespaceAliasDecl ? + // UnresolvedUsingValueDecl ? + // UnresolvedUsingTypenameDecl ? + // StaticAssertDecl ? + + // ObjCImplDecl + void visitObjCImplDeclChildren(ObjCImplDecl *D) { + visitDeclRef(D->getClassInterface()); + } + void visitObjCImplDeclAsContext(ObjCImplDecl *D) { + visitDeclContext(D); + } + + // ObjCInterfaceDecl + void visitCategoryList(ObjCCategoryDecl *D) { + if (!D) return; + + TemporaryContainer C(*this, "categories"); + for (; D; D = D->getNextClassCategory()) + visitDeclRef(D); + } + void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) { + setPointer("typeptr", D->getTypeForDecl()); + setFlag("forward_decl", !D->isThisDeclarationADefinition()); + setFlag("implicit_interface", D->isImplicitInterfaceDecl()); + } + void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) { + visitDeclRef("super", D->getSuperClass()); + visitDeclRef("implementation", D->getImplementation()); + if (D->protocol_begin() != D->protocol_end()) { + TemporaryContainer C(*this, "protocols"); + for (ObjCInterfaceDecl::protocol_iterator + I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) + visitDeclRef(*I); + } + visitCategoryList(D->getCategoryList()); + } + void visitObjCInterfaceDeclAsContext(ObjCInterfaceDecl *D) { + visitDeclContext(D); + } + + // ObjCCategoryDecl + void visitObjCCategoryDeclAttrs(ObjCCategoryDecl *D) { + setFlag("extension", D->IsClassExtension()); + setFlag("synth_bitfield", D->hasSynthBitfield()); + } + void visitObjCCategoryDeclChildren(ObjCCategoryDecl *D) { + visitDeclRef("interface", D->getClassInterface()); + visitDeclRef("implementation", D->getImplementation()); + if (D->protocol_begin() != D->protocol_end()) { + TemporaryContainer C(*this, "protocols"); + for (ObjCCategoryDecl::protocol_iterator + I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) + visitDeclRef(*I); + } + } + void visitObjCCategoryDeclAsContext(ObjCCategoryDecl *D) { + visitDeclContext(D); + } + + // ObjCCategoryImplDecl + void visitObjCCategoryImplDeclAttrs(ObjCCategoryImplDecl *D) { + set("identifier", D->getName()); + } + void visitObjCCategoryImplDeclChildren(ObjCCategoryImplDecl *D) { + visitDeclRef(D->getCategoryDecl()); + } + + // ObjCImplementationDecl + void visitObjCImplementationDeclAttrs(ObjCImplementationDecl *D) { + setFlag("synth_bitfield", D->hasSynthBitfield()); + set("identifier", D->getName()); + } + void visitObjCImplementationDeclChildren(ObjCImplementationDecl *D) { + visitDeclRef("super", D->getSuperClass()); + if (D->init_begin() != D->init_end()) { + TemporaryContainer C(*this, "initializers"); + for (ObjCImplementationDecl::init_iterator + I = D->init_begin(), E = D->init_end(); I != E; ++I) + dispatch(*I); + } + } + + // ObjCProtocolDecl + void visitObjCProtocolDeclChildren(ObjCProtocolDecl *D) { + if (!D->isThisDeclarationADefinition()) + return; + + if (D->protocol_begin() != D->protocol_end()) { + TemporaryContainer C(*this, "protocols"); + for (ObjCInterfaceDecl::protocol_iterator + I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) + visitDeclRef(*I); + } + } + void visitObjCProtocolDeclAsContext(ObjCProtocolDecl *D) { + if (!D->isThisDeclarationADefinition()) + return; + + visitDeclContext(D); + } + + // ObjCMethodDecl + void visitObjCMethodDeclAttrs(ObjCMethodDecl *D) { + // decl qualifier? + // implementation control? + + setFlag("instance", D->isInstanceMethod()); + setFlag("variadic", D->isVariadic()); + setFlag("synthesized", D->isSynthesized()); + setFlag("defined", D->isDefined()); + setFlag("related_result_type", D->hasRelatedResultType()); + } + void visitObjCMethodDeclChildren(ObjCMethodDecl *D) { + dispatch(D->getResultType()); + for (ObjCMethodDecl::param_iterator + I = D->param_begin(), E = D->param_end(); I != E; ++I) + dispatch(*I); + if (D->isThisDeclarationADefinition()) + dispatch(D->getBody()); + } + + // ObjCIvarDecl + void setAccessControl(StringRef prop, ObjCIvarDecl::AccessControl AC) { + switch (AC) { + case ObjCIvarDecl::None: return set(prop, "none"); + case ObjCIvarDecl::Private: return set(prop, "private"); + case ObjCIvarDecl::Protected: return set(prop, "protected"); + case ObjCIvarDecl::Public: return set(prop, "public"); + case ObjCIvarDecl::Package: return set(prop, "package"); + } + } + void visitObjCIvarDeclAttrs(ObjCIvarDecl *D) { + setFlag("synthesize", D->getSynthesize()); + setAccessControl("access", D->getAccessControl()); + } + + // ObjCCompatibleAliasDecl + void visitObjCCompatibleAliasDeclChildren(ObjCCompatibleAliasDecl *D) { + visitDeclRef(D->getClassInterface()); + } + + // FIXME: ObjCPropertyDecl + // FIXME: ObjCPropertyImplDecl + + //---- Types -----------------------------------------------------// + void dispatch(TypeLoc TL) { + dispatch(TL.getType()); // for now + } + + void dispatch(QualType T) { + if (T.hasLocalQualifiers()) { + push("QualType"); + Qualifiers Qs = T.getLocalQualifiers(); + setFlag("const", Qs.hasConst()); + setFlag("volatile", Qs.hasVolatile()); + setFlag("restrict", Qs.hasRestrict()); + if (Qs.hasAddressSpace()) setInteger("addrspace", Qs.getAddressSpace()); + if (Qs.hasObjCGCAttr()) { + switch (Qs.getObjCGCAttr()) { + case Qualifiers::Weak: set("gc", "weak"); break; + case Qualifiers::Strong: set("gc", "strong"); break; + case Qualifiers::GCNone: llvm_unreachable("explicit none"); + } + } + + completeAttrs(); + dispatch(QualType(T.getTypePtr(), 0)); + pop(); + return; + } + + Type *Ty = const_cast<Type*>(T.getTypePtr()); + push(getTypeKindName(Ty)); + XMLTypeVisitor<XMLDumper>::dispatch(const_cast<Type*>(T.getTypePtr())); + pop(); + } + + void setCallingConv(CallingConv CC) { + switch (CC) { + case CC_Default: return; + case CC_C: return set("cc", "cdecl"); + case CC_X86FastCall: return set("cc", "x86_fastcall"); + case CC_X86StdCall: return set("cc", "x86_stdcall"); + case CC_X86ThisCall: return set("cc", "x86_thiscall"); + case CC_X86Pascal: return set("cc", "x86_pascal"); + case CC_AAPCS: return set("cc", "aapcs"); + case CC_AAPCS_VFP: return set("cc", "aapcs_vfp"); + } + } + + void visitTypeAttrs(Type *D) { + setPointer(D); + setFlag("dependent", D->isDependentType()); + setFlag("variably_modified", D->isVariablyModifiedType()); + + setPointer("canonical", D->getCanonicalTypeInternal().getAsOpaquePtr()); + } + + void visitPointerTypeChildren(PointerType *T) { + dispatch(T->getPointeeType()); + } + void visitReferenceTypeChildren(ReferenceType *T) { + dispatch(T->getPointeeType()); + } + void visitObjCObjectPointerTypeChildren(ObjCObjectPointerType *T) { + dispatch(T->getPointeeType()); + } + void visitBlockPointerTypeChildren(BlockPointerType *T) { + dispatch(T->getPointeeType()); + } + + // Types that just wrap declarations. + void visitTagTypeChildren(TagType *T) { + visitDeclRef(T->getDecl()); + } + void visitTypedefTypeChildren(TypedefType *T) { + visitDeclRef(T->getDecl()); + } + void visitObjCInterfaceTypeChildren(ObjCInterfaceType *T) { + visitDeclRef(T->getDecl()); + } + void visitUnresolvedUsingTypeChildren(UnresolvedUsingType *T) { + visitDeclRef(T->getDecl()); + } + void visitInjectedClassNameTypeChildren(InjectedClassNameType *T) { + visitDeclRef(T->getDecl()); + } + + void visitFunctionTypeAttrs(FunctionType *T) { + setFlag("noreturn", T->getNoReturnAttr()); + setCallingConv(T->getCallConv()); + if (T->getHasRegParm()) setInteger("regparm", T->getRegParmType()); + } + void visitFunctionTypeChildren(FunctionType *T) { + dispatch(T->getResultType()); + } + + void visitFunctionProtoTypeAttrs(FunctionProtoType *T) { + setFlag("const", T->getTypeQuals() & Qualifiers::Const); + setFlag("volatile", T->getTypeQuals() & Qualifiers::Volatile); + setFlag("restrict", T->getTypeQuals() & Qualifiers::Restrict); + } + void visitFunctionProtoTypeChildren(FunctionProtoType *T) { + push("parameters"); + setFlag("variadic", T->isVariadic()); + completeAttrs(); + for (FunctionProtoType::arg_type_iterator + I = T->arg_type_begin(), E = T->arg_type_end(); I != E; ++I) + dispatch(*I); + pop(); + + if (T->hasDynamicExceptionSpec()) { + push("exception_specifiers"); + setFlag("any", T->getExceptionSpecType() == EST_MSAny); + completeAttrs(); + for (FunctionProtoType::exception_iterator + I = T->exception_begin(), E = T->exception_end(); I != E; ++I) + dispatch(*I); + pop(); + } + // FIXME: noexcept specifier + } + + void visitTemplateSpecializationTypeChildren(TemplateSpecializationType *T) { + if (const RecordType *RT = T->getAs<RecordType>()) + visitDeclRef(RT->getDecl()); + + // TODO: TemplateName + + push("template_arguments"); + completeAttrs(); + for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I) + dispatch(T->getArg(I)); + pop(); + } + + //---- Statements ------------------------------------------------// + void dispatch(Stmt *S) { + // FIXME: this is not really XML at all + push("Stmt"); + out << ">\n"; + Stack.back().State = NS_Children; // explicitly become non-lazy + S->dump(out, Context.getSourceManager()); + out << '\n'; + pop(); + } +}; +} + +void Decl::dumpXML() const { + dumpXML(llvm::errs()); +} + +void Decl::dumpXML(raw_ostream &out) const { + XMLDumper(out, getASTContext()).dispatch(const_cast<Decl*>(this)); +} + +#else /* ifndef NDEBUG */ + +void Decl::dumpXML() const {} +void Decl::dumpXML(raw_ostream &out) const {} + +#endif |