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/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
+