blob: 5c21999bfa058b29c74366a8e8a22f3e6d7426cb [file] [log] [blame]
Douglas Gregor038f75a2009-06-15 19:02:54 +00001//===--- 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{
24 DocumentXML& Doc;
25
26 void addSubNodes(FunctionDecl* FD)
27 {
28 for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i)
29 {
30 Visit(FD->getParamDecl(i));
31 Doc.toParent();
32 }
33 }
34
35 void addSubNodes(RecordDecl* RD)
36 {
37 for (RecordDecl::field_iterator i = RD->field_begin(*Doc.Ctx), e = RD->field_end(*Doc.Ctx); i != e; ++i)
38 {
39 Visit(*i);
40 Doc.toParent();
41 }
42 }
43
44 void addSubNodes(EnumDecl* ED)
45 {
46 for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(*Doc.Ctx), e = ED->enumerator_end(*Doc.Ctx); i != e; ++i)
47 {
48 Visit(*i);
49 Doc.toParent();
50 }
51 }
52
53 void addSubNodes(EnumConstantDecl* ECD)
54 {
55 if (ECD->getInitExpr())
56 {
57 Doc.PrintStmt(ECD->getInitExpr());
58 }
59 }
60
61 void addSubNodes(FieldDecl* FdD)
62 {
63 if (FdD->isBitField())
64 {
65 Doc.PrintStmt(FdD->getBitWidth());
66 }
67 }
68
69 void addSubNodes(VarDecl* V)
70 {
71 if (V->getInit())
72 {
73 Doc.PrintStmt(V->getInit());
74 }
75 }
76
77 void addSubNodes(ParmVarDecl* argDecl)
78 {
79 if (argDecl->getDefaultArg())
80 {
81 Doc.PrintStmt(argDecl->getDefaultArg());
82 }
83 }
84
85 void addSpecialAttribute(const char* pName, EnumDecl* ED)
86 {
87 const QualType& enumType = ED->getIntegerType();
88 if (!enumType.isNull())
89 {
90 Doc.addAttribute(pName, enumType);
91 }
92 }
93
94 void addIdAttribute(LinkageSpecDecl* ED)
95 {
96 Doc.addAttribute("id", ED);
97 }
98
99 void addIdAttribute(NamedDecl* ND)
100 {
101 Doc.addAttribute("id", ND);
102 }
103
104public:
105 DeclPrinter(DocumentXML& doc) : Doc(doc) {}
106
107#define NODE_XML( CLASS, NAME ) \
108 void Visit##CLASS(CLASS* T) \
109 { \
110 Doc.addSubNode(NAME);
111
112#define ID_ATTRIBUTE_XML addIdAttribute(T);
113#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN);
114#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN);
115#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocation(T->getLocation());
116#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, T);
117
118#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
119 { \
120 const char* pAttributeName = NAME; \
121 const bool optional = false; \
122 switch (T->FN) { \
123 default: assert(0 && "unknown enum value");
124
125#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
126 { \
127 const char* pAttributeName = NAME; \
128 const bool optional = true; \
129 switch (T->FN) { \
130 default: assert(0 && "unknown enum value");
131
132#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
133#define END_ENUM_XML } }
134#define END_NODE_XML }
135
136#define SUB_NODE_XML( CLASS ) addSubNodes(T);
137#define SUB_NODE_SEQUENCE_XML( CLASS ) addSubNodes(T);
138#define SUB_NODE_OPT_XML( CLASS ) addSubNodes(T);
139
140#include "clang/Frontend/DeclXML.def"
141};
142
143
144//---------------------------------------------------------
145void DocumentXML::writeDeclToXML(Decl *D)
146{
147 DeclPrinter(*this).Visit(D);
148 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
149 {
150 if (Stmt *Body = FD->getBody(*Ctx)) {
151 addSubNode("Body");
152 PrintStmt(Body);
153 toParent();
154 }
155 }
156 toParent();
157}
158
159//---------------------------------------------------------
160} // NS clang
161