blob: 8750b1efcab53aa1ab5e0ceee2e6b524da97065a [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));
50 for (CXXRecordDecl::method_iterator i = RD->method_begin(),
51 e = RD->method_end(); i != e; ++i) {
52 Visit(*i);
53 Doc.toParent();
54 }
55 }
56
Mike Stump1eb44332009-09-09 15:08:12 +000057 void addSubNodes(EnumDecl* ED) {
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +000058 for (EnumDecl::enumerator_iterator i = ED->enumerator_begin(),
59 e = ED->enumerator_end(); i != e; ++i) {
Douglas Gregor038f75a2009-06-15 19:02:54 +000060 Visit(*i);
61 Doc.toParent();
62 }
63 }
64
Mike Stump1eb44332009-09-09 15:08:12 +000065 void addSubNodes(EnumConstantDecl* ECD) {
66 if (ECD->getInitExpr())
Douglas Gregor038f75a2009-06-15 19:02:54 +000067 Doc.PrintStmt(ECD->getInitExpr());
Douglas Gregor038f75a2009-06-15 19:02:54 +000068 }
69
Mike Stump1eb44332009-09-09 15:08:12 +000070 void addSubNodes(FieldDecl* FdD) {
Douglas Gregor038f75a2009-06-15 19:02:54 +000071 if (FdD->isBitField())
Douglas Gregor038f75a2009-06-15 19:02:54 +000072 Doc.PrintStmt(FdD->getBitWidth());
Douglas Gregor038f75a2009-06-15 19:02:54 +000073 }
74
Mike Stump1eb44332009-09-09 15:08:12 +000075 void addSubNodes(VarDecl* V) {
76 if (V->getInit())
Douglas Gregor038f75a2009-06-15 19:02:54 +000077 Doc.PrintStmt(V->getInit());
Douglas Gregor038f75a2009-06-15 19:02:54 +000078 }
79
Mike Stump1eb44332009-09-09 15:08:12 +000080 void addSubNodes(ParmVarDecl* argDecl) {
Douglas Gregor038f75a2009-06-15 19:02:54 +000081 if (argDecl->getDefaultArg())
Douglas Gregor038f75a2009-06-15 19:02:54 +000082 Doc.PrintStmt(argDecl->getDefaultArg());
Douglas Gregor038f75a2009-06-15 19:02:54 +000083 }
84
Mike Stump1eb44332009-09-09 15:08:12 +000085 void addSpecialAttribute(const char* pName, EnumDecl* ED) {
Douglas Gregor038f75a2009-06-15 19:02:54 +000086 const QualType& enumType = ED->getIntegerType();
87 if (!enumType.isNull())
Douglas Gregor038f75a2009-06-15 19:02:54 +000088 Doc.addAttribute(pName, enumType);
Douglas Gregor038f75a2009-06-15 19:02:54 +000089 }
90
Mike Stump1eb44332009-09-09 15:08:12 +000091 void addIdAttribute(LinkageSpecDecl* ED) {
Douglas Gregor038f75a2009-06-15 19:02:54 +000092 Doc.addAttribute("id", ED);
93 }
94
Mike Stump1eb44332009-09-09 15:08:12 +000095 void addIdAttribute(NamedDecl* ND) {
Douglas Gregor038f75a2009-06-15 19:02:54 +000096 Doc.addAttribute("id", ND);
97 }
98
99public:
100 DeclPrinter(DocumentXML& doc) : Doc(doc) {}
101
102#define NODE_XML( CLASS, NAME ) \
103 void Visit##CLASS(CLASS* T) \
104 { \
Mike Stump1eb44332009-09-09 15:08:12 +0000105 Doc.addSubNode(NAME);
Douglas Gregor038f75a2009-06-15 19:02:54 +0000106
107#define ID_ATTRIBUTE_XML addIdAttribute(T);
Mike Stump1eb44332009-09-09 15:08:12 +0000108#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, T->FN);
109#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, T->FN);
Douglas Gregor038f75a2009-06-15 19:02:54 +0000110#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocation(T->getLocation());
111#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, T);
112
113#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
114 { \
115 const char* pAttributeName = NAME; \
116 const bool optional = false; \
117 switch (T->FN) { \
Mike Stumpb7166332010-01-20 02:03:14 +0000118 default: assert(0 && "unknown enum value");
Douglas Gregor038f75a2009-06-15 19:02:54 +0000119
120#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
121 { \
122 const char* pAttributeName = NAME; \
123 const bool optional = true; \
124 switch (T->FN) { \
Mike Stumpb7166332010-01-20 02:03:14 +0000125 default: assert(0 && "unknown enum value");
Douglas Gregor038f75a2009-06-15 19:02:54 +0000126
127#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
128#define END_ENUM_XML } }
129#define END_NODE_XML }
130
131#define SUB_NODE_XML( CLASS ) addSubNodes(T);
132#define SUB_NODE_SEQUENCE_XML( CLASS ) addSubNodes(T);
133#define SUB_NODE_OPT_XML( CLASS ) addSubNodes(T);
134
Douglas Gregor07425c92010-03-08 18:51:03 +0000135#define SUB_NODE_FN_BODY_XML addFunctionBody(T);
136
Douglas Gregor038f75a2009-06-15 19:02:54 +0000137#include "clang/Frontend/DeclXML.def"
138};
139
140
Mike Stump1eb44332009-09-09 15:08:12 +0000141//---------------------------------------------------------
142void DocumentXML::writeDeclToXML(Decl *D) {
Douglas Gregor038f75a2009-06-15 19:02:54 +0000143 DeclPrinter(*this).Visit(D);
Douglas Gregor038f75a2009-06-15 19:02:54 +0000144 toParent();
145}
146
Mike Stump1eb44332009-09-09 15:08:12 +0000147//---------------------------------------------------------
Douglas Gregor038f75a2009-06-15 19:02:54 +0000148} // NS clang
149