Index: include/clang/AST/DocumentXML.h
===================================================================
--- include/clang/AST/DocumentXML.h	(revision 0)
+++ include/clang/AST/DocumentXML.h	(revision 0)
@@ -0,0 +1,155 @@
+//===--- DocumentXML.cpp - XML document for ASTs --------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Stmt::dump/Stmt::print methods, which dump out the
+// AST in a form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_DOCUMENTXML_H
+#define LLVM_CLANG_DOCUMENTXML_H
+
+#include <string>
+#include <vector>
+#include <map>
+#include "clang/AST/Type.h"
+
+//--------------------------------------------------------- forwards
+namespace llvm { class raw_ostream; }
+
+namespace clang {
+
+class DeclContext;
+class Decl;
+class NamedDecl;
+class FunctionDecl;
+class ASTContext;
+ 
+//--------------------------------------------------------- 
+struct AttributeXML
+{
+  const char*               Name;
+  std::string               Value;
+  AttributeXML(const char* pName, const std::string& value);
+  AttributeXML(const char* pName, unsigned value);
+};
+
+//--------------------------------------------------------- 
+class NodeXML
+{
+public:
+  std::string               Name;
+  std::vector<AttributeXML> Attributes;
+  std::vector<NodeXML*>     SubNodes;
+  NodeXML*                  Parent;
+
+  NodeXML(const std::string& name, NodeXML* parent = 0);
+  ~NodeXML();
+
+  NodeXML* addSubNode(const std::string& name);
+  void print(llvm::raw_ostream& out, int ident);
+
+private:
+  NodeXML(const NodeXML&);              // not defined
+  NodeXML& operator=(const NodeXML&);   // not defined
+};
+
+
+//--------------------------------------------------------- 
+class DocumentXML
+{
+public:
+  DocumentXML(const std::string& rootName);
+
+  void initialize(ASTContext &Context);
+  void PrintDecl(Decl *D);
+  void print(llvm::raw_ostream& out);
+
+
+  DocumentXML& addSubNode(const std::string& name);   // also enters the sub node, returns *this
+  DocumentXML& toParent();                            // returns *this
+
+  template<class T>
+  void addAttribute(const char* pName, const T& value);
+  
+  void addTypeAttribute(const QualType& pType);  
+  void addRefAttribute(const NamedDecl* D);
+
+  enum tContextUsage { CONTEXT_AS_CONTEXT, CONTEXT_AS_ID };
+  void addContextAttribute(const DeclContext *DC, tContextUsage usage = CONTEXT_AS_CONTEXT);
+  void addSourceFileAttribute(const std::string& fileName);
+
+  PresumedLoc addLocation(const SourceLocation& Loc);
+  void addLocationRange(const SourceRange& R);
+
+  static std::string escapeString(const char* pStr, std::string::size_type len);
+
+private:
+  DocumentXML(const DocumentXML&);              // not defined
+  DocumentXML& operator=(const DocumentXML&);   // not defined
+
+  NodeXML   Root;
+  NodeXML*  CurrentNode;   
+  ASTContext *Ctx;
+
+  struct order_QualType
+  {
+    bool operator()(const QualType& t1, const QualType& t2) const;
+  };
+
+  // id maps:
+  std::map<QualType, std::string, order_QualType> Types;
+  std::map<const DeclContext*, std::string>       Contexts;
+  std::map<const Type*, std::string>              BasicTypes;
+  std::map<std::string, std::string>              SourceFiles;
+  std::map<const NamedDecl*, std::string>         Decls;
+
+  void addContextsRecursively(const DeclContext *DC);
+  void addBasicTypeRecursively(const Type* pType);
+  void addTypeRecursively(const QualType& pType);
+
+  void PrintFunctionDecl(FunctionDecl *FD);
+  void addContextWithGivenId(const DeclContext *DC, const std::string& id);
+  void addDeclIdAttribute(const NamedDecl* D);
+  const std::string& addTypeIdAttribute(const Type* pType);  
+};
+
+//--------------------------------------------------------- inlines
+
+inline void DocumentXML::initialize(ASTContext &Context) 
+{ 
+  Ctx = &Context; 
+}
+
+//--------------------------------------------------------- 
+inline DocumentXML& DocumentXML::toParent() 
+{ 
+  CurrentNode = CurrentNode->Parent; 
+  return *this; 
+}
+
+//--------------------------------------------------------- 
+template<class T>
+inline void DocumentXML::addAttribute(const char* pName, const T& value)
+{
+  CurrentNode->Attributes.push_back(AttributeXML(pName, value));
+}
+
+//--------------------------------------------------------- 
+inline bool DocumentXML::order_QualType::operator()(const QualType& t1, const QualType& t2) const
+{
+  return t1.getTypePtr() < t2.getTypePtr() ||
+         (t1.getTypePtr() == t2.getTypePtr() && t1.getCVRQualifiers() < t2.getCVRQualifiers());
+}
+
+//--------------------------------------------------------- 
+
+} //namespace clang 
+
+#endif //LLVM_CLANG_DOCUMENTXML_H
Index: include/clang/AST/Stmt.h
===================================================================
--- include/clang/AST/Stmt.h	(revision 72107)
+++ include/clang/AST/Stmt.h	(working copy)
@@ -36,7 +36,8 @@
   class StringLiteral;
   class SwitchStmt;
   class PrinterHelper;
-  
+  class DocumentXML;
+
   //===----------------------------------------------------------------------===//
   // ExprIterator - Iterators for iterating over Stmt* arrays that contain
   //  only Expr*.  This is needed because AST nodes use Stmt* arrays to store
@@ -183,6 +184,7 @@
   /// dumpAll - This does a dump of the specified AST fragment and all subtrees.
   void dumpAll() const;
   void dumpAll(SourceManager &SM) const;
+  void dumpXML(DocumentXML &doc) const;
 
   /// dumpPretty/printPretty - These two methods do a "pretty print" of the AST
   /// back to its original source language syntax.
Index: include/clang/Basic/FileManager.h
===================================================================
--- include/clang/Basic/FileManager.h	(revision 72107)
+++ include/clang/Basic/FileManager.h	(working copy)
@@ -24,6 +24,9 @@
 // FIXME: Enhance libsystem to support inode and other fields in stat.
 #include <sys/types.h>
 #include <sys/stat.h>
+#ifndef mode_t
+typedef unsigned short mode_t;
+#endif
 
 namespace clang {
 class FileManager;
Index: include/clang/Frontend/ASTConsumers.h
===================================================================
--- include/clang/Frontend/ASTConsumers.h	(revision 72107)
+++ include/clang/Frontend/ASTConsumers.h	(working copy)
@@ -38,6 +38,12 @@
 // implementation is still incomplete.
 ASTConsumer *CreateASTPrinter(llvm::raw_ostream* OS);
 
+// AST XML-printer: prints out the AST in a XML format 
+// The output is intended to be in a format such that
+// clang or any other tool could re-parse the output back into the same AST, 
+// but the implementation is still incomplete.
+ASTConsumer *CreateASTPrinterXML();
+
 // AST dumper: dumps the raw AST in human-readable form to stderr; this is
 // intended for debugging. A normal dump is done with FullDump = false;
 // with FullDump = true, the dumper waits until the end of the translation
Index: lib/AST/CMakeLists.txt
===================================================================
--- lib/AST/CMakeLists.txt	(revision 72107)
+++ lib/AST/CMakeLists.txt	(working copy)
@@ -13,6 +13,7 @@
   DeclGroup.cpp
   DeclObjC.cpp
   DeclTemplate.cpp
+  DocumentXML.cpp
   ExprConstant.cpp
   Expr.cpp
   ExprCXX.cpp
@@ -24,6 +25,7 @@
   StmtIterator.cpp
   StmtPrinter.cpp
   StmtViz.cpp
+  StmtXML.cpp
   TemplateName.cpp
   Type.cpp
   )
Index: lib/AST/DocumentXML.cpp
===================================================================
--- lib/AST/DocumentXML.cpp	(revision 0)
+++ lib/AST/DocumentXML.cpp	(revision 0)
@@ -0,0 +1,570 @@
+//===--- StmtXML.cpp - Dumping implementation for Stmt ASTs ------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Stmt::dump/Stmt::print methods, which dump out the
+// AST in a form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/DocumentXML.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang {
+
+//--------------------------------------------------------- 
+AttributeXML::AttributeXML(const char* pName, const std::string& value) :
+  Name(pName),
+  Value(value)
+{}
+
+//--------------------------------------------------------- 
+AttributeXML::AttributeXML(const char* pName, unsigned value) :
+  Name(pName)
+{
+  char buffer[32];
+  Value = _ultoa(value, buffer, 10);
+}
+
+//--------------------------------------------------------- 
+NodeXML::NodeXML(const std::string& name, NodeXML* parent) :
+  Name(name),
+  Parent(parent)
+{}
+
+//--------------------------------------------------------- 
+NodeXML* NodeXML::addSubNode(const std::string& name)
+{
+  NodeXML* result = new NodeXML(name, this);
+  SubNodes.push_back(result);
+  return result;
+}
+
+//--------------------------------------------------------- 
+NodeXML::~NodeXML()
+{
+  for (std::vector<NodeXML*>::iterator i = SubNodes.begin(), e = SubNodes.end(); i != e; ++i)
+    delete *i;
+}
+
+//--------------------------------------------------------- 
+void NodeXML::print(llvm::raw_ostream& out, int ident)
+{
+  for (int i = 0; i < ident; ++i)
+    out << ' ';
+ 
+  out << '<' << Name;
+  for (std::vector<AttributeXML>::iterator i = Attributes.begin(), e = Attributes.end(); i != e; ++i)
+  {
+    out << ' ' << i->Name << "=\"" << i->Value << "\"";
+  }
+
+  if (SubNodes.empty())
+  {
+    out << "/>\n";
+  }
+  else
+  {
+    out << ">\n";
+    for (std::vector<NodeXML*>::iterator i = SubNodes.begin(), e = SubNodes.end(); i != e; ++i)
+    {
+      (*i)->print(out, ident + 2);
+    }
+    for (int i = 0; i < ident; ++i)
+      out << ' ';
+    out << "</" << Name << ">\n";
+  }
+}
+
+//--------------------------------------------------------- 
+DocumentXML::DocumentXML(const std::string& rootName) :
+  Root(rootName),
+  CurrentNode(&Root),
+  Ctx(0)
+{}
+
+//--------------------------------------------------------- 
+DocumentXML& DocumentXML::addSubNode(const std::string& name)
+{
+  CurrentNode = CurrentNode->addSubNode(name);
+  return *this;
+}
+
+//--------------------------------------------------------- 
+namespace {
+
+enum tIdType { ID_NORMAL, ID_FILE, ID_LAST };
+
+std::string getNewId(tIdType idType)
+{
+  static unsigned int idCounts[ID_LAST] = { 0 };
+  static const char idPrefix[ID_LAST] = { '_', 'f' };
+  char buffer[33];
+  _ultoa(++idCounts[idType], buffer + 1, 10);
+  buffer[0] = idPrefix[idType];
+  return buffer;
+}
+
+//--------------------------------------------------------- 
+template<class T, class U, class V>
+bool addToMap(std::map<T, std::string, U>& idMap, const V& value, tIdType idType = ID_NORMAL)
+{
+  std::map<T, std::string, U>::iterator i = idMap.find(value);
+  bool toAdd = i == idMap.end();
+  if (toAdd) 
+  {
+    idMap.insert(std::map<T, std::string, U>::value_type(value, getNewId(idType)));
+  }
+  return toAdd;
+}
+
+} // anon NS
+
+//--------------------------------------------------------- 
+std::string DocumentXML::escapeString(const char* pStr, std::string::size_type len)
+{
+  std::string value;
+  value.reserve(len + 1);
+  char buffer[16];
+  for (unsigned i = 0; i < len; ++i) {
+    switch (char C = pStr[i]) {
+    default:
+      if (isprint(C))
+        value += C;
+      else
+      {
+        sprintf(buffer, "\\%03o", C);
+        value += buffer;
+      }
+      break;
+
+    case '\n': value += "\\n"; break;
+    case '\t': value += "\\t"; break;
+    case '\a': value += "\\a"; break;
+    case '\b': value += "\\b"; break;
+    case '\r': value += "\\r"; break;
+
+    case '&': value += "&amp;"; break;
+    case '<': value += "&lt;"; break;
+    case '>': value += "&gt;"; break;
+    case '"': value += "&quot;"; break;
+    case '\'':  value += "&apos;"; break;
+
+    }
+  }
+  return value;
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::print(llvm::raw_ostream& out)
+{
+  assert(CurrentNode == &Root && "not completely backtracked");
+
+  addSubNode("ReferenceSection");
+  addSubNode("Types");
+
+  for (std::map<QualType, std::string, order_QualType>::const_iterator i = Types.begin(), e = Types.end(); i != e; ++i)
+  {
+    if (i->first.getCVRQualifiers() != 0)
+    {
+      addSubNode("CvQualifiedType");
+      addAttribute("id", i->second);
+      addAttribute("type", BasicTypes[i->first.getTypePtr()]);
+      if (i->first.isConstQualified()) addAttribute("const", "1");
+      if (i->first.isVolatileQualified()) addAttribute("volatile", "1");
+      if (i->first.isRestrictQualified()) addAttribute("restrict", "1");
+      toParent();
+    }
+  }
+
+  for (std::map<const Type*, std::string>::const_iterator i = BasicTypes.begin(), e = BasicTypes.end(); i != e; ++i)
+  {
+    // don't use the get methods as they strip of typedef infos
+    if (const BuiltinType *BT = dyn_cast<BuiltinType>(i->first)) {
+      addSubNode("FundamentalType");
+      addAttribute("name", BT->getName());
+    }
+    else if (const PointerType *PT = dyn_cast<PointerType>(i->first)) {
+      addSubNode("PointerType");
+      addTypeAttribute(PT->getPointeeType());
+    }
+    else if (const FunctionType *FT = dyn_cast<FunctionType>(i->first)) {
+      addSubNode("FunctionType");
+    }
+    else if (const ReferenceType *RT = dyn_cast<ReferenceType>(i->first)) {
+      addSubNode("ReferenceType");
+      addTypeAttribute(RT->getPointeeType());
+    }
+    else if (const TypedefType * TT = dyn_cast<TypedefType>(i->first)) {
+      addSubNode("Typedef");
+      addAttribute("name", TT->getDecl()->getNameAsString());
+      addTypeAttribute(TT->getDecl()->getUnderlyingType());
+      addContextAttribute(TT->getDecl()->getDeclContext());
+    }
+    else if (const QualifiedNameType *QT = dyn_cast<QualifiedNameType>(i->first)) {
+      addSubNode("QualifiedNameType");
+      addTypeAttribute(QT->getNamedType());
+    }
+    else if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(i->first)) {
+      addSubNode("ArrayType");
+      addAttribute("min", 0);
+      addAttribute("max", (CAT->getSize() - 1).toString(10, false));
+      addTypeAttribute(CAT->getElementType());
+    }
+    else if (const TagType *RET = dyn_cast<TagType>(i->first)) {
+      const TagDecl *tagDecl = RET->getDecl();
+      std::string tagKind = tagDecl->getKindName();
+      tagKind[0] = std::toupper(tagKind[0]);
+      addSubNode(tagKind);
+      addAttribute("name", tagDecl->getNameAsString());
+      addContextAttribute(tagDecl->getDeclContext());
+    }
+    else 
+    {
+      addSubNode("FIXMEType");
+    }
+    addAttribute("id", i->second);
+    toParent();
+  }
+
+
+  toParent().addSubNode("Contexts");
+
+  for (std::map<const DeclContext*, std::string>::const_iterator i = Contexts.begin(), e = Contexts.end(); i != e; ++i)
+  {
+    addSubNode(i->first->getDeclKindName());
+    addAttribute("id", i->second);
+    if (const NamedDecl *ND = dyn_cast<NamedDecl>(i->first)) {
+      addAttribute("name", ND->getNameAsString());
+    }
+    if (const TagDecl *TD = dyn_cast<TagDecl>(i->first)) {
+      addAttribute("type", BasicTypes[TD->getTypeForDecl()]);
+    }
+    else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(i->first)) {
+      addAttribute("type", BasicTypes[FD->getType()->getAsFunctionType()]);
+    }
+
+    if (const DeclContext* parent = i->first->getParent())
+    {
+      addContextAttribute(parent);
+    } 
+    toParent();
+  }
+
+  toParent().addSubNode("Files");
+
+  for (std::map<std::string, std::string>::const_iterator i = SourceFiles.begin(), e = SourceFiles.end(); i != e; ++i)
+  {
+    addSubNode("File");
+    addAttribute("id", i->second);
+    addAttribute("name", escapeString(i->first.c_str(), i->first.size()));
+    toParent();
+  }
+
+  toParent();
+
+  out << "<?xml version=\"1.0\"?>\n";
+  Root.print(out, 0);
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::addTypeAttribute(const QualType& pType)
+{
+  addTypeRecursively(pType);
+  addAttribute("type", Types[pType]);
+}
+
+//--------------------------------------------------------- 
+const std::string& DocumentXML::addTypeIdAttribute(const Type* pType)
+{
+  addBasicTypeRecursively(pType);
+  const std::string& result = BasicTypes[pType];
+  addAttribute("id", result);
+  return result;
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::addTypeRecursively(const QualType& pType)
+{
+  if (addToMap(Types, pType))
+  {
+    addBasicTypeRecursively(pType.getTypePtr());
+    // beautifier: a non-qualified type shall be transparent
+    if (pType.getCVRQualifiers() == 0)
+    {
+      Types[pType] = BasicTypes[pType.getTypePtr()];   
+    }
+  }
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::addBasicTypeRecursively(const Type* pType)
+{
+  if (addToMap(BasicTypes, pType))
+  {
+    if (const PointerType *PT = dyn_cast<PointerType>(pType)) {
+      addTypeRecursively(PT->getPointeeType());
+    }
+    else if (const ReferenceType *RT = dyn_cast<ReferenceType>(pType)) {
+      addTypeRecursively(RT->getPointeeType());
+    }
+    else if (const TypedefType *TT = dyn_cast<TypedefType>(pType)) {
+      addTypeRecursively(TT->getDecl()->getUnderlyingType());
+      addContextsRecursively(TT->getDecl()->getDeclContext());
+    }
+    else if (const QualifiedNameType *QT = dyn_cast<QualifiedNameType>(pType)) {
+      addTypeRecursively(QT->getNamedType());
+      // FIXME: what to do with NestedNameSpecifier or shall this type be transparent?
+    }
+    else if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(pType)) {
+      addTypeRecursively(CAT->getElementType());
+    }
+  }
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::addContextAttribute(const DeclContext *DC, tContextUsage usage)
+{
+  addContextsRecursively(DC);
+  const char* pAttributeTags[2] = { "context", "id" };
+  addAttribute(pAttributeTags[usage], Contexts[DC]);
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::addContextsRecursively(const DeclContext *DC)
+{
+  if (DC != 0 && addToMap(Contexts, DC))
+  {
+    addContextsRecursively(DC->getParent());
+  } 
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::addContextWithGivenId(const DeclContext *DC, const std::string& id)
+{
+  if (Contexts.find(DC) == Contexts.end())
+  {
+    Contexts[DC] = id;
+    addContextsRecursively(DC->getParent());
+  } 
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::addSourceFileAttribute(const std::string& fileName)
+{
+  addToMap(SourceFiles, fileName, ID_FILE);
+  addAttribute("file", SourceFiles[fileName]);
+}
+
+//--------------------------------------------------------- 
+PresumedLoc DocumentXML::addLocation(const SourceLocation& Loc)
+{
+  SourceManager& SM = Ctx->getSourceManager();
+  SourceLocation SpellingLoc = SM.getSpellingLoc(Loc);
+  PresumedLoc PLoc;
+  if (!SpellingLoc.isInvalid()) 
+  {
+    PLoc = SM.getPresumedLoc(SpellingLoc);
+    addSourceFileAttribute(PLoc.getFilename());
+    addAttribute("line", PLoc.getLine());
+    addAttribute("col", PLoc.getColumn());
+  }
+  // else there is no error in some cases (eg. CXXThisExpr)
+  return PLoc;
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::addLocationRange(const SourceRange& R)
+{
+  PresumedLoc PStartLoc = addLocation(R.getBegin());
+  if (R.getBegin() != R.getEnd()) 
+  {
+    SourceManager& SM = Ctx->getSourceManager();
+    SourceLocation SpellingLoc = SM.getSpellingLoc(R.getEnd());
+    if (!SpellingLoc.isInvalid()) 
+    {
+      PresumedLoc PLoc = SM.getPresumedLoc(SpellingLoc);
+      if (PStartLoc.isInvalid() || 
+          strcmp(PLoc.getFilename(), PStartLoc.getFilename()) != 0) {
+        addToMap(SourceFiles, PLoc.getFilename(), ID_FILE);
+        addAttribute("endfile", PLoc.getFilename());
+        addAttribute("endline", PLoc.getLine());
+        addAttribute("endcol", PLoc.getColumn());
+      } else if (PLoc.getLine() != PStartLoc.getLine()) {
+        addAttribute("endline", PLoc.getLine());
+        addAttribute("endcol", PLoc.getColumn());
+      } else {
+        addAttribute("endcol", PLoc.getColumn());
+      }      
+    }
+  }
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::PrintFunctionDecl(FunctionDecl *FD) 
+{
+  switch (FD->getStorageClass()) {
+  default: assert(0 && "Unknown storage class");
+  case FunctionDecl::None: break;
+  case FunctionDecl::Extern: addAttribute("storage_class", "extern"); break;
+  case FunctionDecl::Static: addAttribute("storage_class", "static"); break;
+  case FunctionDecl::PrivateExtern: addAttribute("storage_class", "__private_extern__"); break;
+  }
+
+  if (FD->isInline())
+    addAttribute("inline", "1");
+  
+  const FunctionType *AFT = FD->getType()->getAsFunctionType();
+  addTypeAttribute(AFT->getResultType());
+  addBasicTypeRecursively(AFT);  
+
+  if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(AFT)) {
+    addAttribute("num_args", FD->getNumParams());
+    for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
+      addSubNode("Argument");
+      ParmVarDecl *argDecl = FD->getParamDecl(i);
+      addAttribute("name", argDecl->getNameAsString());
+      addTypeAttribute(FT->getArgType(i));
+      addDeclIdAttribute(argDecl);
+      if (argDecl->getDefaultArg())
+      {
+        addAttribute("default_arg", "1");
+        argDecl->getDefaultArg()->dumpXML(*this);
+      }
+      toParent();
+    }
+    
+    if (FT->isVariadic()) {
+      addSubNode("Ellipsis").toParent();
+    }
+  } else {
+    assert(isa<FunctionNoProtoType>(AFT));
+  }
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::addRefAttribute(const NamedDecl* D)
+{
+  // FIXME: in case of CXX inline member functions referring to a member defined 
+  // after the function it needs to be tested, if the ids are already there
+  // (should work, but I couldn't test it)
+  if (const DeclContext* DC = dyn_cast<DeclContext>(D))
+  {
+    addAttribute("ref", Contexts[DC]);
+  }
+  else
+  {
+    addAttribute("ref", Decls[D]);
+  }
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::addDeclIdAttribute(const NamedDecl* D)
+{
+  addToMap(Decls, D);
+  addAttribute("id", Decls[D]);
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::PrintDecl(Decl *D)
+{
+  addSubNode(D->getDeclKindName());
+  addContextAttribute(D->getDeclContext());
+  addLocation(D->getLocation());
+  if (DeclContext* DC = dyn_cast<DeclContext>(D))
+  {
+    addContextAttribute(DC, CONTEXT_AS_ID);
+  }
+
+  if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
+    addAttribute("name", ND->getNameAsString());
+
+    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+      PrintFunctionDecl(FD);
+      if (Stmt *Body = FD->getBody(*Ctx)) {
+        addSubNode("Body");
+        Body->dumpXML(*this);
+        toParent();
+      }
+    } else if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
+      addBasicTypeRecursively(RD->getTypeForDecl());
+      addAttribute("type", BasicTypes[RD->getTypeForDecl()]);
+      if (!RD->isDefinition())
+      {
+        addAttribute("forward", "1");
+      }
+
+      for (RecordDecl::field_iterator i = RD->field_begin(*Ctx), e = RD->field_end(*Ctx); i != e; ++i)
+      {
+        PrintDecl(*i);
+      }
+    } else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
+      const QualType& enumType = ED->getIntegerType();
+      if (!enumType.isNull())
+      {
+        addTypeAttribute(enumType);
+        for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(*Ctx), e = ED->enumerator_end(*Ctx); i != e; ++i)
+        {
+          PrintDecl(*i);
+        }
+      }
+    } else if (EnumConstantDecl* ECD = dyn_cast<EnumConstantDecl>(D)) {
+      addTypeAttribute(ECD->getType());
+      addAttribute("value", ECD->getInitVal().toString(10, true));
+      if (ECD->getInitExpr()) 
+      {
+        ECD->getInitExpr()->dumpXML(*this);
+      }
+    } else if (FieldDecl *FdD = dyn_cast<FieldDecl>(D)) {
+      addTypeAttribute(FdD->getType());
+      addDeclIdAttribute(ND);
+      if (FdD->isMutable())
+        addAttribute("mutable", "1");
+      if (FdD->isBitField())
+      {
+        addAttribute("bitfield", "1");
+        FdD->getBitWidth()->dumpXML(*this);
+      }
+    } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
+      addTypeIdAttribute(Ctx->getTypedefType(TD).getTypePtr());
+      addTypeAttribute(TD->getUnderlyingType());
+    } else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
+      addTypeAttribute(VD->getType());
+      addDeclIdAttribute(ND);
+
+      VarDecl *V = dyn_cast<VarDecl>(VD);
+      if (V && V->getStorageClass() != VarDecl::None)
+      {
+        addAttribute("storage_class", VarDecl::getStorageClassSpecifierString(V->getStorageClass()));
+      }
+      
+      if (V && V->getInit()) 
+      {
+        V->getInit()->dumpXML(*this);
+      }
+    }
+  } else if (LinkageSpecDecl* LSD = dyn_cast<LinkageSpecDecl>(D)) {
+    switch (LSD->getLanguage())
+    {
+      case LinkageSpecDecl::lang_c:    addAttribute("lang", "C");  break;
+      case LinkageSpecDecl::lang_cxx:  addAttribute("lang", "CXX");  break;
+      default:                         assert(0 && "Unexpected lang id");
+    }
+  } else {
+    assert(0 && "Unexpected decl");
+  }
+  toParent();
+}
+
+//--------------------------------------------------------- 
+} // NS clang
+
Index: lib/AST/StmtXML.cpp
===================================================================
--- lib/AST/StmtXML.cpp	(revision 0)
+++ lib/AST/StmtXML.cpp	(revision 0)
@@ -0,0 +1,410 @@
+//===--- StmtXML.cpp - Dumping implementation for Stmt ASTs ------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Stmt::dump/Stmt::print methods, which dump out the
+// AST in a form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DocumentXML.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/Compiler.h"
+#include <cstdio>
+using namespace clang;
+
+//===----------------------------------------------------------------------===//
+// StmtXML Visitor
+//===----------------------------------------------------------------------===//
+
+namespace  {
+  class VISIBILITY_HIDDEN StmtXML : public StmtVisitor<StmtXML> {
+    DocumentXML&  Doc;
+
+    static const char *getOpcodeStr(UnaryOperator::Opcode Op);
+    static const char *getOpcodeStr(BinaryOperator::Opcode Op);
+
+  public:
+    StmtXML(DocumentXML& doc)
+      : Doc(doc) {
+    }
+    
+    void DumpSubTree(Stmt *S) {
+      if (S) 
+      {
+        Doc.addSubNode(S->getStmtClassName());
+        Doc.addLocationRange(S->getSourceRange());
+        if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) {
+          VisitDeclStmt(DS);
+        } else {        
+          Visit(S);
+          for (Stmt::child_iterator i = S->child_begin(), e = S->child_end(); i != e; ++i)
+          {
+            DumpSubTree(*i);
+          }
+        }
+        Doc.toParent();
+      } else {
+        Doc.addSubNode("NULL").toParent();
+      }
+    }
+
+    void DumpTypeExpr(const QualType& T)
+    {
+      Doc.addSubNode("TypeExpr");
+      Doc.addTypeAttribute(T);
+      Doc.toParent();
+    }
+
+    void DumpExpr(const Expr *Node) {
+      Doc.addTypeAttribute(Node->getType());
+    }
+
+    // Stmts.
+    void VisitStmt(Stmt *Node);
+    void VisitDeclStmt(DeclStmt *Node);
+    void VisitLabelStmt(LabelStmt *Node);
+    void VisitGotoStmt(GotoStmt *Node);
+    
+    // Exprs
+    void VisitExpr(Expr *Node);
+    void VisitDeclRefExpr(DeclRefExpr *Node);
+    void VisitPredefinedExpr(PredefinedExpr *Node);
+    void VisitCharacterLiteral(CharacterLiteral *Node);
+    void VisitIntegerLiteral(IntegerLiteral *Node);
+    void VisitFloatingLiteral(FloatingLiteral *Node);
+    void VisitStringLiteral(StringLiteral *Str);
+    void VisitUnaryOperator(UnaryOperator *Node);
+    void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node);
+    void VisitMemberExpr(MemberExpr *Node);
+    void VisitExtVectorElementExpr(ExtVectorElementExpr *Node);
+    void VisitBinaryOperator(BinaryOperator *Node);
+    void VisitCompoundAssignOperator(CompoundAssignOperator *Node);
+    void VisitAddrLabelExpr(AddrLabelExpr *Node);
+    void VisitTypesCompatibleExpr(TypesCompatibleExpr *Node);
+
+    // C++
+    void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node);
+    void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node);
+    void VisitCXXThisExpr(CXXThisExpr *Node);
+    void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node);
+    
+    // ObjC
+    void VisitObjCEncodeExpr(ObjCEncodeExpr *Node);
+    void VisitObjCMessageExpr(ObjCMessageExpr* Node);
+    void VisitObjCSelectorExpr(ObjCSelectorExpr *Node);
+    void VisitObjCProtocolExpr(ObjCProtocolExpr *Node);
+    void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node);
+    void VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node);
+    void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
+    void VisitObjCSuperExpr(ObjCSuperExpr *Node);
+  };
+}
+
+//===----------------------------------------------------------------------===//
+//  Stmt printing methods.
+//===----------------------------------------------------------------------===//
+
+void StmtXML::VisitStmt(Stmt *Node) 
+{
+  // nothing special to do
+}
+
+void StmtXML::VisitDeclStmt(DeclStmt *Node) 
+{
+  for (DeclStmt::decl_iterator DI = Node->decl_begin(), DE = Node->decl_end();
+       DI != DE; ++DI) 
+  {
+    Doc.PrintDecl(*DI);
+  }
+}
+
+void StmtXML::VisitLabelStmt(LabelStmt *Node) 
+{
+  Doc.addAttribute("name", Node->getName());
+}
+
+void StmtXML::VisitGotoStmt(GotoStmt *Node) 
+{
+  Doc.addAttribute("name", Node->getLabel()->getName());
+}
+
+//===----------------------------------------------------------------------===//
+//  Expr printing methods.
+//===----------------------------------------------------------------------===//
+
+void StmtXML::VisitExpr(Expr *Node) {
+  DumpExpr(Node);
+}
+
+void StmtXML::VisitDeclRefExpr(DeclRefExpr *Node) {
+  DumpExpr(Node);
+
+  const char* pKind;
+  switch (Node->getDecl()->getKind()) {
+    case Decl::Function: pKind = "FunctionDecl"; break;
+    case Decl::Var: pKind = "Var"; break;
+    case Decl::ParmVar: pKind = "ParmVar"; break;
+    case Decl::EnumConstant: pKind = "EnumConstant"; break;
+    case Decl::Typedef: pKind = "Typedef"; break;
+    case Decl::Record: pKind = "Record"; break;
+    case Decl::Enum: pKind = "Enum"; break;
+    case Decl::CXXRecord: pKind = "CXXRecord"; break;
+    case Decl::ObjCInterface: pKind = "ObjCInterface"; break;
+    case Decl::ObjCClass: pKind = "ObjCClass"; break;
+    default: pKind = "Decl"; break;
+  }
+
+  Doc.addAttribute("kind", pKind);
+  Doc.addAttribute("name", Node->getDecl()->getNameAsString());
+  Doc.addRefAttribute(Node->getDecl());
+}
+
+void StmtXML::VisitPredefinedExpr(PredefinedExpr *Node) {
+  DumpExpr(Node);
+  switch (Node->getIdentType()) {
+    default: assert(0 && "unknown case");
+    case PredefinedExpr::Func:           Doc.addAttribute("predefined", " __func__"); break;
+    case PredefinedExpr::Function:       Doc.addAttribute("predefined", " __FUNCTION__"); break;
+    case PredefinedExpr::PrettyFunction: Doc.addAttribute("predefined", " __PRETTY_FUNCTION__");break;
+  }
+}
+
+void StmtXML::VisitCharacterLiteral(CharacterLiteral *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("value", Node->getValue());
+}
+
+void StmtXML::VisitIntegerLiteral(IntegerLiteral *Node) {
+  DumpExpr(Node);
+  bool isSigned = Node->getType()->isSignedIntegerType();
+  Doc.addAttribute("value", Node->getValue().toString(10, isSigned));
+}
+
+void StmtXML::VisitFloatingLiteral(FloatingLiteral *Node) {
+  DumpExpr(Node);
+  // FIXME: output float as written in source (no approximation or the like)
+  //Doc.addAttribute("value", Node->getValueAsApproximateDouble()));
+  Doc.addAttribute("value", "FIXME");
+}
+
+void StmtXML::VisitStringLiteral(StringLiteral *Str) {
+  DumpExpr(Str);
+  if (Str->isWide())
+    Doc.addAttribute("is_wide", "1");
+
+  Doc.addAttribute("value", Doc.escapeString(Str->getStrData(), Str->getByteLength()));
+}
+
+
+const char *StmtXML::getOpcodeStr(UnaryOperator::Opcode Op) {
+  switch (Op) {
+  default: assert(0 && "Unknown unary operator");
+  case UnaryOperator::PostInc: return "postinc";
+  case UnaryOperator::PostDec: return "postdec";
+  case UnaryOperator::PreInc:  return "preinc";
+  case UnaryOperator::PreDec:  return "predec";
+  case UnaryOperator::AddrOf:  return "addrof";
+  case UnaryOperator::Deref:   return "deref";
+  case UnaryOperator::Plus:    return "plus";
+  case UnaryOperator::Minus:   return "minus";
+  case UnaryOperator::Not:     return "not";
+  case UnaryOperator::LNot:    return "lnot";
+  case UnaryOperator::Real:    return "__real";
+  case UnaryOperator::Imag:    return "__imag";
+  case UnaryOperator::Extension: return "__extension__";
+  case UnaryOperator::OffsetOf: return "__builtin_offsetof";
+  }
+}
+
+
+const char *StmtXML::getOpcodeStr(BinaryOperator::Opcode Op) {
+  switch (Op) {
+  default: assert(0 && "Unknown binary operator");
+  case BinaryOperator::PtrMemD:   return "ptrmemd";
+  case BinaryOperator::PtrMemI:   return "ptrmemi";
+  case BinaryOperator::Mul:       return "mul";
+  case BinaryOperator::Div:       return "div";
+  case BinaryOperator::Rem:       return "rem";
+  case BinaryOperator::Add:       return "add";
+  case BinaryOperator::Sub:       return "sub";
+  case BinaryOperator::Shl:       return "shl";
+  case BinaryOperator::Shr:       return "shr";
+  case BinaryOperator::LT:        return "lt";
+  case BinaryOperator::GT:        return "gt";
+  case BinaryOperator::LE:        return "le";
+  case BinaryOperator::GE:        return "ge";
+  case BinaryOperator::EQ:        return "eq";
+  case BinaryOperator::NE:        return "ne";
+  case BinaryOperator::And:       return "and";
+  case BinaryOperator::Xor:       return "xor";
+  case BinaryOperator::Or:        return "or";
+  case BinaryOperator::LAnd:      return "land";
+  case BinaryOperator::LOr:       return "lor";
+  case BinaryOperator::Assign:    return "assign";
+  case BinaryOperator::MulAssign: return "mulassign";
+  case BinaryOperator::DivAssign: return "divassign";
+  case BinaryOperator::RemAssign: return "remassign";
+  case BinaryOperator::AddAssign: return "addassign";
+  case BinaryOperator::SubAssign: return "subassign";
+  case BinaryOperator::ShlAssign: return "shlassign";
+  case BinaryOperator::ShrAssign: return "shrassign";
+  case BinaryOperator::AndAssign: return "andassign";
+  case BinaryOperator::XorAssign: return "xorassign";
+  case BinaryOperator::OrAssign:  return "orassign";
+  case BinaryOperator::Comma:     return "comma";
+  }
+}
+
+void StmtXML::VisitUnaryOperator(UnaryOperator *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("op_code", getOpcodeStr(Node->getOpcode()));
+}
+
+void StmtXML::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("is_sizeof", Node->isSizeOf() ? "sizeof" : "alignof");
+  Doc.addAttribute("is_type", Node->isArgumentType() ? "1" : "0");
+  if (Node->isArgumentType())
+  {
+    DumpTypeExpr(Node->getArgumentType());
+  }
+}
+
+void StmtXML::VisitMemberExpr(MemberExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("is_deref", Node->isArrow() ? "1" : "0");
+  Doc.addAttribute("name", Node->getMemberDecl()->getNameAsString());
+  Doc.addRefAttribute(Node->getMemberDecl());
+}
+
+void StmtXML::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("name", Node->getAccessor().getName());
+}
+
+void StmtXML::VisitBinaryOperator(BinaryOperator *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("op_code", getOpcodeStr(Node->getOpcode()));
+}
+
+void StmtXML::VisitCompoundAssignOperator(CompoundAssignOperator *Node) {
+  VisitBinaryOperator(Node);
+/* FIXME: is this needed in the AST?
+  DumpExpr(Node);
+  CurrentNode = CurrentNode->addSubNode("ComputeLHSTy");
+  DumpType(Node->getComputationLHSType());
+  CurrentNode = CurrentNode->Parent->addSubNode("ComputeResultTy");
+  DumpType(Node->getComputationResultType());
+  Doc.toParent();
+*/
+}
+
+// GNU extensions.
+
+void StmtXML::VisitAddrLabelExpr(AddrLabelExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("name", Node->getLabel()->getName());
+}
+
+void StmtXML::VisitTypesCompatibleExpr(TypesCompatibleExpr *Node) {
+  DumpExpr(Node);
+  DumpTypeExpr(Node->getArgType1());
+  DumpTypeExpr(Node->getArgType2());
+}
+
+//===----------------------------------------------------------------------===//
+// C++ Expressions
+//===----------------------------------------------------------------------===//
+
+void StmtXML::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("kind", Node->getCastName());
+  DumpTypeExpr(Node->getTypeAsWritten());
+}
+
+void StmtXML::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("value", Node->getValue() ? "true" : "false");
+}
+
+void StmtXML::VisitCXXThisExpr(CXXThisExpr *Node) {
+  DumpExpr(Node);
+}
+
+void StmtXML::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
+  DumpExpr(Node);
+  DumpTypeExpr(Node->getTypeAsWritten());
+}
+
+//===----------------------------------------------------------------------===//
+// Obj-C Expressions
+//===----------------------------------------------------------------------===//
+
+void StmtXML::VisitObjCMessageExpr(ObjCMessageExpr* Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("selector", Node->getSelector().getAsString());
+  IdentifierInfo* clsName = Node->getClassName();
+  if (clsName) 
+    Doc.addAttribute("class", clsName->getName());
+}
+
+void StmtXML::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
+  DumpExpr(Node);
+  DumpTypeExpr(Node->getEncodedType());
+}
+
+void StmtXML::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("selector", Node->getSelector().getAsString());
+}
+
+void StmtXML::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("protocol", Node->getProtocol()->getNameAsString());
+}
+
+void StmtXML::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("property", Node->getProperty()->getNameAsString());
+}
+
+void StmtXML::VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node) {
+  DumpExpr(Node);
+  ObjCMethodDecl *Getter = Node->getGetterMethod();
+  ObjCMethodDecl *Setter = Node->getSetterMethod();
+  Doc.addAttribute("Getter", Getter->getSelector().getAsString());
+  Doc.addAttribute("Setter", Setter ? Setter->getSelector().getAsString().c_str() : "(null)");
+}
+
+void StmtXML::VisitObjCSuperExpr(ObjCSuperExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("super", "1");
+}
+
+void StmtXML::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
+  DumpExpr(Node);
+  Doc.addAttribute("kind", Node->getDecl()->getDeclKindName());
+  Doc.addAttribute("decl", Node->getDecl()->getNameAsString());
+  if (Node->isFreeIvar())
+    Doc.addAttribute("isFreeIvar", "1");
+}
+
+//===----------------------------------------------------------------------===//
+// Stmt method implementations
+//===----------------------------------------------------------------------===//
+
+/// dumpAll - This does a dump of the specified AST fragment and all subtrees.
+void Stmt::dumpXML(DocumentXML& doc) const {
+  StmtXML P(doc);
+  P.DumpSubTree(const_cast<Stmt*>(this));
+}
+
Index: lib/Frontend/ASTConsumers.cpp
===================================================================
--- lib/Frontend/ASTConsumers.cpp	(revision 72107)
+++ lib/Frontend/ASTConsumers.cpp	(working copy)
@@ -19,6 +19,7 @@
 #include "clang/AST/AST.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/DocumentXML.h" 
 #include "clang/CodeGen/ModuleBuilder.h"
 #include "llvm/Module.h"
 #include "llvm/Support/Streams.h"
@@ -587,6 +588,42 @@
 }
 
 //===----------------------------------------------------------------------===//
+/// ASTPrinterXML - XML-printer of ASTs
+
+namespace {
+  class ASTPrinterXML : public ASTConsumer {
+    llvm::raw_ostream&  Out;
+    DocumentXML         Doc;
+
+  public:
+    ASTPrinterXML(llvm::raw_ostream& o) : Out(o), Doc("CLANG_XML") {}
+    
+    void Initialize(ASTContext &Context) {
+      Doc.initialize(Context);
+    }
+
+    virtual void HandleTranslationUnit(ASTContext &Ctx) {
+      Doc.addSubNode("TranslationUnit");
+      for (DeclContext::decl_iterator 
+             D = Ctx.getTranslationUnitDecl()->decls_begin(Ctx),
+             DEnd = Ctx.getTranslationUnitDecl()->decls_end(Ctx);
+           D != DEnd; 
+           ++D)
+      {
+        Doc.PrintDecl(*D);
+      }
+      Doc.toParent();
+      Doc.print(Out);
+    }
+  };
+} // end anonymous namespace
+
+
+ASTConsumer *clang::CreateASTPrinterXML() {
+  return new ASTPrinterXML(llvm::outs());
+}
+ 
+//===----------------------------------------------------------------------===//
 /// ASTDumper - Low-level dumper of ASTs
 
 namespace {
Index: tools/clang-cc/clang-cc.cpp
===================================================================
--- tools/clang-cc/clang-cc.cpp	(revision 72107)
+++ tools/clang-cc/clang-cc.cpp	(working copy)
@@ -68,6 +68,7 @@
 #include "llvm/System/Program.h"
 #include "llvm/System/Signals.h"
 #include <cstdlib>
+#undef HAVE_SYS_TYPES_H
 #if HAVE_SYS_TYPES_H
 #  include <sys/types.h>
 #endif
@@ -194,6 +195,7 @@
   EmitLLVMOnly,                 // Generate LLVM IR, but do not 
   EmitHTML,                     // Translate input source into HTML.
   ASTPrint,                     // Parse ASTs and print them.
+  ASTPrintXML,                  // Parse ASTs and print them in XML.
   ASTDump,                      // Parse ASTs and dump them.
   ASTDumpFull,                  // Parse ASTs and dump them, including the 
                                 // contents of a PCH file.
@@ -236,6 +238,8 @@
                         "Output input source as HTML"),
              clEnumValN(ASTPrint, "ast-print",
                         "Build ASTs and then pretty-print them"),
+             clEnumValN(ASTPrintXML, "ast-print-xml",
+                        "Build ASTs and then print them in XML format to stdout"),
              clEnumValN(ASTDump, "ast-dump",
                         "Build ASTs and then debug dump them"),
              clEnumValN(ASTDumpFull, "ast-dump-full",
@@ -1782,6 +1786,10 @@
     Consumer.reset(CreateASTPrinter(OS.get()));
     break;
     
+  case ASTPrintXML:
+    Consumer.reset(CreateASTPrinterXML());
+    break;
+
   case ASTDump:
     Consumer.reset(CreateASTDumper(false));
     break;
