More XML output support, from Olaf Krzikalla!


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73402 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt
index 649f9da..72d9a7e 100644
--- a/lib/Frontend/CMakeLists.txt
+++ b/lib/Frontend/CMakeLists.txt
@@ -5,6 +5,7 @@
   ASTConsumers.cpp
   Backend.cpp
   CacheTokens.cpp
+  DeclXML.cpp
   DependencyFile.cpp
   DiagChecker.cpp
   DocumentXML.cpp
@@ -31,5 +32,6 @@
   StmtXML.cpp
   TextDiagnosticBuffer.cpp
   TextDiagnosticPrinter.cpp
+  TypeXML.cpp
   Warnings.cpp
   )
diff --git a/lib/Frontend/DeclXML.cpp b/lib/Frontend/DeclXML.cpp
new file mode 100644
index 0000000..5c21999
--- /dev/null
+++ b/lib/Frontend/DeclXML.cpp
@@ -0,0 +1,161 @@
+//===--- DeclXML.cpp - XML implementation for Decl 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 XML document class, which provides the means to 
+// dump out the AST in a XML form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/Expr.h"
+
+namespace clang {
+
+//--------------------------------------------------------- 
+class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter>
+{
+  DocumentXML& Doc;
+
+  void addSubNodes(FunctionDecl* FD)
+  {
+    for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) 
+    {
+      Visit(FD->getParamDecl(i));
+      Doc.toParent();
+    }
+  }
+
+  void addSubNodes(RecordDecl* RD)
+  {
+    for (RecordDecl::field_iterator i = RD->field_begin(*Doc.Ctx), e = RD->field_end(*Doc.Ctx); i != e; ++i)
+    {
+      Visit(*i);
+      Doc.toParent();
+    }
+  }
+
+  void addSubNodes(EnumDecl* ED)
+  {
+    for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(*Doc.Ctx), e = ED->enumerator_end(*Doc.Ctx); i != e; ++i)
+    {
+      Visit(*i);
+      Doc.toParent();
+    }
+  }
+
+  void addSubNodes(EnumConstantDecl* ECD)
+  {
+    if (ECD->getInitExpr()) 
+    {
+      Doc.PrintStmt(ECD->getInitExpr());
+    }
+  }
+
+  void addSubNodes(FieldDecl* FdD)
+  {
+    if (FdD->isBitField())
+    {
+      Doc.PrintStmt(FdD->getBitWidth());
+    }
+  }
+
+  void addSubNodes(VarDecl* V)
+  {
+    if (V->getInit()) 
+    {
+      Doc.PrintStmt(V->getInit());
+    }
+  }
+
+  void addSubNodes(ParmVarDecl* argDecl)
+  {
+    if (argDecl->getDefaultArg())
+    {
+      Doc.PrintStmt(argDecl->getDefaultArg());
+    }
+  }
+
+  void addSpecialAttribute(const char* pName, EnumDecl* ED)
+  {
+    const QualType& enumType = ED->getIntegerType();
+    if (!enumType.isNull())
+    {
+      Doc.addAttribute(pName, enumType);
+    }
+  }
+
+  void addIdAttribute(LinkageSpecDecl* ED)
+  {
+    Doc.addAttribute("id", ED);
+  }
+
+  void addIdAttribute(NamedDecl* ND)
+  {
+    Doc.addAttribute("id", ND);
+  }
+
+public:
+  DeclPrinter(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME )          \
+  void Visit##CLASS(CLASS* T)            \
+  {                                      \
+    Doc.addSubNode(NAME);         
+
+#define ID_ATTRIBUTE_XML                  addIdAttribute(T);
+#define ATTRIBUTE_XML( FN, NAME )         Doc.addAttribute(NAME, T->FN); 
+#define ATTRIBUTE_OPT_XML( FN, NAME )     Doc.addAttributeOptional(NAME, T->FN); 
+#define ATTRIBUTE_FILE_LOCATION_XML       Doc.addLocation(T->getLocation());
+#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, T);
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME )  \
+  {                                     \
+    const char* pAttributeName = NAME;  \
+    const bool optional = false;             \
+    switch (T->FN) {                    \
+      default: assert(0 && "unknown enum value"); 
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME )  \
+  {                                     \
+    const char* pAttributeName = NAME;  \
+    const bool optional = true;              \
+    switch (T->FN) {                    \
+      default: assert(0 && "unknown enum value"); 
+
+#define ENUM_XML( VALUE, NAME )         case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML                    } }
+#define END_NODE_XML                    }
+
+#define SUB_NODE_XML( CLASS )           addSubNodes(T);
+#define SUB_NODE_SEQUENCE_XML( CLASS )  addSubNodes(T);
+#define SUB_NODE_OPT_XML( CLASS )       addSubNodes(T);
+
+#include "clang/Frontend/DeclXML.def"
+};
+
+
+//--------------------------------------------------------- 
+void DocumentXML::writeDeclToXML(Decl *D)
+{
+  DeclPrinter(*this).Visit(D);
+  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 
+  {
+    if (Stmt *Body = FD->getBody(*Ctx)) {
+      addSubNode("Body");
+      PrintStmt(Body);
+      toParent();
+    }
+  }
+  toParent();
+}
+
+//--------------------------------------------------------- 
+} // NS clang
+
diff --git a/lib/Frontend/DocumentXML.cpp b/lib/Frontend/DocumentXML.cpp
index 7562d2a..19a7573 100644
--- a/lib/Frontend/DocumentXML.cpp
+++ b/lib/Frontend/DocumentXML.cpp
@@ -14,92 +14,66 @@
 
 #include "clang/Frontend/DocumentXML.h"
 #include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/Expr.h"
+#include "clang/AST/ASTContext.h"
 #include "clang/Basic/SourceManager.h"
 #include "llvm/ADT/StringExtras.h"
 
 namespace clang {
 
 //--------------------------------------------------------- 
-struct DocumentXML::NodeXML
-{
-  std::string               Name;
-  NodeXML*                  Parent;
-
-  NodeXML(const std::string& name, NodeXML* parent) :
-    Name(name),
-    Parent(parent)
-  {}
-};
-
-//--------------------------------------------------------- 
 DocumentXML::DocumentXML(const std::string& rootName, llvm::raw_ostream& out) :
-  Root(new NodeXML(rootName, 0)),
-  CurrentNode(Root),
   Out(out),
   Ctx(0),
-  CurrentIndent(0),
   HasCurrentNodeSubNodes(false)
 {
+  NodeStack.push(rootName);
   Out << "<?xml version=\"1.0\"?>\n<" << rootName;
 }
 
 //--------------------------------------------------------- 
-DocumentXML::~DocumentXML()
-{
-  assert(CurrentNode == Root && "not completely backtracked");
-  delete Root;
-}
-
-//--------------------------------------------------------- 
 DocumentXML& DocumentXML::addSubNode(const std::string& name)
 {
   if (!HasCurrentNodeSubNodes)
   {
     Out << ">\n";
   }
-  CurrentNode = new NodeXML(name, CurrentNode);
+  NodeStack.push(name);
   HasCurrentNodeSubNodes = false;
-  CurrentIndent += 2;
   Indent();
-  Out << "<" << CurrentNode->Name;
+  Out << "<" << NodeStack.top();
   return *this;
 }
 
 //--------------------------------------------------------- 
 void DocumentXML::Indent() 
 {
-  for (int i = 0; i < CurrentIndent; ++i)
+  for (size_t i = 0, e = (NodeStack.size() - 1) * 2; i < e; ++i)
     Out << ' ';
 }
 
 //--------------------------------------------------------- 
 DocumentXML& DocumentXML::toParent() 
 { 
-  assert(CurrentNode != Root && "to much backtracking");
+  assert(NodeStack.size() > 1 && "to much backtracking");
 
   if (HasCurrentNodeSubNodes)
   {
     Indent();
-    Out << "</" << CurrentNode->Name << ">\n";
+    Out << "</" << NodeStack.top() << ">\n";
   }
   else
   {
     Out << "/>\n";
   }
-  NodeXML* NodeToDelete = CurrentNode;
-  CurrentNode = CurrentNode->Parent; 
-  delete NodeToDelete;
+  NodeStack.pop();
   HasCurrentNodeSubNodes = true;
-  CurrentIndent -= 2;
   return *this; 
 }
 
 //--------------------------------------------------------- 
 namespace {
 
-enum tIdType { ID_NORMAL, ID_FILE, ID_LAST };
+enum tIdType { ID_NORMAL, ID_FILE, ID_LABEL, ID_LAST };
 
 unsigned getNewId(tIdType idType)
 {
@@ -110,7 +84,7 @@
 //--------------------------------------------------------- 
 inline std::string getPrefixedId(unsigned uId, tIdType idType)
 {
-  static const char idPrefix[ID_LAST] = { '_', 'f' };
+  static const char idPrefix[ID_LAST] = { '_', 'f', 'l' };
   char buffer[20];
   char* BufPtr = llvm::utohex_buffer(uId, buffer + 20);
   *--BufPtr = idPrefix[idType];
@@ -132,6 +106,7 @@
 
 } // anon NS
 
+
 //--------------------------------------------------------- 
 std::string DocumentXML::escapeString(const char* pStr, std::string::size_type len)
 {
@@ -170,7 +145,7 @@
 //--------------------------------------------------------- 
 void DocumentXML::finalize()
 {
-  assert(CurrentNode == Root && "not completely backtracked");
+  assert(NodeStack.size() == 1 && "not completely backtracked");
 
   addSubNode("ReferenceSection");
   addSubNode("Types");
@@ -179,71 +154,15 @@
   {
     if (i->first.getCVRQualifiers() != 0)
     {
-      addSubNode("CvQualifiedType");
+      writeTypeToXML(i->first);
       addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
-      addAttribute("type", getPrefixedId(BasicTypes[i->first.getTypePtr()], ID_NORMAL));
-      if (i->first.isConstQualified()) addAttribute("const", "1");
-      if (i->first.isVolatileQualified()) addAttribute("volatile", "1");
-      if (i->first.isRestrictQualified()) addAttribute("restrict", "1");
       toParent();
     }
   }
 
   for (XML::IdMap<const Type*>::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(Ctx->getLangOptions().CPlusPlus));
-    }
-    else if (const PointerType *PT = dyn_cast<PointerType>(i->first)) {
-      addSubNode("PointerType");
-      addTypeAttribute(PT->getPointeeType());
-    }
-    else if (dyn_cast<FunctionType>(i->first) != 0) {
-      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 VariableArrayType *VAT = dyn_cast<VariableArrayType>(i->first)) {
-      addSubNode("VariableArrayType");
-      addTypeAttribute(VAT->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 if (const VectorType* VT = dyn_cast<VectorType>(i->first)) {
-      addSubNode("VectorType");
-      addTypeAttribute(VT->getElementType());
-      addAttribute("num_elements", VT->getNumElements());
-    }
-    else 
-    {
-      addSubNode("FIXMEType");
-    }
+    writeTypeToXML(i->first);
     addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
     toParent();
   }
@@ -267,7 +186,7 @@
 
     if (const DeclContext* parent = i->first->getParent())
     {
-      addContextAttribute(parent);
+      addAttribute("context", parent);
     } 
     toParent();
   }
@@ -285,21 +204,21 @@
   toParent().toParent();
   
   // write the root closing node (which has always subnodes)
-  Out << "</" << CurrentNode->Name << ">\n";
+  Out << "</" << NodeStack.top() << ">\n";
 }
 
 //--------------------------------------------------------- 
-void DocumentXML::addTypeAttribute(const QualType& pType)
+void DocumentXML::addAttribute(const char* pAttributeName, const QualType& pType)
 {
   addTypeRecursively(pType);
-  addAttribute("type", getPrefixedId(Types[pType], ID_NORMAL));
+  addAttribute(pAttributeName, getPrefixedId(Types[pType], ID_NORMAL));
 }
 
 //--------------------------------------------------------- 
-void DocumentXML::addTypeIdAttribute(const Type* pType)
+void DocumentXML::addPtrAttribute(const char* pAttributeName, const Type* pType)
 {
-  addBasicTypeRecursively(pType);
-  addAttribute("id", getPrefixedId(BasicTypes[pType], ID_NORMAL));
+  addTypeRecursively(pType);
+  addAttribute(pAttributeName, getPrefixedId(BasicTypes[pType], ID_NORMAL));
 }
 
 //--------------------------------------------------------- 
@@ -307,7 +226,7 @@
 {
   if (addToMap(Types, pType))
   {
-    addBasicTypeRecursively(pType.getTypePtr());
+    addTypeRecursively(pType.getTypePtr());
     // beautifier: a non-qualified type shall be transparent
     if (pType.getCVRQualifiers() == 0)
     {
@@ -317,43 +236,49 @@
 }
 
 //--------------------------------------------------------- 
-void DocumentXML::addBasicTypeRecursively(const Type* pType)
+void DocumentXML::addTypeRecursively(const Type* pType)
 {
   if (addToMap(BasicTypes, pType))
   {
-    if (const PointerType *PT = dyn_cast<PointerType>(pType)) {
-      addTypeRecursively(PT->getPointeeType());
+    addParentTypes(pType);
+/*
+    // FIXME: doesn't work in the immediate streaming approach
+    if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(pType)) 
+    {
+      addSubNode("VariableArraySizeExpression");
+      PrintStmt(VAT->getSizeExpr());
+      toParent();
     }
-    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 ArrayType *AT = dyn_cast<ArrayType>(pType)) {
-      addTypeRecursively(AT->getElementType());
-      // FIXME: doesn't work in the immediate streaming approach
-      /*if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(AT)) 
-      {
-        addSubNode("VariableArraySizeExpression");
-        PrintStmt(VAT->getSizeExpr());
-        toParent();
-      }*/
-    }
+*/
   }
 }
 
 //--------------------------------------------------------- 
-void DocumentXML::addContextAttribute(const DeclContext *DC, tContextUsage usage)
+void DocumentXML::addPtrAttribute(const char* pName, const DeclContext* DC)
 {
   addContextsRecursively(DC);
-  const char* pAttributeTags[2] = { "context", "id" };
-  addAttribute(pAttributeTags[usage], getPrefixedId(Contexts[DC], ID_NORMAL));
+  addAttribute(pName, getPrefixedId(Contexts[DC], ID_NORMAL));
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::addPtrAttribute(const char* pAttributeName, const NamedDecl* D)
+{
+  if (const DeclContext* DC = dyn_cast<DeclContext>(D))
+  {
+    addContextsRecursively(DC);
+    addAttribute(pAttributeName, getPrefixedId(Contexts[DC], ID_NORMAL));
+  }
+  else
+  {
+    addToMap(Decls, D);
+    addAttribute(pAttributeName, getPrefixedId(Decls[D], ID_NORMAL));
+  }
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::addPtrAttribute(const char* pName, const NamespaceDecl* D)
+{
+  addPtrAttribute(pName, static_cast<const DeclContext*>(D));
 }
 
 //--------------------------------------------------------- 
@@ -372,6 +297,15 @@
   addAttribute("file", getPrefixedId(SourceFiles[fileName], ID_FILE));
 }
 
+
+//--------------------------------------------------------- 
+void DocumentXML::addPtrAttribute(const char* pName, const LabelStmt* L)
+{
+  addToMap(Labels, L, ID_LABEL);
+  addAttribute(pName, getPrefixedId(Labels[L], ID_LABEL));
+}
+
+
 //--------------------------------------------------------- 
 PresumedLoc DocumentXML::addLocation(const SourceLocation& Loc)
 {
@@ -417,161 +351,9 @@
 }
 
 //--------------------------------------------------------- 
-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");
-        PrintStmt(argDecl->getDefaultArg());
-      }
-      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", getPrefixedId(Contexts[DC], ID_NORMAL));
-  }
-  else
-  {
-    addAttribute("ref", getPrefixedId(Decls[D], ID_NORMAL));
-  }
-}
-
-//--------------------------------------------------------- 
-void DocumentXML::addDeclIdAttribute(const NamedDecl* D)
-{
-  addToMap(Decls, D);
-  addAttribute("id", getPrefixedId(Decls[D], ID_NORMAL));
-}
-
-//--------------------------------------------------------- 
 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");
-        PrintStmt(Body);
-        toParent();
-      }
-    } else if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
-      addBasicTypeRecursively(RD->getTypeForDecl());
-      addAttribute("type", getPrefixedId(BasicTypes[RD->getTypeForDecl()], ID_NORMAL));
-      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()) 
-      {
-        PrintStmt(ECD->getInitExpr());
-      }
-    } 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");
-        PrintStmt(FdD->getBitWidth());
-      }
-    } 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()) 
-      {
-        PrintStmt(V->getInit());
-      }
-    }
-  } 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 if (isa<FileScopeAsmDecl>(D)) {
-    // FIXME: Implement this
-  } else {
-    assert(0 && "Unexpected decl");
-  }
-  toParent();
+  writeDeclToXML(D);
 }
 
 //--------------------------------------------------------- 
diff --git a/lib/Frontend/StmtXML.cpp b/lib/Frontend/StmtXML.cpp
index c861881..6ba0a28 100644
--- a/lib/Frontend/StmtXML.cpp
+++ b/lib/Frontend/StmtXML.cpp
@@ -28,8 +28,31 @@
   class VISIBILITY_HIDDEN StmtXML : public StmtVisitor<StmtXML> {
     DocumentXML&  Doc;
 
-    static const char *getOpcodeStr(UnaryOperator::Opcode Op);
-    static const char *getOpcodeStr(BinaryOperator::Opcode Op);
+    //static const char *getOpcodeStr(UnaryOperator::Opcode Op);
+    //static const char *getOpcodeStr(BinaryOperator::Opcode Op);
+
+
+  void addSpecialAttribute(const char* pName, StringLiteral* Str)
+  {
+    Doc.addAttribute(pName, Doc.escapeString(Str->getStrData(), Str->getByteLength()));
+  }
+
+  void addSpecialAttribute(const char* pName, SizeOfAlignOfExpr* S)
+  {
+    if (S->isArgumentType())
+    {
+      Doc.addAttribute(pName, S->getArgumentType());
+    }
+  }
+
+  void addSpecialAttribute(const char* pName, CXXTypeidExpr* S)
+  {
+    if (S->isTypeOperand())
+    {
+      Doc.addAttribute(pName, S->getTypeOperand());
+    }
+  }
+
 
   public:
     StmtXML(DocumentXML& doc)
@@ -39,12 +62,21 @@
     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);
+        Visit(S);
+        if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) 
+        {
+          for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
+               DI != DE; ++DI) 
+          {
+            Doc.PrintDecl(*DI);
+          }
+        } 
+        else 
+        {    
+          if (CXXConditionDeclExpr* CCDE = dyn_cast<CXXConditionDeclExpr>(S))
+          {
+            Doc.PrintDecl(CCDE->getVarDecl());
+          }
           for (Stmt::child_iterator i = S->child_begin(), e = S->child_end(); i != e; ++i)
           {
             DumpSubTree(*i);
@@ -56,17 +88,46 @@
       }
     }
 
-    void DumpTypeExpr(const QualType& T)
-    {
-      Doc.addSubNode("TypeExpr");
-      Doc.addTypeAttribute(T);
-      Doc.toParent();
-    }
 
-    void DumpExpr(const Expr *Node) {
-      Doc.addTypeAttribute(Node->getType());
-    }
+#define NODE_XML( CLASS, NAME )          \
+  void Visit##CLASS(CLASS* S)            \
+  {                                      \
+    typedef CLASS tStmtType;             \
+    Doc.addSubNode(NAME);         
 
+#define ATTRIBUTE_XML( FN, NAME )         Doc.addAttribute(NAME, S->FN); 
+#define TYPE_ATTRIBUTE_XML( FN )          ATTRIBUTE_XML(FN, "type")
+#define ATTRIBUTE_OPT_XML( FN, NAME )     Doc.addAttributeOptional(NAME, S->FN); 
+#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, S); 
+#define ATTRIBUTE_FILE_LOCATION_XML       Doc.addLocationRange(S->getSourceRange());
+
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME )  \
+  {                                     \
+    const char* pAttributeName = NAME;  \
+    const bool optional = false;        \
+    switch (S->FN) {                    \
+      default: assert(0 && "unknown enum value"); 
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME )  \
+  {                                         \
+    const char* pAttributeName = NAME;      \
+    const bool optional = true;             \
+    switch (S->FN) {                        \
+      default: assert(0 && "unknown enum value"); 
+
+#define ENUM_XML( VALUE, NAME )         case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML                    } }
+#define END_NODE_XML                    }
+
+#define ID_ATTRIBUTE_XML                Doc.addAttribute("id", S);
+#define SUB_NODE_XML( CLASS )
+#define SUB_NODE_SEQUENCE_XML( CLASS )
+#define SUB_NODE_OPT_XML( CLASS )
+
+#include "clang/Frontend/StmtXML.def"
+
+#if (0)
     // Stmts.
     void VisitStmt(Stmt *Node);
     void VisitDeclStmt(DeclStmt *Node);
@@ -105,13 +166,14 @@
     void VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node);
     void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
     void VisitObjCSuperExpr(ObjCSuperExpr *Node);
+#endif
   };
 }
 
 //===----------------------------------------------------------------------===//
 //  Stmt printing methods.
 //===----------------------------------------------------------------------===//
-
+#if (0)
 void StmtXML::VisitStmt(Stmt *Node) 
 {
   // nothing special to do
@@ -396,7 +458,7 @@
   if (Node->isFreeIvar())
     Doc.addAttribute("isFreeIvar", "1");
 }
-
+#endif
 //===----------------------------------------------------------------------===//
 // Stmt method implementations
 //===----------------------------------------------------------------------===//
diff --git a/lib/Frontend/TypeXML.cpp b/lib/Frontend/TypeXML.cpp
new file mode 100644
index 0000000..f32fbbd
--- /dev/null
+++ b/lib/Frontend/TypeXML.cpp
@@ -0,0 +1,127 @@
+//===--- 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 XML document class, which provides the means to 
+// dump out the AST in a XML form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/TypeVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/Decl.h"
+
+namespace clang {
+  namespace XML {
+    namespace {
+
+//--------------------------------------------------------- 
+class TypeWriter : public TypeVisitor<TypeWriter>
+{
+  DocumentXML& Doc;
+
+public:
+  TypeWriter(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME )          \
+  void Visit##CLASS(CLASS* T)            \
+  {                                      \
+    Doc.addSubNode(NAME);         
+
+#define ID_ATTRIBUTE_XML                // done by the Document class itself
+#define ATTRIBUTE_XML( FN, NAME )       Doc.addAttribute(NAME, T->FN); 
+#define TYPE_ATTRIBUTE_XML( FN )        ATTRIBUTE_XML(FN, "type")
+#define CONTEXT_ATTRIBUTE_XML( FN )     ATTRIBUTE_XML(FN, "context")
+#define ATTRIBUTE_OPT_XML( FN, NAME )   Doc.addAttributeOptional(NAME, T->FN); 
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME )  \
+  {                                     \
+    const char* pAttributeName = NAME;  \
+    const bool optional = false;             \
+    switch (T->FN) {                    \
+      default: assert(0 && "unknown enum value"); 
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME )  \
+  {                                     \
+    const char* pAttributeName = NAME;  \
+    const bool optional = true;              \
+    switch (T->FN) {                    \
+      default: assert(0 && "unknown enum value"); 
+
+#define ENUM_XML( VALUE, NAME )         case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML                    } }
+#define END_NODE_XML                    }
+
+#include "clang/Frontend/TypeXML.def"
+
+};
+
+//--------------------------------------------------------- 
+    } // anon clang
+  } // NS XML
+
+//--------------------------------------------------------- 
+class DocumentXML::TypeAdder : public TypeVisitor<DocumentXML::TypeAdder>
+{
+  DocumentXML& Doc;
+
+  void addIfType(const Type* pType)
+  {
+    Doc.addTypeRecursively(pType);
+  }
+
+  void addIfType(const QualType& pType)
+  {
+    Doc.addTypeRecursively(pType);
+  }
+
+  template<class T> void addIfType(T) {}
+
+public:
+  TypeAdder(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME )          \
+  void Visit##CLASS(CLASS* T)            \
+  {                                      
+
+#define ID_ATTRIBUTE_XML                
+#define TYPE_ATTRIBUTE_XML( FN )        Doc.addTypeRecursively(T->FN); 
+#define CONTEXT_ATTRIBUTE_XML( FN )     
+#define ATTRIBUTE_XML( FN, NAME )       addIfType(T->FN); 
+#define ATTRIBUTE_OPT_XML( FN, NAME )   
+#define ATTRIBUTE_ENUM_XML( FN, NAME )  
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME )  
+#define ENUM_XML( VALUE, NAME )         
+#define END_ENUM_XML                    
+#define END_NODE_XML                    }
+
+#include "clang/Frontend/TypeXML.def"
+};
+
+//--------------------------------------------------------- 
+void DocumentXML::addParentTypes(const Type* pType)
+{
+  TypeAdder(*this).Visit(const_cast<Type*>(pType));
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::writeTypeToXML(const Type* pType)
+{
+  XML::TypeWriter(*this).Visit(const_cast<Type*>(pType));
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::writeTypeToXML(const QualType& pType)
+{
+  XML::TypeWriter(*this).VisitQualType(const_cast<QualType*>(&pType));
+}
+
+//--------------------------------------------------------- 
+} // NS clang
+