blob: 5f1a3969d1aaaaebdf2e4dc3deb9ec4932d3d022 [file] [log] [blame]
John McCall2a80a9e2010-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 {
56 llvm::StringRef Name;
57 NodeState State;
58 Node(llvm::StringRef name) : Name(name), State(NS_Attrs) {}
59
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()) {
69 default: llvm_unreachable("Decl that isn't part of DeclNodes.inc!");
70#define DECL(DERIVED, BASE) \
71 case Decl::DERIVED: \
72 DISPATCH(dispatch##DERIVED##DeclAttrs, DERIVED##Decl); \
73 static_cast<Impl*>(this)->completeAttrs(); \
74 DISPATCH(dispatch##DERIVED##DeclChildren, DERIVED##Decl); \
75 DISPATCH(dispatch##DERIVED##DeclAsContext, DERIVED##Decl); \
76 break;
77#define ABSTRACT_DECL(DECL)
78#include "clang/AST/DeclNodes.inc"
79 }
80 }
81
82#define DECL(DERIVED, BASE) \
83 void dispatch##DERIVED##DeclAttrs(DERIVED##Decl *D) { \
84 DISPATCH(dispatch##BASE##Attrs, BASE); \
85 DISPATCH(visit##DERIVED##DeclAttrs, DERIVED##Decl); \
86 } \
87 void visit##DERIVED##DeclAttrs(DERIVED##Decl *D) {} \
88 void dispatch##DERIVED##DeclChildren(DERIVED##Decl *D) { \
89 DISPATCH(dispatch##BASE##Children, BASE); \
90 DISPATCH(visit##DERIVED##DeclChildren, DERIVED##Decl); \
91 } \
92 void visit##DERIVED##DeclChildren(DERIVED##Decl *D) {} \
93 void dispatch##DERIVED##DeclAsContext(DERIVED##Decl *D) { \
94 DISPATCH(dispatch##BASE##AsContext, BASE); \
95 DISPATCH(visit##DERIVED##DeclAsContext, DERIVED##Decl); \
96 } \
97 void visit##DERIVED##DeclAsContext(DERIVED##Decl *D) {}
98#include "clang/AST/DeclNodes.inc"
99
100 void dispatchDeclAttrs(Decl *D) {
101 DISPATCH(visitDeclAttrs, Decl);
102 }
103 void visitDeclAttrs(Decl *D) {}
104
105 void dispatchDeclChildren(Decl *D) {
106 DISPATCH(visitDeclChildren, Decl);
107 }
108 void visitDeclChildren(Decl *D) {}
109
110 void dispatchDeclAsContext(Decl *D) {
111 DISPATCH(visitDeclAsContext, Decl);
112 }
113 void visitDeclAsContext(Decl *D) {}
114
115#undef DISPATCH
116};
117
118template <class Impl> struct XMLTypeVisitor {
119#define DISPATCH(NAME, CLASS) \
120 static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(T))
121
122 void dispatch(Type *T) {
123 switch (T->getTypeClass()) {
124 default: llvm_unreachable("Type that isn't part of TypeNodes.inc!");
125#define TYPE(DERIVED, BASE) \
126 case Type::DERIVED: \
127 DISPATCH(dispatch##DERIVED##TypeAttrs, DERIVED##Type); \
128 static_cast<Impl*>(this)->completeAttrs(); \
129 DISPATCH(dispatch##DERIVED##TypeChildren, DERIVED##Type); \
130 break;
131#define ABSTRACT_TYPE(DERIVED, BASE)
132#include "clang/AST/TypeNodes.def"
133 }
134 }
135
136#define TYPE(DERIVED, BASE) \
137 void dispatch##DERIVED##TypeAttrs(DERIVED##Type *T) { \
138 DISPATCH(dispatch##BASE##Attrs, BASE); \
139 DISPATCH(visit##DERIVED##TypeAttrs, DERIVED##Type); \
140 } \
141 void visit##DERIVED##TypeAttrs(DERIVED##Type *T) {} \
142 void dispatch##DERIVED##TypeChildren(DERIVED##Type *T) { \
143 DISPATCH(dispatch##BASE##Children, BASE); \
144 DISPATCH(visit##DERIVED##TypeChildren, DERIVED##Type); \
145 } \
146 void visit##DERIVED##TypeChildren(DERIVED##Type *T) {}
147#include "clang/AST/TypeNodes.def"
148
149 void dispatchTypeAttrs(Type *T) {
150 DISPATCH(visitTypeAttrs, Type);
151 }
152 void visitTypeAttrs(Type *T) {}
153
154 void dispatchTypeChildren(Type *T) {
155 DISPATCH(visitTypeChildren, Type);
156 }
157 void visitTypeChildren(Type *T) {}
158
159#undef DISPATCH
160};
161
162static llvm::StringRef getTypeKindName(Type *T) {
163 switch (T->getTypeClass()) {
164#define TYPE(DERIVED, BASE) case Type::DERIVED: return #DERIVED "Type";
165#define ABSTRACT_TYPE(DERIVED, BASE)
166#include "clang/AST/TypeNodes.def"
167 }
168
169 llvm_unreachable("unknown type kind!");
170 return "unknown_type";
171}
172
173struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
174 public XMLTypeVisitor<XMLDumper> {
175 llvm::raw_ostream &out;
176 ASTContext &Context;
177 llvm::SmallVector<Node, 16> Stack;
178 unsigned Indent;
179 explicit XMLDumper(llvm::raw_ostream &OS, ASTContext &context)
180 : out(OS), Context(context), Indent(0) {}
181
182 void indent() {
183 for (unsigned I = Indent; I; --I)
184 out << ' ';
185 }
186
187 /// Push a new node on the stack.
188 void push(llvm::StringRef name) {
189 if (!Stack.empty()) {
190 assert(Stack.back().isDoneWithAttrs());
191 if (Stack.back().State == NS_LazyChildren) {
192 Stack.back().State = NS_Children;
193 out << ">\n";
194 }
195 Indent++;
196 indent();
197 }
198 Stack.push_back(Node(name));
199 out << '<' << name;
200 }
201
202 /// Set the given attribute to the given value.
203 void set(llvm::StringRef attr, llvm::StringRef value) {
204 assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
205 out << ' ' << attr << '=' << '"' << value << '"'; // TODO: quotation
206 }
207
208 /// Finish attributes.
209 void completeAttrs() {
210 assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
211 Stack.back().State = NS_LazyChildren;
212 }
213
214 /// Pop a node.
215 void pop() {
216 assert(!Stack.empty() && Stack.back().isDoneWithAttrs());
217 if (Stack.back().State == NS_LazyChildren) {
218 out << "/>\n";
219 } else {
220 indent();
221 out << "</" << Stack.back().Name << ">\n";
222 }
223 if (Stack.size() > 1) Indent--;
224 Stack.pop_back();
225 }
226
227 //---- General utilities -------------------------------------------//
228
229 void setPointer(llvm::StringRef prop, void *p) {
230 llvm::SmallString<10> buffer;
231 llvm::raw_svector_ostream os(buffer);
232 os << p;
233 os.flush();
234 set(prop, buffer);
235 }
236
237 void setPointer(void *p) {
238 setPointer("ptr", p);
239 }
240
241 void setInteger(llvm::StringRef prop, const llvm::APSInt &v) {
242 set(prop, v.toString(10));
243 }
244
245 void setInteger(llvm::StringRef prop, unsigned n) {
246 llvm::SmallString<10> buffer;
247 llvm::raw_svector_ostream os(buffer);
248 os << n;
249 os.flush();
250 set(prop, buffer);
251 }
252
253 void setFlag(llvm::StringRef prop, bool flag) {
254 if (flag) set(prop, "true");
255 }
256
257 void setName(DeclarationName Name) {
John McCalla048c302010-11-30 10:12:16 +0000258 if (!Name)
259 return set("name", "");
260
John McCall2a80a9e2010-11-24 11:30:07 +0000261 // Common case.
262 if (Name.isIdentifier())
263 return set("name", Name.getAsIdentifierInfo()->getName());
264
265 set("name", "<unsupported>");
266 }
267
268 class TemporaryContainer {
269 XMLDumper &Dumper;
270 public:
271 TemporaryContainer(XMLDumper &dumper, llvm::StringRef name)
272 : Dumper(dumper) {
273 Dumper.push(name);
274 Dumper.completeAttrs();
275 }
276
277 ~TemporaryContainer() {
278 Dumper.pop();
279 }
280 };
281
282 void visitTemplateParameters(TemplateParameterList *L) {
283 push("template_parameters");
284 completeAttrs();
285 for (TemplateParameterList::iterator
286 I = L->begin(), E = L->end(); I != E; ++I)
287 dispatch(*I);
288 pop();
289 }
290
291 void visitTemplateArguments(const TemplateArgumentList &L) {
292 push("template_arguments");
293 completeAttrs();
294 for (unsigned I = 0, E = L.size(); I != E; ++I)
295 dispatch(L[I]);
296 pop();
297 }
298
299 /// Visits a reference to the given declaration.
300 void visitDeclRef(Decl *D) {
301 push(D->getDeclKindName());
302 setPointer("ref", D);
303 completeAttrs();
304 pop();
305 }
306
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:
318 case TemplateArgument::Declaration: {
319 visitDeclRef(A.getAsDecl());
320 break;
321 }
322 case TemplateArgument::Integral: {
323 push("integer");
324 setInteger("value", *A.getAsIntegral());
325 completeAttrs();
326 pop();
327 break;
328 }
329 case TemplateArgument::Expression: {
330 dispatch(A.getAsExpr());
331 break;
332 }
333 case TemplateArgument::Pack: {
334 // TODO
335 break;
336 }
337 }
338 }
339
340 void dispatch(const TemplateArgumentLoc &A) {
341 dispatch(A.getArgument());
342 }
343
344 //---- Declarations ------------------------------------------------//
345 // Calls are made in this order:
346 // # Enter a new node.
347 // push("FieldDecl")
348 //
349 // # In this phase, attributes are set on the node.
350 // visitDeclAttrs(D)
351 // visitNamedDeclAttrs(D)
352 // ...
353 // visitFieldDeclAttrs(D)
354 //
355 // # No more attributes after this point.
356 // completeAttrs()
357 //
358 // # Create "header" child nodes, i.e. those which logically
359 // # belong to the declaration itself.
360 // visitDeclChildren(D)
361 // visitNamedDeclChildren(D)
362 // ...
363 // visitFieldDeclChildren(D)
364 //
365 // # Create nodes for the lexical children.
366 // visitDeclAsContext(D)
367 // visitNamedDeclAsContext(D)
368 // ...
369 // visitFieldDeclAsContext(D)
370 //
371 // # Finish the node.
372 // pop();
373 void dispatch(Decl *D) {
374 push(D->getDeclKindName());
John McCallf6d24ae2010-11-24 11:53:13 +0000375 XMLDeclVisitor<XMLDumper>::dispatch(D);
John McCall2a80a9e2010-11-24 11:30:07 +0000376 pop();
377 }
378 void visitDeclAttrs(Decl *D) {
379 setPointer(D);
380 }
381
382 /// Visit all the lexical decls in the given context.
383 void visitDeclContext(DeclContext *DC) {
384 for (DeclContext::decl_iterator
385 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
386 dispatch(*I);
387
388 // FIXME: point out visible declarations not in lexical context?
389 }
390
391 /// Set the "access" attribute on the current node according to the
392 /// given specifier.
393 void setAccess(AccessSpecifier AS) {
394 switch (AS) {
395 case AS_public: return set("access", "public");
396 case AS_protected: return set("access", "protected");
397 case AS_private: return set("access", "private");
398 case AS_none: llvm_unreachable("explicit forbidden access");
399 }
400 }
401
402 template <class T> void visitRedeclarableAttrs(T *D) {
403 if (T *Prev = D->getPreviousDeclaration())
404 setPointer("previous", Prev);
405 }
406
407
408 // TranslationUnitDecl
409 void visitTranslationUnitDeclAsContext(TranslationUnitDecl *D) {
410 visitDeclContext(D);
411 }
412
413 // LinkageSpecDecl
414 void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) {
415 llvm::StringRef lang = "";
416 switch (D->getLanguage()) {
417 case LinkageSpecDecl::lang_c: lang = "C"; break;
418 case LinkageSpecDecl::lang_cxx: lang = "C++"; break;
419 }
420 set("lang", lang);
421 }
422 void visitLinkageSpecDeclAsContext(LinkageSpecDecl *D) {
423 visitDeclContext(D);
424 }
425
426 // NamespaceDecl
427 void visitNamespaceDeclAttrs(NamespaceDecl *D) {
428 setFlag("inline", D->isInline());
429 if (!D->isOriginalNamespace())
430 setPointer("original", D->getOriginalNamespace());
431 }
432 void visitNamespaceDeclAsContext(NamespaceDecl *D) {
433 visitDeclContext(D);
434 }
435
436 // NamedDecl
437 void visitNamedDeclAttrs(NamedDecl *D) {
438 setName(D->getDeclName());
439 }
440
441 // ValueDecl
442 void visitValueDeclChildren(ValueDecl *D) {
443 dispatch(D->getType());
444 }
445
446 // DeclaratorDecl
447 void visitDeclaratorDeclChildren(DeclaratorDecl *D) {
448 //dispatch(D->getTypeSourceInfo()->getTypeLoc());
449 }
450
451 // VarDecl
452 void visitVarDeclAttrs(VarDecl *D) {
453 visitRedeclarableAttrs(D);
454 if (D->getStorageClass() != SC_None)
455 set("storage",
456 VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
457 setFlag("directinit", D->hasCXXDirectInitializer());
458 setFlag("nrvo", D->isNRVOVariable());
459 // TODO: instantiation, etc.
460 }
461 void visitVarDeclChildren(VarDecl *D) {
462 if (D->hasInit()) dispatch(D->getInit());
463 }
464
465 // ParmVarDecl?
466
467 // FunctionDecl
468 void visitFunctionDeclAttrs(FunctionDecl *D) {
469 visitRedeclarableAttrs(D);
470 setFlag("pure", D->isPure());
471 setFlag("trivial", D->isTrivial());
472 setFlag("returnzero", D->hasImplicitReturnZero());
473 setFlag("prototype", D->hasWrittenPrototype());
474 setFlag("deleted", D->isDeleted());
475 if (D->getStorageClass() != SC_None)
476 set("storage",
477 VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
478 setFlag("inline", D->isInlineSpecified());
479 // TODO: instantiation, etc.
480 }
481 void visitFunctionDeclChildren(FunctionDecl *D) {
482 for (FunctionDecl::param_iterator
483 I = D->param_begin(), E = D->param_end(); I != E; ++I)
484 dispatch(*I);
485 if (D->isThisDeclarationADefinition())
486 dispatch(D->getBody());
487 }
488
489 // CXXMethodDecl ?
490 // CXXConstructorDecl ?
491 // CXXDestructorDecl ?
492 // CXXConversionDecl ?
493
494 // FieldDecl
495 void visitFieldDeclAttrs(FieldDecl *D) {
496 setFlag("mutable", D->isMutable());
497 }
498 void visitFieldDeclChildren(FieldDecl *D) {
499 if (D->isBitField()) {
500 TemporaryContainer C(*this, "bitwidth");
501 dispatch(D->getBitWidth());
502 }
503 // TODO: C++0x member initializer
504 }
505
506 // EnumConstantDecl
507 void visitEnumConstantDeclChildren(EnumConstantDecl *D) {
508 // value in any case?
509 if (D->getInitExpr()) dispatch(D->getInitExpr());
510 }
511
512 // IndirectFieldDecl
513 void visitIndirectFieldDeclChildren(IndirectFieldDecl *D) {
514 for (IndirectFieldDecl::chain_iterator
515 I = D->chain_begin(), E = D->chain_end(); I != E; ++I) {
516 NamedDecl *VD = const_cast<NamedDecl*>(*I);
517 push(isa<VarDecl>(VD) ? "variable" : "field");
518 setPointer("ptr", VD);
519 completeAttrs();
520 pop();
521 }
522 }
523
524 // TypeDecl
525 void visitTypeDeclAttrs(TypeDecl *D) {
526 setPointer("typeptr", D->getTypeForDecl());
527 }
528
529 // TypedefDecl
530 void visitTypedefDeclAttrs(TypedefDecl *D) {
531 visitRedeclarableAttrs(D);
532 }
533 void visitTypedefDeclChildren(TypedefDecl *D) {
534 dispatch(D->getTypeSourceInfo()->getTypeLoc());
535 }
536
537 // TagDecl
538 void visitTagDeclAttrs(TagDecl *D) {
539 visitRedeclarableAttrs(D);
540 }
541 void visitTagDeclAsContext(TagDecl *D) {
542 visitDeclContext(D);
543 }
544
545 // EnumDecl
546 void visitEnumDeclAttrs(EnumDecl *D) {
547 setFlag("scoped", D->isScoped());
548 setFlag("fixed", D->isFixed());
549 }
550 void visitEnumDeclChildren(EnumDecl *D) {
551 {
552 TemporaryContainer C(*this, "promotion_type");
553 dispatch(D->getPromotionType());
554 }
555 {
556 TemporaryContainer C(*this, "integer_type");
557 dispatch(D->getIntegerType());
558 }
559 }
560
561 // RecordDecl ?
562
563 void visitCXXRecordDeclChildren(CXXRecordDecl *D) {
564 if (!D->isThisDeclarationADefinition()) return;
565
566 for (CXXRecordDecl::base_class_iterator
567 I = D->bases_begin(), E = D->bases_end(); I != E; ++I) {
568 push("base");
569 setAccess(I->getAccessSpecifier());
570 completeAttrs();
571 dispatch(I->getTypeSourceInfo()->getTypeLoc());
572 pop();
573 }
574 }
575
576 // ClassTemplateSpecializationDecl ?
577
578 // FileScopeAsmDecl ?
579
580 // BlockDecl
581 void visitBlockDeclAttrs(BlockDecl *D) {
582 setFlag("variadic", D->isVariadic());
583 }
584 void visitBlockDeclChildren(BlockDecl *D) {
585 for (FunctionDecl::param_iterator
586 I = D->param_begin(), E = D->param_end(); I != E; ++I)
587 dispatch(*I);
588 dispatch(D->getBody());
589 }
590
591 // AccessSpecDecl
592 void visitAccessSpecDeclAttrs(AccessSpecDecl *D) {
593 setAccess(D->getAccess());
594 }
595
596 // TemplateDecl
597 void visitTemplateDeclChildren(TemplateDecl *D) {
598 visitTemplateParameters(D->getTemplateParameters());
599 dispatch(D->getTemplatedDecl());
600 }
601
602 // FunctionTemplateDecl
603 void visitFunctionTemplateDeclAttrs(FunctionTemplateDecl *D) {
604 visitRedeclarableAttrs(D);
605 }
606 void visitFunctionTemplateDeclChildren(FunctionTemplateDecl *D) {
607 // Mention all the specializations which don't have explicit
608 // declarations elsewhere.
609 for (FunctionTemplateDecl::spec_iterator
610 I = D->spec_begin(), E = D->spec_end(); I != E; ++I) {
611 FunctionTemplateSpecializationInfo *Info
612 = I->getTemplateSpecializationInfo();
613
614 bool Unknown = false;
615 switch (Info->getTemplateSpecializationKind()) {
616 case TSK_ImplicitInstantiation: Unknown = false; break;
617 case TSK_Undeclared: Unknown = true; break;
618
619 // These will be covered at their respective sites.
620 case TSK_ExplicitSpecialization: continue;
621 case TSK_ExplicitInstantiationDeclaration: continue;
622 case TSK_ExplicitInstantiationDefinition: continue;
623 }
624
625 TemporaryContainer C(*this,
626 Unknown ? "uninstantiated" : "instantiation");
627 visitTemplateArguments(*Info->TemplateArguments);
628 dispatch(Info->Function);
629 }
630 }
631
632 // ClasTemplateDecl
633 void visitClassTemplateDeclAttrs(ClassTemplateDecl *D) {
634 visitRedeclarableAttrs(D);
635 }
636 void visitClassTemplateDeclChildren(ClassTemplateDecl *D) {
637 // Mention all the specializations which don't have explicit
638 // declarations elsewhere.
639 for (ClassTemplateDecl::spec_iterator
640 I = D->spec_begin(), E = D->spec_end(); I != E; ++I) {
641
642 bool Unknown = false;
643 switch (I->getTemplateSpecializationKind()) {
644 case TSK_ImplicitInstantiation: Unknown = false; break;
645 case TSK_Undeclared: Unknown = true; break;
646
647 // These will be covered at their respective sites.
648 case TSK_ExplicitSpecialization: continue;
649 case TSK_ExplicitInstantiationDeclaration: continue;
650 case TSK_ExplicitInstantiationDefinition: continue;
651 }
652
653 TemporaryContainer C(*this,
654 Unknown ? "uninstantiated" : "instantiation");
655 visitTemplateArguments(I->getTemplateArgs());
656 dispatch(*I);
657 }
658 }
659
660 // TemplateTypeParmDecl
661 void visitTemplateTypeParmDeclAttrs(TemplateTypeParmDecl *D) {
662 setInteger("depth", D->getDepth());
663 setInteger("index", D->getIndex());
664 }
665 void visitTemplateTypeParmDeclChildren(TemplateTypeParmDecl *D) {
666 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
667 dispatch(D->getDefaultArgumentInfo()->getTypeLoc());
668 // parameter pack?
669 }
670
671 // NonTypeTemplateParmDecl
672 void visitNonTypeTemplateParmDeclAttrs(NonTypeTemplateParmDecl *D) {
673 setInteger("depth", D->getDepth());
674 setInteger("index", D->getIndex());
675 }
676 void visitNonTypeTemplateParmDeclChildren(NonTypeTemplateParmDecl *D) {
677 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
678 dispatch(D->getDefaultArgument());
679 // parameter pack?
680 }
681
682 // TemplateTemplateParmDecl
683 void visitTemplateTemplateParmDeclAttrs(TemplateTemplateParmDecl *D) {
684 setInteger("depth", D->getDepth());
685 setInteger("index", D->getIndex());
686 }
687 void visitTemplateTemplateParmDeclChildren(TemplateTemplateParmDecl *D) {
688 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
689 dispatch(D->getDefaultArgument());
690 // parameter pack?
691 }
692
693 // FriendDecl
694 void visitFriendDeclChildren(FriendDecl *D) {
695 if (TypeSourceInfo *T = D->getFriendType())
696 dispatch(T->getTypeLoc());
697 else
698 dispatch(D->getFriendDecl());
699 }
700
701 // UsingDirectiveDecl ?
702 // UsingDecl ?
703 // UsingShadowDecl ?
704 // NamespaceAliasDecl ?
705 // UnresolvedUsingValueDecl ?
706 // UnresolvedUsingTypenameDecl ?
707 // StaticAssertDecl ?
708
709 //---- Types -----------------------------------------------------//
710 void dispatch(TypeLoc TL) {
711 dispatch(TL.getType()); // for now
712 }
713
714 void dispatch(QualType T) {
715 if (T.hasLocalQualifiers()) {
716 push("QualType");
717 Qualifiers Qs = T.getLocalQualifiers();
718 setFlag("const", Qs.hasConst());
719 setFlag("volatile", Qs.hasVolatile());
720 setFlag("restrict", Qs.hasRestrict());
721 if (Qs.hasAddressSpace()) setInteger("addrspace", Qs.getAddressSpace());
722 if (Qs.hasObjCGCAttr()) {
723 switch (Qs.getObjCGCAttr()) {
724 case Qualifiers::Weak: set("gc", "weak"); break;
725 case Qualifiers::Strong: set("gc", "strong"); break;
726 case Qualifiers::GCNone: llvm_unreachable("explicit none");
727 }
728 }
729
730 completeAttrs();
731 dispatch(QualType(T.getTypePtr(), 0));
732 pop();
733 return;
734 }
735
736 Type *Ty = const_cast<Type*>(T.getTypePtr());
737 push(getTypeKindName(Ty));
John McCallf6d24ae2010-11-24 11:53:13 +0000738 XMLTypeVisitor<XMLDumper>::dispatch(const_cast<Type*>(T.getTypePtr()));
John McCall2a80a9e2010-11-24 11:30:07 +0000739 pop();
740 }
741
742 void setCallingConv(CallingConv CC) {
743 switch (CC) {
744 case CC_Default: return;
745 case CC_C: return set("cc", "cdecl");
746 case CC_X86FastCall: return set("cc", "x86_fastcall");
747 case CC_X86StdCall: return set("cc", "x86_stdcall");
748 case CC_X86ThisCall: return set("cc", "x86_thiscall");
749 case CC_X86Pascal: return set("cc", "x86_pascal");
750 }
751 }
752
753 void visitTypeAttrs(Type *D) {
754 setPointer(D);
755 setFlag("dependent", D->isDependentType());
756 setFlag("variably_modified", D->isVariablyModifiedType());
757
758 setPointer("canonical", D->getCanonicalTypeInternal().getAsOpaquePtr());
759 }
760
761 void visitPointerTypeChildren(PointerType *T) {
762 dispatch(T->getPointeeType());
763 }
764 void visitReferenceTypeChildren(ReferenceType *T) {
765 dispatch(T->getPointeeType());
766 }
767 void visitObjCObjectPointerTypeChildren(ObjCObjectPointerType *T) {
768 dispatch(T->getPointeeType());
769 }
770 void visitBlockPointerTypeChildren(BlockPointerType *T) {
771 dispatch(T->getPointeeType());
772 }
773
774 // Types that just wrap declarations.
775 void visitTagTypeChildren(TagType *T) {
776 visitDeclRef(T->getDecl());
777 }
778 void visitTypedefTypeChildren(TypedefType *T) {
779 visitDeclRef(T->getDecl());
780 }
781 void visitObjCInterfaceTypeChildren(ObjCInterfaceType *T) {
782 visitDeclRef(T->getDecl());
783 }
784 void visitUnresolvedUsingTypeChildren(UnresolvedUsingType *T) {
785 visitDeclRef(T->getDecl());
786 }
787 void visitInjectedClassNameTypeChildren(InjectedClassNameType *T) {
788 visitDeclRef(T->getDecl());
789 }
790
791 void visitFunctionTypeAttrs(FunctionType *T) {
792 setFlag("noreturn", T->getNoReturnAttr());
793 setCallingConv(T->getCallConv());
794 if (T->getRegParmType()) setInteger("regparm", T->getRegParmType());
795 }
796 void visitFunctionTypeChildren(FunctionType *T) {
797 dispatch(T->getResultType());
798 }
799
800 void visitFunctionProtoTypeAttrs(FunctionProtoType *T) {
801 setFlag("const", T->getTypeQuals() & Qualifiers::Const);
802 setFlag("volatile", T->getTypeQuals() & Qualifiers::Volatile);
803 setFlag("restrict", T->getTypeQuals() & Qualifiers::Restrict);
804 }
805 void visitFunctionProtoTypeChildren(FunctionProtoType *T) {
806 push("parameters");
807 setFlag("variadic", T->isVariadic());
808 completeAttrs();
809 for (FunctionProtoType::arg_type_iterator
810 I = T->arg_type_begin(), E = T->arg_type_end(); I != E; ++I)
811 dispatch(*I);
812 pop();
813
814 if (T->hasExceptionSpec()) {
815 push("exception_specifiers");
816 setFlag("any", T->hasAnyExceptionSpec());
817 completeAttrs();
818 for (FunctionProtoType::exception_iterator
819 I = T->exception_begin(), E = T->exception_end(); I != E; ++I)
820 dispatch(*I);
821 pop();
822 }
823 }
824
825 void visitTemplateSpecializationTypeChildren(TemplateSpecializationType *T) {
826 if (const RecordType *RT = T->getAs<RecordType>())
827 visitDeclRef(RT->getDecl());
828
829 // TODO: TemplateName
830
831 push("template_arguments");
832 completeAttrs();
833 for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I)
834 dispatch(T->getArg(I));
835 pop();
836 }
837
838 //---- Statements ------------------------------------------------//
839 void dispatch(Stmt *S) {
840 // FIXME: this is not really XML at all
841 push("Stmt");
842 out << '\n';
843 Stack.back().State = NS_Children; // explicitly become non-lazy
844 S->dump(out, Context.getSourceManager());
845 out << '\n';
846 pop();
847 }
848};
849}
850
851void Decl::dumpXML() const {
852 dumpXML(llvm::errs());
853}
854
855void Decl::dumpXML(llvm::raw_ostream &out) const {
856 XMLDumper(out, getASTContext()).dispatch(const_cast<Decl*>(this));
857}
858
859#else /* ifndef NDEBUG */
860
861void Decl::dumpXML() const {}
862void Decl::dumpXML(llvm::raw_ostream &out) const {}
863
864#endif