summaryrefslogtreecommitdiffstats
path: root/lib/Frontend/DeclXML.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Frontend/DeclXML.cpp')
-rw-r--r--lib/Frontend/DeclXML.cpp161
1 files changed, 161 insertions, 0 deletions
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
+
OpenPOWER on IntegriCloud