diff options
| -rw-r--r-- | clang/lib/AST/DumpXML.cpp | 861 | 
1 files changed, 861 insertions, 0 deletions
diff --git a/clang/lib/AST/DumpXML.cpp b/clang/lib/AST/DumpXML.cpp new file mode 100644 index 00000000000..127d18d8729 --- /dev/null +++ b/clang/lib/AST/DumpXML.cpp @@ -0,0 +1,861 @@ +//===--- 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/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +using namespace clang; + +#ifndef NDEBUG + +namespace { + +enum NodeState { +  NS_Attrs, NS_LazyChildren, NS_Children +}; + +struct Node { +  llvm::StringRef Name; +  NodeState State; +  Node(llvm::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()) { +      default: llvm_unreachable("Decl that isn't part of DeclNodes.inc!"); +#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()) { +      default: llvm_unreachable("Type that isn't part of TypeNodes.inc!"); +#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 llvm::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!"); +  return "unknown_type"; +} + +struct XMLDumper : public XMLDeclVisitor<XMLDumper>, +                   public XMLTypeVisitor<XMLDumper> { +  llvm::raw_ostream &out; +  ASTContext &Context; +  llvm::SmallVector<Node, 16> Stack; +  unsigned Indent; +  explicit XMLDumper(llvm::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(llvm::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(llvm::StringRef attr, llvm::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(llvm::StringRef prop, void *p) { +    llvm::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(llvm::StringRef prop, const llvm::APSInt &v) { +    set(prop, v.toString(10)); +  } + +  void setInteger(llvm::StringRef prop, unsigned n) { +    llvm::SmallString<10> buffer; +    llvm::raw_svector_ostream os(buffer); +    os << n; +    os.flush(); +    set(prop, buffer); +  } + +  void setFlag(llvm::StringRef prop, bool flag) { +    if (flag) set(prop, "true"); +  } + +  void setName(DeclarationName Name) { +    // Common case. +    if (Name.isIdentifier()) +      return set("name", Name.getAsIdentifierInfo()->getName()); + +    set("name", "<unsupported>"); +  } + +  class TemporaryContainer { +    XMLDumper &Dumper; +  public: +    TemporaryContainer(XMLDumper &dumper, llvm::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 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::Declaration: { +      visitDeclRef(A.getAsDecl()); +      break; +    } +    case TemplateArgument::Integral: { +      push("integer"); +      setInteger("value", *A.getAsIntegral()); +      completeAttrs(); +      pop(); +      break; +    } +    case TemplateArgument::Expression: { +      dispatch(A.getAsExpr()); +      break; +    } +    case TemplateArgument::Pack: { +      // TODO +      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::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->getPreviousDeclaration()) +      setPointer("previous", Prev); +  } + + +  // TranslationUnitDecl +  void visitTranslationUnitDeclAsContext(TranslationUnitDecl *D) { +    visitDeclContext(D); +  } + +  // LinkageSpecDecl +  void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) { +    llvm::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())); +    setFlag("directinit", D->hasCXXDirectInitializer()); +    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->isDeleted()); +    if (D->getStorageClass() != SC_None) +      set("storage", +          VarDecl::getStorageClassSpecifierString(D->getStorageClass())); +    setFlag("inline", D->isInlineSpecified()); +    // TODO: instantiation, etc. +  } +  void visitFunctionDeclChildren(FunctionDecl *D) { +    for (FunctionDecl::param_iterator +           I = D->param_begin(), E = D->param_end(); I != E; ++I) +      dispatch(*I); +    if (D->isThisDeclarationADefinition()) +      dispatch(D->getBody()); +  } + +  // CXXMethodDecl ? +  // CXXConstructorDecl ? +  // CXXDestructorDecl ? +  // CXXConversionDecl ? + +  // 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(D); +  } +  void visitTypedefDeclChildren(TypedefDecl *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()); +    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 ? + +  //---- 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::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"); +    } +  } + +  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->getRegParmType()) 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->hasExceptionSpec()) { +      push("exception_specifiers"); +      setFlag("any", T->hasAnyExceptionSpec()); +      completeAttrs(); +      for (FunctionProtoType::exception_iterator +             I = T->exception_begin(), E = T->exception_end(); I != E; ++I) +        dispatch(*I); +      pop(); +    } +  } + +  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(llvm::raw_ostream &out) const { +  XMLDumper(out, getASTContext()).dispatch(const_cast<Decl*>(this)); +} + +#else /* ifndef NDEBUG */ + +void Decl::dumpXML() const {} +void Decl::dumpXML(llvm::raw_ostream &out) const {} + +#endif  | 

