[cfe-commits] r72224 - in /cfe/trunk: include/clang/Frontend/ASTConsumers.h include/clang/Frontend/DocumentXML.h lib/AST/CMakeLists.txt lib/Frontend/ASTConsumers.cpp lib/Frontend/DocumentXML.cpp lib/Frontend/StmtXML.cpp test/Coverage/ast-printing.c tools/clang-cc/clang-cc.cpp

Douglas Gregor dgregor at apple.com
Thu May 21 13:55:57 PDT 2009


Author: dgregor
Date: Thu May 21 15:55:50 2009
New Revision: 72224

URL: http://llvm.org/viewvc/llvm-project?rev=72224&view=rev
Log:
AST XML dump, from Olaf Krzikalla!

Added:
    cfe/trunk/include/clang/Frontend/DocumentXML.h
    cfe/trunk/lib/Frontend/DocumentXML.cpp
    cfe/trunk/lib/Frontend/StmtXML.cpp
Modified:
    cfe/trunk/include/clang/Frontend/ASTConsumers.h
    cfe/trunk/lib/AST/CMakeLists.txt
    cfe/trunk/lib/Frontend/ASTConsumers.cpp
    cfe/trunk/test/Coverage/ast-printing.c
    cfe/trunk/tools/clang-cc/clang-cc.cpp

Modified: cfe/trunk/include/clang/Frontend/ASTConsumers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/ASTConsumers.h?rev=72224&r1=72223&r2=72224&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/ASTConsumers.h (original)
+++ cfe/trunk/include/clang/Frontend/ASTConsumers.h Thu May 21 15:55:50 2009
@@ -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(llvm::raw_ostream* OS);
+
 // 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

Added: cfe/trunk/include/clang/Frontend/DocumentXML.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/DocumentXML.h?rev=72224&view=auto

==============================================================================
--- cfe/trunk/include/clang/Frontend/DocumentXML.h (added)
+++ cfe/trunk/include/clang/Frontend/DocumentXML.h Thu May 21 15:55:50 2009
@@ -0,0 +1,128 @@
+//===--- DocumentXML.h - XML document for ASTs ------------------*- C++ -*-===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_FRONTEND_DOCUMENTXML_H
+#define LLVM_CLANG_FRONTEND_DOCUMENTXML_H
+
+#include <string>
+#include <map>
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeOrdering.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/DenseMap.h"
+
+namespace clang {
+
+//--------------------------------------------------------- forwards
+class DeclContext;
+class Decl;
+class NamedDecl;
+class FunctionDecl;
+class ASTContext;
+ 
+//--------------------------------------------------------- 
+namespace XML
+{
+  // id maps:
+  template<class T>
+  struct IdMap : llvm::DenseMap<T, unsigned> {};
+
+  template<>
+  struct IdMap<QualType> : std::map<QualType, unsigned, QualTypeOrdering> {};
+
+  template<>
+  struct IdMap<std::string> : std::map<std::string, unsigned> {};
+}
+
+//--------------------------------------------------------- 
+class DocumentXML
+{
+public:
+  DocumentXML(const std::string& rootName, llvm::raw_ostream& out);
+  ~DocumentXML();
+
+  void initialize(ASTContext &Context);
+  void PrintDecl(Decl *D);
+  void PrintStmt(const Stmt *S);    // defined in StmtXML.cpp
+
+  void finalize();
+
+
+  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
+
+  struct NodeXML;
+
+  NodeXML*  Root;
+  NodeXML*  CurrentNode;   // always after Root
+  llvm::raw_ostream& Out;
+  ASTContext *Ctx;
+  int       CurrentIndent;
+  bool      HasCurrentNodeSubNodes;
+
+
+  XML::IdMap<QualType>                 Types;
+  XML::IdMap<const DeclContext*>       Contexts;
+  XML::IdMap<const Type*>              BasicTypes;
+  XML::IdMap<std::string>              SourceFiles;
+  XML::IdMap<const NamedDecl*>         Decls;
+
+  void addContextsRecursively(const DeclContext *DC);
+  void addBasicTypeRecursively(const Type* pType);
+  void addTypeRecursively(const QualType& pType);
+
+  void PrintFunctionDecl(FunctionDecl *FD);
+  void addDeclIdAttribute(const NamedDecl* D);
+  void addTypeIdAttribute(const Type* pType);  
+  void Indent();
+};
+
+//--------------------------------------------------------- inlines
+
+inline void DocumentXML::initialize(ASTContext &Context) 
+{ 
+  Ctx = &Context; 
+}
+
+//--------------------------------------------------------- 
+template<class T>
+inline void DocumentXML::addAttribute(const char* pName, const T& value)
+{
+  Out << ' ' << pName << "=\"" << value << "\"";
+}
+
+//--------------------------------------------------------- 
+
+} //namespace clang 
+
+#endif //LLVM_CLANG_DOCUMENTXML_H

Modified: cfe/trunk/lib/AST/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CMakeLists.txt?rev=72224&r1=72223&r2=72224&view=diff

==============================================================================
--- cfe/trunk/lib/AST/CMakeLists.txt (original)
+++ cfe/trunk/lib/AST/CMakeLists.txt Thu May 21 15:55:50 2009
@@ -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
   )

Modified: cfe/trunk/lib/Frontend/ASTConsumers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/ASTConsumers.cpp?rev=72224&r1=72223&r2=72224&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/ASTConsumers.cpp (original)
+++ cfe/trunk/lib/Frontend/ASTConsumers.cpp Thu May 21 15:55:50 2009
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/Frontend/ASTConsumers.h"
+#include "clang/Frontend/DocumentXML.h" 
 #include "clang/Frontend/PathDiagnosticClients.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/SourceManager.h"
@@ -587,6 +588,41 @@
 }
 
 //===----------------------------------------------------------------------===//
+/// ASTPrinterXML - XML-printer of ASTs
+
+namespace {
+  class ASTPrinterXML : public ASTConsumer {
+    DocumentXML         Doc;
+
+  public:
+    ASTPrinterXML(llvm::raw_ostream& o) : Doc("CLANG_XML", o) {}
+    
+    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.finalize();
+    }
+  };
+} // end anonymous namespace
+
+
+ASTConsumer *clang::CreateASTPrinterXML(llvm::raw_ostream* out) {
+  return new ASTPrinterXML(out ? *out : llvm::outs());
+}
+ 
+//===----------------------------------------------------------------------===//
 /// ASTDumper - Low-level dumper of ASTs
 
 namespace {

Added: cfe/trunk/lib/Frontend/DocumentXML.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/DocumentXML.cpp?rev=72224&view=auto

==============================================================================
--- cfe/trunk/lib/Frontend/DocumentXML.cpp (added)
+++ cfe/trunk/lib/Frontend/DocumentXML.cpp Thu May 21 15:55:50 2009
@@ -0,0 +1,577 @@
+//===--- 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/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.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)
+{
+  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);
+  HasCurrentNodeSubNodes = false;
+  CurrentIndent += 2;
+  Indent();
+  Out << "<" << CurrentNode->Name;
+  return *this;
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::Indent() 
+{
+  for (int i = 0; i < CurrentIndent; ++i)
+    Out << ' ';
+}
+
+//--------------------------------------------------------- 
+DocumentXML& DocumentXML::toParent() 
+{ 
+  assert(CurrentNode != Root && "to much backtracking");
+
+  if (HasCurrentNodeSubNodes)
+  {
+    Indent();
+    Out << "</" << CurrentNode->Name << ">\n";
+  }
+  else
+  {
+    Out << "/>\n";
+  }
+  NodeXML* NodeToDelete = CurrentNode;
+  CurrentNode = CurrentNode->Parent; 
+  delete NodeToDelete;
+  HasCurrentNodeSubNodes = true;
+  CurrentIndent -= 2;
+  return *this; 
+}
+
+//--------------------------------------------------------- 
+namespace {
+
+enum tIdType { ID_NORMAL, ID_FILE, ID_LAST };
+
+unsigned getNewId(tIdType idType)
+{
+  static unsigned int idCounts[ID_LAST] = { 0 };
+  return ++idCounts[idType];
+}
+
+//--------------------------------------------------------- 
+inline std::string getPrefixedId(unsigned uId, tIdType idType)
+{
+  static const char idPrefix[ID_LAST] = { '_', 'f' };
+  char buffer[20];
+  char* BufPtr = llvm::utohex_buffer(uId, buffer + 20);
+  *--BufPtr = idPrefix[idType];
+  return BufPtr;
+}
+
+//--------------------------------------------------------- 
+template<class T, class V>
+bool addToMap(T& idMap, const V& value, tIdType idType = ID_NORMAL)
+{
+  typename T::iterator i = idMap.find(value);
+  bool toAdd = i == idMap.end();
+  if (toAdd) 
+  {
+    idMap.insert(typename T::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 += "&"; break;
+    case '<': value += "<"; break;
+    case '>': value += ">"; break;
+    case '"': value += """; break;
+    case '\'':  value += "'"; break;
+
+    }
+  }
+  return value;
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::finalize()
+{
+  assert(CurrentNode == Root && "not completely backtracked");
+
+  addSubNode("ReferenceSection");
+  addSubNode("Types");
+
+  for (XML::IdMap<QualType>::iterator i = Types.begin(), e = Types.end(); i != e; ++i)
+  {
+    if (i->first.getCVRQualifiers() != 0)
+    {
+      addSubNode("CvQualifiedType");
+      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());
+    }
+    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");
+    }
+    addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
+    toParent();
+  }
+
+
+  toParent().addSubNode("Contexts");
+
+  for (XML::IdMap<const DeclContext*>::iterator i = Contexts.begin(), e = Contexts.end(); i != e; ++i)
+  {
+    addSubNode(i->first->getDeclKindName());
+    addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
+    if (const NamedDecl *ND = dyn_cast<NamedDecl>(i->first)) {
+      addAttribute("name", ND->getNameAsString());
+    }
+    if (const TagDecl *TD = dyn_cast<TagDecl>(i->first)) {
+      addAttribute("type", getPrefixedId(BasicTypes[TD->getTypeForDecl()], ID_NORMAL));
+    }
+    else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(i->first)) {
+      addAttribute("type", getPrefixedId(BasicTypes[FD->getType()->getAsFunctionType()], ID_NORMAL));
+    }
+
+    if (const DeclContext* parent = i->first->getParent())
+    {
+      addContextAttribute(parent);
+    } 
+    toParent();
+  }
+
+  toParent().addSubNode("Files");
+
+  for (XML::IdMap<std::string>::iterator i = SourceFiles.begin(), e = SourceFiles.end(); i != e; ++i)
+  {
+    addSubNode("File");
+    addAttribute("id", getPrefixedId(i->second, ID_FILE));
+    addAttribute("name", escapeString(i->first.c_str(), i->first.size()));
+    toParent();
+  }
+
+  toParent().toParent();
+  
+  // write the root closing node (which has always subnodes)
+  Out << "</" << CurrentNode->Name << ">\n";
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::addTypeAttribute(const QualType& pType)
+{
+  addTypeRecursively(pType);
+  addAttribute("type", getPrefixedId(Types[pType], ID_NORMAL));
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::addTypeIdAttribute(const Type* pType)
+{
+  addBasicTypeRecursively(pType);
+  addAttribute("id", getPrefixedId(BasicTypes[pType], ID_NORMAL));
+}
+
+//--------------------------------------------------------- 
+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 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)
+{
+  addContextsRecursively(DC);
+  const char* pAttributeTags[2] = { "context", "id" };
+  addAttribute(pAttributeTags[usage], getPrefixedId(Contexts[DC], ID_NORMAL));
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::addContextsRecursively(const DeclContext *DC)
+{
+  if (DC != 0 && addToMap(Contexts, DC))
+  {
+    addContextsRecursively(DC->getParent());
+  } 
+}
+
+//--------------------------------------------------------- 
+void DocumentXML::addSourceFileAttribute(const std::string& fileName)
+{
+  addToMap(SourceFiles, fileName, ID_FILE);
+  addAttribute("file", getPrefixedId(SourceFiles[fileName], ID_FILE));
+}
+
+//--------------------------------------------------------- 
+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");
+        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 {
+    assert(0 && "Unexpected decl");
+  }
+  toParent();
+}
+
+//--------------------------------------------------------- 
+} // NS clang
+

Added: cfe/trunk/lib/Frontend/StmtXML.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/StmtXML.cpp?rev=72224&view=auto

==============================================================================
--- cfe/trunk/lib/Frontend/StmtXML.cpp (added)
+++ cfe/trunk/lib/Frontend/StmtXML.cpp Thu May 21 15:55:50 2009
@@ -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));
+}
+

Modified: cfe/trunk/test/Coverage/ast-printing.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Coverage/ast-printing.c?rev=72224&r1=72223&r2=72224&view=diff

==============================================================================
--- cfe/trunk/test/Coverage/ast-printing.c (original)
+++ cfe/trunk/test/Coverage/ast-printing.c Thu May 21 15:55:50 2009
@@ -1,5 +1,6 @@
 // RUN: clang-cc --fsyntax-only %s &&
 // RUN: clang-cc --ast-print %s &&
-// RUN: clang-cc --ast-dump %s
+// RUN: clang-cc --ast-dump %s &&
+// RUN: clang-cc --ast-print-xml -o %t %s
 
 #include "c-language-features.inc"

Modified: cfe/trunk/tools/clang-cc/clang-cc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-cc/clang-cc.cpp?rev=72224&r1=72223&r2=72224&view=diff

==============================================================================
--- cfe/trunk/tools/clang-cc/clang-cc.cpp (original)
+++ cfe/trunk/tools/clang-cc/clang-cc.cpp Thu May 21 15:55:50 2009
@@ -194,6 +194,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 +237,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"),
              clEnumValN(ASTDump, "ast-dump",
                         "Build ASTs and then debug dump them"),
              clEnumValN(ASTDumpFull, "ast-dump-full",
@@ -1755,6 +1758,11 @@
     Consumer.reset(CreateASTPrinter(OS.get()));
     break;
     
+  case ASTPrintXML:
+    OS.reset(ComputeOutFile(InFile, "xml", false, OutPath));
+    Consumer.reset(CreateASTPrinterXML(OS.get()));
+    break;
+
   case ASTDump:
     Consumer.reset(CreateASTDumper(false));
     break;





More information about the cfe-commits mailing list