//===--- 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& 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(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