diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Frontend/DeclXML.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Frontend/DeclXML.cpp | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/Frontend/DeclXML.cpp b/contrib/llvm/tools/clang/lib/Frontend/DeclXML.cpp new file mode 100644 index 0000000..97a7f55 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Frontend/DeclXML.cpp @@ -0,0 +1,189 @@ +//===--- 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 addFunctionBody(FunctionDecl* FD) { + if (FD->isThisDeclarationADefinition()) { + Doc.addSubNode("Body"); + Doc.PrintStmt(FD->getBody()); + Doc.toParent(); + } + } + + void addSubNodes(RecordDecl* RD) { + for (RecordDecl::field_iterator i = RD->field_begin(), + e = RD->field_end(); i != e; ++i) { + Visit(*i); + Doc.toParent(); + } + } + + void addSubNodes(CXXRecordDecl* RD) { + addSubNodes(cast<RecordDecl>(RD)); + + if (RD->isDefinition()) { + // FIXME: This breaks XML generation + //Doc.addAttribute("num_bases", RD->getNumBases()); + + for (CXXRecordDecl::base_class_iterator + base = RD->bases_begin(), + bend = RD->bases_end(); + base != bend; + ++base) { + Doc.addSubNode("Base"); + Doc.addAttribute("id", base->getType()); + AccessSpecifier as = base->getAccessSpecifierAsWritten(); + const char* as_name = ""; + switch(as) { + case AS_none: as_name = ""; break; + case AS_public: as_name = "public"; break; + case AS_protected: as_name = "protected"; break; + case AS_private: as_name = "private"; break; + } + Doc.addAttributeOptional("access", as_name); + Doc.addAttribute("is_virtual", base->isVirtual()); + Doc.toParent(); + } + + for (CXXRecordDecl::method_iterator i = RD->method_begin(), + e = RD->method_end(); i != e; ++i) { + Visit(*i); + Doc.toParent(); + } + + } + + } + + void addSubNodes(EnumDecl* ED) { + for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(), + e = ED->enumerator_end(); 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 addSubNodes(NamespaceDecl* ns) { + + for (DeclContext::decl_iterator + d = ns->decls_begin(), + dend = ns->decls_end(); + d != dend; + ++d) { + Visit(*d); + Doc.toParent(); + } + } + + 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); + +#define SUB_NODE_FN_BODY_XML addFunctionBody(T); + +#include "clang/Frontend/DeclXML.def" +}; + + +//--------------------------------------------------------- +void DocumentXML::writeDeclToXML(Decl *D) { + DeclPrinter(*this).Visit(D); + toParent(); +} + +//--------------------------------------------------------- +} // NS clang + |