blob: 3ae25f9b7da024fe4fbff048ca059bd0f1226e67 [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 }
46 }
47
Douglas Gregor07425c92010-03-08 18:51:03 +000048 void addSubNodes(CXXRecordDecl* RD) {
49 addSubNodes(cast<RecordDecl>(RD));
Douglas Gregor4bd98e82010-05-10 17:43:18 +000050
51 if (RD->isDefinition()) {
52 Doc.addAttribute("num_bases", RD->getNumBases());
53
54 for (CXXRecordDecl::base_class_iterator
55 base = RD->bases_begin(),
56 bend = RD->bases_end();
57 base != bend;
58 ++base) {
59 Doc.addSubNode("Base");
60 Doc.addAttribute("id", base->getType());
61 AccessSpecifier as = base->getAccessSpecifierAsWritten();
62 const char* as_name = "";
63 switch(as) {
64 case AS_none: as_name = ""; break;
65 case AS_public: as_name = "public"; break;
66 case AS_protected: as_name = "protected"; break;
67 case AS_private: as_name = "private"; break;
68 }
69 Doc.addAttributeOptional("access", as_name);
70 Doc.addAttribute("is_virtual", base->isVirtual());
71 Doc.toParent();
72 }
73
74 for (CXXRecordDecl::method_iterator i = RD->method_begin(),
75 e = RD->method_end(); i != e; ++i) {
76 Visit(*i);
77 Doc.toParent();
78 }
79
Douglas Gregor07425c92010-03-08 18:51:03 +000080 }
Douglas Gregor4bd98e82010-05-10 17:43:18 +000081
Douglas Gregor07425c92010-03-08 18:51:03 +000082 }
83
Mike Stump1eb44332009-09-09 15:08:12 +000084 void addSubNodes(EnumDecl* ED) {
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +000085 for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(),
86 e = ED->enumerator_end(); i != e; ++i) {
Douglas Gregor038f75a2009-06-15 19:02:54 +000087 Visit(*i);
88 Doc.toParent();
89 }
90 }
91
Mike Stump1eb44332009-09-09 15:08:12 +000092 void addSubNodes(EnumConstantDecl* ECD) {
93 if (ECD->getInitExpr())
Douglas Gregor038f75a2009-06-15 19:02:54 +000094 Doc.PrintStmt(ECD->getInitExpr());
Douglas Gregor038f75a2009-06-15 19:02:54 +000095 }
96
Mike Stump1eb44332009-09-09 15:08:12 +000097 void addSubNodes(FieldDecl* FdD) {
Douglas Gregor038f75a2009-06-15 19:02:54 +000098 if (FdD->isBitField())
Douglas Gregor038f75a2009-06-15 19:02:54 +000099 Doc.PrintStmt(FdD->getBitWidth());
Douglas Gregor038f75a2009-06-15 19:02:54 +0000100 }
101
Mike Stump1eb44332009-09-09 15:08:12 +0000102 void addSubNodes(VarDecl* V) {
103 if (V->getInit())
Douglas Gregor038f75a2009-06-15 19:02:54 +0000104 Doc.PrintStmt(V->getInit());
Douglas Gregor038f75a2009-06-15 19:02:54 +0000105 }
106
Mike Stump1eb44332009-09-09 15:08:12 +0000107 void addSubNodes(ParmVarDecl* argDecl) {
Douglas Gregor038f75a2009-06-15 19:02:54 +0000108 if (argDecl->getDefaultArg())
Douglas Gregor038f75a2009-06-15 19:02:54 +0000109 Doc.PrintStmt(argDecl->getDefaultArg());
Douglas Gregor038f75a2009-06-15 19:02:54 +0000110 }
111
Douglas Gregor4bd98e82010-05-10 17:43:18 +0000112 void addSubNodes(NamespaceDecl* ns) {
113
114 for (DeclContext::decl_iterator
115 d = ns->decls_begin(),
116 dend = ns->decls_end();
117 d != dend;
118 ++d) {
119 Visit(*d);
120 Doc.toParent();
121 }
122 }
123
Mike Stump1eb44332009-09-09 15:08:12 +0000124 void addSpecialAttribute(const char* pName, EnumDecl* ED) {
Douglas Gregor038f75a2009-06-15 19:02:54 +0000125 const QualType& enumType = ED->getIntegerType();
126 if (!enumType.isNull())
Douglas Gregor038f75a2009-06-15 19:02:54 +0000127 Doc.addAttribute(pName, enumType);
Douglas Gregor038f75a2009-06-15 19:02:54 +0000128 }
129
Mike Stump1eb44332009-09-09 15:08:12 +0000130 void addIdAttribute(LinkageSpecDecl* ED) {
Douglas Gregor038f75a2009-06-15 19:02:54 +0000131 Doc.addAttribute("id", ED);
132 }
133
Mike Stump1eb44332009-09-09 15:08:12 +0000134 void addIdAttribute(NamedDecl* ND) {
Douglas Gregor038f75a2009-06-15 19:02:54 +0000135 Doc.addAttribute("id", ND);
136 }
137
138public:
139 DeclPrinter(DocumentXML& doc) : Doc(doc) {}
140
141#define NODE_XML( CLASS, NAME ) \
142 void Visit##CLASS(CLASS* T) \
143 { \
Mike Stump1eb44332009-09-09 15:08:12 +0000144 Doc.addSubNode(NAME);
Douglas Gregor038f75a2009-06-15 19:02:54 +0000145
146#define ID_ATTRIBUTE_XML addIdAttribute(T);
Mike Stump1eb44332009-09-09 15:08:12 +0000147#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN);
148#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN);
Douglas Gregor038f75a2009-06-15 19:02:54 +0000149#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocation(T->getLocation());
150#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, T);
151
152#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
153 { \
154 const char* pAttributeName = NAME; \
155 const bool optional = false; \
156 switch (T->FN) { \
Mike Stumpb7166332010-01-20 02:03:14 +0000157 default: assert(0 && "unknown enum value");
Douglas Gregor038f75a2009-06-15 19:02:54 +0000158
159#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
160 { \
161 const char* pAttributeName = NAME; \
162 const bool optional = true; \
163 switch (T->FN) { \
Mike Stumpb7166332010-01-20 02:03:14 +0000164 default: assert(0 && "unknown enum value");
Douglas Gregor038f75a2009-06-15 19:02:54 +0000165
166#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
167#define END_ENUM_XML } }
168#define END_NODE_XML }
169
170#define SUB_NODE_XML( CLASS ) addSubNodes(T);
171#define SUB_NODE_SEQUENCE_XML( CLASS ) addSubNodes(T);
172#define SUB_NODE_OPT_XML( CLASS ) addSubNodes(T);
173
Douglas Gregor07425c92010-03-08 18:51:03 +0000174#define SUB_NODE_FN_BODY_XML addFunctionBody(T);
175
Douglas Gregor038f75a2009-06-15 19:02:54 +0000176#include "clang/Frontend/DeclXML.def"
177};
178
179
Mike Stump1eb44332009-09-09 15:08:12 +0000180//---------------------------------------------------------
181void DocumentXML::writeDeclToXML(Decl *D) {
Douglas Gregor038f75a2009-06-15 19:02:54 +0000182 DeclPrinter(*this).Visit(D);
Douglas Gregor038f75a2009-06-15 19:02:54 +0000183 toParent();
184}
185
Mike Stump1eb44332009-09-09 15:08:12 +0000186//---------------------------------------------------------
Douglas Gregor038f75a2009-06-15 19:02:54 +0000187} // NS clang
188