blob: d7470d92a9463294315e5a80b817b6bdcfc6b9b7 [file] [log] [blame]
Shih-wei Liaof8fd82b2010-02-10 11:10:31 -08001//===--- DeclXML.cpp - XML implementation for Decl ASTs -------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the XML document class, which provides the means to
11// dump out the AST in a XML form that exposes type details and other fields.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Frontend/DocumentXML.h"
16#include "clang/AST/DeclVisitor.h"
17#include "clang/AST/Expr.h"
18
19namespace clang {
20
21//---------------------------------------------------------
22class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter> {
23 DocumentXML& Doc;
24
25 void addSubNodes(FunctionDecl* FD) {
26 for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
27 Visit(FD->getParamDecl(i));
28 Doc.toParent();
29 }
30 }
31
32 void addSubNodes(RecordDecl* RD) {
33 for (RecordDecl::field_iterator i = RD->field_begin(),
34 e = RD->field_end(); i != e; ++i) {
35 Visit(*i);
36 Doc.toParent();
37 }
38 }
39
40 void addSubNodes(EnumDecl* ED) {
41 for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(),
42 e = ED->enumerator_end(); i != e; ++i) {
43 Visit(*i);
44 Doc.toParent();
45 }
46 }
47
48 void addSubNodes(EnumConstantDecl* ECD) {
49 if (ECD->getInitExpr())
50 Doc.PrintStmt(ECD->getInitExpr());
51 }
52
53 void addSubNodes(FieldDecl* FdD) {
54 if (FdD->isBitField())
55 Doc.PrintStmt(FdD->getBitWidth());
56 }
57
58 void addSubNodes(VarDecl* V) {
59 if (V->getInit())
60 Doc.PrintStmt(V->getInit());
61 }
62
63 void addSubNodes(ParmVarDecl* argDecl) {
64 if (argDecl->getDefaultArg())
65 Doc.PrintStmt(argDecl->getDefaultArg());
66 }
67
68 void addSpecialAttribute(const char* pName, EnumDecl* ED) {
69 const QualType& enumType = ED->getIntegerType();
70 if (!enumType.isNull())
71 Doc.addAttribute(pName, enumType);
72 }
73
74 void addIdAttribute(LinkageSpecDecl* ED) {
75 Doc.addAttribute("id", ED);
76 }
77
78 void addIdAttribute(NamedDecl* ND) {
79 Doc.addAttribute("id", ND);
80 }
81
82public:
83 DeclPrinter(DocumentXML& doc) : Doc(doc) {}
84
85#define NODE_XML( CLASS, NAME ) \
86 void Visit##CLASS(CLASS* T) \
87 { \
88 Doc.addSubNode(NAME);
89
90#define ID_ATTRIBUTE_XML addIdAttribute(T);
91#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN);
92#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN);
93#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocation(T->getLocation());
94#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, T);
95
96#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
97 { \
98 const char* pAttributeName = NAME; \
99 const bool optional = false; \
100 switch (T->FN) { \
101 default: assert(0 && "unknown enum value");
102
103#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
104 { \
105 const char* pAttributeName = NAME; \
106 const bool optional = true; \
107 switch (T->FN) { \
108 default: assert(0 && "unknown enum value");
109
110#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
111#define END_ENUM_XML } }
112#define END_NODE_XML }
113
114#define SUB_NODE_XML( CLASS ) addSubNodes(T);
115#define SUB_NODE_SEQUENCE_XML( CLASS ) addSubNodes(T);
116#define SUB_NODE_OPT_XML( CLASS ) addSubNodes(T);
117
118#include "clang/Frontend/DeclXML.def"
119};
120
121
122//---------------------------------------------------------
123void DocumentXML::writeDeclToXML(Decl *D) {
124 DeclPrinter(*this).Visit(D);
125 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
126 if (Stmt *Body = FD->getBody()) {
127 addSubNode("Body");
128 PrintStmt(Body);
129 toParent();
130 }
131 }
132 toParent();
133}
134
135//---------------------------------------------------------
136} // NS clang
137