forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			1022 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			1022 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C++
		
	
	
	
//===--- 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) {
 | 
						|
    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, 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 visitDeclRef(llvm::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::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<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->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 ?
 | 
						|
 | 
						|
  void dispatch(CXXBaseOrMemberInitializer *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(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 ?
 | 
						|
 | 
						|
  // ObjCImplDecl
 | 
						|
  void visitObjCImplDeclChildren(ObjCImplDecl *D) {
 | 
						|
    visitDeclRef(D->getClassInterface());
 | 
						|
  }
 | 
						|
  void visitObjCImplDeclAsContext(ObjCImplDecl *D) {
 | 
						|
    visitDeclContext(D);
 | 
						|
  }
 | 
						|
 | 
						|
  // ObjCClassDecl
 | 
						|
  void visitObjCClassDeclChildren(ObjCClassDecl *D) {
 | 
						|
    for (ObjCClassDecl::iterator I = D->begin(), E = D->end(); I != E; ++I)
 | 
						|
      visitDeclRef(I->getInterface());
 | 
						|
  }
 | 
						|
 | 
						|
  // 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->isForwardDecl());
 | 
						|
    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);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // ObjCForwardProtocolDecl
 | 
						|
  void visitObjCForwardProtocolDeclChildren(ObjCForwardProtocolDecl *D) {
 | 
						|
    for (ObjCForwardProtocolDecl::protocol_iterator
 | 
						|
           I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
 | 
						|
      visitDeclRef(*I);
 | 
						|
  }
 | 
						|
 | 
						|
  // ObjCProtocolDecl
 | 
						|
  void visitObjCProtocolDeclAttrs(ObjCProtocolDecl *D) {
 | 
						|
    setFlag("forward_decl", D->isForwardDecl());
 | 
						|
  }
 | 
						|
  void visitObjCProtocolDeclChildren(ObjCProtocolDecl *D) {
 | 
						|
    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) {
 | 
						|
    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());
 | 
						|
  }
 | 
						|
  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(llvm::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");
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  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
 |