blob: be22ae450b62abf0fa9b2b4873844260a45a2a06 [file] [log] [blame]
Nick Lewycky49c67c42012-10-18 07:55:46 +00001//===--- DumpXML.cpp - Detailed XML dumping -------------------------------===//
John McCall26c25c92010-11-24 11:30:07 +00002//
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 defines the Decl::dumpXML() method, a debugging tool to
11// print a detailed graph of an AST in an unspecified XML format.
12//
13// There is no guarantee of stability for this format.
14//
15//===----------------------------------------------------------------------===//
16
17// Only pay for this in code size in assertions-enabled builds.
18
19#include "clang/AST/ASTContext.h"
Benjamin Kramer2fa67ef2012-12-01 15:09:41 +000020#include "clang/AST/Attr.h"
John McCall26c25c92010-11-24 11:30:07 +000021#include "clang/AST/Decl.h"
22#include "clang/AST/DeclCXX.h"
23#include "clang/AST/DeclFriend.h"
24#include "clang/AST/DeclObjC.h"
25#include "clang/AST/DeclTemplate.h"
26#include "clang/AST/DeclVisitor.h"
27#include "clang/AST/Expr.h"
28#include "clang/AST/ExprCXX.h"
29#include "clang/AST/ExprObjC.h"
30#include "clang/AST/NestedNameSpecifier.h"
31#include "clang/AST/Stmt.h"
32#include "clang/AST/StmtCXX.h"
33#include "clang/AST/StmtObjC.h"
34#include "clang/AST/StmtVisitor.h"
35#include "clang/AST/TemplateBase.h"
36#include "clang/AST/TemplateName.h"
37#include "clang/AST/Type.h"
38#include "clang/AST/TypeLoc.h"
39#include "clang/AST/TypeLocVisitor.h"
40#include "clang/AST/TypeVisitor.h"
Benjamin Kramer8fe83e12012-02-04 13:45:25 +000041#include "llvm/ADT/SmallString.h"
John McCall26c25c92010-11-24 11:30:07 +000042
43using namespace clang;
44
45#ifndef NDEBUG
46
47namespace {
48
49enum NodeState {
50 NS_Attrs, NS_LazyChildren, NS_Children
51};
52
53struct Node {
Chris Lattner5f9e2722011-07-23 10:55:15 +000054 StringRef Name;
John McCall26c25c92010-11-24 11:30:07 +000055 NodeState State;
Chris Lattner5f9e2722011-07-23 10:55:15 +000056 Node(StringRef name) : Name(name), State(NS_Attrs) {}
John McCall26c25c92010-11-24 11:30:07 +000057
58 bool isDoneWithAttrs() const { return State != NS_Attrs; }
59};
60
61template <class Impl> struct XMLDeclVisitor {
62#define DISPATCH(NAME, CLASS) \
63 static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(D))
64
65 void dispatch(Decl *D) {
Nick Lewycky49c67c42012-10-18 07:55:46 +000066 if (D->isUsed())
67 static_cast<Impl*>(this)->set("used", "1");
John McCall26c25c92010-11-24 11:30:07 +000068 switch (D->getKind()) {
John McCall26c25c92010-11-24 11:30:07 +000069#define DECL(DERIVED, BASE) \
70 case Decl::DERIVED: \
71 DISPATCH(dispatch##DERIVED##DeclAttrs, DERIVED##Decl); \
72 static_cast<Impl*>(this)->completeAttrs(); \
73 DISPATCH(dispatch##DERIVED##DeclChildren, DERIVED##Decl); \
74 DISPATCH(dispatch##DERIVED##DeclAsContext, DERIVED##Decl); \
75 break;
76#define ABSTRACT_DECL(DECL)
77#include "clang/AST/DeclNodes.inc"
78 }
79 }
80
81#define DECL(DERIVED, BASE) \
82 void dispatch##DERIVED##DeclAttrs(DERIVED##Decl *D) { \
83 DISPATCH(dispatch##BASE##Attrs, BASE); \
84 DISPATCH(visit##DERIVED##DeclAttrs, DERIVED##Decl); \
85 } \
86 void visit##DERIVED##DeclAttrs(DERIVED##Decl *D) {} \
87 void dispatch##DERIVED##DeclChildren(DERIVED##Decl *D) { \
88 DISPATCH(dispatch##BASE##Children, BASE); \
89 DISPATCH(visit##DERIVED##DeclChildren, DERIVED##Decl); \
90 } \
91 void visit##DERIVED##DeclChildren(DERIVED##Decl *D) {} \
92 void dispatch##DERIVED##DeclAsContext(DERIVED##Decl *D) { \
93 DISPATCH(dispatch##BASE##AsContext, BASE); \
94 DISPATCH(visit##DERIVED##DeclAsContext, DERIVED##Decl); \
95 } \
96 void visit##DERIVED##DeclAsContext(DERIVED##Decl *D) {}
97#include "clang/AST/DeclNodes.inc"
98
99 void dispatchDeclAttrs(Decl *D) {
100 DISPATCH(visitDeclAttrs, Decl);
101 }
102 void visitDeclAttrs(Decl *D) {}
103
104 void dispatchDeclChildren(Decl *D) {
105 DISPATCH(visitDeclChildren, Decl);
106 }
107 void visitDeclChildren(Decl *D) {}
108
109 void dispatchDeclAsContext(Decl *D) {
110 DISPATCH(visitDeclAsContext, Decl);
111 }
112 void visitDeclAsContext(Decl *D) {}
113
114#undef DISPATCH
115};
116
117template <class Impl> struct XMLTypeVisitor {
118#define DISPATCH(NAME, CLASS) \
119 static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(T))
120
121 void dispatch(Type *T) {
122 switch (T->getTypeClass()) {
John McCall26c25c92010-11-24 11:30:07 +0000123#define TYPE(DERIVED, BASE) \
124 case Type::DERIVED: \
125 DISPATCH(dispatch##DERIVED##TypeAttrs, DERIVED##Type); \
126 static_cast<Impl*>(this)->completeAttrs(); \
127 DISPATCH(dispatch##DERIVED##TypeChildren, DERIVED##Type); \
128 break;
129#define ABSTRACT_TYPE(DERIVED, BASE)
130#include "clang/AST/TypeNodes.def"
131 }
132 }
133
134#define TYPE(DERIVED, BASE) \
135 void dispatch##DERIVED##TypeAttrs(DERIVED##Type *T) { \
136 DISPATCH(dispatch##BASE##Attrs, BASE); \
137 DISPATCH(visit##DERIVED##TypeAttrs, DERIVED##Type); \
138 } \
139 void visit##DERIVED##TypeAttrs(DERIVED##Type *T) {} \
140 void dispatch##DERIVED##TypeChildren(DERIVED##Type *T) { \
141 DISPATCH(dispatch##BASE##Children, BASE); \
142 DISPATCH(visit##DERIVED##TypeChildren, DERIVED##Type); \
143 } \
144 void visit##DERIVED##TypeChildren(DERIVED##Type *T) {}
145#include "clang/AST/TypeNodes.def"
146
147 void dispatchTypeAttrs(Type *T) {
148 DISPATCH(visitTypeAttrs, Type);
149 }
150 void visitTypeAttrs(Type *T) {}
151
152 void dispatchTypeChildren(Type *T) {
153 DISPATCH(visitTypeChildren, Type);
154 }
155 void visitTypeChildren(Type *T) {}
156
157#undef DISPATCH
158};
159
Chris Lattner5f9e2722011-07-23 10:55:15 +0000160static StringRef getTypeKindName(Type *T) {
John McCall26c25c92010-11-24 11:30:07 +0000161 switch (T->getTypeClass()) {
162#define TYPE(DERIVED, BASE) case Type::DERIVED: return #DERIVED "Type";
163#define ABSTRACT_TYPE(DERIVED, BASE)
164#include "clang/AST/TypeNodes.def"
165 }
166
167 llvm_unreachable("unknown type kind!");
John McCall26c25c92010-11-24 11:30:07 +0000168}
169
170struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
171 public XMLTypeVisitor<XMLDumper> {
Chris Lattner5f9e2722011-07-23 10:55:15 +0000172 raw_ostream &out;
John McCall26c25c92010-11-24 11:30:07 +0000173 ASTContext &Context;
Chris Lattner5f9e2722011-07-23 10:55:15 +0000174 SmallVector<Node, 16> Stack;
John McCall26c25c92010-11-24 11:30:07 +0000175 unsigned Indent;
Chris Lattner5f9e2722011-07-23 10:55:15 +0000176 explicit XMLDumper(raw_ostream &OS, ASTContext &context)
John McCall26c25c92010-11-24 11:30:07 +0000177 : out(OS), Context(context), Indent(0) {}
178
179 void indent() {
180 for (unsigned I = Indent; I; --I)
181 out << ' ';
182 }
183
184 /// Push a new node on the stack.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000185 void push(StringRef name) {
John McCall26c25c92010-11-24 11:30:07 +0000186 if (!Stack.empty()) {
187 assert(Stack.back().isDoneWithAttrs());
188 if (Stack.back().State == NS_LazyChildren) {
189 Stack.back().State = NS_Children;
190 out << ">\n";
191 }
192 Indent++;
193 indent();
194 }
195 Stack.push_back(Node(name));
196 out << '<' << name;
197 }
198
199 /// Set the given attribute to the given value.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000200 void set(StringRef attr, StringRef value) {
John McCall26c25c92010-11-24 11:30:07 +0000201 assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
202 out << ' ' << attr << '=' << '"' << value << '"'; // TODO: quotation
203 }
204
205 /// Finish attributes.
206 void completeAttrs() {
207 assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
208 Stack.back().State = NS_LazyChildren;
209 }
210
211 /// Pop a node.
212 void pop() {
213 assert(!Stack.empty() && Stack.back().isDoneWithAttrs());
214 if (Stack.back().State == NS_LazyChildren) {
215 out << "/>\n";
216 } else {
217 indent();
218 out << "</" << Stack.back().Name << ">\n";
219 }
220 if (Stack.size() > 1) Indent--;
221 Stack.pop_back();
222 }
223
224 //---- General utilities -------------------------------------------//
225
Chris Lattner5f9e2722011-07-23 10:55:15 +0000226 void setPointer(StringRef prop, const void *p) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000227 SmallString<10> buffer;
John McCall26c25c92010-11-24 11:30:07 +0000228 llvm::raw_svector_ostream os(buffer);
229 os << p;
230 os.flush();
231 set(prop, buffer);
232 }
233
234 void setPointer(void *p) {
235 setPointer("ptr", p);
236 }
237
Chris Lattner5f9e2722011-07-23 10:55:15 +0000238 void setInteger(StringRef prop, const llvm::APSInt &v) {
John McCall26c25c92010-11-24 11:30:07 +0000239 set(prop, v.toString(10));
240 }
241
Chris Lattner5f9e2722011-07-23 10:55:15 +0000242 void setInteger(StringRef prop, unsigned n) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000243 SmallString<10> buffer;
John McCall26c25c92010-11-24 11:30:07 +0000244 llvm::raw_svector_ostream os(buffer);
245 os << n;
246 os.flush();
247 set(prop, buffer);
248 }
249
Chris Lattner5f9e2722011-07-23 10:55:15 +0000250 void setFlag(StringRef prop, bool flag) {
John McCall26c25c92010-11-24 11:30:07 +0000251 if (flag) set(prop, "true");
252 }
253
254 void setName(DeclarationName Name) {
John McCall6710cf12010-11-30 10:12:16 +0000255 if (!Name)
256 return set("name", "");
257
John McCall26c25c92010-11-24 11:30:07 +0000258 // Common case.
259 if (Name.isIdentifier())
260 return set("name", Name.getAsIdentifierInfo()->getName());
261
John McCall7bd245b2010-12-02 10:37:08 +0000262 set("name", Name.getAsString());
John McCall26c25c92010-11-24 11:30:07 +0000263 }
264
265 class TemporaryContainer {
266 XMLDumper &Dumper;
267 public:
Chris Lattner5f9e2722011-07-23 10:55:15 +0000268 TemporaryContainer(XMLDumper &dumper, StringRef name)
John McCall26c25c92010-11-24 11:30:07 +0000269 : Dumper(dumper) {
270 Dumper.push(name);
271 Dumper.completeAttrs();
272 }
273
274 ~TemporaryContainer() {
275 Dumper.pop();
276 }
277 };
278
279 void visitTemplateParameters(TemplateParameterList *L) {
280 push("template_parameters");
281 completeAttrs();
282 for (TemplateParameterList::iterator
283 I = L->begin(), E = L->end(); I != E; ++I)
284 dispatch(*I);
285 pop();
286 }
287
288 void visitTemplateArguments(const TemplateArgumentList &L) {
289 push("template_arguments");
290 completeAttrs();
291 for (unsigned I = 0, E = L.size(); I != E; ++I)
292 dispatch(L[I]);
293 pop();
294 }
295
296 /// Visits a reference to the given declaration.
297 void visitDeclRef(Decl *D) {
298 push(D->getDeclKindName());
299 setPointer("ref", D);
300 completeAttrs();
301 pop();
302 }
Chris Lattner5f9e2722011-07-23 10:55:15 +0000303 void visitDeclRef(StringRef Name, Decl *D) {
John McCall3bddf5c2010-12-02 10:24:56 +0000304 TemporaryContainer C(*this, Name);
305 if (D) visitDeclRef(D);
306 }
John McCall26c25c92010-11-24 11:30:07 +0000307
308 void dispatch(const TemplateArgument &A) {
309 switch (A.getKind()) {
310 case TemplateArgument::Null: {
311 TemporaryContainer C(*this, "null");
312 break;
313 }
314 case TemplateArgument::Type: {
315 dispatch(A.getAsType());
316 break;
317 }
318 case TemplateArgument::Template:
Douglas Gregora7fc9012011-01-05 18:58:31 +0000319 case TemplateArgument::TemplateExpansion:
Eli Friedmand7a6b162012-09-26 02:36:12 +0000320 case TemplateArgument::NullPtr:
Douglas Gregora7fc9012011-01-05 18:58:31 +0000321 // FIXME: Implement!
322 break;
323
John McCall26c25c92010-11-24 11:30:07 +0000324 case TemplateArgument::Declaration: {
Eli Friedmand7a6b162012-09-26 02:36:12 +0000325 visitDeclRef(A.getAsDecl());
John McCall26c25c92010-11-24 11:30:07 +0000326 break;
327 }
328 case TemplateArgument::Integral: {
329 push("integer");
Benjamin Kramer85524372012-06-07 15:09:51 +0000330 setInteger("value", A.getAsIntegral());
John McCall26c25c92010-11-24 11:30:07 +0000331 completeAttrs();
332 pop();
333 break;
334 }
335 case TemplateArgument::Expression: {
336 dispatch(A.getAsExpr());
337 break;
338 }
339 case TemplateArgument::Pack: {
Douglas Gregor87dd6972010-12-20 16:52:59 +0000340 for (TemplateArgument::pack_iterator P = A.pack_begin(),
341 PEnd = A.pack_end();
342 P != PEnd; ++P)
343 dispatch(*P);
John McCall26c25c92010-11-24 11:30:07 +0000344 break;
345 }
346 }
347 }
348
349 void dispatch(const TemplateArgumentLoc &A) {
350 dispatch(A.getArgument());
351 }
352
353 //---- Declarations ------------------------------------------------//
354 // Calls are made in this order:
355 // # Enter a new node.
356 // push("FieldDecl")
357 //
358 // # In this phase, attributes are set on the node.
359 // visitDeclAttrs(D)
360 // visitNamedDeclAttrs(D)
361 // ...
362 // visitFieldDeclAttrs(D)
363 //
364 // # No more attributes after this point.
365 // completeAttrs()
366 //
367 // # Create "header" child nodes, i.e. those which logically
368 // # belong to the declaration itself.
369 // visitDeclChildren(D)
370 // visitNamedDeclChildren(D)
371 // ...
372 // visitFieldDeclChildren(D)
373 //
374 // # Create nodes for the lexical children.
375 // visitDeclAsContext(D)
376 // visitNamedDeclAsContext(D)
377 // ...
378 // visitFieldDeclAsContext(D)
379 //
380 // # Finish the node.
381 // pop();
382 void dispatch(Decl *D) {
383 push(D->getDeclKindName());
John McCall13cf5e22010-11-24 11:53:13 +0000384 XMLDeclVisitor<XMLDumper>::dispatch(D);
John McCall26c25c92010-11-24 11:30:07 +0000385 pop();
386 }
387 void visitDeclAttrs(Decl *D) {
388 setPointer(D);
389 }
390
391 /// Visit all the lexical decls in the given context.
392 void visitDeclContext(DeclContext *DC) {
393 for (DeclContext::decl_iterator
394 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
395 dispatch(*I);
396
397 // FIXME: point out visible declarations not in lexical context?
398 }
399
400 /// Set the "access" attribute on the current node according to the
401 /// given specifier.
402 void setAccess(AccessSpecifier AS) {
403 switch (AS) {
404 case AS_public: return set("access", "public");
405 case AS_protected: return set("access", "protected");
406 case AS_private: return set("access", "private");
407 case AS_none: llvm_unreachable("explicit forbidden access");
408 }
409 }
410
411 template <class T> void visitRedeclarableAttrs(T *D) {
Douglas Gregoref96ee02012-01-14 16:38:05 +0000412 if (T *Prev = D->getPreviousDecl())
John McCall26c25c92010-11-24 11:30:07 +0000413 setPointer("previous", Prev);
414 }
415
416
417 // TranslationUnitDecl
418 void visitTranslationUnitDeclAsContext(TranslationUnitDecl *D) {
419 visitDeclContext(D);
420 }
421
422 // LinkageSpecDecl
423 void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) {
Chris Lattner5f9e2722011-07-23 10:55:15 +0000424 StringRef lang = "";
John McCall26c25c92010-11-24 11:30:07 +0000425 switch (D->getLanguage()) {
426 case LinkageSpecDecl::lang_c: lang = "C"; break;
427 case LinkageSpecDecl::lang_cxx: lang = "C++"; break;
428 }
429 set("lang", lang);
430 }
431 void visitLinkageSpecDeclAsContext(LinkageSpecDecl *D) {
432 visitDeclContext(D);
433 }
434
435 // NamespaceDecl
436 void visitNamespaceDeclAttrs(NamespaceDecl *D) {
437 setFlag("inline", D->isInline());
438 if (!D->isOriginalNamespace())
439 setPointer("original", D->getOriginalNamespace());
440 }
441 void visitNamespaceDeclAsContext(NamespaceDecl *D) {
442 visitDeclContext(D);
443 }
444
445 // NamedDecl
446 void visitNamedDeclAttrs(NamedDecl *D) {
447 setName(D->getDeclName());
448 }
449
450 // ValueDecl
451 void visitValueDeclChildren(ValueDecl *D) {
452 dispatch(D->getType());
453 }
454
455 // DeclaratorDecl
456 void visitDeclaratorDeclChildren(DeclaratorDecl *D) {
457 //dispatch(D->getTypeSourceInfo()->getTypeLoc());
458 }
459
460 // VarDecl
461 void visitVarDeclAttrs(VarDecl *D) {
462 visitRedeclarableAttrs(D);
463 if (D->getStorageClass() != SC_None)
464 set("storage",
465 VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
Sebastian Redl5b9cc5d2012-02-11 23:51:47 +0000466 StringRef initStyle = "";
467 switch (D->getInitStyle()) {
468 case VarDecl::CInit: initStyle = "c"; break;
469 case VarDecl::CallInit: initStyle = "call"; break;
470 case VarDecl::ListInit: initStyle = "list"; break;
471 }
472 set("initstyle", initStyle);
John McCall26c25c92010-11-24 11:30:07 +0000473 setFlag("nrvo", D->isNRVOVariable());
474 // TODO: instantiation, etc.
475 }
476 void visitVarDeclChildren(VarDecl *D) {
477 if (D->hasInit()) dispatch(D->getInit());
478 }
479
480 // ParmVarDecl?
481
482 // FunctionDecl
483 void visitFunctionDeclAttrs(FunctionDecl *D) {
484 visitRedeclarableAttrs(D);
485 setFlag("pure", D->isPure());
486 setFlag("trivial", D->isTrivial());
487 setFlag("returnzero", D->hasImplicitReturnZero());
488 setFlag("prototype", D->hasWrittenPrototype());
Sean Hunt10620eb2011-05-06 20:44:56 +0000489 setFlag("deleted", D->isDeletedAsWritten());
John McCall26c25c92010-11-24 11:30:07 +0000490 if (D->getStorageClass() != SC_None)
491 set("storage",
492 VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
493 setFlag("inline", D->isInlineSpecified());
Joerg Sonnenbergercbea7632011-05-13 21:10:39 +0000494 if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>())
495 set("asmlabel", ALA->getLabel());
John McCall26c25c92010-11-24 11:30:07 +0000496 // TODO: instantiation, etc.
497 }
498 void visitFunctionDeclChildren(FunctionDecl *D) {
499 for (FunctionDecl::param_iterator
500 I = D->param_begin(), E = D->param_end(); I != E; ++I)
501 dispatch(*I);
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +0000502 for (ArrayRef<NamedDecl *>::iterator I = D->getDeclsInPrototypeScope().begin(),
503 E = D->getDeclsInPrototypeScope().end();
James Molloy16f1f712012-02-29 10:24:19 +0000504 I != E; ++I)
505 dispatch(*I);
Sean Hunt10620eb2011-05-06 20:44:56 +0000506 if (D->doesThisDeclarationHaveABody())
John McCall26c25c92010-11-24 11:30:07 +0000507 dispatch(D->getBody());
508 }
509
510 // CXXMethodDecl ?
511 // CXXConstructorDecl ?
512 // CXXDestructorDecl ?
513 // CXXConversionDecl ?
514
Sean Huntcbb67482011-01-08 20:30:50 +0000515 void dispatch(CXXCtorInitializer *Init) {
John McCall3bddf5c2010-12-02 10:24:56 +0000516 // TODO
517 }
518
John McCall26c25c92010-11-24 11:30:07 +0000519 // FieldDecl
520 void visitFieldDeclAttrs(FieldDecl *D) {
521 setFlag("mutable", D->isMutable());
522 }
523 void visitFieldDeclChildren(FieldDecl *D) {
524 if (D->isBitField()) {
525 TemporaryContainer C(*this, "bitwidth");
526 dispatch(D->getBitWidth());
527 }
528 // TODO: C++0x member initializer
529 }
530
531 // EnumConstantDecl
532 void visitEnumConstantDeclChildren(EnumConstantDecl *D) {
533 // value in any case?
534 if (D->getInitExpr()) dispatch(D->getInitExpr());
535 }
536
537 // IndirectFieldDecl
538 void visitIndirectFieldDeclChildren(IndirectFieldDecl *D) {
539 for (IndirectFieldDecl::chain_iterator
540 I = D->chain_begin(), E = D->chain_end(); I != E; ++I) {
541 NamedDecl *VD = const_cast<NamedDecl*>(*I);
542 push(isa<VarDecl>(VD) ? "variable" : "field");
543 setPointer("ptr", VD);
544 completeAttrs();
545 pop();
546 }
547 }
548
549 // TypeDecl
550 void visitTypeDeclAttrs(TypeDecl *D) {
551 setPointer("typeptr", D->getTypeForDecl());
552 }
553
554 // TypedefDecl
555 void visitTypedefDeclAttrs(TypedefDecl *D) {
Richard Smith162e1c12011-04-15 14:24:37 +0000556 visitRedeclarableAttrs<TypedefNameDecl>(D);
John McCall26c25c92010-11-24 11:30:07 +0000557 }
558 void visitTypedefDeclChildren(TypedefDecl *D) {
559 dispatch(D->getTypeSourceInfo()->getTypeLoc());
560 }
561
Richard Smith162e1c12011-04-15 14:24:37 +0000562 // TypeAliasDecl
563 void visitTypeAliasDeclAttrs(TypeAliasDecl *D) {
564 visitRedeclarableAttrs<TypedefNameDecl>(D);
565 }
566 void visitTypeAliasDeclChildren(TypeAliasDecl *D) {
567 dispatch(D->getTypeSourceInfo()->getTypeLoc());
568 }
569
John McCall26c25c92010-11-24 11:30:07 +0000570 // TagDecl
571 void visitTagDeclAttrs(TagDecl *D) {
572 visitRedeclarableAttrs(D);
573 }
574 void visitTagDeclAsContext(TagDecl *D) {
575 visitDeclContext(D);
576 }
577
578 // EnumDecl
579 void visitEnumDeclAttrs(EnumDecl *D) {
580 setFlag("scoped", D->isScoped());
581 setFlag("fixed", D->isFixed());
582 }
583 void visitEnumDeclChildren(EnumDecl *D) {
584 {
585 TemporaryContainer C(*this, "promotion_type");
586 dispatch(D->getPromotionType());
587 }
588 {
589 TemporaryContainer C(*this, "integer_type");
590 dispatch(D->getIntegerType());
591 }
592 }
593
594 // RecordDecl ?
595
596 void visitCXXRecordDeclChildren(CXXRecordDecl *D) {
597 if (!D->isThisDeclarationADefinition()) return;
598
599 for (CXXRecordDecl::base_class_iterator
600 I = D->bases_begin(), E = D->bases_end(); I != E; ++I) {
601 push("base");
602 setAccess(I->getAccessSpecifier());
603 completeAttrs();
604 dispatch(I->getTypeSourceInfo()->getTypeLoc());
605 pop();
606 }
607 }
608
609 // ClassTemplateSpecializationDecl ?
610
611 // FileScopeAsmDecl ?
612
613 // BlockDecl
614 void visitBlockDeclAttrs(BlockDecl *D) {
615 setFlag("variadic", D->isVariadic());
616 }
617 void visitBlockDeclChildren(BlockDecl *D) {
618 for (FunctionDecl::param_iterator
619 I = D->param_begin(), E = D->param_end(); I != E; ++I)
620 dispatch(*I);
621 dispatch(D->getBody());
622 }
623
624 // AccessSpecDecl
625 void visitAccessSpecDeclAttrs(AccessSpecDecl *D) {
626 setAccess(D->getAccess());
627 }
628
629 // TemplateDecl
630 void visitTemplateDeclChildren(TemplateDecl *D) {
631 visitTemplateParameters(D->getTemplateParameters());
Richard Smith3e4c6c42011-05-05 21:57:07 +0000632 if (D->getTemplatedDecl())
633 dispatch(D->getTemplatedDecl());
John McCall26c25c92010-11-24 11:30:07 +0000634 }
635
636 // FunctionTemplateDecl
637 void visitFunctionTemplateDeclAttrs(FunctionTemplateDecl *D) {
638 visitRedeclarableAttrs(D);
639 }
640 void visitFunctionTemplateDeclChildren(FunctionTemplateDecl *D) {
641 // Mention all the specializations which don't have explicit
642 // declarations elsewhere.
643 for (FunctionTemplateDecl::spec_iterator
644 I = D->spec_begin(), E = D->spec_end(); I != E; ++I) {
645 FunctionTemplateSpecializationInfo *Info
646 = I->getTemplateSpecializationInfo();
647
648 bool Unknown = false;
649 switch (Info->getTemplateSpecializationKind()) {
650 case TSK_ImplicitInstantiation: Unknown = false; break;
651 case TSK_Undeclared: Unknown = true; break;
652
653 // These will be covered at their respective sites.
654 case TSK_ExplicitSpecialization: continue;
655 case TSK_ExplicitInstantiationDeclaration: continue;
656 case TSK_ExplicitInstantiationDefinition: continue;
657 }
658
659 TemporaryContainer C(*this,
660 Unknown ? "uninstantiated" : "instantiation");
661 visitTemplateArguments(*Info->TemplateArguments);
662 dispatch(Info->Function);
663 }
664 }
665
666 // ClasTemplateDecl
667 void visitClassTemplateDeclAttrs(ClassTemplateDecl *D) {
668 visitRedeclarableAttrs(D);
669 }
670 void visitClassTemplateDeclChildren(ClassTemplateDecl *D) {
671 // Mention all the specializations which don't have explicit
672 // declarations elsewhere.
673 for (ClassTemplateDecl::spec_iterator
674 I = D->spec_begin(), E = D->spec_end(); I != E; ++I) {
675
676 bool Unknown = false;
677 switch (I->getTemplateSpecializationKind()) {
678 case TSK_ImplicitInstantiation: Unknown = false; break;
679 case TSK_Undeclared: Unknown = true; break;
680
681 // These will be covered at their respective sites.
682 case TSK_ExplicitSpecialization: continue;
683 case TSK_ExplicitInstantiationDeclaration: continue;
684 case TSK_ExplicitInstantiationDefinition: continue;
685 }
686
687 TemporaryContainer C(*this,
688 Unknown ? "uninstantiated" : "instantiation");
689 visitTemplateArguments(I->getTemplateArgs());
690 dispatch(*I);
691 }
692 }
693
694 // TemplateTypeParmDecl
695 void visitTemplateTypeParmDeclAttrs(TemplateTypeParmDecl *D) {
696 setInteger("depth", D->getDepth());
697 setInteger("index", D->getIndex());
698 }
699 void visitTemplateTypeParmDeclChildren(TemplateTypeParmDecl *D) {
700 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
701 dispatch(D->getDefaultArgumentInfo()->getTypeLoc());
702 // parameter pack?
703 }
704
705 // NonTypeTemplateParmDecl
706 void visitNonTypeTemplateParmDeclAttrs(NonTypeTemplateParmDecl *D) {
707 setInteger("depth", D->getDepth());
708 setInteger("index", D->getIndex());
709 }
710 void visitNonTypeTemplateParmDeclChildren(NonTypeTemplateParmDecl *D) {
711 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
712 dispatch(D->getDefaultArgument());
713 // parameter pack?
714 }
715
716 // TemplateTemplateParmDecl
717 void visitTemplateTemplateParmDeclAttrs(TemplateTemplateParmDecl *D) {
718 setInteger("depth", D->getDepth());
719 setInteger("index", D->getIndex());
720 }
721 void visitTemplateTemplateParmDeclChildren(TemplateTemplateParmDecl *D) {
722 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
723 dispatch(D->getDefaultArgument());
724 // parameter pack?
725 }
726
727 // FriendDecl
728 void visitFriendDeclChildren(FriendDecl *D) {
729 if (TypeSourceInfo *T = D->getFriendType())
730 dispatch(T->getTypeLoc());
731 else
732 dispatch(D->getFriendDecl());
733 }
734
735 // UsingDirectiveDecl ?
736 // UsingDecl ?
737 // UsingShadowDecl ?
738 // NamespaceAliasDecl ?
739 // UnresolvedUsingValueDecl ?
740 // UnresolvedUsingTypenameDecl ?
741 // StaticAssertDecl ?
742
John McCall3bddf5c2010-12-02 10:24:56 +0000743 // ObjCImplDecl
744 void visitObjCImplDeclChildren(ObjCImplDecl *D) {
745 visitDeclRef(D->getClassInterface());
746 }
747 void visitObjCImplDeclAsContext(ObjCImplDecl *D) {
748 visitDeclContext(D);
749 }
750
John McCall3bddf5c2010-12-02 10:24:56 +0000751 void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) {
752 setPointer("typeptr", D->getTypeForDecl());
Douglas Gregor7723fec2011-12-15 20:29:51 +0000753 setFlag("forward_decl", !D->isThisDeclarationADefinition());
John McCall3bddf5c2010-12-02 10:24:56 +0000754 setFlag("implicit_interface", D->isImplicitInterfaceDecl());
755 }
756 void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) {
757 visitDeclRef("super", D->getSuperClass());
758 visitDeclRef("implementation", D->getImplementation());
759 if (D->protocol_begin() != D->protocol_end()) {
760 TemporaryContainer C(*this, "protocols");
761 for (ObjCInterfaceDecl::protocol_iterator
762 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
763 visitDeclRef(*I);
764 }
Douglas Gregord3297242013-01-16 23:00:23 +0000765
766 if (!D->visible_categories_empty()) {
767 TemporaryContainer C(*this, "categories");
768
769 for (ObjCInterfaceDecl::visible_categories_iterator
770 Cat = D->visible_categories_begin(),
771 CatEnd = D->visible_categories_end();
772 Cat != CatEnd; ++Cat) {
773 visitDeclRef(*Cat);
774 }
775 }
John McCall3bddf5c2010-12-02 10:24:56 +0000776 }
777 void visitObjCInterfaceDeclAsContext(ObjCInterfaceDecl *D) {
778 visitDeclContext(D);
779 }
780
781 // ObjCCategoryDecl
782 void visitObjCCategoryDeclAttrs(ObjCCategoryDecl *D) {
783 setFlag("extension", D->IsClassExtension());
John McCall3bddf5c2010-12-02 10:24:56 +0000784 }
785 void visitObjCCategoryDeclChildren(ObjCCategoryDecl *D) {
786 visitDeclRef("interface", D->getClassInterface());
787 visitDeclRef("implementation", D->getImplementation());
788 if (D->protocol_begin() != D->protocol_end()) {
789 TemporaryContainer C(*this, "protocols");
790 for (ObjCCategoryDecl::protocol_iterator
791 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
792 visitDeclRef(*I);
793 }
794 }
795 void visitObjCCategoryDeclAsContext(ObjCCategoryDecl *D) {
796 visitDeclContext(D);
797 }
798
799 // ObjCCategoryImplDecl
800 void visitObjCCategoryImplDeclAttrs(ObjCCategoryImplDecl *D) {
801 set("identifier", D->getName());
802 }
803 void visitObjCCategoryImplDeclChildren(ObjCCategoryImplDecl *D) {
804 visitDeclRef(D->getCategoryDecl());
805 }
806
807 // ObjCImplementationDecl
808 void visitObjCImplementationDeclAttrs(ObjCImplementationDecl *D) {
John McCall3bddf5c2010-12-02 10:24:56 +0000809 set("identifier", D->getName());
810 }
811 void visitObjCImplementationDeclChildren(ObjCImplementationDecl *D) {
812 visitDeclRef("super", D->getSuperClass());
813 if (D->init_begin() != D->init_end()) {
814 TemporaryContainer C(*this, "initializers");
815 for (ObjCImplementationDecl::init_iterator
816 I = D->init_begin(), E = D->init_end(); I != E; ++I)
817 dispatch(*I);
818 }
819 }
820
John McCall3bddf5c2010-12-02 10:24:56 +0000821 // ObjCProtocolDecl
John McCall3bddf5c2010-12-02 10:24:56 +0000822 void visitObjCProtocolDeclChildren(ObjCProtocolDecl *D) {
Douglas Gregorbd9482d2012-01-01 21:23:57 +0000823 if (!D->isThisDeclarationADefinition())
824 return;
825
John McCall3bddf5c2010-12-02 10:24:56 +0000826 if (D->protocol_begin() != D->protocol_end()) {
827 TemporaryContainer C(*this, "protocols");
828 for (ObjCInterfaceDecl::protocol_iterator
829 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
830 visitDeclRef(*I);
831 }
832 }
833 void visitObjCProtocolDeclAsContext(ObjCProtocolDecl *D) {
Douglas Gregorbd9482d2012-01-01 21:23:57 +0000834 if (!D->isThisDeclarationADefinition())
835 return;
836
John McCall3bddf5c2010-12-02 10:24:56 +0000837 visitDeclContext(D);
838 }
839
840 // ObjCMethodDecl
841 void visitObjCMethodDeclAttrs(ObjCMethodDecl *D) {
842 // decl qualifier?
843 // implementation control?
844
845 setFlag("instance", D->isInstanceMethod());
846 setFlag("variadic", D->isVariadic());
Jordan Rose1e4691b2012-10-10 16:42:25 +0000847 setFlag("property_accessor", D->isPropertyAccessor());
John McCall3bddf5c2010-12-02 10:24:56 +0000848 setFlag("defined", D->isDefined());
Douglas Gregor926df6c2011-06-11 01:09:30 +0000849 setFlag("related_result_type", D->hasRelatedResultType());
John McCall3bddf5c2010-12-02 10:24:56 +0000850 }
851 void visitObjCMethodDeclChildren(ObjCMethodDecl *D) {
852 dispatch(D->getResultType());
853 for (ObjCMethodDecl::param_iterator
854 I = D->param_begin(), E = D->param_end(); I != E; ++I)
855 dispatch(*I);
856 if (D->isThisDeclarationADefinition())
857 dispatch(D->getBody());
858 }
859
860 // ObjCIvarDecl
Chris Lattner5f9e2722011-07-23 10:55:15 +0000861 void setAccessControl(StringRef prop, ObjCIvarDecl::AccessControl AC) {
John McCall3bddf5c2010-12-02 10:24:56 +0000862 switch (AC) {
863 case ObjCIvarDecl::None: return set(prop, "none");
864 case ObjCIvarDecl::Private: return set(prop, "private");
865 case ObjCIvarDecl::Protected: return set(prop, "protected");
866 case ObjCIvarDecl::Public: return set(prop, "public");
867 case ObjCIvarDecl::Package: return set(prop, "package");
868 }
869 }
870 void visitObjCIvarDeclAttrs(ObjCIvarDecl *D) {
871 setFlag("synthesize", D->getSynthesize());
872 setAccessControl("access", D->getAccessControl());
873 }
874
875 // ObjCCompatibleAliasDecl
876 void visitObjCCompatibleAliasDeclChildren(ObjCCompatibleAliasDecl *D) {
877 visitDeclRef(D->getClassInterface());
878 }
879
880 // FIXME: ObjCPropertyDecl
881 // FIXME: ObjCPropertyImplDecl
882
John McCall26c25c92010-11-24 11:30:07 +0000883 //---- Types -----------------------------------------------------//
884 void dispatch(TypeLoc TL) {
885 dispatch(TL.getType()); // for now
886 }
887
888 void dispatch(QualType T) {
889 if (T.hasLocalQualifiers()) {
890 push("QualType");
891 Qualifiers Qs = T.getLocalQualifiers();
892 setFlag("const", Qs.hasConst());
893 setFlag("volatile", Qs.hasVolatile());
894 setFlag("restrict", Qs.hasRestrict());
895 if (Qs.hasAddressSpace()) setInteger("addrspace", Qs.getAddressSpace());
896 if (Qs.hasObjCGCAttr()) {
897 switch (Qs.getObjCGCAttr()) {
898 case Qualifiers::Weak: set("gc", "weak"); break;
899 case Qualifiers::Strong: set("gc", "strong"); break;
900 case Qualifiers::GCNone: llvm_unreachable("explicit none");
901 }
902 }
903
904 completeAttrs();
905 dispatch(QualType(T.getTypePtr(), 0));
906 pop();
907 return;
908 }
909
910 Type *Ty = const_cast<Type*>(T.getTypePtr());
911 push(getTypeKindName(Ty));
John McCall13cf5e22010-11-24 11:53:13 +0000912 XMLTypeVisitor<XMLDumper>::dispatch(const_cast<Type*>(T.getTypePtr()));
John McCall26c25c92010-11-24 11:30:07 +0000913 pop();
914 }
915
916 void setCallingConv(CallingConv CC) {
917 switch (CC) {
918 case CC_Default: return;
919 case CC_C: return set("cc", "cdecl");
920 case CC_X86FastCall: return set("cc", "x86_fastcall");
921 case CC_X86StdCall: return set("cc", "x86_stdcall");
922 case CC_X86ThisCall: return set("cc", "x86_thiscall");
923 case CC_X86Pascal: return set("cc", "x86_pascal");
Anton Korobeynikov414d8962011-04-14 20:06:49 +0000924 case CC_AAPCS: return set("cc", "aapcs");
925 case CC_AAPCS_VFP: return set("cc", "aapcs_vfp");
Derek Schuff263366f2012-10-16 22:30:41 +0000926 case CC_PnaclCall: return set("cc", "pnaclcall");
Guy Benyei38980082012-12-25 08:53:55 +0000927 case CC_IntelOclBicc: return set("cc", "intel_ocl_bicc");
John McCall26c25c92010-11-24 11:30:07 +0000928 }
929 }
930
931 void visitTypeAttrs(Type *D) {
932 setPointer(D);
933 setFlag("dependent", D->isDependentType());
934 setFlag("variably_modified", D->isVariablyModifiedType());
935
936 setPointer("canonical", D->getCanonicalTypeInternal().getAsOpaquePtr());
937 }
938
939 void visitPointerTypeChildren(PointerType *T) {
940 dispatch(T->getPointeeType());
941 }
942 void visitReferenceTypeChildren(ReferenceType *T) {
943 dispatch(T->getPointeeType());
944 }
945 void visitObjCObjectPointerTypeChildren(ObjCObjectPointerType *T) {
946 dispatch(T->getPointeeType());
947 }
948 void visitBlockPointerTypeChildren(BlockPointerType *T) {
949 dispatch(T->getPointeeType());
950 }
951
952 // Types that just wrap declarations.
953 void visitTagTypeChildren(TagType *T) {
954 visitDeclRef(T->getDecl());
955 }
956 void visitTypedefTypeChildren(TypedefType *T) {
957 visitDeclRef(T->getDecl());
958 }
959 void visitObjCInterfaceTypeChildren(ObjCInterfaceType *T) {
960 visitDeclRef(T->getDecl());
961 }
962 void visitUnresolvedUsingTypeChildren(UnresolvedUsingType *T) {
963 visitDeclRef(T->getDecl());
964 }
965 void visitInjectedClassNameTypeChildren(InjectedClassNameType *T) {
966 visitDeclRef(T->getDecl());
967 }
968
969 void visitFunctionTypeAttrs(FunctionType *T) {
970 setFlag("noreturn", T->getNoReturnAttr());
971 setCallingConv(T->getCallConv());
Eli Friedmana49218e2011-04-09 08:18:08 +0000972 if (T->getHasRegParm()) setInteger("regparm", T->getRegParmType());
John McCall26c25c92010-11-24 11:30:07 +0000973 }
974 void visitFunctionTypeChildren(FunctionType *T) {
975 dispatch(T->getResultType());
976 }
977
978 void visitFunctionProtoTypeAttrs(FunctionProtoType *T) {
David Blaikie4ef832f2012-08-10 00:55:35 +0000979 setFlag("const", T->isConst());
980 setFlag("volatile", T->isVolatile());
981 setFlag("restrict", T->isRestrict());
Richard Smith03e6fda2012-10-21 23:00:34 +0000982 switch (T->getExceptionSpecType()) {
983 case EST_None: break;
984 case EST_DynamicNone: set("exception_spec", "throw()"); break;
985 case EST_Dynamic: set("exception_spec", "throw(T)"); break;
986 case EST_MSAny: set("exception_spec", "throw(...)"); break;
987 case EST_BasicNoexcept: set("exception_spec", "noexcept"); break;
988 case EST_ComputedNoexcept: set("exception_spec", "noexcept(expr)"); break;
989 case EST_Unevaluated: set("exception_spec", "unevaluated"); break;
990 case EST_Uninstantiated: set("exception_spec", "uninstantiated"); break;
991 }
John McCall26c25c92010-11-24 11:30:07 +0000992 }
993 void visitFunctionProtoTypeChildren(FunctionProtoType *T) {
994 push("parameters");
995 setFlag("variadic", T->isVariadic());
996 completeAttrs();
997 for (FunctionProtoType::arg_type_iterator
998 I = T->arg_type_begin(), E = T->arg_type_end(); I != E; ++I)
999 dispatch(*I);
1000 pop();
1001
Sebastian Redl60618fa2011-03-12 11:50:43 +00001002 if (T->hasDynamicExceptionSpec()) {
John McCall26c25c92010-11-24 11:30:07 +00001003 push("exception_specifiers");
Sebastian Redl60618fa2011-03-12 11:50:43 +00001004 setFlag("any", T->getExceptionSpecType() == EST_MSAny);
John McCall26c25c92010-11-24 11:30:07 +00001005 completeAttrs();
1006 for (FunctionProtoType::exception_iterator
1007 I = T->exception_begin(), E = T->exception_end(); I != E; ++I)
1008 dispatch(*I);
1009 pop();
1010 }
Sebastian Redl60618fa2011-03-12 11:50:43 +00001011 // FIXME: noexcept specifier
John McCall26c25c92010-11-24 11:30:07 +00001012 }
1013
1014 void visitTemplateSpecializationTypeChildren(TemplateSpecializationType *T) {
1015 if (const RecordType *RT = T->getAs<RecordType>())
1016 visitDeclRef(RT->getDecl());
1017
1018 // TODO: TemplateName
1019
1020 push("template_arguments");
1021 completeAttrs();
1022 for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I)
1023 dispatch(T->getArg(I));
1024 pop();
1025 }
1026
1027 //---- Statements ------------------------------------------------//
1028 void dispatch(Stmt *S) {
1029 // FIXME: this is not really XML at all
1030 push("Stmt");
John McCall3bddf5c2010-12-02 10:24:56 +00001031 out << ">\n";
John McCall26c25c92010-11-24 11:30:07 +00001032 Stack.back().State = NS_Children; // explicitly become non-lazy
1033 S->dump(out, Context.getSourceManager());
1034 out << '\n';
1035 pop();
1036 }
1037};
1038}
1039
Benjamin Kramer42c72c22012-08-14 14:50:32 +00001040void Decl::dumpXML() const {
Benjamin Kramer54c2f882012-08-22 08:38:23 +00001041 dumpXML(llvm::errs());
Benjamin Kramer42c72c22012-08-14 14:50:32 +00001042}
1043
Chris Lattner5f9e2722011-07-23 10:55:15 +00001044void Decl::dumpXML(raw_ostream &out) const {
John McCall26c25c92010-11-24 11:30:07 +00001045 XMLDumper(out, getASTContext()).dispatch(const_cast<Decl*>(this));
1046}
1047
1048#else /* ifndef NDEBUG */
1049
Benjamin Kramer42c72c22012-08-14 14:50:32 +00001050void Decl::dumpXML() const {}
Chris Lattner5f9e2722011-07-23 10:55:15 +00001051void Decl::dumpXML(raw_ostream &out) const {}
John McCall26c25c92010-11-24 11:30:07 +00001052
1053#endif