blob: 3b600ffd2f41071df11196a5ba95288f20f352d3 [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//
Mike Stump1eb44332009-09-09 15:08:12 +000010// This file implements the XML document class, which provides the means to
Douglas Gregor038f75a2009-06-15 19:02:54 +000011// 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
Mike Stump1eb44332009-09-09 15:08:12 +000021//---------------------------------------------------------
22class DocumentXML::DeclPrinter : public DeclVisitor<DocumentXML::DeclPrinter> {
Douglas Gregor038f75a2009-06-15 19:02:54 +000023 DocumentXML& Doc;
24
Mike Stump1eb44332009-09-09 15:08:12 +000025 void addSubNodes(FunctionDecl* FD) {
26 for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) {
Douglas Gregor038f75a2009-06-15 19:02:54 +000027 Visit(FD->getParamDecl(i));
28 Doc.toParent();
29 }
30 }
31
Douglas Gregor07425c92010-03-08 18:51:03 +000032 void addFunctionBody(FunctionDecl* FD) {
33 if (FD->isThisDeclarationADefinition()) {
34 Doc.addSubNode("Body");
35 Doc.PrintStmt(FD->getBody());
36 Doc.toParent();
37 }
38 }
39
Mike Stump1eb44332009-09-09 15:08:12 +000040 void addSubNodes(RecordDecl* RD) {
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +000041 for (RecordDecl::field_iterator i = RD->field_begin(),
42 e = RD->field_end(); i != e; ++i) {
Douglas Gregor038f75a2009-06-15 19:02:54 +000043 Visit(*i);
44 Doc.toParent();
45 }
Daniel Dunbar54d56a52010-09-29 16:09:28 +000046
47 for (RecordDecl::decl_iterator i = RD->decls_begin(),
48 e = RD->decls_end(); i != e; ++i) {
49 Decl *d = *i;
50 if (isa<RecordDecl>(d)) {
51 RecordDecl* pRec = cast<RecordDecl>(d);
52 if (pRec->isDefinition()) {
53 Visit(pRec);
54 Doc.toParent();
55 }
56 }
57 }
Douglas Gregor038f75a2009-06-15 19:02:54 +000058 }
59
Douglas Gregor07425c92010-03-08 18:51:03 +000060 void addSubNodes(CXXRecordDecl* RD) {
61 addSubNodes(cast<RecordDecl>(RD));
Douglas Gregor4bd98e82010-05-10 17:43:18 +000062
63 if (RD->isDefinition()) {
Chris Lattneredd8df92010-05-12 23:27:11 +000064 // FIXME: This breaks XML generation
65 //Doc.addAttribute("num_bases", RD->getNumBases());
Douglas Gregor4bd98e82010-05-10 17:43:18 +000066
67 for (CXXRecordDecl::base_class_iterator
68 base = RD->bases_begin(),
69 bend = RD->bases_end();
70 base != bend;
71 ++base) {
72 Doc.addSubNode("Base");
73 Doc.addAttribute("id", base->getType());
74 AccessSpecifier as = base->getAccessSpecifierAsWritten();
75 const char* as_name = "";
76 switch(as) {
77 case AS_none: as_name = ""; break;
78 case AS_public: as_name = "public"; break;
79 case AS_protected: as_name = "protected"; break;
80 case AS_private: as_name = "private"; break;
81 }
82 Doc.addAttributeOptional("access", as_name);
83 Doc.addAttribute("is_virtual", base->isVirtual());
84 Doc.toParent();
85 }
86
87 for (CXXRecordDecl::method_iterator i = RD->method_begin(),
88 e = RD->method_end(); i != e; ++i) {
89 Visit(*i);
90 Doc.toParent();
91 }
92
Douglas Gregor07425c92010-03-08 18:51:03 +000093 }
Douglas Gregor4bd98e82010-05-10 17:43:18 +000094
Douglas Gregor07425c92010-03-08 18:51:03 +000095 }
96
Mike Stump1eb44332009-09-09 15:08:12 +000097 void addSubNodes(EnumDecl* ED) {
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +000098 for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(),
99 e = ED->enumerator_end(); i != e; ++i) {
Douglas Gregor038f75a2009-06-15 19:02:54 +0000100 Visit(*i);
101 Doc.toParent();
102 }
103 }
104
Mike Stump1eb44332009-09-09 15:08:12 +0000105 void addSubNodes(EnumConstantDecl* ECD) {
106 if (ECD->getInitExpr())
Douglas Gregor038f75a2009-06-15 19:02:54 +0000107 Doc.PrintStmt(ECD->getInitExpr());
Douglas Gregor038f75a2009-06-15 19:02:54 +0000108 }
109
Mike Stump1eb44332009-09-09 15:08:12 +0000110 void addSubNodes(FieldDecl* FdD) {
Douglas Gregor038f75a2009-06-15 19:02:54 +0000111 if (FdD->isBitField())
Douglas Gregor038f75a2009-06-15 19:02:54 +0000112 Doc.PrintStmt(FdD->getBitWidth());
Douglas Gregor038f75a2009-06-15 19:02:54 +0000113 }
114
Mike Stump1eb44332009-09-09 15:08:12 +0000115 void addSubNodes(VarDecl* V) {
116 if (V->getInit())
Douglas Gregor038f75a2009-06-15 19:02:54 +0000117 Doc.PrintStmt(V->getInit());
Douglas Gregor038f75a2009-06-15 19:02:54 +0000118 }
119
Mike Stump1eb44332009-09-09 15:08:12 +0000120 void addSubNodes(ParmVarDecl* argDecl) {
Douglas Gregor038f75a2009-06-15 19:02:54 +0000121 if (argDecl->getDefaultArg())
Douglas Gregor038f75a2009-06-15 19:02:54 +0000122 Doc.PrintStmt(argDecl->getDefaultArg());
Douglas Gregor038f75a2009-06-15 19:02:54 +0000123 }
124
Douglas Gregor4bd98e82010-05-10 17:43:18 +0000125 void addSubNodes(NamespaceDecl* ns) {
126
127 for (DeclContext::decl_iterator
128 d = ns->decls_begin(),
129 dend = ns->decls_end();
130 d != dend;
131 ++d) {
132 Visit(*d);
133 Doc.toParent();
134 }
135 }
136
Mike Stump1eb44332009-09-09 15:08:12 +0000137 void addSpecialAttribute(const char* pName, EnumDecl* ED) {
Douglas Gregor038f75a2009-06-15 19:02:54 +0000138 const QualType& enumType = ED->getIntegerType();
139 if (!enumType.isNull())
Douglas Gregor038f75a2009-06-15 19:02:54 +0000140 Doc.addAttribute(pName, enumType);
Douglas Gregor038f75a2009-06-15 19:02:54 +0000141 }
142
Mike Stump1eb44332009-09-09 15:08:12 +0000143 void addIdAttribute(LinkageSpecDecl* ED) {
Douglas Gregor038f75a2009-06-15 19:02:54 +0000144 Doc.addAttribute("id", ED);
145 }
146
Mike Stump1eb44332009-09-09 15:08:12 +0000147 void addIdAttribute(NamedDecl* ND) {
Douglas Gregor038f75a2009-06-15 19:02:54 +0000148 Doc.addAttribute("id", ND);
149 }
150
151public:
152 DeclPrinter(DocumentXML& doc) : Doc(doc) {}
153
154#define NODE_XML( CLASS, NAME ) \
155 void Visit##CLASS(CLASS* T) \
156 { \
Mike Stump1eb44332009-09-09 15:08:12 +0000157 Doc.addSubNode(NAME);
Douglas Gregor038f75a2009-06-15 19:02:54 +0000158
159#define ID_ATTRIBUTE_XML addIdAttribute(T);
Mike Stump1eb44332009-09-09 15:08:12 +0000160#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN);
161#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN);
Douglas Gregor038f75a2009-06-15 19:02:54 +0000162#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocation(T->getLocation());
163#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, T);
164
165#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
166 { \
167 const char* pAttributeName = NAME; \
168 const bool optional = false; \
169 switch (T->FN) { \
Mike Stumpb7166332010-01-20 02:03:14 +0000170 default: assert(0 && "unknown enum value");
Douglas Gregor038f75a2009-06-15 19:02:54 +0000171
172#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
173 { \
174 const char* pAttributeName = NAME; \
175 const bool optional = true; \
176 switch (T->FN) { \
Mike Stumpb7166332010-01-20 02:03:14 +0000177 default: assert(0 && "unknown enum value");
Douglas Gregor038f75a2009-06-15 19:02:54 +0000178
179#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
180#define END_ENUM_XML } }
181#define END_NODE_XML }
182
183#define SUB_NODE_XML( CLASS ) addSubNodes(T);
184#define SUB_NODE_SEQUENCE_XML( CLASS ) addSubNodes(T);
185#define SUB_NODE_OPT_XML( CLASS ) addSubNodes(T);
186
Douglas Gregor07425c92010-03-08 18:51:03 +0000187#define SUB_NODE_FN_BODY_XML addFunctionBody(T);
188
Douglas Gregor038f75a2009-06-15 19:02:54 +0000189#include "clang/Frontend/DeclXML.def"
190};
191
192
Mike Stump1eb44332009-09-09 15:08:12 +0000193//---------------------------------------------------------
194void DocumentXML::writeDeclToXML(Decl *D) {
Douglas Gregor038f75a2009-06-15 19:02:54 +0000195 DeclPrinter(*this).Visit(D);
Douglas Gregor038f75a2009-06-15 19:02:54 +0000196 toParent();
197}
198
Mike Stump1eb44332009-09-09 15:08:12 +0000199//---------------------------------------------------------
Douglas Gregor038f75a2009-06-15 19:02:54 +0000200} // NS clang
201