blob: 6ba0a28c7d201996ec1c90ed10417db88ebefdfe [file] [log] [blame]
Douglas Gregoree75c052009-05-21 20:55:50 +00001//===--- StmtXML.cpp - XML implementation for Stmt 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 Stmt::dumpXML methods, which dump out the
11// AST to an XML document.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Frontend/DocumentXML.h"
16#include "clang/AST/StmtVisitor.h"
17#include "clang/AST/DeclObjC.h"
18#include "clang/AST/DeclCXX.h"
19#include "clang/Basic/SourceManager.h"
20#include "llvm/Support/Compiler.h"
21using namespace clang;
22
23//===----------------------------------------------------------------------===//
24// StmtXML Visitor
25//===----------------------------------------------------------------------===//
26
27namespace {
28 class VISIBILITY_HIDDEN StmtXML : public StmtVisitor<StmtXML> {
29 DocumentXML& Doc;
30
Douglas Gregor038f75a2009-06-15 19:02:54 +000031 //static const char *getOpcodeStr(UnaryOperator::Opcode Op);
32 //static const char *getOpcodeStr(BinaryOperator::Opcode Op);
33
34
35 void addSpecialAttribute(const char* pName, StringLiteral* Str)
36 {
37 Doc.addAttribute(pName, Doc.escapeString(Str->getStrData(), Str->getByteLength()));
38 }
39
40 void addSpecialAttribute(const char* pName, SizeOfAlignOfExpr* S)
41 {
42 if (S->isArgumentType())
43 {
44 Doc.addAttribute(pName, S->getArgumentType());
45 }
46 }
47
48 void addSpecialAttribute(const char* pName, CXXTypeidExpr* S)
49 {
50 if (S->isTypeOperand())
51 {
52 Doc.addAttribute(pName, S->getTypeOperand());
53 }
54 }
55
Douglas Gregoree75c052009-05-21 20:55:50 +000056
57 public:
58 StmtXML(DocumentXML& doc)
59 : Doc(doc) {
60 }
61
62 void DumpSubTree(Stmt *S) {
63 if (S)
64 {
Douglas Gregor038f75a2009-06-15 19:02:54 +000065 Visit(S);
66 if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
67 {
68 for (DeclStmt::decl_iterator DI = DS->decl_begin(), DE = DS->decl_end();
69 DI != DE; ++DI)
70 {
71 Doc.PrintDecl(*DI);
72 }
73 }
74 else
75 {
76 if (CXXConditionDeclExpr* CCDE = dyn_cast<CXXConditionDeclExpr>(S))
77 {
78 Doc.PrintDecl(CCDE->getVarDecl());
79 }
Douglas Gregoree75c052009-05-21 20:55:50 +000080 for (Stmt::child_iterator i = S->child_begin(), e = S->child_end(); i != e; ++i)
81 {
82 DumpSubTree(*i);
83 }
84 }
85 Doc.toParent();
86 } else {
87 Doc.addSubNode("NULL").toParent();
88 }
89 }
90
Douglas Gregoree75c052009-05-21 20:55:50 +000091
Douglas Gregor038f75a2009-06-15 19:02:54 +000092#define NODE_XML( CLASS, NAME ) \
93 void Visit##CLASS(CLASS* S) \
94 { \
95 typedef CLASS tStmtType; \
96 Doc.addSubNode(NAME);
Douglas Gregoree75c052009-05-21 20:55:50 +000097
Douglas Gregor038f75a2009-06-15 19:02:54 +000098#define ATTRIBUTE_XML( FN, NAME ) Doc.addAttribute(NAME, S->FN);
99#define TYPE_ATTRIBUTE_XML( FN ) ATTRIBUTE_XML(FN, "type")
100#define ATTRIBUTE_OPT_XML( FN, NAME ) Doc.addAttributeOptional(NAME, S->FN);
101#define ATTRIBUTE_SPECIAL_XML( FN, NAME ) addSpecialAttribute(NAME, S);
102#define ATTRIBUTE_FILE_LOCATION_XML Doc.addLocationRange(S->getSourceRange());
103
104
105#define ATTRIBUTE_ENUM_XML( FN, NAME ) \
106 { \
107 const char* pAttributeName = NAME; \
108 const bool optional = false; \
109 switch (S->FN) { \
110 default: assert(0 && "unknown enum value");
111
112#define ATTRIBUTE_ENUM_OPT_XML( FN, NAME ) \
113 { \
114 const char* pAttributeName = NAME; \
115 const bool optional = true; \
116 switch (S->FN) { \
117 default: assert(0 && "unknown enum value");
118
119#define ENUM_XML( VALUE, NAME ) case VALUE: if ((!optional) || NAME[0]) Doc.addAttribute(pAttributeName, NAME); break;
120#define END_ENUM_XML } }
121#define END_NODE_XML }
122
123#define ID_ATTRIBUTE_XML Doc.addAttribute("id", S);
124#define SUB_NODE_XML( CLASS )
125#define SUB_NODE_SEQUENCE_XML( CLASS )
126#define SUB_NODE_OPT_XML( CLASS )
127
128#include "clang/Frontend/StmtXML.def"
129
130#if (0)
Douglas Gregoree75c052009-05-21 20:55:50 +0000131 // Stmts.
132 void VisitStmt(Stmt *Node);
133 void VisitDeclStmt(DeclStmt *Node);
134 void VisitLabelStmt(LabelStmt *Node);
135 void VisitGotoStmt(GotoStmt *Node);
136
137 // Exprs
138 void VisitExpr(Expr *Node);
139 void VisitDeclRefExpr(DeclRefExpr *Node);
140 void VisitPredefinedExpr(PredefinedExpr *Node);
141 void VisitCharacterLiteral(CharacterLiteral *Node);
142 void VisitIntegerLiteral(IntegerLiteral *Node);
143 void VisitFloatingLiteral(FloatingLiteral *Node);
144 void VisitStringLiteral(StringLiteral *Str);
145 void VisitUnaryOperator(UnaryOperator *Node);
146 void VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node);
147 void VisitMemberExpr(MemberExpr *Node);
148 void VisitExtVectorElementExpr(ExtVectorElementExpr *Node);
149 void VisitBinaryOperator(BinaryOperator *Node);
150 void VisitCompoundAssignOperator(CompoundAssignOperator *Node);
151 void VisitAddrLabelExpr(AddrLabelExpr *Node);
152 void VisitTypesCompatibleExpr(TypesCompatibleExpr *Node);
153
154 // C++
155 void VisitCXXNamedCastExpr(CXXNamedCastExpr *Node);
156 void VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node);
157 void VisitCXXThisExpr(CXXThisExpr *Node);
158 void VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node);
159
160 // ObjC
161 void VisitObjCEncodeExpr(ObjCEncodeExpr *Node);
162 void VisitObjCMessageExpr(ObjCMessageExpr* Node);
163 void VisitObjCSelectorExpr(ObjCSelectorExpr *Node);
164 void VisitObjCProtocolExpr(ObjCProtocolExpr *Node);
165 void VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node);
166 void VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node);
167 void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
168 void VisitObjCSuperExpr(ObjCSuperExpr *Node);
Douglas Gregor038f75a2009-06-15 19:02:54 +0000169#endif
Douglas Gregoree75c052009-05-21 20:55:50 +0000170 };
171}
172
173//===----------------------------------------------------------------------===//
174// Stmt printing methods.
175//===----------------------------------------------------------------------===//
Douglas Gregor038f75a2009-06-15 19:02:54 +0000176#if (0)
Douglas Gregoree75c052009-05-21 20:55:50 +0000177void StmtXML::VisitStmt(Stmt *Node)
178{
179 // nothing special to do
180}
181
182void StmtXML::VisitDeclStmt(DeclStmt *Node)
183{
184 for (DeclStmt::decl_iterator DI = Node->decl_begin(), DE = Node->decl_end();
185 DI != DE; ++DI)
186 {
187 Doc.PrintDecl(*DI);
188 }
189}
190
191void StmtXML::VisitLabelStmt(LabelStmt *Node)
192{
193 Doc.addAttribute("name", Node->getName());
194}
195
196void StmtXML::VisitGotoStmt(GotoStmt *Node)
197{
198 Doc.addAttribute("name", Node->getLabel()->getName());
199}
200
201//===----------------------------------------------------------------------===//
202// Expr printing methods.
203//===----------------------------------------------------------------------===//
204
205void StmtXML::VisitExpr(Expr *Node) {
206 DumpExpr(Node);
207}
208
209void StmtXML::VisitDeclRefExpr(DeclRefExpr *Node) {
210 DumpExpr(Node);
211
212 const char* pKind;
213 switch (Node->getDecl()->getKind()) {
214 case Decl::Function: pKind = "FunctionDecl"; break;
215 case Decl::Var: pKind = "Var"; break;
216 case Decl::ParmVar: pKind = "ParmVar"; break;
217 case Decl::EnumConstant: pKind = "EnumConstant"; break;
218 case Decl::Typedef: pKind = "Typedef"; break;
219 case Decl::Record: pKind = "Record"; break;
220 case Decl::Enum: pKind = "Enum"; break;
221 case Decl::CXXRecord: pKind = "CXXRecord"; break;
222 case Decl::ObjCInterface: pKind = "ObjCInterface"; break;
223 case Decl::ObjCClass: pKind = "ObjCClass"; break;
224 default: pKind = "Decl"; break;
225 }
226
227 Doc.addAttribute("kind", pKind);
228 Doc.addAttribute("name", Node->getDecl()->getNameAsString());
229 Doc.addRefAttribute(Node->getDecl());
230}
231
232void StmtXML::VisitPredefinedExpr(PredefinedExpr *Node) {
233 DumpExpr(Node);
234 switch (Node->getIdentType()) {
235 default: assert(0 && "unknown case");
236 case PredefinedExpr::Func: Doc.addAttribute("predefined", " __func__"); break;
237 case PredefinedExpr::Function: Doc.addAttribute("predefined", " __FUNCTION__"); break;
238 case PredefinedExpr::PrettyFunction: Doc.addAttribute("predefined", " __PRETTY_FUNCTION__");break;
239 }
240}
241
242void StmtXML::VisitCharacterLiteral(CharacterLiteral *Node) {
243 DumpExpr(Node);
244 Doc.addAttribute("value", Node->getValue());
245}
246
247void StmtXML::VisitIntegerLiteral(IntegerLiteral *Node) {
248 DumpExpr(Node);
249 bool isSigned = Node->getType()->isSignedIntegerType();
250 Doc.addAttribute("value", Node->getValue().toString(10, isSigned));
251}
252
253void StmtXML::VisitFloatingLiteral(FloatingLiteral *Node) {
254 DumpExpr(Node);
255 // FIXME: output float as written in source (no approximation or the like)
256 //Doc.addAttribute("value", Node->getValueAsApproximateDouble()));
257 Doc.addAttribute("value", "FIXME");
258}
259
260void StmtXML::VisitStringLiteral(StringLiteral *Str) {
261 DumpExpr(Str);
262 if (Str->isWide())
263 Doc.addAttribute("is_wide", "1");
264
265 Doc.addAttribute("value", Doc.escapeString(Str->getStrData(), Str->getByteLength()));
266}
267
268
269const char *StmtXML::getOpcodeStr(UnaryOperator::Opcode Op) {
270 switch (Op) {
271 default: assert(0 && "Unknown unary operator");
272 case UnaryOperator::PostInc: return "postinc";
273 case UnaryOperator::PostDec: return "postdec";
274 case UnaryOperator::PreInc: return "preinc";
275 case UnaryOperator::PreDec: return "predec";
276 case UnaryOperator::AddrOf: return "addrof";
277 case UnaryOperator::Deref: return "deref";
278 case UnaryOperator::Plus: return "plus";
279 case UnaryOperator::Minus: return "minus";
280 case UnaryOperator::Not: return "not";
281 case UnaryOperator::LNot: return "lnot";
282 case UnaryOperator::Real: return "__real";
283 case UnaryOperator::Imag: return "__imag";
284 case UnaryOperator::Extension: return "__extension__";
285 case UnaryOperator::OffsetOf: return "__builtin_offsetof";
286 }
287}
288
289
290const char *StmtXML::getOpcodeStr(BinaryOperator::Opcode Op) {
291 switch (Op) {
292 default: assert(0 && "Unknown binary operator");
293 case BinaryOperator::PtrMemD: return "ptrmemd";
294 case BinaryOperator::PtrMemI: return "ptrmemi";
295 case BinaryOperator::Mul: return "mul";
296 case BinaryOperator::Div: return "div";
297 case BinaryOperator::Rem: return "rem";
298 case BinaryOperator::Add: return "add";
299 case BinaryOperator::Sub: return "sub";
300 case BinaryOperator::Shl: return "shl";
301 case BinaryOperator::Shr: return "shr";
302 case BinaryOperator::LT: return "lt";
303 case BinaryOperator::GT: return "gt";
304 case BinaryOperator::LE: return "le";
305 case BinaryOperator::GE: return "ge";
306 case BinaryOperator::EQ: return "eq";
307 case BinaryOperator::NE: return "ne";
308 case BinaryOperator::And: return "and";
309 case BinaryOperator::Xor: return "xor";
310 case BinaryOperator::Or: return "or";
311 case BinaryOperator::LAnd: return "land";
312 case BinaryOperator::LOr: return "lor";
313 case BinaryOperator::Assign: return "assign";
314 case BinaryOperator::MulAssign: return "mulassign";
315 case BinaryOperator::DivAssign: return "divassign";
316 case BinaryOperator::RemAssign: return "remassign";
317 case BinaryOperator::AddAssign: return "addassign";
318 case BinaryOperator::SubAssign: return "subassign";
319 case BinaryOperator::ShlAssign: return "shlassign";
320 case BinaryOperator::ShrAssign: return "shrassign";
321 case BinaryOperator::AndAssign: return "andassign";
322 case BinaryOperator::XorAssign: return "xorassign";
323 case BinaryOperator::OrAssign: return "orassign";
324 case BinaryOperator::Comma: return "comma";
325 }
326}
327
328void StmtXML::VisitUnaryOperator(UnaryOperator *Node) {
329 DumpExpr(Node);
330 Doc.addAttribute("op_code", getOpcodeStr(Node->getOpcode()));
331}
332
333void StmtXML::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
334 DumpExpr(Node);
335 Doc.addAttribute("is_sizeof", Node->isSizeOf() ? "sizeof" : "alignof");
336 Doc.addAttribute("is_type", Node->isArgumentType() ? "1" : "0");
337 if (Node->isArgumentType())
338 {
339 DumpTypeExpr(Node->getArgumentType());
340 }
341}
342
343void StmtXML::VisitMemberExpr(MemberExpr *Node) {
344 DumpExpr(Node);
345 Doc.addAttribute("is_deref", Node->isArrow() ? "1" : "0");
346 Doc.addAttribute("name", Node->getMemberDecl()->getNameAsString());
347 Doc.addRefAttribute(Node->getMemberDecl());
348}
349
350void StmtXML::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
351 DumpExpr(Node);
352 Doc.addAttribute("name", Node->getAccessor().getName());
353}
354
355void StmtXML::VisitBinaryOperator(BinaryOperator *Node) {
356 DumpExpr(Node);
357 Doc.addAttribute("op_code", getOpcodeStr(Node->getOpcode()));
358}
359
360void StmtXML::VisitCompoundAssignOperator(CompoundAssignOperator *Node) {
361 VisitBinaryOperator(Node);
362/* FIXME: is this needed in the AST?
363 DumpExpr(Node);
364 CurrentNode = CurrentNode->addSubNode("ComputeLHSTy");
365 DumpType(Node->getComputationLHSType());
366 CurrentNode = CurrentNode->Parent->addSubNode("ComputeResultTy");
367 DumpType(Node->getComputationResultType());
368 Doc.toParent();
369*/
370}
371
372// GNU extensions.
373
374void StmtXML::VisitAddrLabelExpr(AddrLabelExpr *Node) {
375 DumpExpr(Node);
376 Doc.addAttribute("name", Node->getLabel()->getName());
377}
378
379void StmtXML::VisitTypesCompatibleExpr(TypesCompatibleExpr *Node) {
380 DumpExpr(Node);
381 DumpTypeExpr(Node->getArgType1());
382 DumpTypeExpr(Node->getArgType2());
383}
384
385//===----------------------------------------------------------------------===//
386// C++ Expressions
387//===----------------------------------------------------------------------===//
388
389void StmtXML::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) {
390 DumpExpr(Node);
391 Doc.addAttribute("kind", Node->getCastName());
392 DumpTypeExpr(Node->getTypeAsWritten());
393}
394
395void StmtXML::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
396 DumpExpr(Node);
397 Doc.addAttribute("value", Node->getValue() ? "true" : "false");
398}
399
400void StmtXML::VisitCXXThisExpr(CXXThisExpr *Node) {
401 DumpExpr(Node);
402}
403
404void StmtXML::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
405 DumpExpr(Node);
406 DumpTypeExpr(Node->getTypeAsWritten());
407}
408
409//===----------------------------------------------------------------------===//
410// Obj-C Expressions
411//===----------------------------------------------------------------------===//
412
413void StmtXML::VisitObjCMessageExpr(ObjCMessageExpr* Node) {
414 DumpExpr(Node);
415 Doc.addAttribute("selector", Node->getSelector().getAsString());
416 IdentifierInfo* clsName = Node->getClassName();
417 if (clsName)
418 Doc.addAttribute("class", clsName->getName());
419}
420
421void StmtXML::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
422 DumpExpr(Node);
423 DumpTypeExpr(Node->getEncodedType());
424}
425
426void StmtXML::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
427 DumpExpr(Node);
428 Doc.addAttribute("selector", Node->getSelector().getAsString());
429}
430
431void StmtXML::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
432 DumpExpr(Node);
433 Doc.addAttribute("protocol", Node->getProtocol()->getNameAsString());
434}
435
436void StmtXML::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
437 DumpExpr(Node);
438 Doc.addAttribute("property", Node->getProperty()->getNameAsString());
439}
440
441void StmtXML::VisitObjCKVCRefExpr(ObjCKVCRefExpr *Node) {
442 DumpExpr(Node);
443 ObjCMethodDecl *Getter = Node->getGetterMethod();
444 ObjCMethodDecl *Setter = Node->getSetterMethod();
445 Doc.addAttribute("Getter", Getter->getSelector().getAsString());
446 Doc.addAttribute("Setter", Setter ? Setter->getSelector().getAsString().c_str() : "(null)");
447}
448
449void StmtXML::VisitObjCSuperExpr(ObjCSuperExpr *Node) {
450 DumpExpr(Node);
451 Doc.addAttribute("super", "1");
452}
453
454void StmtXML::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
455 DumpExpr(Node);
456 Doc.addAttribute("kind", Node->getDecl()->getDeclKindName());
457 Doc.addAttribute("decl", Node->getDecl()->getNameAsString());
458 if (Node->isFreeIvar())
459 Doc.addAttribute("isFreeIvar", "1");
460}
Douglas Gregor038f75a2009-06-15 19:02:54 +0000461#endif
Douglas Gregoree75c052009-05-21 20:55:50 +0000462//===----------------------------------------------------------------------===//
463// Stmt method implementations
464//===----------------------------------------------------------------------===//
465
466/// dumpAll - This does a dump of the specified AST fragment and all subtrees.
467void DocumentXML::PrintStmt(const Stmt *S) {
468 StmtXML P(*this);
469 P.DumpSubTree(const_cast<Stmt*>(S));
470}
471