blob: b6d04810bfa18e0af273dd49f6785d7b9b018754 [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);
Fariborz Jahanian09105f52009-08-20 17:02:02 +0000166 void VisitObjCImplicitSetterGetterRefExpr(
167 ObjCImplicitSetterGetterRefExpr *Node);
Douglas Gregoree75c052009-05-21 20:55:50 +0000168 void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node);
169 void VisitObjCSuperExpr(ObjCSuperExpr *Node);
Douglas Gregor038f75a2009-06-15 19:02:54 +0000170#endif
Douglas Gregoree75c052009-05-21 20:55:50 +0000171 };
172}
173
174//===----------------------------------------------------------------------===//
175// Stmt printing methods.
176//===----------------------------------------------------------------------===//
Douglas Gregor038f75a2009-06-15 19:02:54 +0000177#if (0)
Douglas Gregoree75c052009-05-21 20:55:50 +0000178void StmtXML::VisitStmt(Stmt *Node)
179{
180 // nothing special to do
181}
182
183void StmtXML::VisitDeclStmt(DeclStmt *Node)
184{
185 for (DeclStmt::decl_iterator DI = Node->decl_begin(), DE = Node->decl_end();
186 DI != DE; ++DI)
187 {
188 Doc.PrintDecl(*DI);
189 }
190}
191
192void StmtXML::VisitLabelStmt(LabelStmt *Node)
193{
194 Doc.addAttribute("name", Node->getName());
195}
196
197void StmtXML::VisitGotoStmt(GotoStmt *Node)
198{
199 Doc.addAttribute("name", Node->getLabel()->getName());
200}
201
202//===----------------------------------------------------------------------===//
203// Expr printing methods.
204//===----------------------------------------------------------------------===//
205
206void StmtXML::VisitExpr(Expr *Node) {
207 DumpExpr(Node);
208}
209
210void StmtXML::VisitDeclRefExpr(DeclRefExpr *Node) {
211 DumpExpr(Node);
212
213 const char* pKind;
214 switch (Node->getDecl()->getKind()) {
215 case Decl::Function: pKind = "FunctionDecl"; break;
216 case Decl::Var: pKind = "Var"; break;
217 case Decl::ParmVar: pKind = "ParmVar"; break;
218 case Decl::EnumConstant: pKind = "EnumConstant"; break;
219 case Decl::Typedef: pKind = "Typedef"; break;
220 case Decl::Record: pKind = "Record"; break;
221 case Decl::Enum: pKind = "Enum"; break;
222 case Decl::CXXRecord: pKind = "CXXRecord"; break;
223 case Decl::ObjCInterface: pKind = "ObjCInterface"; break;
224 case Decl::ObjCClass: pKind = "ObjCClass"; break;
225 default: pKind = "Decl"; break;
226 }
227
228 Doc.addAttribute("kind", pKind);
229 Doc.addAttribute("name", Node->getDecl()->getNameAsString());
230 Doc.addRefAttribute(Node->getDecl());
231}
232
233void StmtXML::VisitPredefinedExpr(PredefinedExpr *Node) {
234 DumpExpr(Node);
235 switch (Node->getIdentType()) {
236 default: assert(0 && "unknown case");
237 case PredefinedExpr::Func: Doc.addAttribute("predefined", " __func__"); break;
238 case PredefinedExpr::Function: Doc.addAttribute("predefined", " __FUNCTION__"); break;
239 case PredefinedExpr::PrettyFunction: Doc.addAttribute("predefined", " __PRETTY_FUNCTION__");break;
240 }
241}
242
243void StmtXML::VisitCharacterLiteral(CharacterLiteral *Node) {
244 DumpExpr(Node);
245 Doc.addAttribute("value", Node->getValue());
246}
247
248void StmtXML::VisitIntegerLiteral(IntegerLiteral *Node) {
249 DumpExpr(Node);
250 bool isSigned = Node->getType()->isSignedIntegerType();
251 Doc.addAttribute("value", Node->getValue().toString(10, isSigned));
252}
253
254void StmtXML::VisitFloatingLiteral(FloatingLiteral *Node) {
255 DumpExpr(Node);
256 // FIXME: output float as written in source (no approximation or the like)
257 //Doc.addAttribute("value", Node->getValueAsApproximateDouble()));
258 Doc.addAttribute("value", "FIXME");
259}
260
261void StmtXML::VisitStringLiteral(StringLiteral *Str) {
262 DumpExpr(Str);
263 if (Str->isWide())
264 Doc.addAttribute("is_wide", "1");
265
266 Doc.addAttribute("value", Doc.escapeString(Str->getStrData(), Str->getByteLength()));
267}
268
269
270const char *StmtXML::getOpcodeStr(UnaryOperator::Opcode Op) {
271 switch (Op) {
272 default: assert(0 && "Unknown unary operator");
273 case UnaryOperator::PostInc: return "postinc";
274 case UnaryOperator::PostDec: return "postdec";
275 case UnaryOperator::PreInc: return "preinc";
276 case UnaryOperator::PreDec: return "predec";
277 case UnaryOperator::AddrOf: return "addrof";
278 case UnaryOperator::Deref: return "deref";
279 case UnaryOperator::Plus: return "plus";
280 case UnaryOperator::Minus: return "minus";
281 case UnaryOperator::Not: return "not";
282 case UnaryOperator::LNot: return "lnot";
283 case UnaryOperator::Real: return "__real";
284 case UnaryOperator::Imag: return "__imag";
285 case UnaryOperator::Extension: return "__extension__";
286 case UnaryOperator::OffsetOf: return "__builtin_offsetof";
287 }
288}
289
290
291const char *StmtXML::getOpcodeStr(BinaryOperator::Opcode Op) {
292 switch (Op) {
293 default: assert(0 && "Unknown binary operator");
294 case BinaryOperator::PtrMemD: return "ptrmemd";
295 case BinaryOperator::PtrMemI: return "ptrmemi";
296 case BinaryOperator::Mul: return "mul";
297 case BinaryOperator::Div: return "div";
298 case BinaryOperator::Rem: return "rem";
299 case BinaryOperator::Add: return "add";
300 case BinaryOperator::Sub: return "sub";
301 case BinaryOperator::Shl: return "shl";
302 case BinaryOperator::Shr: return "shr";
303 case BinaryOperator::LT: return "lt";
304 case BinaryOperator::GT: return "gt";
305 case BinaryOperator::LE: return "le";
306 case BinaryOperator::GE: return "ge";
307 case BinaryOperator::EQ: return "eq";
308 case BinaryOperator::NE: return "ne";
309 case BinaryOperator::And: return "and";
310 case BinaryOperator::Xor: return "xor";
311 case BinaryOperator::Or: return "or";
312 case BinaryOperator::LAnd: return "land";
313 case BinaryOperator::LOr: return "lor";
314 case BinaryOperator::Assign: return "assign";
315 case BinaryOperator::MulAssign: return "mulassign";
316 case BinaryOperator::DivAssign: return "divassign";
317 case BinaryOperator::RemAssign: return "remassign";
318 case BinaryOperator::AddAssign: return "addassign";
319 case BinaryOperator::SubAssign: return "subassign";
320 case BinaryOperator::ShlAssign: return "shlassign";
321 case BinaryOperator::ShrAssign: return "shrassign";
322 case BinaryOperator::AndAssign: return "andassign";
323 case BinaryOperator::XorAssign: return "xorassign";
324 case BinaryOperator::OrAssign: return "orassign";
325 case BinaryOperator::Comma: return "comma";
326 }
327}
328
329void StmtXML::VisitUnaryOperator(UnaryOperator *Node) {
330 DumpExpr(Node);
331 Doc.addAttribute("op_code", getOpcodeStr(Node->getOpcode()));
332}
333
334void StmtXML::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
335 DumpExpr(Node);
336 Doc.addAttribute("is_sizeof", Node->isSizeOf() ? "sizeof" : "alignof");
337 Doc.addAttribute("is_type", Node->isArgumentType() ? "1" : "0");
338 if (Node->isArgumentType())
339 {
340 DumpTypeExpr(Node->getArgumentType());
341 }
342}
343
344void StmtXML::VisitMemberExpr(MemberExpr *Node) {
345 DumpExpr(Node);
346 Doc.addAttribute("is_deref", Node->isArrow() ? "1" : "0");
347 Doc.addAttribute("name", Node->getMemberDecl()->getNameAsString());
348 Doc.addRefAttribute(Node->getMemberDecl());
349}
350
351void StmtXML::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) {
352 DumpExpr(Node);
353 Doc.addAttribute("name", Node->getAccessor().getName());
354}
355
356void StmtXML::VisitBinaryOperator(BinaryOperator *Node) {
357 DumpExpr(Node);
358 Doc.addAttribute("op_code", getOpcodeStr(Node->getOpcode()));
359}
360
361void StmtXML::VisitCompoundAssignOperator(CompoundAssignOperator *Node) {
362 VisitBinaryOperator(Node);
363/* FIXME: is this needed in the AST?
364 DumpExpr(Node);
365 CurrentNode = CurrentNode->addSubNode("ComputeLHSTy");
366 DumpType(Node->getComputationLHSType());
367 CurrentNode = CurrentNode->Parent->addSubNode("ComputeResultTy");
368 DumpType(Node->getComputationResultType());
369 Doc.toParent();
370*/
371}
372
373// GNU extensions.
374
375void StmtXML::VisitAddrLabelExpr(AddrLabelExpr *Node) {
376 DumpExpr(Node);
377 Doc.addAttribute("name", Node->getLabel()->getName());
378}
379
380void StmtXML::VisitTypesCompatibleExpr(TypesCompatibleExpr *Node) {
381 DumpExpr(Node);
382 DumpTypeExpr(Node->getArgType1());
383 DumpTypeExpr(Node->getArgType2());
384}
385
386//===----------------------------------------------------------------------===//
387// C++ Expressions
388//===----------------------------------------------------------------------===//
389
390void StmtXML::VisitCXXNamedCastExpr(CXXNamedCastExpr *Node) {
391 DumpExpr(Node);
392 Doc.addAttribute("kind", Node->getCastName());
393 DumpTypeExpr(Node->getTypeAsWritten());
394}
395
396void StmtXML::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
397 DumpExpr(Node);
398 Doc.addAttribute("value", Node->getValue() ? "true" : "false");
399}
400
401void StmtXML::VisitCXXThisExpr(CXXThisExpr *Node) {
402 DumpExpr(Node);
403}
404
405void StmtXML::VisitCXXFunctionalCastExpr(CXXFunctionalCastExpr *Node) {
406 DumpExpr(Node);
407 DumpTypeExpr(Node->getTypeAsWritten());
408}
409
410//===----------------------------------------------------------------------===//
411// Obj-C Expressions
412//===----------------------------------------------------------------------===//
413
414void StmtXML::VisitObjCMessageExpr(ObjCMessageExpr* Node) {
415 DumpExpr(Node);
416 Doc.addAttribute("selector", Node->getSelector().getAsString());
417 IdentifierInfo* clsName = Node->getClassName();
418 if (clsName)
419 Doc.addAttribute("class", clsName->getName());
420}
421
422void StmtXML::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) {
423 DumpExpr(Node);
424 DumpTypeExpr(Node->getEncodedType());
425}
426
427void StmtXML::VisitObjCSelectorExpr(ObjCSelectorExpr *Node) {
428 DumpExpr(Node);
429 Doc.addAttribute("selector", Node->getSelector().getAsString());
430}
431
432void StmtXML::VisitObjCProtocolExpr(ObjCProtocolExpr *Node) {
433 DumpExpr(Node);
434 Doc.addAttribute("protocol", Node->getProtocol()->getNameAsString());
435}
436
437void StmtXML::VisitObjCPropertyRefExpr(ObjCPropertyRefExpr *Node) {
438 DumpExpr(Node);
439 Doc.addAttribute("property", Node->getProperty()->getNameAsString());
440}
441
Fariborz Jahanian09105f52009-08-20 17:02:02 +0000442void StmtXML::VisitObjCImplicitSetterGetterRefExpr(
443 ObjCImplicitSetterGetterRefExpr *Node) {
Douglas Gregoree75c052009-05-21 20:55:50 +0000444 DumpExpr(Node);
445 ObjCMethodDecl *Getter = Node->getGetterMethod();
446 ObjCMethodDecl *Setter = Node->getSetterMethod();
447 Doc.addAttribute("Getter", Getter->getSelector().getAsString());
448 Doc.addAttribute("Setter", Setter ? Setter->getSelector().getAsString().c_str() : "(null)");
449}
450
451void StmtXML::VisitObjCSuperExpr(ObjCSuperExpr *Node) {
452 DumpExpr(Node);
453 Doc.addAttribute("super", "1");
454}
455
456void StmtXML::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
457 DumpExpr(Node);
458 Doc.addAttribute("kind", Node->getDecl()->getDeclKindName());
459 Doc.addAttribute("decl", Node->getDecl()->getNameAsString());
460 if (Node->isFreeIvar())
461 Doc.addAttribute("isFreeIvar", "1");
462}
Douglas Gregor038f75a2009-06-15 19:02:54 +0000463#endif
Douglas Gregoree75c052009-05-21 20:55:50 +0000464//===----------------------------------------------------------------------===//
465// Stmt method implementations
466//===----------------------------------------------------------------------===//
467
468/// dumpAll - This does a dump of the specified AST fragment and all subtrees.
469void DocumentXML::PrintStmt(const Stmt *S) {
470 StmtXML P(*this);
471 P.DumpSubTree(const_cast<Stmt*>(S));
472}
473