blob: b180e808ab40525dfe9ab0bedeebdf908b8972f0 [file] [log] [blame]
John McCall26c25c92010-11-24 11:30:07 +00001//===--- DumpXML.cpp - Detailed XML dumping ---------------------*- C++ -*-===//
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 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"
20#include "clang/AST/Decl.h"
21#include "clang/AST/DeclCXX.h"
22#include "clang/AST/DeclFriend.h"
23#include "clang/AST/DeclObjC.h"
24#include "clang/AST/DeclTemplate.h"
25#include "clang/AST/DeclVisitor.h"
26#include "clang/AST/Expr.h"
27#include "clang/AST/ExprCXX.h"
28#include "clang/AST/ExprObjC.h"
29#include "clang/AST/NestedNameSpecifier.h"
30#include "clang/AST/Stmt.h"
31#include "clang/AST/StmtCXX.h"
32#include "clang/AST/StmtObjC.h"
33#include "clang/AST/StmtVisitor.h"
34#include "clang/AST/TemplateBase.h"
35#include "clang/AST/TemplateName.h"
36#include "clang/AST/Type.h"
37#include "clang/AST/TypeLoc.h"
38#include "clang/AST/TypeLocVisitor.h"
39#include "clang/AST/TypeVisitor.h"
40#include "clang/AST/Expr.h"
41#include "clang/AST/ExprCXX.h"
Benjamin Kramer8fe83e12012-02-04 13:45:25 +000042#include "llvm/ADT/SmallString.h"
John McCall26c25c92010-11-24 11:30:07 +000043
44using namespace clang;
45
46#ifndef NDEBUG
47
48namespace {
49
50enum NodeState {
51 NS_Attrs, NS_LazyChildren, NS_Children
52};
53
54struct Node {
Chris Lattner5f9e2722011-07-23 10:55:15 +000055 StringRef Name;
John McCall26c25c92010-11-24 11:30:07 +000056 NodeState State;
Chris Lattner5f9e2722011-07-23 10:55:15 +000057 Node(StringRef name) : Name(name), State(NS_Attrs) {}
John McCall26c25c92010-11-24 11:30:07 +000058
59 bool isDoneWithAttrs() const { return State != NS_Attrs; }
60};
61
62template <class Impl> struct XMLDeclVisitor {
63#define DISPATCH(NAME, CLASS) \
64 static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(D))
65
66 void dispatch(Decl *D) {
67 switch (D->getKind()) {
John McCall26c25c92010-11-24 11:30:07 +000068#define DECL(DERIVED, BASE) \
69 case Decl::DERIVED: \
70 DISPATCH(dispatch##DERIVED##DeclAttrs, DERIVED##Decl); \
71 static_cast<Impl*>(this)->completeAttrs(); \
72 DISPATCH(dispatch##DERIVED##DeclChildren, DERIVED##Decl); \
73 DISPATCH(dispatch##DERIVED##DeclAsContext, DERIVED##Decl); \
74 break;
75#define ABSTRACT_DECL(DECL)
76#include "clang/AST/DeclNodes.inc"
77 }
78 }
79
80#define DECL(DERIVED, BASE) \
81 void dispatch##DERIVED##DeclAttrs(DERIVED##Decl *D) { \
82 DISPATCH(dispatch##BASE##Attrs, BASE); \
83 DISPATCH(visit##DERIVED##DeclAttrs, DERIVED##Decl); \
84 } \
85 void visit##DERIVED##DeclAttrs(DERIVED##Decl *D) {} \
86 void dispatch##DERIVED##DeclChildren(DERIVED##Decl *D) { \
87 DISPATCH(dispatch##BASE##Children, BASE); \
88 DISPATCH(visit##DERIVED##DeclChildren, DERIVED##Decl); \
89 } \
90 void visit##DERIVED##DeclChildren(DERIVED##Decl *D) {} \
91 void dispatch##DERIVED##DeclAsContext(DERIVED##Decl *D) { \
92 DISPATCH(dispatch##BASE##AsContext, BASE); \
93 DISPATCH(visit##DERIVED##DeclAsContext, DERIVED##Decl); \
94 } \
95 void visit##DERIVED##DeclAsContext(DERIVED##Decl *D) {}
96#include "clang/AST/DeclNodes.inc"
97
98 void dispatchDeclAttrs(Decl *D) {
99 DISPATCH(visitDeclAttrs, Decl);
100 }
101 void visitDeclAttrs(Decl *D) {}
102
103 void dispatchDeclChildren(Decl *D) {
104 DISPATCH(visitDeclChildren, Decl);
105 }
106 void visitDeclChildren(Decl *D) {}
107
108 void dispatchDeclAsContext(Decl *D) {
109 DISPATCH(visitDeclAsContext, Decl);
110 }
111 void visitDeclAsContext(Decl *D) {}
112
113#undef DISPATCH
114};
115
116template <class Impl> struct XMLTypeVisitor {
117#define DISPATCH(NAME, CLASS) \
118 static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(T))
119
120 void dispatch(Type *T) {
121 switch (T->getTypeClass()) {
John McCall26c25c92010-11-24 11:30:07 +0000122#define TYPE(DERIVED, BASE) \
123 case Type::DERIVED: \
124 DISPATCH(dispatch##DERIVED##TypeAttrs, DERIVED##Type); \
125 static_cast<Impl*>(this)->completeAttrs(); \
126 DISPATCH(dispatch##DERIVED##TypeChildren, DERIVED##Type); \
127 break;
128#define ABSTRACT_TYPE(DERIVED, BASE)
129#include "clang/AST/TypeNodes.def"
130 }
131 }
132
133#define TYPE(DERIVED, BASE) \
134 void dispatch##DERIVED##TypeAttrs(DERIVED##Type *T) { \
135 DISPATCH(dispatch##BASE##Attrs, BASE); \
136 DISPATCH(visit##DERIVED##TypeAttrs, DERIVED##Type); \
137 } \
138 void visit##DERIVED##TypeAttrs(DERIVED##Type *T) {} \
139 void dispatch##DERIVED##TypeChildren(DERIVED##Type *T) { \
140 DISPATCH(dispatch##BASE##Children, BASE); \
141 DISPATCH(visit##DERIVED##TypeChildren, DERIVED##Type); \
142 } \
143 void visit##DERIVED##TypeChildren(DERIVED##Type *T) {}
144#include "clang/AST/TypeNodes.def"
145
146 void dispatchTypeAttrs(Type *T) {
147 DISPATCH(visitTypeAttrs, Type);
148 }
149 void visitTypeAttrs(Type *T) {}
150
151 void dispatchTypeChildren(Type *T) {
152 DISPATCH(visitTypeChildren, Type);
153 }
154 void visitTypeChildren(Type *T) {}
155
156#undef DISPATCH
157};
158
Chris Lattner5f9e2722011-07-23 10:55:15 +0000159static StringRef getTypeKindName(Type *T) {
John McCall26c25c92010-11-24 11:30:07 +0000160 switch (T->getTypeClass()) {
161#define TYPE(DERIVED, BASE) case Type::DERIVED: return #DERIVED "Type";
162#define ABSTRACT_TYPE(DERIVED, BASE)
163#include "clang/AST/TypeNodes.def"
164 }
165
166 llvm_unreachable("unknown type kind!");
John McCall26c25c92010-11-24 11:30:07 +0000167}
168
169struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
170 public XMLTypeVisitor<XMLDumper> {
Chris Lattner5f9e2722011-07-23 10:55:15 +0000171 raw_ostream &out;
John McCall26c25c92010-11-24 11:30:07 +0000172 ASTContext &Context;
Chris Lattner5f9e2722011-07-23 10:55:15 +0000173 SmallVector<Node, 16> Stack;
John McCall26c25c92010-11-24 11:30:07 +0000174 unsigned Indent;
Chris Lattner5f9e2722011-07-23 10:55:15 +0000175 explicit XMLDumper(raw_ostream &OS, ASTContext &context)
John McCall26c25c92010-11-24 11:30:07 +0000176 : out(OS), Context(context), Indent(0) {}
177
178 void indent() {
179 for (unsigned I = Indent; I; --I)
180 out << ' ';
181 }
182
183 /// Push a new node on the stack.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000184 void push(StringRef name) {
John McCall26c25c92010-11-24 11:30:07 +0000185 if (!Stack.empty()) {
186 assert(Stack.back().isDoneWithAttrs());
187 if (Stack.back().State == NS_LazyChildren) {
188 Stack.back().State = NS_Children;
189 out << ">\n";
190 }
191 Indent++;
192 indent();
193 }
194 Stack.push_back(Node(name));
195 out << '<' << name;
196 }
197
198 /// Set the given attribute to the given value.
Chris Lattner5f9e2722011-07-23 10:55:15 +0000199 void set(StringRef attr, StringRef value) {
John McCall26c25c92010-11-24 11:30:07 +0000200 assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
201 out << ' ' << attr << '=' << '"' << value << '"'; // TODO: quotation
202 }
203
204 /// Finish attributes.
205 void completeAttrs() {
206 assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
207 Stack.back().State = NS_LazyChildren;
208 }
209
210 /// Pop a node.
211 void pop() {
212 assert(!Stack.empty() && Stack.back().isDoneWithAttrs());
213 if (Stack.back().State == NS_LazyChildren) {
214 out << "/>\n";
215 } else {
216 indent();
217 out << "</" << Stack.back().Name << ">\n";
218 }
219 if (Stack.size() > 1) Indent--;
220 Stack.pop_back();
221 }
222
223 //---- General utilities -------------------------------------------//
224
Chris Lattner5f9e2722011-07-23 10:55:15 +0000225 void setPointer(StringRef prop, const void *p) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000226 SmallString<10> buffer;
John McCall26c25c92010-11-24 11:30:07 +0000227 llvm::raw_svector_ostream os(buffer);
228 os << p;
229 os.flush();
230 set(prop, buffer);
231 }
232
233 void setPointer(void *p) {
234 setPointer("ptr", p);
235 }
236
Chris Lattner5f9e2722011-07-23 10:55:15 +0000237 void setInteger(StringRef prop, const llvm::APSInt &v) {
John McCall26c25c92010-11-24 11:30:07 +0000238 set(prop, v.toString(10));
239 }
240
Chris Lattner5f9e2722011-07-23 10:55:15 +0000241 void setInteger(StringRef prop, unsigned n) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +0000242 SmallString<10> buffer;
John McCall26c25c92010-11-24 11:30:07 +0000243 llvm::raw_svector_ostream os(buffer);
244 os << n;
245 os.flush();
246 set(prop, buffer);
247 }
248
Chris Lattner5f9e2722011-07-23 10:55:15 +0000249 void setFlag(StringRef prop, bool flag) {
John McCall26c25c92010-11-24 11:30:07 +0000250 if (flag) set(prop, "true");
251 }
252
253 void setName(DeclarationName Name) {
John McCall6710cf12010-11-30 10:12:16 +0000254 if (!Name)
255 return set("name", "");
256
John McCall26c25c92010-11-24 11:30:07 +0000257 // Common case.
258 if (Name.isIdentifier())
259 return set("name", Name.getAsIdentifierInfo()->getName());
260
John McCall7bd245b2010-12-02 10:37:08 +0000261 set("name", Name.getAsString());
John McCall26c25c92010-11-24 11:30:07 +0000262 }
263
264 class TemporaryContainer {
265 XMLDumper &Dumper;
266 public:
Chris Lattner5f9e2722011-07-23 10:55:15 +0000267 TemporaryContainer(XMLDumper &dumper, StringRef name)
John McCall26c25c92010-11-24 11:30:07 +0000268 : Dumper(dumper) {
269 Dumper.push(name);
270 Dumper.completeAttrs();
271 }
272
273 ~TemporaryContainer() {
274 Dumper.pop();
275 }
276 };
277
278 void visitTemplateParameters(TemplateParameterList *L) {
279 push("template_parameters");
280 completeAttrs();
281 for (TemplateParameterList::iterator
282 I = L->begin(), E = L->end(); I != E; ++I)
283 dispatch(*I);
284 pop();
285 }
286
287 void visitTemplateArguments(const TemplateArgumentList &L) {
288 push("template_arguments");
289 completeAttrs();
290 for (unsigned I = 0, E = L.size(); I != E; ++I)
291 dispatch(L[I]);
292 pop();
293 }
294
295 /// Visits a reference to the given declaration.
296 void visitDeclRef(Decl *D) {
297 push(D->getDeclKindName());
298 setPointer("ref", D);
299 completeAttrs();
300 pop();
301 }
Chris Lattner5f9e2722011-07-23 10:55:15 +0000302 void visitDeclRef(StringRef Name, Decl *D) {
John McCall3bddf5c2010-12-02 10:24:56 +0000303 TemporaryContainer C(*this, Name);
304 if (D) visitDeclRef(D);
305 }
John McCall26c25c92010-11-24 11:30:07 +0000306
307 void dispatch(const TemplateArgument &A) {
308 switch (A.getKind()) {
309 case TemplateArgument::Null: {
310 TemporaryContainer C(*this, "null");
311 break;
312 }
313 case TemplateArgument::Type: {
314 dispatch(A.getAsType());
315 break;
316 }
317 case TemplateArgument::Template:
Douglas Gregora7fc9012011-01-05 18:58:31 +0000318 case TemplateArgument::TemplateExpansion:
319 // FIXME: Implement!
320 break;
321
John McCall26c25c92010-11-24 11:30:07 +0000322 case TemplateArgument::Declaration: {
323 visitDeclRef(A.getAsDecl());
324 break;
325 }
326 case TemplateArgument::Integral: {
327 push("integer");
328 setInteger("value", *A.getAsIntegral());
329 completeAttrs();
330 pop();
331 break;
332 }
333 case TemplateArgument::Expression: {
334 dispatch(A.getAsExpr());
335 break;
336 }
337 case TemplateArgument::Pack: {
Douglas Gregor87dd6972010-12-20 16:52:59 +0000338 for (TemplateArgument::pack_iterator P = A.pack_begin(),
339 PEnd = A.pack_end();
340 P != PEnd; ++P)
341 dispatch(*P);
John McCall26c25c92010-11-24 11:30:07 +0000342 break;
343 }
344 }
345 }
346
347 void dispatch(const TemplateArgumentLoc &A) {
348 dispatch(A.getArgument());
349 }
350
351 //---- Declarations ------------------------------------------------//
352 // Calls are made in this order:
353 // # Enter a new node.
354 // push("FieldDecl")
355 //
356 // # In this phase, attributes are set on the node.
357 // visitDeclAttrs(D)
358 // visitNamedDeclAttrs(D)
359 // ...
360 // visitFieldDeclAttrs(D)
361 //
362 // # No more attributes after this point.
363 // completeAttrs()
364 //
365 // # Create "header" child nodes, i.e. those which logically
366 // # belong to the declaration itself.
367 // visitDeclChildren(D)
368 // visitNamedDeclChildren(D)
369 // ...
370 // visitFieldDeclChildren(D)
371 //
372 // # Create nodes for the lexical children.
373 // visitDeclAsContext(D)
374 // visitNamedDeclAsContext(D)
375 // ...
376 // visitFieldDeclAsContext(D)
377 //
378 // # Finish the node.
379 // pop();
380 void dispatch(Decl *D) {
381 push(D->getDeclKindName());
John McCall13cf5e22010-11-24 11:53:13 +0000382 XMLDeclVisitor<XMLDumper>::dispatch(D);
John McCall26c25c92010-11-24 11:30:07 +0000383 pop();
384 }
385 void visitDeclAttrs(Decl *D) {
386 setPointer(D);
387 }
388
389 /// Visit all the lexical decls in the given context.
390 void visitDeclContext(DeclContext *DC) {
391 for (DeclContext::decl_iterator
392 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
393 dispatch(*I);
394
395 // FIXME: point out visible declarations not in lexical context?
396 }
397
398 /// Set the "access" attribute on the current node according to the
399 /// given specifier.
400 void setAccess(AccessSpecifier AS) {
401 switch (AS) {
402 case AS_public: return set("access", "public");
403 case AS_protected: return set("access", "protected");
404 case AS_private: return set("access", "private");
405 case AS_none: llvm_unreachable("explicit forbidden access");
406 }
407 }
408
409 template <class T> void visitRedeclarableAttrs(T *D) {
Douglas Gregoref96ee02012-01-14 16:38:05 +0000410 if (T *Prev = D->getPreviousDecl())
John McCall26c25c92010-11-24 11:30:07 +0000411 setPointer("previous", Prev);
412 }
413
414
415 // TranslationUnitDecl
416 void visitTranslationUnitDeclAsContext(TranslationUnitDecl *D) {
417 visitDeclContext(D);
418 }
419
420 // LinkageSpecDecl
421 void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) {
Chris Lattner5f9e2722011-07-23 10:55:15 +0000422 StringRef lang = "";
John McCall26c25c92010-11-24 11:30:07 +0000423 switch (D->getLanguage()) {
424 case LinkageSpecDecl::lang_c: lang = "C"; break;
425 case LinkageSpecDecl::lang_cxx: lang = "C++"; break;
426 }
427 set("lang", lang);
428 }
429 void visitLinkageSpecDeclAsContext(LinkageSpecDecl *D) {
430 visitDeclContext(D);
431 }
432
433 // NamespaceDecl
434 void visitNamespaceDeclAttrs(NamespaceDecl *D) {
435 setFlag("inline", D->isInline());
436 if (!D->isOriginalNamespace())
437 setPointer("original", D->getOriginalNamespace());
438 }
439 void visitNamespaceDeclAsContext(NamespaceDecl *D) {
440 visitDeclContext(D);
441 }
442
443 // NamedDecl
444 void visitNamedDeclAttrs(NamedDecl *D) {
445 setName(D->getDeclName());
446 }
447
448 // ValueDecl
449 void visitValueDeclChildren(ValueDecl *D) {
450 dispatch(D->getType());
451 }
452
453 // DeclaratorDecl
454 void visitDeclaratorDeclChildren(DeclaratorDecl *D) {
455 //dispatch(D->getTypeSourceInfo()->getTypeLoc());
456 }
457
458 // VarDecl
459 void visitVarDeclAttrs(VarDecl *D) {
460 visitRedeclarableAttrs(D);
461 if (D->getStorageClass() != SC_None)
462 set("storage",
463 VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
Sebastian Redl5b9cc5d2012-02-11 23:51:47 +0000464 StringRef initStyle = "";
465 switch (D->getInitStyle()) {
466 case VarDecl::CInit: initStyle = "c"; break;
467 case VarDecl::CallInit: initStyle = "call"; break;
468 case VarDecl::ListInit: initStyle = "list"; break;
469 }
470 set("initstyle", initStyle);
John McCall26c25c92010-11-24 11:30:07 +0000471 setFlag("nrvo", D->isNRVOVariable());
472 // TODO: instantiation, etc.
473 }
474 void visitVarDeclChildren(VarDecl *D) {
475 if (D->hasInit()) dispatch(D->getInit());
476 }
477
478 // ParmVarDecl?
479
480 // FunctionDecl
481 void visitFunctionDeclAttrs(FunctionDecl *D) {
482 visitRedeclarableAttrs(D);
483 setFlag("pure", D->isPure());
484 setFlag("trivial", D->isTrivial());
485 setFlag("returnzero", D->hasImplicitReturnZero());
486 setFlag("prototype", D->hasWrittenPrototype());
Sean Hunt10620eb2011-05-06 20:44:56 +0000487 setFlag("deleted", D->isDeletedAsWritten());
John McCall26c25c92010-11-24 11:30:07 +0000488 if (D->getStorageClass() != SC_None)
489 set("storage",
490 VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
491 setFlag("inline", D->isInlineSpecified());
Joerg Sonnenbergercbea7632011-05-13 21:10:39 +0000492 if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>())
493 set("asmlabel", ALA->getLabel());
John McCall26c25c92010-11-24 11:30:07 +0000494 // TODO: instantiation, etc.
495 }
496 void visitFunctionDeclChildren(FunctionDecl *D) {
497 for (FunctionDecl::param_iterator
498 I = D->param_begin(), E = D->param_end(); I != E; ++I)
499 dispatch(*I);
James Molloy16f1f712012-02-29 10:24:19 +0000500 for (llvm::ArrayRef<NamedDecl*>::iterator
501 I = D->getDeclsInPrototypeScope().begin(), E = D->getDeclsInPrototypeScope().end();
502 I != E; ++I)
503 dispatch(*I);
Sean Hunt10620eb2011-05-06 20:44:56 +0000504 if (D->doesThisDeclarationHaveABody())
John McCall26c25c92010-11-24 11:30:07 +0000505 dispatch(D->getBody());
506 }
507
508 // CXXMethodDecl ?
509 // CXXConstructorDecl ?
510 // CXXDestructorDecl ?
511 // CXXConversionDecl ?
512
Sean Huntcbb67482011-01-08 20:30:50 +0000513 void dispatch(CXXCtorInitializer *Init) {
John McCall3bddf5c2010-12-02 10:24:56 +0000514 // TODO
515 }
516
John McCall26c25c92010-11-24 11:30:07 +0000517 // FieldDecl
518 void visitFieldDeclAttrs(FieldDecl *D) {
519 setFlag("mutable", D->isMutable());
520 }
521 void visitFieldDeclChildren(FieldDecl *D) {
522 if (D->isBitField()) {
523 TemporaryContainer C(*this, "bitwidth");
524 dispatch(D->getBitWidth());
525 }
526 // TODO: C++0x member initializer
527 }
528
529 // EnumConstantDecl
530 void visitEnumConstantDeclChildren(EnumConstantDecl *D) {
531 // value in any case?
532 if (D->getInitExpr()) dispatch(D->getInitExpr());
533 }
534
535 // IndirectFieldDecl
536 void visitIndirectFieldDeclChildren(IndirectFieldDecl *D) {
537 for (IndirectFieldDecl::chain_iterator
538 I = D->chain_begin(), E = D->chain_end(); I != E; ++I) {
539 NamedDecl *VD = const_cast<NamedDecl*>(*I);
540 push(isa<VarDecl>(VD) ? "variable" : "field");
541 setPointer("ptr", VD);
542 completeAttrs();
543 pop();
544 }
545 }
546
547 // TypeDecl
548 void visitTypeDeclAttrs(TypeDecl *D) {
549 setPointer("typeptr", D->getTypeForDecl());
550 }
551
552 // TypedefDecl
553 void visitTypedefDeclAttrs(TypedefDecl *D) {
Richard Smith162e1c12011-04-15 14:24:37 +0000554 visitRedeclarableAttrs<TypedefNameDecl>(D);
John McCall26c25c92010-11-24 11:30:07 +0000555 }
556 void visitTypedefDeclChildren(TypedefDecl *D) {
557 dispatch(D->getTypeSourceInfo()->getTypeLoc());
558 }
559
Richard Smith162e1c12011-04-15 14:24:37 +0000560 // TypeAliasDecl
561 void visitTypeAliasDeclAttrs(TypeAliasDecl *D) {
562 visitRedeclarableAttrs<TypedefNameDecl>(D);
563 }
564 void visitTypeAliasDeclChildren(TypeAliasDecl *D) {
565 dispatch(D->getTypeSourceInfo()->getTypeLoc());
566 }
567
John McCall26c25c92010-11-24 11:30:07 +0000568 // TagDecl
569 void visitTagDeclAttrs(TagDecl *D) {
570 visitRedeclarableAttrs(D);
571 }
572 void visitTagDeclAsContext(TagDecl *D) {
573 visitDeclContext(D);
574 }
575
576 // EnumDecl
577 void visitEnumDeclAttrs(EnumDecl *D) {
578 setFlag("scoped", D->isScoped());
579 setFlag("fixed", D->isFixed());
580 }
581 void visitEnumDeclChildren(EnumDecl *D) {
582 {
583 TemporaryContainer C(*this, "promotion_type");
584 dispatch(D->getPromotionType());
585 }
586 {
587 TemporaryContainer C(*this, "integer_type");
588 dispatch(D->getIntegerType());
589 }
590 }
591
592 // RecordDecl ?
593
594 void visitCXXRecordDeclChildren(CXXRecordDecl *D) {
595 if (!D->isThisDeclarationADefinition()) return;
596
597 for (CXXRecordDecl::base_class_iterator
598 I = D->bases_begin(), E = D->bases_end(); I != E; ++I) {
599 push("base");
600 setAccess(I->getAccessSpecifier());
601 completeAttrs();
602 dispatch(I->getTypeSourceInfo()->getTypeLoc());
603 pop();
604 }
605 }
606
607 // ClassTemplateSpecializationDecl ?
608
609 // FileScopeAsmDecl ?
610
611 // BlockDecl
612 void visitBlockDeclAttrs(BlockDecl *D) {
613 setFlag("variadic", D->isVariadic());
614 }
615 void visitBlockDeclChildren(BlockDecl *D) {
616 for (FunctionDecl::param_iterator
617 I = D->param_begin(), E = D->param_end(); I != E; ++I)
618 dispatch(*I);
619 dispatch(D->getBody());
620 }
621
622 // AccessSpecDecl
623 void visitAccessSpecDeclAttrs(AccessSpecDecl *D) {
624 setAccess(D->getAccess());
625 }
626
627 // TemplateDecl
628 void visitTemplateDeclChildren(TemplateDecl *D) {
629 visitTemplateParameters(D->getTemplateParameters());
Richard Smith3e4c6c42011-05-05 21:57:07 +0000630 if (D->getTemplatedDecl())
631 dispatch(D->getTemplatedDecl());
John McCall26c25c92010-11-24 11:30:07 +0000632 }
633
634 // FunctionTemplateDecl
635 void visitFunctionTemplateDeclAttrs(FunctionTemplateDecl *D) {
636 visitRedeclarableAttrs(D);
637 }
638 void visitFunctionTemplateDeclChildren(FunctionTemplateDecl *D) {
639 // Mention all the specializations which don't have explicit
640 // declarations elsewhere.
641 for (FunctionTemplateDecl::spec_iterator
642 I = D->spec_begin(), E = D->spec_end(); I != E; ++I) {
643 FunctionTemplateSpecializationInfo *Info
644 = I->getTemplateSpecializationInfo();
645
646 bool Unknown = false;
647 switch (Info->getTemplateSpecializationKind()) {
648 case TSK_ImplicitInstantiation: Unknown = false; break;
649 case TSK_Undeclared: Unknown = true; break;
650
651 // These will be covered at their respective sites.
652 case TSK_ExplicitSpecialization: continue;
653 case TSK_ExplicitInstantiationDeclaration: continue;
654 case TSK_ExplicitInstantiationDefinition: continue;
655 }
656
657 TemporaryContainer C(*this,
658 Unknown ? "uninstantiated" : "instantiation");
659 visitTemplateArguments(*Info->TemplateArguments);
660 dispatch(Info->Function);
661 }
662 }
663
664 // ClasTemplateDecl
665 void visitClassTemplateDeclAttrs(ClassTemplateDecl *D) {
666 visitRedeclarableAttrs(D);
667 }
668 void visitClassTemplateDeclChildren(ClassTemplateDecl *D) {
669 // Mention all the specializations which don't have explicit
670 // declarations elsewhere.
671 for (ClassTemplateDecl::spec_iterator
672 I = D->spec_begin(), E = D->spec_end(); I != E; ++I) {
673
674 bool Unknown = false;
675 switch (I->getTemplateSpecializationKind()) {
676 case TSK_ImplicitInstantiation: Unknown = false; break;
677 case TSK_Undeclared: Unknown = true; break;
678
679 // These will be covered at their respective sites.
680 case TSK_ExplicitSpecialization: continue;
681 case TSK_ExplicitInstantiationDeclaration: continue;
682 case TSK_ExplicitInstantiationDefinition: continue;
683 }
684
685 TemporaryContainer C(*this,
686 Unknown ? "uninstantiated" : "instantiation");
687 visitTemplateArguments(I->getTemplateArgs());
688 dispatch(*I);
689 }
690 }
691
692 // TemplateTypeParmDecl
693 void visitTemplateTypeParmDeclAttrs(TemplateTypeParmDecl *D) {
694 setInteger("depth", D->getDepth());
695 setInteger("index", D->getIndex());
696 }
697 void visitTemplateTypeParmDeclChildren(TemplateTypeParmDecl *D) {
698 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
699 dispatch(D->getDefaultArgumentInfo()->getTypeLoc());
700 // parameter pack?
701 }
702
703 // NonTypeTemplateParmDecl
704 void visitNonTypeTemplateParmDeclAttrs(NonTypeTemplateParmDecl *D) {
705 setInteger("depth", D->getDepth());
706 setInteger("index", D->getIndex());
707 }
708 void visitNonTypeTemplateParmDeclChildren(NonTypeTemplateParmDecl *D) {
709 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
710 dispatch(D->getDefaultArgument());
711 // parameter pack?
712 }
713
714 // TemplateTemplateParmDecl
715 void visitTemplateTemplateParmDeclAttrs(TemplateTemplateParmDecl *D) {
716 setInteger("depth", D->getDepth());
717 setInteger("index", D->getIndex());
718 }
719 void visitTemplateTemplateParmDeclChildren(TemplateTemplateParmDecl *D) {
720 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
721 dispatch(D->getDefaultArgument());
722 // parameter pack?
723 }
724
725 // FriendDecl
726 void visitFriendDeclChildren(FriendDecl *D) {
727 if (TypeSourceInfo *T = D->getFriendType())
728 dispatch(T->getTypeLoc());
729 else
730 dispatch(D->getFriendDecl());
731 }
732
733 // UsingDirectiveDecl ?
734 // UsingDecl ?
735 // UsingShadowDecl ?
736 // NamespaceAliasDecl ?
737 // UnresolvedUsingValueDecl ?
738 // UnresolvedUsingTypenameDecl ?
739 // StaticAssertDecl ?
740
John McCall3bddf5c2010-12-02 10:24:56 +0000741 // ObjCImplDecl
742 void visitObjCImplDeclChildren(ObjCImplDecl *D) {
743 visitDeclRef(D->getClassInterface());
744 }
745 void visitObjCImplDeclAsContext(ObjCImplDecl *D) {
746 visitDeclContext(D);
747 }
748
John McCall3bddf5c2010-12-02 10:24:56 +0000749 // ObjCInterfaceDecl
750 void visitCategoryList(ObjCCategoryDecl *D) {
751 if (!D) return;
752
753 TemporaryContainer C(*this, "categories");
754 for (; D; D = D->getNextClassCategory())
755 visitDeclRef(D);
756 }
757 void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) {
758 setPointer("typeptr", D->getTypeForDecl());
Douglas Gregor7723fec2011-12-15 20:29:51 +0000759 setFlag("forward_decl", !D->isThisDeclarationADefinition());
John McCall3bddf5c2010-12-02 10:24:56 +0000760 setFlag("implicit_interface", D->isImplicitInterfaceDecl());
761 }
762 void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) {
763 visitDeclRef("super", D->getSuperClass());
764 visitDeclRef("implementation", D->getImplementation());
765 if (D->protocol_begin() != D->protocol_end()) {
766 TemporaryContainer C(*this, "protocols");
767 for (ObjCInterfaceDecl::protocol_iterator
768 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
769 visitDeclRef(*I);
770 }
771 visitCategoryList(D->getCategoryList());
772 }
773 void visitObjCInterfaceDeclAsContext(ObjCInterfaceDecl *D) {
774 visitDeclContext(D);
775 }
776
777 // ObjCCategoryDecl
778 void visitObjCCategoryDeclAttrs(ObjCCategoryDecl *D) {
779 setFlag("extension", D->IsClassExtension());
780 setFlag("synth_bitfield", D->hasSynthBitfield());
781 }
782 void visitObjCCategoryDeclChildren(ObjCCategoryDecl *D) {
783 visitDeclRef("interface", D->getClassInterface());
784 visitDeclRef("implementation", D->getImplementation());
785 if (D->protocol_begin() != D->protocol_end()) {
786 TemporaryContainer C(*this, "protocols");
787 for (ObjCCategoryDecl::protocol_iterator
788 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
789 visitDeclRef(*I);
790 }
791 }
792 void visitObjCCategoryDeclAsContext(ObjCCategoryDecl *D) {
793 visitDeclContext(D);
794 }
795
796 // ObjCCategoryImplDecl
797 void visitObjCCategoryImplDeclAttrs(ObjCCategoryImplDecl *D) {
798 set("identifier", D->getName());
799 }
800 void visitObjCCategoryImplDeclChildren(ObjCCategoryImplDecl *D) {
801 visitDeclRef(D->getCategoryDecl());
802 }
803
804 // ObjCImplementationDecl
805 void visitObjCImplementationDeclAttrs(ObjCImplementationDecl *D) {
806 setFlag("synth_bitfield", D->hasSynthBitfield());
807 set("identifier", D->getName());
808 }
809 void visitObjCImplementationDeclChildren(ObjCImplementationDecl *D) {
810 visitDeclRef("super", D->getSuperClass());
811 if (D->init_begin() != D->init_end()) {
812 TemporaryContainer C(*this, "initializers");
813 for (ObjCImplementationDecl::init_iterator
814 I = D->init_begin(), E = D->init_end(); I != E; ++I)
815 dispatch(*I);
816 }
817 }
818
John McCall3bddf5c2010-12-02 10:24:56 +0000819 // ObjCProtocolDecl
John McCall3bddf5c2010-12-02 10:24:56 +0000820 void visitObjCProtocolDeclChildren(ObjCProtocolDecl *D) {
Douglas Gregorbd9482d2012-01-01 21:23:57 +0000821 if (!D->isThisDeclarationADefinition())
822 return;
823
John McCall3bddf5c2010-12-02 10:24:56 +0000824 if (D->protocol_begin() != D->protocol_end()) {
825 TemporaryContainer C(*this, "protocols");
826 for (ObjCInterfaceDecl::protocol_iterator
827 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
828 visitDeclRef(*I);
829 }
830 }
831 void visitObjCProtocolDeclAsContext(ObjCProtocolDecl *D) {
Douglas Gregorbd9482d2012-01-01 21:23:57 +0000832 if (!D->isThisDeclarationADefinition())
833 return;
834
John McCall3bddf5c2010-12-02 10:24:56 +0000835 visitDeclContext(D);
836 }
837
838 // ObjCMethodDecl
839 void visitObjCMethodDeclAttrs(ObjCMethodDecl *D) {
840 // decl qualifier?
841 // implementation control?
842
843 setFlag("instance", D->isInstanceMethod());
844 setFlag("variadic", D->isVariadic());
845 setFlag("synthesized", D->isSynthesized());
846 setFlag("defined", D->isDefined());
Douglas Gregor926df6c2011-06-11 01:09:30 +0000847 setFlag("related_result_type", D->hasRelatedResultType());
John McCall3bddf5c2010-12-02 10:24:56 +0000848 }
849 void visitObjCMethodDeclChildren(ObjCMethodDecl *D) {
850 dispatch(D->getResultType());
851 for (ObjCMethodDecl::param_iterator
852 I = D->param_begin(), E = D->param_end(); I != E; ++I)
853 dispatch(*I);
854 if (D->isThisDeclarationADefinition())
855 dispatch(D->getBody());
856 }
857
858 // ObjCIvarDecl
Chris Lattner5f9e2722011-07-23 10:55:15 +0000859 void setAccessControl(StringRef prop, ObjCIvarDecl::AccessControl AC) {
John McCall3bddf5c2010-12-02 10:24:56 +0000860 switch (AC) {
861 case ObjCIvarDecl::None: return set(prop, "none");
862 case ObjCIvarDecl::Private: return set(prop, "private");
863 case ObjCIvarDecl::Protected: return set(prop, "protected");
864 case ObjCIvarDecl::Public: return set(prop, "public");
865 case ObjCIvarDecl::Package: return set(prop, "package");
866 }
867 }
868 void visitObjCIvarDeclAttrs(ObjCIvarDecl *D) {
869 setFlag("synthesize", D->getSynthesize());
870 setAccessControl("access", D->getAccessControl());
871 }
872
873 // ObjCCompatibleAliasDecl
874 void visitObjCCompatibleAliasDeclChildren(ObjCCompatibleAliasDecl *D) {
875 visitDeclRef(D->getClassInterface());
876 }
877
878 // FIXME: ObjCPropertyDecl
879 // FIXME: ObjCPropertyImplDecl
880
John McCall26c25c92010-11-24 11:30:07 +0000881 //---- Types -----------------------------------------------------//
882 void dispatch(TypeLoc TL) {
883 dispatch(TL.getType()); // for now
884 }
885
886 void dispatch(QualType T) {
887 if (T.hasLocalQualifiers()) {
888 push("QualType");
889 Qualifiers Qs = T.getLocalQualifiers();
890 setFlag("const", Qs.hasConst());
891 setFlag("volatile", Qs.hasVolatile());
892 setFlag("restrict", Qs.hasRestrict());
893 if (Qs.hasAddressSpace()) setInteger("addrspace", Qs.getAddressSpace());
894 if (Qs.hasObjCGCAttr()) {
895 switch (Qs.getObjCGCAttr()) {
896 case Qualifiers::Weak: set("gc", "weak"); break;
897 case Qualifiers::Strong: set("gc", "strong"); break;
898 case Qualifiers::GCNone: llvm_unreachable("explicit none");
899 }
900 }
901
902 completeAttrs();
903 dispatch(QualType(T.getTypePtr(), 0));
904 pop();
905 return;
906 }
907
908 Type *Ty = const_cast<Type*>(T.getTypePtr());
909 push(getTypeKindName(Ty));
John McCall13cf5e22010-11-24 11:53:13 +0000910 XMLTypeVisitor<XMLDumper>::dispatch(const_cast<Type*>(T.getTypePtr()));
John McCall26c25c92010-11-24 11:30:07 +0000911 pop();
912 }
913
914 void setCallingConv(CallingConv CC) {
915 switch (CC) {
916 case CC_Default: return;
917 case CC_C: return set("cc", "cdecl");
918 case CC_X86FastCall: return set("cc", "x86_fastcall");
919 case CC_X86StdCall: return set("cc", "x86_stdcall");
920 case CC_X86ThisCall: return set("cc", "x86_thiscall");
921 case CC_X86Pascal: return set("cc", "x86_pascal");
Anton Korobeynikov414d8962011-04-14 20:06:49 +0000922 case CC_AAPCS: return set("cc", "aapcs");
923 case CC_AAPCS_VFP: return set("cc", "aapcs_vfp");
John McCall26c25c92010-11-24 11:30:07 +0000924 }
925 }
926
927 void visitTypeAttrs(Type *D) {
928 setPointer(D);
929 setFlag("dependent", D->isDependentType());
930 setFlag("variably_modified", D->isVariablyModifiedType());
931
932 setPointer("canonical", D->getCanonicalTypeInternal().getAsOpaquePtr());
933 }
934
935 void visitPointerTypeChildren(PointerType *T) {
936 dispatch(T->getPointeeType());
937 }
938 void visitReferenceTypeChildren(ReferenceType *T) {
939 dispatch(T->getPointeeType());
940 }
941 void visitObjCObjectPointerTypeChildren(ObjCObjectPointerType *T) {
942 dispatch(T->getPointeeType());
943 }
944 void visitBlockPointerTypeChildren(BlockPointerType *T) {
945 dispatch(T->getPointeeType());
946 }
947
948 // Types that just wrap declarations.
949 void visitTagTypeChildren(TagType *T) {
950 visitDeclRef(T->getDecl());
951 }
952 void visitTypedefTypeChildren(TypedefType *T) {
953 visitDeclRef(T->getDecl());
954 }
955 void visitObjCInterfaceTypeChildren(ObjCInterfaceType *T) {
956 visitDeclRef(T->getDecl());
957 }
958 void visitUnresolvedUsingTypeChildren(UnresolvedUsingType *T) {
959 visitDeclRef(T->getDecl());
960 }
961 void visitInjectedClassNameTypeChildren(InjectedClassNameType *T) {
962 visitDeclRef(T->getDecl());
963 }
964
965 void visitFunctionTypeAttrs(FunctionType *T) {
966 setFlag("noreturn", T->getNoReturnAttr());
967 setCallingConv(T->getCallConv());
Eli Friedmana49218e2011-04-09 08:18:08 +0000968 if (T->getHasRegParm()) setInteger("regparm", T->getRegParmType());
John McCall26c25c92010-11-24 11:30:07 +0000969 }
970 void visitFunctionTypeChildren(FunctionType *T) {
971 dispatch(T->getResultType());
972 }
973
974 void visitFunctionProtoTypeAttrs(FunctionProtoType *T) {
975 setFlag("const", T->getTypeQuals() & Qualifiers::Const);
976 setFlag("volatile", T->getTypeQuals() & Qualifiers::Volatile);
977 setFlag("restrict", T->getTypeQuals() & Qualifiers::Restrict);
978 }
979 void visitFunctionProtoTypeChildren(FunctionProtoType *T) {
980 push("parameters");
981 setFlag("variadic", T->isVariadic());
982 completeAttrs();
983 for (FunctionProtoType::arg_type_iterator
984 I = T->arg_type_begin(), E = T->arg_type_end(); I != E; ++I)
985 dispatch(*I);
986 pop();
987
Sebastian Redl60618fa2011-03-12 11:50:43 +0000988 if (T->hasDynamicExceptionSpec()) {
John McCall26c25c92010-11-24 11:30:07 +0000989 push("exception_specifiers");
Sebastian Redl60618fa2011-03-12 11:50:43 +0000990 setFlag("any", T->getExceptionSpecType() == EST_MSAny);
John McCall26c25c92010-11-24 11:30:07 +0000991 completeAttrs();
992 for (FunctionProtoType::exception_iterator
993 I = T->exception_begin(), E = T->exception_end(); I != E; ++I)
994 dispatch(*I);
995 pop();
996 }
Sebastian Redl60618fa2011-03-12 11:50:43 +0000997 // FIXME: noexcept specifier
John McCall26c25c92010-11-24 11:30:07 +0000998 }
999
1000 void visitTemplateSpecializationTypeChildren(TemplateSpecializationType *T) {
1001 if (const RecordType *RT = T->getAs<RecordType>())
1002 visitDeclRef(RT->getDecl());
1003
1004 // TODO: TemplateName
1005
1006 push("template_arguments");
1007 completeAttrs();
1008 for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I)
1009 dispatch(T->getArg(I));
1010 pop();
1011 }
1012
1013 //---- Statements ------------------------------------------------//
1014 void dispatch(Stmt *S) {
1015 // FIXME: this is not really XML at all
1016 push("Stmt");
John McCall3bddf5c2010-12-02 10:24:56 +00001017 out << ">\n";
John McCall26c25c92010-11-24 11:30:07 +00001018 Stack.back().State = NS_Children; // explicitly become non-lazy
1019 S->dump(out, Context.getSourceManager());
1020 out << '\n';
1021 pop();
1022 }
1023};
1024}
1025
1026void Decl::dumpXML() const {
1027 dumpXML(llvm::errs());
1028}
1029
Chris Lattner5f9e2722011-07-23 10:55:15 +00001030void Decl::dumpXML(raw_ostream &out) const {
John McCall26c25c92010-11-24 11:30:07 +00001031 XMLDumper(out, getASTContext()).dispatch(const_cast<Decl*>(this));
1032}
1033
1034#else /* ifndef NDEBUG */
1035
1036void Decl::dumpXML() const {}
Chris Lattner5f9e2722011-07-23 10:55:15 +00001037void Decl::dumpXML(raw_ostream &out) const {}
John McCall26c25c92010-11-24 11:30:07 +00001038
1039#endif