More XML output support, from Olaf Krzikalla!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@73402 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Frontend/CMakeLists.txt b/lib/Frontend/CMakeLists.txt
index 649f9da..72d9a7e 100644
--- a/lib/Frontend/CMakeLists.txt
+++ b/lib/Frontend/CMakeLists.txt
@@ -5,6 +5,7 @@
ASTConsumers.cpp
Backend.cpp
CacheTokens.cpp
+ DeclXML.cpp
DependencyFile.cpp
DiagChecker.cpp
DocumentXML.cpp
@@ -31,5 +32,6 @@
StmtXML.cpp
TextDiagnosticBuffer.cpp
TextDiagnosticPrinter.cpp
+ TypeXML.cpp
Warnings.cpp
)
diff --git a/lib/Frontend/DeclXML.cpp b/lib/Frontend/DeclXML.cpp
new file mode 100644
index 0000000..5c21999
--- /dev/null
+++ b/lib/Frontend/DeclXML.cpp
@@ -0,0 +1,161 @@
+//===--- DeclXML.cpp - XML implementation for Decl ASTs -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the XML document class, which provides the means to
+// dump out the AST in a XML form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/Expr.h"
+
+namespace clang {
+
+//---------------------------------------------------------
+class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter>
+{
+ DocumentXML& Doc;
+
+ void addSubNodes(FunctionDecl* FD)
+ {
+ for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i)
+ {
+ Visit(FD->getParamDecl(i));
+ Doc.toParent();
+ }
+ }
+
+ void addSubNodes(RecordDecl* RD)
+ {
+ for (RecordDecl::field_iterator i = RD->field_begin(*Doc.Ctx), e = RD->field_end(*Doc.Ctx); i != e; ++i)
+ {
+ Visit(*i);
+ Doc.toParent();
+ }
+ }
+
+ void addSubNodes(EnumDecl* ED)
+ {
+ for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(*Doc.Ctx), e = ED->enumerator_end(*Doc.Ctx); i != e; ++i)
+ {
+ Visit(*i);
+ Doc.toParent();
+ }
+ }
+
+ void addSubNodes(EnumConstantDecl* ECD)
+ {
+ if (ECD->getInitExpr())
+ {
+ Doc.PrintStmt(ECD->getInitExpr());
+ }
+ }
+
+ void addSubNodes(FieldDecl* FdD)
+ {
+ if (FdD->isBitField())
+ {
+ Doc.PrintStmt(FdD->getBitWidth());
+ }
+ }
+
+ void addSubNodes(VarDecl* V)
+ {
+ if (V->getInit())
+ {
+ Doc.PrintStmt(V->getInit());
+ }
+ }
+
+ void addSubNodes(ParmVarDecl* argDecl)
+ {
+ if (argDecl->getDefaultArg())
+ {
+ Doc.PrintStmt(argDecl->getDefaultArg());
+ }
+ }
+
+ void addSpecialAttribute(const char* pName, EnumDecl* ED)
+ {
+ const QualType& enumType = ED->getIntegerType();
+ if (!enumType.isNull())
+ {
+ Doc.addAttribute(pName, enumType);
+ }
+ }
+
+ void addIdAttribute(LinkageSpecDecl* ED)
+ {
+ Doc.addAttribute("id", ED);
+ }
+
+ void addIdAttribute(NamedDecl* ND)
+ {
+ Doc.addAttribute("id", ND);
+ }
+
+public:
+ DeclPrinter(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(CLASS* T) \
+ { \
+ Doc.addSubNode(NAME);
+
+#define ID_ATTRIBUTE_XML addIdAttribute(T);
+#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN);
+#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN);
+#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocation(T->getLocation());
+#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, T);
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = false; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = true; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML } }
+#define END_NODE_XML }
+
+#define SUB_NODE_XML( CLASS ) addSubNodes(T);
+#define SUB_NODE_SEQUENCE_XML( CLASS ) addSubNodes(T);
+#define SUB_NODE_OPT_XML( CLASS ) addSubNodes(T);
+
+#include "clang/Frontend/DeclXML.def"
+};
+
+
+//---------------------------------------------------------
+void DocumentXML::writeDeclToXML(Decl *D)
+{
+ DeclPrinter(*this).Visit(D);
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+ {
+ if (Stmt *Body = FD->getBody(*Ctx)) {
+ addSubNode("Body");
+ PrintStmt(Body);
+ toParent();
+ }
+ }
+ toParent();
+}
+
+//---------------------------------------------------------
+} // NS clang
+
diff --git a/lib/Frontend/DocumentXML.cpp b/lib/Frontend/DocumentXML.cpp
index 7562d2a..19a7573 100644
--- a/lib/Frontend/DocumentXML.cpp
+++ b/lib/Frontend/DocumentXML.cpp
@@ -14,92 +14,66 @@
#include "clang/Frontend/DocumentXML.h"
#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/Expr.h"
+#include "clang/AST/ASTContext.h"
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/StringExtras.h"
namespace clang {
//---------------------------------------------------------
-struct DocumentXML::NodeXML
-{
- std::string Name;
- NodeXML* Parent;
-
- NodeXML(const std::string& name, NodeXML* parent) :
- Name(name),
- Parent(parent)
- {}
-};
-
-//---------------------------------------------------------
DocumentXML::DocumentXML(const std::string& rootName, llvm::raw_ostream& out) :
- Root(new NodeXML(rootName, 0)),
- CurrentNode(Root),
Out(out),
Ctx(0),
- CurrentIndent(0),
HasCurrentNodeSubNodes(false)
{
+ NodeStack.push(rootName);
Out << "<?xml version=\"1.0\"?>\n<" << rootName;
}
//---------------------------------------------------------
-DocumentXML::~DocumentXML()
-{
- assert(CurrentNode == Root && "not completely backtracked");
- delete Root;
-}
-
-//---------------------------------------------------------
DocumentXML& DocumentXML::addSubNode(const std::string& name)
{
if (!HasCurrentNodeSubNodes)
{
Out << ">\n";
}
- CurrentNode = new NodeXML(name, CurrentNode);
+ NodeStack.push(name);
HasCurrentNodeSubNodes = false;
- CurrentIndent += 2;
Indent();
- Out << "<" << CurrentNode->Name;
+ Out << "<" << NodeStack.top();
return *this;
}
//---------------------------------------------------------
void DocumentXML::Indent()
{
- for (int i = 0; i < CurrentIndent; ++i)
+ for (size_t i = 0, e = (NodeStack.size() - 1) * 2; i < e; ++i)
Out << ' ';
}
//---------------------------------------------------------
DocumentXML& DocumentXML::toParent()
{
- assert(CurrentNode != Root && "to much backtracking");
+ assert(NodeStack.size() > 1 && "to much backtracking");
if (HasCurrentNodeSubNodes)
{
Indent();
- Out << "</" << CurrentNode->Name << ">\n";
+ Out << "</" << NodeStack.top() << ">\n";
}
else
{
Out << "/>\n";
}
- NodeXML* NodeToDelete = CurrentNode;
- CurrentNode = CurrentNode->Parent;
- delete NodeToDelete;
+ NodeStack.pop();
HasCurrentNodeSubNodes = true;
- CurrentIndent -= 2;
return *this;
}
//---------------------------------------------------------
namespace {
-enum tIdType { ID_NORMAL, ID_FILE, ID_LAST };
+enum tIdType { ID_NORMAL, ID_FILE, ID_LABEL, ID_LAST };
unsigned getNewId(tIdType idType)
{
@@ -110,7 +84,7 @@
//---------------------------------------------------------
inline std::string getPrefixedId(unsigned uId, tIdType idType)
{
- static const char idPrefix[ID_LAST] = { '_', 'f' };
+ static const char idPrefix[ID_LAST] = { '_', 'f', 'l' };
char buffer[20];
char* BufPtr = llvm::utohex_buffer(uId, buffer + 20);
*--BufPtr = idPrefix[idType];
@@ -132,6 +106,7 @@
} // anon NS
+
//---------------------------------------------------------
std::string DocumentXML::escapeString(const char* pStr, std::string::size_type len)
{
@@ -170,7 +145,7 @@
//---------------------------------------------------------
void DocumentXML::finalize()
{
- assert(CurrentNode == Root && "not completely backtracked");
+ assert(NodeStack.size() == 1 && "not completely backtracked");
addSubNode("ReferenceSection");
addSubNode("Types");
@@ -179,71 +154,15 @@
{
if (i->first.getCVRQualifiers() != 0)
{
- addSubNode("CvQualifiedType");
+ writeTypeToXML(i->first);
addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
- addAttribute("type", getPrefixedId(BasicTypes[i->first.getTypePtr()], ID_NORMAL));
- if (i->first.isConstQualified()) addAttribute("const", "1");
- if (i->first.isVolatileQualified()) addAttribute("volatile", "1");
- if (i->first.isRestrictQualified()) addAttribute("restrict", "1");
toParent();
}
}
for (XML::IdMap<const Type*>::iterator i = BasicTypes.begin(), e = BasicTypes.end(); i != e; ++i)
{
- // don't use the get methods as they strip of typedef infos
- if (const BuiltinType *BT = dyn_cast<BuiltinType>(i->first)) {
- addSubNode("FundamentalType");
- addAttribute("name", BT->getName(Ctx->getLangOptions().CPlusPlus));
- }
- else if (const PointerType *PT = dyn_cast<PointerType>(i->first)) {
- addSubNode("PointerType");
- addTypeAttribute(PT->getPointeeType());
- }
- else if (dyn_cast<FunctionType>(i->first) != 0) {
- addSubNode("FunctionType");
- }
- else if (const ReferenceType *RT = dyn_cast<ReferenceType>(i->first)) {
- addSubNode("ReferenceType");
- addTypeAttribute(RT->getPointeeType());
- }
- else if (const TypedefType * TT = dyn_cast<TypedefType>(i->first)) {
- addSubNode("Typedef");
- addAttribute("name", TT->getDecl()->getNameAsString());
- addTypeAttribute(TT->getDecl()->getUnderlyingType());
- addContextAttribute(TT->getDecl()->getDeclContext());
- }
- else if (const QualifiedNameType *QT = dyn_cast<QualifiedNameType>(i->first)) {
- addSubNode("QualifiedNameType");
- addTypeAttribute(QT->getNamedType());
- }
- else if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(i->first)) {
- addSubNode("ArrayType");
- addAttribute("min", 0);
- addAttribute("max", (CAT->getSize() - 1).toString(10, false));
- addTypeAttribute(CAT->getElementType());
- }
- else if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(i->first)) {
- addSubNode("VariableArrayType");
- addTypeAttribute(VAT->getElementType());
- }
- else if (const TagType *RET = dyn_cast<TagType>(i->first)) {
- const TagDecl *tagDecl = RET->getDecl();
- std::string tagKind = tagDecl->getKindName();
- tagKind[0] = std::toupper(tagKind[0]);
- addSubNode(tagKind);
- addAttribute("name", tagDecl->getNameAsString());
- addContextAttribute(tagDecl->getDeclContext());
- }
- else if (const VectorType* VT = dyn_cast<VectorType>(i->first)) {
- addSubNode("VectorType");
- addTypeAttribute(VT->getElementType());
- addAttribute("num_elements", VT->getNumElements());
- }
- else
- {
- addSubNode("FIXMEType");
- }
+ writeTypeToXML(i->first);
addAttribute("id", getPrefixedId(i->second, ID_NORMAL));
toParent();
}
@@ -267,7 +186,7 @@
if (const DeclContext* parent = i->first->getParent())
{
- addContextAttribute(parent);
+ addAttribute("context", parent);
}
toParent();
}
@@ -285,21 +204,21 @@
toParent().toParent();
// write the root closing node (which has always subnodes)
- Out << "</" << CurrentNode->Name << ">\n";
+ Out << "</" << NodeStack.top() << ">\n";
}
//---------------------------------------------------------
-void DocumentXML::addTypeAttribute(const QualType& pType)
+void DocumentXML::addAttribute(const char* pAttributeName, const QualType& pType)
{
addTypeRecursively(pType);
- addAttribute("type", getPrefixedId(Types[pType], ID_NORMAL));
+ addAttribute(pAttributeName, getPrefixedId(Types[pType], ID_NORMAL));
}
//---------------------------------------------------------
-void DocumentXML::addTypeIdAttribute(const Type* pType)
+void DocumentXML::addPtrAttribute(const char* pAttributeName, const Type* pType)
{
- addBasicTypeRecursively(pType);
- addAttribute("id", getPrefixedId(BasicTypes[pType], ID_NORMAL));
+ addTypeRecursively(pType);
+ addAttribute(pAttributeName, getPrefixedId(BasicTypes[pType], ID_NORMAL));
}
//---------------------------------------------------------
@@ -307,7 +226,7 @@
{
if (addToMap(Types, pType))
{
- addBasicTypeRecursively(pType.getTypePtr());
+ addTypeRecursively(pType.getTypePtr());
// beautifier: a non-qualified type shall be transparent
if (pType.getCVRQualifiers() == 0)
{
@@ -317,43 +236,49 @@
}
//---------------------------------------------------------
-void DocumentXML::addBasicTypeRecursively(const Type* pType)
+void DocumentXML::addTypeRecursively(const Type* pType)
{
if (addToMap(BasicTypes, pType))
{
- if (const PointerType *PT = dyn_cast<PointerType>(pType)) {
- addTypeRecursively(PT->getPointeeType());
+ addParentTypes(pType);
+/*
+ // FIXME: doesn't work in the immediate streaming approach
+ if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(pType))
+ {
+ addSubNode("VariableArraySizeExpression");
+ PrintStmt(VAT->getSizeExpr());
+ toParent();
}
- else if (const ReferenceType *RT = dyn_cast<ReferenceType>(pType)) {
- addTypeRecursively(RT->getPointeeType());
- }
- else if (const TypedefType *TT = dyn_cast<TypedefType>(pType)) {
- addTypeRecursively(TT->getDecl()->getUnderlyingType());
- addContextsRecursively(TT->getDecl()->getDeclContext());
- }
- else if (const QualifiedNameType *QT = dyn_cast<QualifiedNameType>(pType)) {
- addTypeRecursively(QT->getNamedType());
- // FIXME: what to do with NestedNameSpecifier or shall this type be transparent?
- }
- else if (const ArrayType *AT = dyn_cast<ArrayType>(pType)) {
- addTypeRecursively(AT->getElementType());
- // FIXME: doesn't work in the immediate streaming approach
- /*if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(AT))
- {
- addSubNode("VariableArraySizeExpression");
- PrintStmt(VAT->getSizeExpr());
- toParent();
- }*/
- }
+*/
}
}
//---------------------------------------------------------
-void DocumentXML::addContextAttribute(const DeclContext *DC, tContextUsage usage)
+void DocumentXML::addPtrAttribute(const char* pName, const DeclContext* DC)
{
addContextsRecursively(DC);
- const char* pAttributeTags[2] = { "context", "id" };
- addAttribute(pAttributeTags[usage], getPrefixedId(Contexts[DC], ID_NORMAL));
+ addAttribute(pName, getPrefixedId(Contexts[DC], ID_NORMAL));
+}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pAttributeName, const NamedDecl* D)
+{
+ if (const DeclContext* DC = dyn_cast<DeclContext>(D))
+ {
+ addContextsRecursively(DC);
+ addAttribute(pAttributeName, getPrefixedId(Contexts[DC], ID_NORMAL));
+ }
+ else
+ {
+ addToMap(Decls, D);
+ addAttribute(pAttributeName, getPrefixedId(Decls[D], ID_NORMAL));
+ }
+}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pName, const NamespaceDecl* D)
+{
+ addPtrAttribute(pName, static_cast<const DeclContext*>(D));
}
//---------------------------------------------------------
@@ -372,6 +297,15 @@
addAttribute("file", getPrefixedId(SourceFiles[fileName], ID_FILE));
}
+
+//---------------------------------------------------------
+void DocumentXML::addPtrAttribute(const char* pName, const LabelStmt* L)
+{
+ addToMap(Labels, L, ID_LABEL);
+ addAttribute(pName, getPrefixedId(Labels[L], ID_LABEL));
+}
+
+
//---------------------------------------------------------
PresumedLoc DocumentXML::addLocation(const SourceLocation& Loc)
{
@@ -417,161 +351,9 @@
}
//---------------------------------------------------------
-void DocumentXML::PrintFunctionDecl(FunctionDecl *FD)
-{
- switch (FD->getStorageClass()) {
- default: assert(0 && "Unknown storage class");
- case FunctionDecl::None: break;
- case FunctionDecl::Extern: addAttribute("storage_class", "extern"); break;
- case FunctionDecl::Static: addAttribute("storage_class", "static"); break;
- case FunctionDecl::PrivateExtern: addAttribute("storage_class", "__private_extern__"); break;
- }
-
- if (FD->isInline())
- addAttribute("inline", "1");
-
- const FunctionType *AFT = FD->getType()->getAsFunctionType();
- addTypeAttribute(AFT->getResultType());
- addBasicTypeRecursively(AFT);
-
- if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(AFT)) {
- addAttribute("num_args", FD->getNumParams());
- for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
- addSubNode("Argument");
- ParmVarDecl *argDecl = FD->getParamDecl(i);
- addAttribute("name", argDecl->getNameAsString());
- addTypeAttribute(FT->getArgType(i));
- addDeclIdAttribute(argDecl);
- if (argDecl->getDefaultArg())
- {
- addAttribute("default_arg", "1");
- PrintStmt(argDecl->getDefaultArg());
- }
- toParent();
- }
-
- if (FT->isVariadic()) {
- addSubNode("Ellipsis").toParent();
- }
- } else {
- assert(isa<FunctionNoProtoType>(AFT));
- }
-}
-
-//---------------------------------------------------------
-void DocumentXML::addRefAttribute(const NamedDecl* D)
-{
- // FIXME: in case of CXX inline member functions referring to a member defined
- // after the function it needs to be tested, if the ids are already there
- // (should work, but I couldn't test it)
- if (const DeclContext* DC = dyn_cast<DeclContext>(D))
- {
- addAttribute("ref", getPrefixedId(Contexts[DC], ID_NORMAL));
- }
- else
- {
- addAttribute("ref", getPrefixedId(Decls[D], ID_NORMAL));
- }
-}
-
-//---------------------------------------------------------
-void DocumentXML::addDeclIdAttribute(const NamedDecl* D)
-{
- addToMap(Decls, D);
- addAttribute("id", getPrefixedId(Decls[D], ID_NORMAL));
-}
-
-//---------------------------------------------------------
void DocumentXML::PrintDecl(Decl *D)
{
- addSubNode(D->getDeclKindName());
- addContextAttribute(D->getDeclContext());
- addLocation(D->getLocation());
- if (DeclContext* DC = dyn_cast<DeclContext>(D))
- {
- addContextAttribute(DC, CONTEXT_AS_ID);
- }
-
- if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
- addAttribute("name", ND->getNameAsString());
-
- if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- PrintFunctionDecl(FD);
- if (Stmt *Body = FD->getBody(*Ctx)) {
- addSubNode("Body");
- PrintStmt(Body);
- toParent();
- }
- } else if (RecordDecl *RD = dyn_cast<RecordDecl>(D)) {
- addBasicTypeRecursively(RD->getTypeForDecl());
- addAttribute("type", getPrefixedId(BasicTypes[RD->getTypeForDecl()], ID_NORMAL));
- if (!RD->isDefinition())
- {
- addAttribute("forward", "1");
- }
-
- for (RecordDecl::field_iterator i = RD->field_begin(*Ctx), e = RD->field_end(*Ctx); i != e; ++i)
- {
- PrintDecl(*i);
- }
- } else if (EnumDecl *ED = dyn_cast<EnumDecl>(D)) {
- const QualType& enumType = ED->getIntegerType();
- if (!enumType.isNull())
- {
- addTypeAttribute(enumType);
- for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(*Ctx), e = ED->enumerator_end(*Ctx); i != e; ++i)
- {
- PrintDecl(*i);
- }
- }
- } else if (EnumConstantDecl* ECD = dyn_cast<EnumConstantDecl>(D)) {
- addTypeAttribute(ECD->getType());
- addAttribute("value", ECD->getInitVal().toString(10, true));
- if (ECD->getInitExpr())
- {
- PrintStmt(ECD->getInitExpr());
- }
- } else if (FieldDecl *FdD = dyn_cast<FieldDecl>(D)) {
- addTypeAttribute(FdD->getType());
- addDeclIdAttribute(ND);
- if (FdD->isMutable())
- addAttribute("mutable", "1");
- if (FdD->isBitField())
- {
- addAttribute("bitfield", "1");
- PrintStmt(FdD->getBitWidth());
- }
- } else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) {
- addTypeIdAttribute(Ctx->getTypedefType(TD).getTypePtr());
- addTypeAttribute(TD->getUnderlyingType());
- } else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
- addTypeAttribute(VD->getType());
- addDeclIdAttribute(ND);
-
- VarDecl *V = dyn_cast<VarDecl>(VD);
- if (V && V->getStorageClass() != VarDecl::None)
- {
- addAttribute("storage_class", VarDecl::getStorageClassSpecifierString(V->getStorageClass()));
- }
-
- if (V && V->getInit())
- {
- PrintStmt(V->getInit());
- }
- }
- } else if (LinkageSpecDecl* LSD = dyn_cast<LinkageSpecDecl>(D)) {
- switch (LSD->getLanguage())
- {
- case LinkageSpecDecl::lang_c: addAttribute("lang", "C"); break;
- case LinkageSpecDecl::lang_cxx: addAttribute("lang", "CXX"); break;
- default: assert(0 && "Unexpected lang id");
- }
- } else if (isa<FileScopeAsmDecl>(D)) {
- // FIXME: Implement this
- } else {
- assert(0 && "Unexpected decl");
- }
- toParent();
+ writeDeclToXML(D);
}
//---------------------------------------------------------
diff --git a/lib/Frontend/StmtXML.cpp b/lib/Frontend/StmtXML.cpp
index c861881..6ba0a28 100644
--- a/lib/Frontend/StmtXML.cpp
+++ b/lib/Frontend/StmtXML.cpp
@@ -28,8 +28,31 @@
class VISIBILITY_HIDDEN StmtXML : public StmtVisitor<StmtXML> {
DocumentXML& Doc;
- static const char *getOpcodeStr(UnaryOperator::Opcode Op);
- static const char *getOpcodeStr(BinaryOperator::Opcode Op);
+ //static const char *getOpcodeStr(UnaryOperator::Opcode Op);
+ //static const char *getOpcodeStr(BinaryOperator::Opcode Op);
+
+
+ void addSpecialAttribute(const char* pName, StringLiteral* Str)
+ {
+ Doc.addAttribute(pName, Doc.escapeString(Str->getStrData(), Str->getByteLength()));
+ }
+
+ void addSpecialAttribute(const char* pName, SizeOfAlignOfExpr* S)
+ {
+ if (S->isArgumentType())
+ {
+ Doc.addAttribute(pName, S->getArgumentType());
+ }
+ }
+
+ void addSpecialAttribute(const char* pName, CXXTypeidExpr* S)
+ {
+ if (S->isTypeOperand())
+ {
+ Doc.addAttribute(pName, S->getTypeOperand());
+ }
+ }
+
public:
StmtXML(DocumentXML& doc)
@@ -39,12 +62,21 @@
void DumpSubTree(Stmt *S) {
if (S)
{
- Doc.addSubNode(S->getStmtClassName());
- Doc.addLocationRange(S->getSourceRange());
- if (DeclStmt* DS = dyn_cast<DeclStmt>(S)) {
- VisitDeclStmt(DS);
- } else {
- Visit(S);
+ Visit(S);
+ if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
+ {
+ for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
+ DI != DE; ++DI)
+ {
+ Doc.PrintDecl(*DI);
+ }
+ }
+ else
+ {
+ if (CXXConditionDeclExpr* CCDE = dyn_cast<CXXConditionDeclExpr>(S))
+ {
+ Doc.PrintDecl(CCDE->getVarDecl());
+ }
for (Stmt::child_iterator i = S->child_begin(), e = S->child_end(); i != e; ++i)
{
DumpSubTree(*i);
@@ -56,17 +88,46 @@
}
}
- void DumpTypeExpr(const QualType& T)
- {
- Doc.addSubNode("TypeExpr");
- Doc.addTypeAttribute(T);
- Doc.toParent();
- }
- void DumpExpr(const Expr *Node) {
- Doc.addTypeAttribute(Node->getType());
- }
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(CLASS* S) \
+ { \
+ typedef CLASS tStmtType; \
+ Doc.addSubNode(NAME);
+#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, S->FN);
+#define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
+#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, S->FN);
+#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, S);
+#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocationRange(S->getSourceRange());
+
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = false; \
+ switch (S->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = true; \
+ switch (S->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML } }
+#define END_NODE_XML }
+
+#define ID_ATTRIBUTE_XML Doc.addAttribute("id", S);
+#define SUB_NODE_XML( CLASS )
+#define SUB_NODE_SEQUENCE_XML( CLASS )
+#define SUB_NODE_OPT_XML( CLASS )
+
+#include "clang/Frontend/StmtXML.def"
+
+#if (0)
// Stmts.
void VisitStmt(Stmt *Node);
void VisitDeclStmt(DeclStmt *Node);
@@ -105,13 +166,14 @@
void VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node);
void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
void VisitObjCSuperExpr(ObjCSuperExpr *Node);
+#endif
};
}
//===----------------------------------------------------------------------===//
// Stmt printing methods.
//===----------------------------------------------------------------------===//
-
+#if (0)
void StmtXML::VisitStmt(Stmt *Node)
{
// nothing special to do
@@ -396,7 +458,7 @@
if (Node->isFreeIvar())
Doc.addAttribute("isFreeIvar", "1");
}
-
+#endif
//===----------------------------------------------------------------------===//
// Stmt method implementations
//===----------------------------------------------------------------------===//
diff --git a/lib/Frontend/TypeXML.cpp b/lib/Frontend/TypeXML.cpp
new file mode 100644
index 0000000..f32fbbd
--- /dev/null
+++ b/lib/Frontend/TypeXML.cpp
@@ -0,0 +1,127 @@
+//===--- DocumentXML.cpp - XML document for ASTs --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the XML document class, which provides the means to
+// dump out the AST in a XML form that exposes type details and other fields.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Frontend/DocumentXML.h"
+#include "clang/AST/TypeVisitor.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/Decl.h"
+
+namespace clang {
+ namespace XML {
+ namespace {
+
+//---------------------------------------------------------
+class TypeWriter : public TypeVisitor<TypeWriter>
+{
+ DocumentXML& Doc;
+
+public:
+ TypeWriter(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(CLASS* T) \
+ { \
+ Doc.addSubNode(NAME);
+
+#define ID_ATTRIBUTE_XML // done by the Document class itself
+#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN);
+#define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
+#define CONTEXT_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "context")
+#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN);
+
+#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = false; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
+ { \
+ const char* pAttributeName = NAME; \
+ const bool optional = true; \
+ switch (T->FN) { \
+ default: assert(0 && "unknown enum value");
+
+#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
+#define END_ENUM_XML } }
+#define END_NODE_XML }
+
+#include "clang/Frontend/TypeXML.def"
+
+};
+
+//---------------------------------------------------------
+ } // anon clang
+ } // NS XML
+
+//---------------------------------------------------------
+class DocumentXML::TypeAdder : public TypeVisitor<DocumentXML::TypeAdder>
+{
+ DocumentXML& Doc;
+
+ void addIfType(const Type* pType)
+ {
+ Doc.addTypeRecursively(pType);
+ }
+
+ void addIfType(const QualType& pType)
+ {
+ Doc.addTypeRecursively(pType);
+ }
+
+ template<class T> void addIfType(T) {}
+
+public:
+ TypeAdder(DocumentXML& doc) : Doc(doc) {}
+
+#define NODE_XML( CLASS, NAME ) \
+ void Visit##CLASS(CLASS* T) \
+ {
+
+#define ID_ATTRIBUTE_XML
+#define TYPE_ATTRIBUTE_XML( FN ) Doc.addTypeRecursively(T->FN);
+#define CONTEXT_ATTRIBUTE_XML( FN )
+#define ATTRIBUTE_XML( FN, NAME ) addIfType(T->FN);
+#define ATTRIBUTE_OPT_XML( FN, NAME )
+#define ATTRIBUTE_ENUM_XML( FN, NAME )
+#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME )
+#define ENUM_XML( VALUE, NAME )
+#define END_ENUM_XML
+#define END_NODE_XML }
+
+#include "clang/Frontend/TypeXML.def"
+};
+
+//---------------------------------------------------------
+void DocumentXML::addParentTypes(const Type* pType)
+{
+ TypeAdder(*this).Visit(const_cast<Type*>(pType));
+}
+
+//---------------------------------------------------------
+void DocumentXML::writeTypeToXML(const Type* pType)
+{
+ XML::TypeWriter(*this).Visit(const_cast<Type*>(pType));
+}
+
+//---------------------------------------------------------
+void DocumentXML::writeTypeToXML(const QualType& pType)
+{
+ XML::TypeWriter(*this).VisitQualType(const_cast<QualType*>(&pType));
+}
+
+//---------------------------------------------------------
+} // NS clang
+