AST XML dump, from Olaf Krzikalla!


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72224 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/StmtXML.cpp b/lib/Frontend/StmtXML.cpp
new file mode 100644
index 0000000..c861881
--- /dev/null
+++ b/lib/Frontend/StmtXML.cpp
@@ -0,0 +1,409 @@
+//===--- StmtXML.cpp - XML 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::dumpXML methods, which dump out the
+// AST to an XML document.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/Basic/SourceManager.h"
+#include "llvm/Support/Compiler.h"
+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 DocumentXML::PrintStmt(const Stmt *S) {
+  StmtXML P(*this);
+  P.DumpSubTree(const_cast<Stmt*>(S));
+}
+