blob: c5e23ccc6eade449ec23642d8245db09f7bff443 [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"
42#include "llvm/ADT/SmallVector.h"
43#include "llvm/ADT/StringRef.h"
44
45using namespace clang;
46
47#ifndef NDEBUG
48
49namespace {
50
51enum NodeState {
52 NS_Attrs, NS_LazyChildren, NS_Children
53};
54
55struct Node {
Chris Lattner5f9e2722011-07-23 10:55:15 +000056 StringRef Name;
John McCall26c25c92010-11-24 11:30:07 +000057 NodeState State;
Chris Lattner5f9e2722011-07-23 10:55:15 +000058 Node(StringRef name) : Name(name), State(NS_Attrs) {}
John McCall26c25c92010-11-24 11:30:07 +000059
60 bool isDoneWithAttrs() const { return State != NS_Attrs; }
61};
62
63template <class Impl> struct XMLDeclVisitor {
64#define DISPATCH(NAME, CLASS) \
65 static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(D))
66
67 void dispatch(Decl *D) {
68 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) {
John McCall26c25c92010-11-24 11:30:07 +0000227 llvm::SmallString<10> buffer;
228 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) {
John McCall26c25c92010-11-24 11:30:07 +0000243 llvm::SmallString<10> buffer;
244 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:
320 // FIXME: Implement!
321 break;
322
John McCall26c25c92010-11-24 11:30:07 +0000323 case TemplateArgument::Declaration: {
324 visitDeclRef(A.getAsDecl());
325 break;
326 }
327 case TemplateArgument::Integral: {
328 push("integer");
329 setInteger("value", *A.getAsIntegral());
330 completeAttrs();
331 pop();
332 break;
333 }
334 case TemplateArgument::Expression: {
335 dispatch(A.getAsExpr());
336 break;
337 }
338 case TemplateArgument::Pack: {
Douglas Gregor87dd6972010-12-20 16:52:59 +0000339 for (TemplateArgument::pack_iterator P = A.pack_begin(),
340 PEnd = A.pack_end();
341 P != PEnd; ++P)
342 dispatch(*P);
John McCall26c25c92010-11-24 11:30:07 +0000343 break;
344 }
345 }
346 }
347
348 void dispatch(const TemplateArgumentLoc &A) {
349 dispatch(A.getArgument());
350 }
351
352 //---- Declarations ------------------------------------------------//
353 // Calls are made in this order:
354 // # Enter a new node.
355 // push("FieldDecl")
356 //
357 // # In this phase, attributes are set on the node.
358 // visitDeclAttrs(D)
359 // visitNamedDeclAttrs(D)
360 // ...
361 // visitFieldDeclAttrs(D)
362 //
363 // # No more attributes after this point.
364 // completeAttrs()
365 //
366 // # Create "header" child nodes, i.e. those which logically
367 // # belong to the declaration itself.
368 // visitDeclChildren(D)
369 // visitNamedDeclChildren(D)
370 // ...
371 // visitFieldDeclChildren(D)
372 //
373 // # Create nodes for the lexical children.
374 // visitDeclAsContext(D)
375 // visitNamedDeclAsContext(D)
376 // ...
377 // visitFieldDeclAsContext(D)
378 //
379 // # Finish the node.
380 // pop();
381 void dispatch(Decl *D) {
382 push(D->getDeclKindName());
John McCall13cf5e22010-11-24 11:53:13 +0000383 XMLDeclVisitor<XMLDumper>::dispatch(D);
John McCall26c25c92010-11-24 11:30:07 +0000384 pop();
385 }
386 void visitDeclAttrs(Decl *D) {
387 setPointer(D);
388 }
389
390 /// Visit all the lexical decls in the given context.
391 void visitDeclContext(DeclContext *DC) {
392 for (DeclContext::decl_iterator
393 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
394 dispatch(*I);
395
396 // FIXME: point out visible declarations not in lexical context?
397 }
398
399 /// Set the "access" attribute on the current node according to the
400 /// given specifier.
401 void setAccess(AccessSpecifier AS) {
402 switch (AS) {
403 case AS_public: return set("access", "public");
404 case AS_protected: return set("access", "protected");
405 case AS_private: return set("access", "private");
406 case AS_none: llvm_unreachable("explicit forbidden access");
407 }
408 }
409
410 template <class T> void visitRedeclarableAttrs(T *D) {
Douglas Gregoref96ee02012-01-14 16:38:05 +0000411 if (T *Prev = D->getPreviousDecl())
John McCall26c25c92010-11-24 11:30:07 +0000412 setPointer("previous", Prev);
413 }
414
415
416 // TranslationUnitDecl
417 void visitTranslationUnitDeclAsContext(TranslationUnitDecl *D) {
418 visitDeclContext(D);
419 }
420
421 // LinkageSpecDecl
422 void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) {
Chris Lattner5f9e2722011-07-23 10:55:15 +0000423 StringRef lang = "";
John McCall26c25c92010-11-24 11:30:07 +0000424 switch (D->getLanguage()) {
425 case LinkageSpecDecl::lang_c: lang = "C"; break;
426 case LinkageSpecDecl::lang_cxx: lang = "C++"; break;
427 }
428 set("lang", lang);
429 }
430 void visitLinkageSpecDeclAsContext(LinkageSpecDecl *D) {
431 visitDeclContext(D);
432 }
433
434 // NamespaceDecl
435 void visitNamespaceDeclAttrs(NamespaceDecl *D) {
436 setFlag("inline", D->isInline());
437 if (!D->isOriginalNamespace())
438 setPointer("original", D->getOriginalNamespace());
439 }
440 void visitNamespaceDeclAsContext(NamespaceDecl *D) {
441 visitDeclContext(D);
442 }
443
444 // NamedDecl
445 void visitNamedDeclAttrs(NamedDecl *D) {
446 setName(D->getDeclName());
447 }
448
449 // ValueDecl
450 void visitValueDeclChildren(ValueDecl *D) {
451 dispatch(D->getType());
452 }
453
454 // DeclaratorDecl
455 void visitDeclaratorDeclChildren(DeclaratorDecl *D) {
456 //dispatch(D->getTypeSourceInfo()->getTypeLoc());
457 }
458
459 // VarDecl
460 void visitVarDeclAttrs(VarDecl *D) {
461 visitRedeclarableAttrs(D);
462 if (D->getStorageClass() != SC_None)
463 set("storage",
464 VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
465 setFlag("directinit", D->hasCXXDirectInitializer());
466 setFlag("nrvo", D->isNRVOVariable());
467 // TODO: instantiation, etc.
468 }
469 void visitVarDeclChildren(VarDecl *D) {
470 if (D->hasInit()) dispatch(D->getInit());
471 }
472
473 // ParmVarDecl?
474
475 // FunctionDecl
476 void visitFunctionDeclAttrs(FunctionDecl *D) {
477 visitRedeclarableAttrs(D);
478 setFlag("pure", D->isPure());
479 setFlag("trivial", D->isTrivial());
480 setFlag("returnzero", D->hasImplicitReturnZero());
481 setFlag("prototype", D->hasWrittenPrototype());
Sean Hunt10620eb2011-05-06 20:44:56 +0000482 setFlag("deleted", D->isDeletedAsWritten());
John McCall26c25c92010-11-24 11:30:07 +0000483 if (D->getStorageClass() != SC_None)
484 set("storage",
485 VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
486 setFlag("inline", D->isInlineSpecified());
Joerg Sonnenbergercbea7632011-05-13 21:10:39 +0000487 if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>())
488 set("asmlabel", ALA->getLabel());
John McCall26c25c92010-11-24 11:30:07 +0000489 // TODO: instantiation, etc.
490 }
491 void visitFunctionDeclChildren(FunctionDecl *D) {
492 for (FunctionDecl::param_iterator
493 I = D->param_begin(), E = D->param_end(); I != E; ++I)
494 dispatch(*I);
Sean Hunt10620eb2011-05-06 20:44:56 +0000495 if (D->doesThisDeclarationHaveABody())
John McCall26c25c92010-11-24 11:30:07 +0000496 dispatch(D->getBody());
497 }
498
499 // CXXMethodDecl ?
500 // CXXConstructorDecl ?
501 // CXXDestructorDecl ?
502 // CXXConversionDecl ?
503
Sean Huntcbb67482011-01-08 20:30:50 +0000504 void dispatch(CXXCtorInitializer *Init) {
John McCall3bddf5c2010-12-02 10:24:56 +0000505 // TODO
506 }
507
John McCall26c25c92010-11-24 11:30:07 +0000508 // FieldDecl
509 void visitFieldDeclAttrs(FieldDecl *D) {
510 setFlag("mutable", D->isMutable());
511 }
512 void visitFieldDeclChildren(FieldDecl *D) {
513 if (D->isBitField()) {
514 TemporaryContainer C(*this, "bitwidth");
515 dispatch(D->getBitWidth());
516 }
517 // TODO: C++0x member initializer
518 }
519
520 // EnumConstantDecl
521 void visitEnumConstantDeclChildren(EnumConstantDecl *D) {
522 // value in any case?
523 if (D->getInitExpr()) dispatch(D->getInitExpr());
524 }
525
526 // IndirectFieldDecl
527 void visitIndirectFieldDeclChildren(IndirectFieldDecl *D) {
528 for (IndirectFieldDecl::chain_iterator
529 I = D->chain_begin(), E = D->chain_end(); I != E; ++I) {
530 NamedDecl *VD = const_cast<NamedDecl*>(*I);
531 push(isa<VarDecl>(VD) ? "variable" : "field");
532 setPointer("ptr", VD);
533 completeAttrs();
534 pop();
535 }
536 }
537
538 // TypeDecl
539 void visitTypeDeclAttrs(TypeDecl *D) {
540 setPointer("typeptr", D->getTypeForDecl());
541 }
542
543 // TypedefDecl
544 void visitTypedefDeclAttrs(TypedefDecl *D) {
Richard Smith162e1c12011-04-15 14:24:37 +0000545 visitRedeclarableAttrs<TypedefNameDecl>(D);
John McCall26c25c92010-11-24 11:30:07 +0000546 }
547 void visitTypedefDeclChildren(TypedefDecl *D) {
548 dispatch(D->getTypeSourceInfo()->getTypeLoc());
549 }
550
Richard Smith162e1c12011-04-15 14:24:37 +0000551 // TypeAliasDecl
552 void visitTypeAliasDeclAttrs(TypeAliasDecl *D) {
553 visitRedeclarableAttrs<TypedefNameDecl>(D);
554 }
555 void visitTypeAliasDeclChildren(TypeAliasDecl *D) {
556 dispatch(D->getTypeSourceInfo()->getTypeLoc());
557 }
558
John McCall26c25c92010-11-24 11:30:07 +0000559 // TagDecl
560 void visitTagDeclAttrs(TagDecl *D) {
561 visitRedeclarableAttrs(D);
562 }
563 void visitTagDeclAsContext(TagDecl *D) {
564 visitDeclContext(D);
565 }
566
567 // EnumDecl
568 void visitEnumDeclAttrs(EnumDecl *D) {
569 setFlag("scoped", D->isScoped());
570 setFlag("fixed", D->isFixed());
571 }
572 void visitEnumDeclChildren(EnumDecl *D) {
573 {
574 TemporaryContainer C(*this, "promotion_type");
575 dispatch(D->getPromotionType());
576 }
577 {
578 TemporaryContainer C(*this, "integer_type");
579 dispatch(D->getIntegerType());
580 }
581 }
582
583 // RecordDecl ?
584
585 void visitCXXRecordDeclChildren(CXXRecordDecl *D) {
586 if (!D->isThisDeclarationADefinition()) return;
587
588 for (CXXRecordDecl::base_class_iterator
589 I = D->bases_begin(), E = D->bases_end(); I != E; ++I) {
590 push("base");
591 setAccess(I->getAccessSpecifier());
592 completeAttrs();
593 dispatch(I->getTypeSourceInfo()->getTypeLoc());
594 pop();
595 }
596 }
597
598 // ClassTemplateSpecializationDecl ?
599
600 // FileScopeAsmDecl ?
601
602 // BlockDecl
603 void visitBlockDeclAttrs(BlockDecl *D) {
604 setFlag("variadic", D->isVariadic());
605 }
606 void visitBlockDeclChildren(BlockDecl *D) {
607 for (FunctionDecl::param_iterator
608 I = D->param_begin(), E = D->param_end(); I != E; ++I)
609 dispatch(*I);
610 dispatch(D->getBody());
611 }
612
613 // AccessSpecDecl
614 void visitAccessSpecDeclAttrs(AccessSpecDecl *D) {
615 setAccess(D->getAccess());
616 }
617
618 // TemplateDecl
619 void visitTemplateDeclChildren(TemplateDecl *D) {
620 visitTemplateParameters(D->getTemplateParameters());
Richard Smith3e4c6c42011-05-05 21:57:07 +0000621 if (D->getTemplatedDecl())
622 dispatch(D->getTemplatedDecl());
John McCall26c25c92010-11-24 11:30:07 +0000623 }
624
625 // FunctionTemplateDecl
626 void visitFunctionTemplateDeclAttrs(FunctionTemplateDecl *D) {
627 visitRedeclarableAttrs(D);
628 }
629 void visitFunctionTemplateDeclChildren(FunctionTemplateDecl *D) {
630 // Mention all the specializations which don't have explicit
631 // declarations elsewhere.
632 for (FunctionTemplateDecl::spec_iterator
633 I = D->spec_begin(), E = D->spec_end(); I != E; ++I) {
634 FunctionTemplateSpecializationInfo *Info
635 = I->getTemplateSpecializationInfo();
636
637 bool Unknown = false;
638 switch (Info->getTemplateSpecializationKind()) {
639 case TSK_ImplicitInstantiation: Unknown = false; break;
640 case TSK_Undeclared: Unknown = true; break;
641
642 // These will be covered at their respective sites.
643 case TSK_ExplicitSpecialization: continue;
644 case TSK_ExplicitInstantiationDeclaration: continue;
645 case TSK_ExplicitInstantiationDefinition: continue;
646 }
647
648 TemporaryContainer C(*this,
649 Unknown ? "uninstantiated" : "instantiation");
650 visitTemplateArguments(*Info->TemplateArguments);
651 dispatch(Info->Function);
652 }
653 }
654
655 // ClasTemplateDecl
656 void visitClassTemplateDeclAttrs(ClassTemplateDecl *D) {
657 visitRedeclarableAttrs(D);
658 }
659 void visitClassTemplateDeclChildren(ClassTemplateDecl *D) {
660 // Mention all the specializations which don't have explicit
661 // declarations elsewhere.
662 for (ClassTemplateDecl::spec_iterator
663 I = D->spec_begin(), E = D->spec_end(); I != E; ++I) {
664
665 bool Unknown = false;
666 switch (I->getTemplateSpecializationKind()) {
667 case TSK_ImplicitInstantiation: Unknown = false; break;
668 case TSK_Undeclared: Unknown = true; break;
669
670 // These will be covered at their respective sites.
671 case TSK_ExplicitSpecialization: continue;
672 case TSK_ExplicitInstantiationDeclaration: continue;
673 case TSK_ExplicitInstantiationDefinition: continue;
674 }
675
676 TemporaryContainer C(*this,
677 Unknown ? "uninstantiated" : "instantiation");
678 visitTemplateArguments(I->getTemplateArgs());
679 dispatch(*I);
680 }
681 }
682
683 // TemplateTypeParmDecl
684 void visitTemplateTypeParmDeclAttrs(TemplateTypeParmDecl *D) {
685 setInteger("depth", D->getDepth());
686 setInteger("index", D->getIndex());
687 }
688 void visitTemplateTypeParmDeclChildren(TemplateTypeParmDecl *D) {
689 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
690 dispatch(D->getDefaultArgumentInfo()->getTypeLoc());
691 // parameter pack?
692 }
693
694 // NonTypeTemplateParmDecl
695 void visitNonTypeTemplateParmDeclAttrs(NonTypeTemplateParmDecl *D) {
696 setInteger("depth", D->getDepth());
697 setInteger("index", D->getIndex());
698 }
699 void visitNonTypeTemplateParmDeclChildren(NonTypeTemplateParmDecl *D) {
700 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
701 dispatch(D->getDefaultArgument());
702 // parameter pack?
703 }
704
705 // TemplateTemplateParmDecl
706 void visitTemplateTemplateParmDeclAttrs(TemplateTemplateParmDecl *D) {
707 setInteger("depth", D->getDepth());
708 setInteger("index", D->getIndex());
709 }
710 void visitTemplateTemplateParmDeclChildren(TemplateTemplateParmDecl *D) {
711 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
712 dispatch(D->getDefaultArgument());
713 // parameter pack?
714 }
715
716 // FriendDecl
717 void visitFriendDeclChildren(FriendDecl *D) {
718 if (TypeSourceInfo *T = D->getFriendType())
719 dispatch(T->getTypeLoc());
720 else
721 dispatch(D->getFriendDecl());
722 }
723
724 // UsingDirectiveDecl ?
725 // UsingDecl ?
726 // UsingShadowDecl ?
727 // NamespaceAliasDecl ?
728 // UnresolvedUsingValueDecl ?
729 // UnresolvedUsingTypenameDecl ?
730 // StaticAssertDecl ?
731
John McCall3bddf5c2010-12-02 10:24:56 +0000732 // ObjCImplDecl
733 void visitObjCImplDeclChildren(ObjCImplDecl *D) {
734 visitDeclRef(D->getClassInterface());
735 }
736 void visitObjCImplDeclAsContext(ObjCImplDecl *D) {
737 visitDeclContext(D);
738 }
739
John McCall3bddf5c2010-12-02 10:24:56 +0000740 // ObjCInterfaceDecl
741 void visitCategoryList(ObjCCategoryDecl *D) {
742 if (!D) return;
743
744 TemporaryContainer C(*this, "categories");
745 for (; D; D = D->getNextClassCategory())
746 visitDeclRef(D);
747 }
748 void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) {
749 setPointer("typeptr", D->getTypeForDecl());
Douglas Gregor7723fec2011-12-15 20:29:51 +0000750 setFlag("forward_decl", !D->isThisDeclarationADefinition());
John McCall3bddf5c2010-12-02 10:24:56 +0000751 setFlag("implicit_interface", D->isImplicitInterfaceDecl());
752 }
753 void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) {
754 visitDeclRef("super", D->getSuperClass());
755 visitDeclRef("implementation", D->getImplementation());
756 if (D->protocol_begin() != D->protocol_end()) {
757 TemporaryContainer C(*this, "protocols");
758 for (ObjCInterfaceDecl::protocol_iterator
759 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
760 visitDeclRef(*I);
761 }
762 visitCategoryList(D->getCategoryList());
763 }
764 void visitObjCInterfaceDeclAsContext(ObjCInterfaceDecl *D) {
765 visitDeclContext(D);
766 }
767
768 // ObjCCategoryDecl
769 void visitObjCCategoryDeclAttrs(ObjCCategoryDecl *D) {
770 setFlag("extension", D->IsClassExtension());
771 setFlag("synth_bitfield", D->hasSynthBitfield());
772 }
773 void visitObjCCategoryDeclChildren(ObjCCategoryDecl *D) {
774 visitDeclRef("interface", D->getClassInterface());
775 visitDeclRef("implementation", D->getImplementation());
776 if (D->protocol_begin() != D->protocol_end()) {
777 TemporaryContainer C(*this, "protocols");
778 for (ObjCCategoryDecl::protocol_iterator
779 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
780 visitDeclRef(*I);
781 }
782 }
783 void visitObjCCategoryDeclAsContext(ObjCCategoryDecl *D) {
784 visitDeclContext(D);
785 }
786
787 // ObjCCategoryImplDecl
788 void visitObjCCategoryImplDeclAttrs(ObjCCategoryImplDecl *D) {
789 set("identifier", D->getName());
790 }
791 void visitObjCCategoryImplDeclChildren(ObjCCategoryImplDecl *D) {
792 visitDeclRef(D->getCategoryDecl());
793 }
794
795 // ObjCImplementationDecl
796 void visitObjCImplementationDeclAttrs(ObjCImplementationDecl *D) {
797 setFlag("synth_bitfield", D->hasSynthBitfield());
798 set("identifier", D->getName());
799 }
800 void visitObjCImplementationDeclChildren(ObjCImplementationDecl *D) {
801 visitDeclRef("super", D->getSuperClass());
802 if (D->init_begin() != D->init_end()) {
803 TemporaryContainer C(*this, "initializers");
804 for (ObjCImplementationDecl::init_iterator
805 I = D->init_begin(), E = D->init_end(); I != E; ++I)
806 dispatch(*I);
807 }
808 }
809
John McCall3bddf5c2010-12-02 10:24:56 +0000810 // ObjCProtocolDecl
John McCall3bddf5c2010-12-02 10:24:56 +0000811 void visitObjCProtocolDeclChildren(ObjCProtocolDecl *D) {
Douglas Gregorbd9482d2012-01-01 21:23:57 +0000812 if (!D->isThisDeclarationADefinition())
813 return;
814
John McCall3bddf5c2010-12-02 10:24:56 +0000815 if (D->protocol_begin() != D->protocol_end()) {
816 TemporaryContainer C(*this, "protocols");
817 for (ObjCInterfaceDecl::protocol_iterator
818 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
819 visitDeclRef(*I);
820 }
821 }
822 void visitObjCProtocolDeclAsContext(ObjCProtocolDecl *D) {
Douglas Gregorbd9482d2012-01-01 21:23:57 +0000823 if (!D->isThisDeclarationADefinition())
824 return;
825
John McCall3bddf5c2010-12-02 10:24:56 +0000826 visitDeclContext(D);
827 }
828
829 // ObjCMethodDecl
830 void visitObjCMethodDeclAttrs(ObjCMethodDecl *D) {
831 // decl qualifier?
832 // implementation control?
833
834 setFlag("instance", D->isInstanceMethod());
835 setFlag("variadic", D->isVariadic());
836 setFlag("synthesized", D->isSynthesized());
837 setFlag("defined", D->isDefined());
Douglas Gregor926df6c2011-06-11 01:09:30 +0000838 setFlag("related_result_type", D->hasRelatedResultType());
John McCall3bddf5c2010-12-02 10:24:56 +0000839 }
840 void visitObjCMethodDeclChildren(ObjCMethodDecl *D) {
841 dispatch(D->getResultType());
842 for (ObjCMethodDecl::param_iterator
843 I = D->param_begin(), E = D->param_end(); I != E; ++I)
844 dispatch(*I);
845 if (D->isThisDeclarationADefinition())
846 dispatch(D->getBody());
847 }
848
849 // ObjCIvarDecl
Chris Lattner5f9e2722011-07-23 10:55:15 +0000850 void setAccessControl(StringRef prop, ObjCIvarDecl::AccessControl AC) {
John McCall3bddf5c2010-12-02 10:24:56 +0000851 switch (AC) {
852 case ObjCIvarDecl::None: return set(prop, "none");
853 case ObjCIvarDecl::Private: return set(prop, "private");
854 case ObjCIvarDecl::Protected: return set(prop, "protected");
855 case ObjCIvarDecl::Public: return set(prop, "public");
856 case ObjCIvarDecl::Package: return set(prop, "package");
857 }
858 }
859 void visitObjCIvarDeclAttrs(ObjCIvarDecl *D) {
860 setFlag("synthesize", D->getSynthesize());
861 setAccessControl("access", D->getAccessControl());
862 }
863
864 // ObjCCompatibleAliasDecl
865 void visitObjCCompatibleAliasDeclChildren(ObjCCompatibleAliasDecl *D) {
866 visitDeclRef(D->getClassInterface());
867 }
868
869 // FIXME: ObjCPropertyDecl
870 // FIXME: ObjCPropertyImplDecl
871
John McCall26c25c92010-11-24 11:30:07 +0000872 //---- Types -----------------------------------------------------//
873 void dispatch(TypeLoc TL) {
874 dispatch(TL.getType()); // for now
875 }
876
877 void dispatch(QualType T) {
878 if (T.hasLocalQualifiers()) {
879 push("QualType");
880 Qualifiers Qs = T.getLocalQualifiers();
881 setFlag("const", Qs.hasConst());
882 setFlag("volatile", Qs.hasVolatile());
883 setFlag("restrict", Qs.hasRestrict());
884 if (Qs.hasAddressSpace()) setInteger("addrspace", Qs.getAddressSpace());
885 if (Qs.hasObjCGCAttr()) {
886 switch (Qs.getObjCGCAttr()) {
887 case Qualifiers::Weak: set("gc", "weak"); break;
888 case Qualifiers::Strong: set("gc", "strong"); break;
889 case Qualifiers::GCNone: llvm_unreachable("explicit none");
890 }
891 }
892
893 completeAttrs();
894 dispatch(QualType(T.getTypePtr(), 0));
895 pop();
896 return;
897 }
898
899 Type *Ty = const_cast<Type*>(T.getTypePtr());
900 push(getTypeKindName(Ty));
John McCall13cf5e22010-11-24 11:53:13 +0000901 XMLTypeVisitor<XMLDumper>::dispatch(const_cast<Type*>(T.getTypePtr()));
John McCall26c25c92010-11-24 11:30:07 +0000902 pop();
903 }
904
905 void setCallingConv(CallingConv CC) {
906 switch (CC) {
907 case CC_Default: return;
908 case CC_C: return set("cc", "cdecl");
909 case CC_X86FastCall: return set("cc", "x86_fastcall");
910 case CC_X86StdCall: return set("cc", "x86_stdcall");
911 case CC_X86ThisCall: return set("cc", "x86_thiscall");
912 case CC_X86Pascal: return set("cc", "x86_pascal");
Anton Korobeynikov414d8962011-04-14 20:06:49 +0000913 case CC_AAPCS: return set("cc", "aapcs");
914 case CC_AAPCS_VFP: return set("cc", "aapcs_vfp");
John McCall26c25c92010-11-24 11:30:07 +0000915 }
916 }
917
918 void visitTypeAttrs(Type *D) {
919 setPointer(D);
920 setFlag("dependent", D->isDependentType());
921 setFlag("variably_modified", D->isVariablyModifiedType());
922
923 setPointer("canonical", D->getCanonicalTypeInternal().getAsOpaquePtr());
924 }
925
926 void visitPointerTypeChildren(PointerType *T) {
927 dispatch(T->getPointeeType());
928 }
929 void visitReferenceTypeChildren(ReferenceType *T) {
930 dispatch(T->getPointeeType());
931 }
932 void visitObjCObjectPointerTypeChildren(ObjCObjectPointerType *T) {
933 dispatch(T->getPointeeType());
934 }
935 void visitBlockPointerTypeChildren(BlockPointerType *T) {
936 dispatch(T->getPointeeType());
937 }
938
939 // Types that just wrap declarations.
940 void visitTagTypeChildren(TagType *T) {
941 visitDeclRef(T->getDecl());
942 }
943 void visitTypedefTypeChildren(TypedefType *T) {
944 visitDeclRef(T->getDecl());
945 }
946 void visitObjCInterfaceTypeChildren(ObjCInterfaceType *T) {
947 visitDeclRef(T->getDecl());
948 }
949 void visitUnresolvedUsingTypeChildren(UnresolvedUsingType *T) {
950 visitDeclRef(T->getDecl());
951 }
952 void visitInjectedClassNameTypeChildren(InjectedClassNameType *T) {
953 visitDeclRef(T->getDecl());
954 }
955
956 void visitFunctionTypeAttrs(FunctionType *T) {
957 setFlag("noreturn", T->getNoReturnAttr());
958 setCallingConv(T->getCallConv());
Eli Friedmana49218e2011-04-09 08:18:08 +0000959 if (T->getHasRegParm()) setInteger("regparm", T->getRegParmType());
John McCall26c25c92010-11-24 11:30:07 +0000960 }
961 void visitFunctionTypeChildren(FunctionType *T) {
962 dispatch(T->getResultType());
963 }
964
965 void visitFunctionProtoTypeAttrs(FunctionProtoType *T) {
966 setFlag("const", T->getTypeQuals() & Qualifiers::Const);
967 setFlag("volatile", T->getTypeQuals() & Qualifiers::Volatile);
968 setFlag("restrict", T->getTypeQuals() & Qualifiers::Restrict);
969 }
970 void visitFunctionProtoTypeChildren(FunctionProtoType *T) {
971 push("parameters");
972 setFlag("variadic", T->isVariadic());
973 completeAttrs();
974 for (FunctionProtoType::arg_type_iterator
975 I = T->arg_type_begin(), E = T->arg_type_end(); I != E; ++I)
976 dispatch(*I);
977 pop();
978
Sebastian Redl60618fa2011-03-12 11:50:43 +0000979 if (T->hasDynamicExceptionSpec()) {
John McCall26c25c92010-11-24 11:30:07 +0000980 push("exception_specifiers");
Sebastian Redl60618fa2011-03-12 11:50:43 +0000981 setFlag("any", T->getExceptionSpecType() == EST_MSAny);
John McCall26c25c92010-11-24 11:30:07 +0000982 completeAttrs();
983 for (FunctionProtoType::exception_iterator
984 I = T->exception_begin(), E = T->exception_end(); I != E; ++I)
985 dispatch(*I);
986 pop();
987 }
Sebastian Redl60618fa2011-03-12 11:50:43 +0000988 // FIXME: noexcept specifier
John McCall26c25c92010-11-24 11:30:07 +0000989 }
990
991 void visitTemplateSpecializationTypeChildren(TemplateSpecializationType *T) {
992 if (const RecordType *RT = T->getAs<RecordType>())
993 visitDeclRef(RT->getDecl());
994
995 // TODO: TemplateName
996
997 push("template_arguments");
998 completeAttrs();
999 for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I)
1000 dispatch(T->getArg(I));
1001 pop();
1002 }
1003
1004 //---- Statements ------------------------------------------------//
1005 void dispatch(Stmt *S) {
1006 // FIXME: this is not really XML at all
1007 push("Stmt");
John McCall3bddf5c2010-12-02 10:24:56 +00001008 out << ">\n";
John McCall26c25c92010-11-24 11:30:07 +00001009 Stack.back().State = NS_Children; // explicitly become non-lazy
1010 S->dump(out, Context.getSourceManager());
1011 out << '\n';
1012 pop();
1013 }
1014};
1015}
1016
1017void Decl::dumpXML() const {
1018 dumpXML(llvm::errs());
1019}
1020
Chris Lattner5f9e2722011-07-23 10:55:15 +00001021void Decl::dumpXML(raw_ostream &out) const {
John McCall26c25c92010-11-24 11:30:07 +00001022 XMLDumper(out, getASTContext()).dispatch(const_cast<Decl*>(this));
1023}
1024
1025#else /* ifndef NDEBUG */
1026
1027void Decl::dumpXML() const {}
Chris Lattner5f9e2722011-07-23 10:55:15 +00001028void Decl::dumpXML(raw_ostream &out) const {}
John McCall26c25c92010-11-24 11:30:07 +00001029
1030#endif