[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