| //===--- 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(), | 
 |                                     e = RD->field_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 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()) { | 
 |       addSubNode("Body"); | 
 |       PrintStmt(Body); | 
 |       toParent(); | 
 |     } | 
 |   } | 
 |   toParent(); | 
 | } | 
 |  | 
 | //--------------------------------------------------------- | 
 | } // NS clang | 
 |  |