]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/tools/clang/lib/AST/DumpXML.cpp
MFC r244628:
[FreeBSD/stable/9.git] / contrib / llvm / tools / clang / lib / AST / DumpXML.cpp
1 //===--- DumpXML.cpp - Detailed XML dumping -------------------------------===//
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/SmallString.h"
43
44 using namespace clang;
45
46 #ifndef NDEBUG
47
48 namespace {
49
50 enum NodeState {
51   NS_Attrs, NS_LazyChildren, NS_Children
52 };
53
54 struct Node {
55   StringRef Name;
56   NodeState State;
57   Node(StringRef name) : Name(name), State(NS_Attrs) {}
58
59   bool isDoneWithAttrs() const { return State != NS_Attrs; }
60 };
61
62 template <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     if (D->isUsed())
68       static_cast<Impl*>(this)->set("used", "1");
69     switch (D->getKind()) {
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
118 template <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 #define TYPE(DERIVED, BASE) \
125       case Type::DERIVED: \
126         DISPATCH(dispatch##DERIVED##TypeAttrs, DERIVED##Type); \
127         static_cast<Impl*>(this)->completeAttrs(); \
128         DISPATCH(dispatch##DERIVED##TypeChildren, DERIVED##Type); \
129         break;
130 #define ABSTRACT_TYPE(DERIVED, BASE)
131 #include "clang/AST/TypeNodes.def"
132     }
133   }
134
135 #define TYPE(DERIVED, BASE) \
136   void dispatch##DERIVED##TypeAttrs(DERIVED##Type *T) { \
137     DISPATCH(dispatch##BASE##Attrs, BASE); \
138     DISPATCH(visit##DERIVED##TypeAttrs, DERIVED##Type); \
139   } \
140   void visit##DERIVED##TypeAttrs(DERIVED##Type *T) {} \
141   void dispatch##DERIVED##TypeChildren(DERIVED##Type *T) { \
142     DISPATCH(dispatch##BASE##Children, BASE); \
143     DISPATCH(visit##DERIVED##TypeChildren, DERIVED##Type); \
144   } \
145   void visit##DERIVED##TypeChildren(DERIVED##Type *T) {}
146 #include "clang/AST/TypeNodes.def"
147
148   void dispatchTypeAttrs(Type *T) {
149     DISPATCH(visitTypeAttrs, Type);
150   }
151   void visitTypeAttrs(Type *T) {}
152
153   void dispatchTypeChildren(Type *T) {
154     DISPATCH(visitTypeChildren, Type);
155   }
156   void visitTypeChildren(Type *T) {}
157
158 #undef DISPATCH  
159 };
160
161 static StringRef getTypeKindName(Type *T) {
162   switch (T->getTypeClass()) {
163 #define TYPE(DERIVED, BASE) case Type::DERIVED: return #DERIVED "Type";
164 #define ABSTRACT_TYPE(DERIVED, BASE)
165 #include "clang/AST/TypeNodes.def"
166   }
167
168   llvm_unreachable("unknown type kind!");
169 }
170
171 struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
172                    public XMLTypeVisitor<XMLDumper> {
173   raw_ostream &out;
174   ASTContext &Context;
175   SmallVector<Node, 16> Stack;
176   unsigned Indent;
177   explicit XMLDumper(raw_ostream &OS, ASTContext &context)
178     : out(OS), Context(context), Indent(0) {}
179
180   void indent() {
181     for (unsigned I = Indent; I; --I)
182       out << ' ';
183   }
184
185   /// Push a new node on the stack.
186   void push(StringRef name) {
187     if (!Stack.empty()) {
188       assert(Stack.back().isDoneWithAttrs());
189       if (Stack.back().State == NS_LazyChildren) {
190         Stack.back().State = NS_Children;
191         out << ">\n";
192       }
193       Indent++;
194       indent();
195     }
196     Stack.push_back(Node(name));
197     out << '<' << name;
198   }
199
200   /// Set the given attribute to the given value.
201   void set(StringRef attr, StringRef value) {
202     assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
203     out << ' ' << attr << '=' << '"' << value << '"'; // TODO: quotation
204   }
205
206   /// Finish attributes.
207   void completeAttrs() {
208     assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
209     Stack.back().State = NS_LazyChildren;
210   }
211
212   /// Pop a node.
213   void pop() {
214     assert(!Stack.empty() && Stack.back().isDoneWithAttrs());
215     if (Stack.back().State == NS_LazyChildren) {
216       out << "/>\n";
217     } else {
218       indent();
219       out << "</" << Stack.back().Name << ">\n";
220     }
221     if (Stack.size() > 1) Indent--;
222     Stack.pop_back();
223   }
224
225   //---- General utilities -------------------------------------------//
226
227   void setPointer(StringRef prop, const void *p) {
228     SmallString<10> buffer;
229     llvm::raw_svector_ostream os(buffer);
230     os << p;
231     os.flush();
232     set(prop, buffer);
233   }
234
235   void setPointer(void *p) {
236     setPointer("ptr", p);
237   }
238
239   void setInteger(StringRef prop, const llvm::APSInt &v) {
240     set(prop, v.toString(10));
241   }
242
243   void setInteger(StringRef prop, unsigned n) {
244     SmallString<10> buffer;
245     llvm::raw_svector_ostream os(buffer);
246     os << n;
247     os.flush();
248     set(prop, buffer);
249   }
250
251   void setFlag(StringRef prop, bool flag) {
252     if (flag) set(prop, "true");
253   }
254
255   void setName(DeclarationName Name) {
256     if (!Name)
257       return set("name", "");
258
259     // Common case.
260     if (Name.isIdentifier())
261       return set("name", Name.getAsIdentifierInfo()->getName());
262
263     set("name", Name.getAsString());
264   }
265
266   class TemporaryContainer {
267     XMLDumper &Dumper;
268   public:
269     TemporaryContainer(XMLDumper &dumper, StringRef name)
270       : Dumper(dumper) {
271       Dumper.push(name);
272       Dumper.completeAttrs();
273     }
274
275     ~TemporaryContainer() {
276       Dumper.pop();
277     }
278   };
279
280   void visitTemplateParameters(TemplateParameterList *L) {
281     push("template_parameters");
282     completeAttrs();
283     for (TemplateParameterList::iterator
284            I = L->begin(), E = L->end(); I != E; ++I)
285       dispatch(*I);
286     pop();
287   }
288
289   void visitTemplateArguments(const TemplateArgumentList &L) {
290     push("template_arguments");
291     completeAttrs();
292     for (unsigned I = 0, E = L.size(); I != E; ++I)
293       dispatch(L[I]);
294     pop();
295   }
296
297   /// Visits a reference to the given declaration.
298   void visitDeclRef(Decl *D) {
299     push(D->getDeclKindName());
300     setPointer("ref", D);
301     completeAttrs();
302     pop();
303   }
304   void visitDeclRef(StringRef Name, Decl *D) {
305     TemporaryContainer C(*this, Name);
306     if (D) visitDeclRef(D);
307   }
308
309   void dispatch(const TemplateArgument &A) {
310     switch (A.getKind()) {
311     case TemplateArgument::Null: {
312       TemporaryContainer C(*this, "null");
313       break;
314     }
315     case TemplateArgument::Type: {
316       dispatch(A.getAsType());
317       break;
318     }
319     case TemplateArgument::Template:
320     case TemplateArgument::TemplateExpansion:
321     case TemplateArgument::NullPtr:
322       // FIXME: Implement!
323       break;
324         
325     case TemplateArgument::Declaration: {
326       visitDeclRef(A.getAsDecl());
327       break;
328     }
329     case TemplateArgument::Integral: {
330       push("integer");
331       setInteger("value", A.getAsIntegral());
332       completeAttrs();
333       pop();
334       break;
335     }
336     case TemplateArgument::Expression: {
337       dispatch(A.getAsExpr());
338       break;
339     }
340     case TemplateArgument::Pack: {
341       for (TemplateArgument::pack_iterator P = A.pack_begin(), 
342                                         PEnd = A.pack_end();
343            P != PEnd; ++P)
344         dispatch(*P);
345       break;
346     }
347     }
348   }
349
350   void dispatch(const TemplateArgumentLoc &A) {
351     dispatch(A.getArgument());
352   }
353
354   //---- Declarations ------------------------------------------------//
355   // Calls are made in this order:
356   //   # Enter a new node.
357   //   push("FieldDecl")
358   //
359   //   # In this phase, attributes are set on the node.
360   //   visitDeclAttrs(D)
361   //   visitNamedDeclAttrs(D)
362   //   ...
363   //   visitFieldDeclAttrs(D)
364   //
365   //   # No more attributes after this point.
366   //   completeAttrs()
367   //
368   //   # Create "header" child nodes, i.e. those which logically
369   //   # belong to the declaration itself.
370   //   visitDeclChildren(D)
371   //   visitNamedDeclChildren(D)
372   //   ...
373   //   visitFieldDeclChildren(D)
374   //
375   //   # Create nodes for the lexical children.
376   //   visitDeclAsContext(D)
377   //   visitNamedDeclAsContext(D)
378   //   ...
379   //   visitFieldDeclAsContext(D)
380   //
381   //   # Finish the node.
382   //   pop();
383   void dispatch(Decl *D) {
384     push(D->getDeclKindName());
385     XMLDeclVisitor<XMLDumper>::dispatch(D);
386     pop();
387   }
388   void visitDeclAttrs(Decl *D) {
389     setPointer(D);
390   }
391
392   /// Visit all the lexical decls in the given context.
393   void visitDeclContext(DeclContext *DC) {
394     for (DeclContext::decl_iterator
395            I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
396       dispatch(*I);
397
398     // FIXME: point out visible declarations not in lexical context?
399   }
400
401   /// Set the "access" attribute on the current node according to the
402   /// given specifier.
403   void setAccess(AccessSpecifier AS) {
404     switch (AS) {
405     case AS_public: return set("access", "public");
406     case AS_protected: return set("access", "protected");
407     case AS_private: return set("access", "private");
408     case AS_none: llvm_unreachable("explicit forbidden access");
409     }
410   }
411
412   template <class T> void visitRedeclarableAttrs(T *D) {
413     if (T *Prev = D->getPreviousDecl())
414       setPointer("previous", Prev);
415   }
416
417
418   // TranslationUnitDecl
419   void visitTranslationUnitDeclAsContext(TranslationUnitDecl *D) {
420     visitDeclContext(D);
421   }
422
423   // LinkageSpecDecl
424   void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) {
425     StringRef lang = "";
426     switch (D->getLanguage()) {
427     case LinkageSpecDecl::lang_c: lang = "C"; break;
428     case LinkageSpecDecl::lang_cxx: lang = "C++"; break;
429     }
430     set("lang", lang);
431   }
432   void visitLinkageSpecDeclAsContext(LinkageSpecDecl *D) {
433     visitDeclContext(D);
434   }
435
436   // NamespaceDecl
437   void visitNamespaceDeclAttrs(NamespaceDecl *D) {
438     setFlag("inline", D->isInline());
439     if (!D->isOriginalNamespace())
440       setPointer("original", D->getOriginalNamespace());
441   }
442   void visitNamespaceDeclAsContext(NamespaceDecl *D) {
443     visitDeclContext(D);
444   }
445
446   // NamedDecl
447   void visitNamedDeclAttrs(NamedDecl *D) {
448     setName(D->getDeclName());
449   }
450
451   // ValueDecl
452   void visitValueDeclChildren(ValueDecl *D) {
453     dispatch(D->getType());
454   }
455
456   // DeclaratorDecl
457   void visitDeclaratorDeclChildren(DeclaratorDecl *D) {
458     //dispatch(D->getTypeSourceInfo()->getTypeLoc());
459   }
460
461   // VarDecl
462   void visitVarDeclAttrs(VarDecl *D) {
463     visitRedeclarableAttrs(D);
464     if (D->getStorageClass() != SC_None)
465       set("storage",
466           VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
467     StringRef initStyle = "";
468     switch (D->getInitStyle()) {
469     case VarDecl::CInit: initStyle = "c"; break;
470     case VarDecl::CallInit: initStyle = "call"; break;
471     case VarDecl::ListInit: initStyle = "list"; break;
472     }
473     set("initstyle", initStyle);
474     setFlag("nrvo", D->isNRVOVariable());
475     // TODO: instantiation, etc.
476   }
477   void visitVarDeclChildren(VarDecl *D) {
478     if (D->hasInit()) dispatch(D->getInit());
479   }
480
481   // ParmVarDecl?
482
483   // FunctionDecl
484   void visitFunctionDeclAttrs(FunctionDecl *D) {
485     visitRedeclarableAttrs(D);
486     setFlag("pure", D->isPure());
487     setFlag("trivial", D->isTrivial());
488     setFlag("returnzero", D->hasImplicitReturnZero());
489     setFlag("prototype", D->hasWrittenPrototype());
490     setFlag("deleted", D->isDeletedAsWritten());
491     if (D->getStorageClass() != SC_None)
492       set("storage",
493           VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
494     setFlag("inline", D->isInlineSpecified());
495     if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>())
496       set("asmlabel", ALA->getLabel());
497     // TODO: instantiation, etc.
498   }
499   void visitFunctionDeclChildren(FunctionDecl *D) {
500     for (FunctionDecl::param_iterator
501            I = D->param_begin(), E = D->param_end(); I != E; ++I)
502       dispatch(*I);
503     for (llvm::ArrayRef<NamedDecl*>::iterator
504            I = D->getDeclsInPrototypeScope().begin(), E = D->getDeclsInPrototypeScope().end();
505          I != E; ++I)
506       dispatch(*I);
507     if (D->doesThisDeclarationHaveABody())
508       dispatch(D->getBody());
509   }
510
511   // CXXMethodDecl ?
512   // CXXConstructorDecl ?
513   // CXXDestructorDecl ?
514   // CXXConversionDecl ?
515
516   void dispatch(CXXCtorInitializer *Init) {
517     // TODO
518   }
519
520   // FieldDecl
521   void visitFieldDeclAttrs(FieldDecl *D) {
522     setFlag("mutable", D->isMutable());
523   }
524   void visitFieldDeclChildren(FieldDecl *D) {
525     if (D->isBitField()) {
526       TemporaryContainer C(*this, "bitwidth");
527       dispatch(D->getBitWidth());
528     }
529     // TODO: C++0x member initializer
530   }
531
532   // EnumConstantDecl
533   void visitEnumConstantDeclChildren(EnumConstantDecl *D) {
534     // value in any case?
535     if (D->getInitExpr()) dispatch(D->getInitExpr());
536   }
537
538   // IndirectFieldDecl
539   void visitIndirectFieldDeclChildren(IndirectFieldDecl *D) {
540     for (IndirectFieldDecl::chain_iterator
541            I = D->chain_begin(), E = D->chain_end(); I != E; ++I) {
542       NamedDecl *VD = const_cast<NamedDecl*>(*I);
543       push(isa<VarDecl>(VD) ? "variable" : "field");
544       setPointer("ptr", VD);
545       completeAttrs();
546       pop();
547     }
548   }
549
550   // TypeDecl
551   void visitTypeDeclAttrs(TypeDecl *D) {
552     setPointer("typeptr", D->getTypeForDecl());
553   }
554
555   // TypedefDecl
556   void visitTypedefDeclAttrs(TypedefDecl *D) {
557     visitRedeclarableAttrs<TypedefNameDecl>(D);
558   }
559   void visitTypedefDeclChildren(TypedefDecl *D) {
560     dispatch(D->getTypeSourceInfo()->getTypeLoc());
561   }
562
563   // TypeAliasDecl
564   void visitTypeAliasDeclAttrs(TypeAliasDecl *D) {
565     visitRedeclarableAttrs<TypedefNameDecl>(D);
566   }
567   void visitTypeAliasDeclChildren(TypeAliasDecl *D) {
568     dispatch(D->getTypeSourceInfo()->getTypeLoc());
569   }
570
571   // TagDecl
572   void visitTagDeclAttrs(TagDecl *D) {
573     visitRedeclarableAttrs(D);
574   }
575   void visitTagDeclAsContext(TagDecl *D) {
576     visitDeclContext(D);
577   }
578
579   // EnumDecl
580   void visitEnumDeclAttrs(EnumDecl *D) {
581     setFlag("scoped", D->isScoped());
582     setFlag("fixed", D->isFixed());
583   }
584   void visitEnumDeclChildren(EnumDecl *D) {
585     {
586       TemporaryContainer C(*this, "promotion_type");
587       dispatch(D->getPromotionType());
588     }
589     {
590       TemporaryContainer C(*this, "integer_type");
591       dispatch(D->getIntegerType());
592     }
593   }
594
595   // RecordDecl ?
596
597   void visitCXXRecordDeclChildren(CXXRecordDecl *D) {
598     if (!D->isThisDeclarationADefinition()) return;
599
600     for (CXXRecordDecl::base_class_iterator
601            I = D->bases_begin(), E = D->bases_end(); I != E; ++I) {
602       push("base");
603       setAccess(I->getAccessSpecifier());
604       completeAttrs();
605       dispatch(I->getTypeSourceInfo()->getTypeLoc());
606       pop();
607     }
608   }
609
610   // ClassTemplateSpecializationDecl ?
611
612   // FileScopeAsmDecl ?
613
614   // BlockDecl
615   void visitBlockDeclAttrs(BlockDecl *D) {
616     setFlag("variadic", D->isVariadic());
617   }
618   void visitBlockDeclChildren(BlockDecl *D) {
619     for (FunctionDecl::param_iterator
620            I = D->param_begin(), E = D->param_end(); I != E; ++I)
621       dispatch(*I);
622     dispatch(D->getBody());
623   }
624
625   // AccessSpecDecl
626   void visitAccessSpecDeclAttrs(AccessSpecDecl *D) {
627     setAccess(D->getAccess());
628   }
629
630   // TemplateDecl
631   void visitTemplateDeclChildren(TemplateDecl *D) {
632     visitTemplateParameters(D->getTemplateParameters());
633     if (D->getTemplatedDecl())
634       dispatch(D->getTemplatedDecl());
635   }
636
637   // FunctionTemplateDecl
638   void visitFunctionTemplateDeclAttrs(FunctionTemplateDecl *D) {
639     visitRedeclarableAttrs(D);
640   }
641   void visitFunctionTemplateDeclChildren(FunctionTemplateDecl *D) {
642     // Mention all the specializations which don't have explicit
643     // declarations elsewhere.
644     for (FunctionTemplateDecl::spec_iterator
645            I = D->spec_begin(), E = D->spec_end(); I != E; ++I) {
646       FunctionTemplateSpecializationInfo *Info
647         = I->getTemplateSpecializationInfo();
648
649       bool Unknown = false;
650       switch (Info->getTemplateSpecializationKind()) {
651       case TSK_ImplicitInstantiation: Unknown = false; break;
652       case TSK_Undeclared: Unknown = true; break;
653
654       // These will be covered at their respective sites.
655       case TSK_ExplicitSpecialization: continue;
656       case TSK_ExplicitInstantiationDeclaration: continue;
657       case TSK_ExplicitInstantiationDefinition: continue;
658       }
659
660       TemporaryContainer C(*this,
661                            Unknown ? "uninstantiated" : "instantiation");
662       visitTemplateArguments(*Info->TemplateArguments);
663       dispatch(Info->Function);
664     }
665   }
666
667   // ClasTemplateDecl
668   void visitClassTemplateDeclAttrs(ClassTemplateDecl *D) {
669     visitRedeclarableAttrs(D);
670   }
671   void visitClassTemplateDeclChildren(ClassTemplateDecl *D) {
672     // Mention all the specializations which don't have explicit
673     // declarations elsewhere.
674     for (ClassTemplateDecl::spec_iterator
675            I = D->spec_begin(), E = D->spec_end(); I != E; ++I) {
676
677       bool Unknown = false;
678       switch (I->getTemplateSpecializationKind()) {
679       case TSK_ImplicitInstantiation: Unknown = false; break;
680       case TSK_Undeclared: Unknown = true; break;
681
682       // These will be covered at their respective sites.
683       case TSK_ExplicitSpecialization: continue;
684       case TSK_ExplicitInstantiationDeclaration: continue;
685       case TSK_ExplicitInstantiationDefinition: continue;
686       }
687
688       TemporaryContainer C(*this,
689                            Unknown ? "uninstantiated" : "instantiation");
690       visitTemplateArguments(I->getTemplateArgs());
691       dispatch(*I);
692     }
693   }
694
695   // TemplateTypeParmDecl
696   void visitTemplateTypeParmDeclAttrs(TemplateTypeParmDecl *D) {
697     setInteger("depth", D->getDepth());
698     setInteger("index", D->getIndex());
699   }
700   void visitTemplateTypeParmDeclChildren(TemplateTypeParmDecl *D) {
701     if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
702       dispatch(D->getDefaultArgumentInfo()->getTypeLoc());
703     // parameter pack?
704   }
705
706   // NonTypeTemplateParmDecl
707   void visitNonTypeTemplateParmDeclAttrs(NonTypeTemplateParmDecl *D) {
708     setInteger("depth", D->getDepth());
709     setInteger("index", D->getIndex());
710   }
711   void visitNonTypeTemplateParmDeclChildren(NonTypeTemplateParmDecl *D) {
712     if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
713       dispatch(D->getDefaultArgument());
714     // parameter pack?
715   }
716
717   // TemplateTemplateParmDecl
718   void visitTemplateTemplateParmDeclAttrs(TemplateTemplateParmDecl *D) {
719     setInteger("depth", D->getDepth());
720     setInteger("index", D->getIndex());
721   }
722   void visitTemplateTemplateParmDeclChildren(TemplateTemplateParmDecl *D) {
723     if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
724       dispatch(D->getDefaultArgument());
725     // parameter pack?
726   }
727
728   // FriendDecl
729   void visitFriendDeclChildren(FriendDecl *D) {
730     if (TypeSourceInfo *T = D->getFriendType())
731       dispatch(T->getTypeLoc());
732     else
733       dispatch(D->getFriendDecl());
734   }
735
736   // UsingDirectiveDecl ?
737   // UsingDecl ?
738   // UsingShadowDecl ?
739   // NamespaceAliasDecl ?
740   // UnresolvedUsingValueDecl ?
741   // UnresolvedUsingTypenameDecl ?
742   // StaticAssertDecl ?
743
744   // ObjCImplDecl
745   void visitObjCImplDeclChildren(ObjCImplDecl *D) {
746     visitDeclRef(D->getClassInterface());
747   }
748   void visitObjCImplDeclAsContext(ObjCImplDecl *D) {
749     visitDeclContext(D);
750   }
751
752   // ObjCInterfaceDecl
753   void visitCategoryList(ObjCCategoryDecl *D) {
754     if (!D) return;
755
756     TemporaryContainer C(*this, "categories");
757     for (; D; D = D->getNextClassCategory())
758       visitDeclRef(D);
759   }
760   void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) {
761     setPointer("typeptr", D->getTypeForDecl());
762     setFlag("forward_decl", !D->isThisDeclarationADefinition());
763     setFlag("implicit_interface", D->isImplicitInterfaceDecl());
764   }
765   void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) {
766     visitDeclRef("super", D->getSuperClass());
767     visitDeclRef("implementation", D->getImplementation());
768     if (D->protocol_begin() != D->protocol_end()) {
769       TemporaryContainer C(*this, "protocols");
770       for (ObjCInterfaceDecl::protocol_iterator
771              I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
772         visitDeclRef(*I);
773     }
774     visitCategoryList(D->getCategoryList());
775   }
776   void visitObjCInterfaceDeclAsContext(ObjCInterfaceDecl *D) {
777     visitDeclContext(D);
778   }
779
780   // ObjCCategoryDecl
781   void visitObjCCategoryDeclAttrs(ObjCCategoryDecl *D) {
782     setFlag("extension", D->IsClassExtension());
783   }
784   void visitObjCCategoryDeclChildren(ObjCCategoryDecl *D) {
785     visitDeclRef("interface", D->getClassInterface());
786     visitDeclRef("implementation", D->getImplementation());
787     if (D->protocol_begin() != D->protocol_end()) {
788       TemporaryContainer C(*this, "protocols");
789       for (ObjCCategoryDecl::protocol_iterator
790              I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
791         visitDeclRef(*I);
792     }
793   }
794   void visitObjCCategoryDeclAsContext(ObjCCategoryDecl *D) {
795     visitDeclContext(D);
796   }
797
798   // ObjCCategoryImplDecl
799   void visitObjCCategoryImplDeclAttrs(ObjCCategoryImplDecl *D) {
800     set("identifier", D->getName());
801   }
802   void visitObjCCategoryImplDeclChildren(ObjCCategoryImplDecl *D) {
803     visitDeclRef(D->getCategoryDecl());
804   }
805
806   // ObjCImplementationDecl
807   void visitObjCImplementationDeclAttrs(ObjCImplementationDecl *D) {
808     set("identifier", D->getName());
809   }
810   void visitObjCImplementationDeclChildren(ObjCImplementationDecl *D) {
811     visitDeclRef("super", D->getSuperClass());
812     if (D->init_begin() != D->init_end()) {
813       TemporaryContainer C(*this, "initializers");
814       for (ObjCImplementationDecl::init_iterator
815              I = D->init_begin(), E = D->init_end(); I != E; ++I)
816         dispatch(*I);
817     }
818   }
819
820   // ObjCProtocolDecl
821   void visitObjCProtocolDeclChildren(ObjCProtocolDecl *D) {
822     if (!D->isThisDeclarationADefinition())
823       return;
824     
825     if (D->protocol_begin() != D->protocol_end()) {
826       TemporaryContainer C(*this, "protocols");
827       for (ObjCInterfaceDecl::protocol_iterator
828              I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
829         visitDeclRef(*I);
830     }
831   }
832   void visitObjCProtocolDeclAsContext(ObjCProtocolDecl *D) {
833     if (!D->isThisDeclarationADefinition())
834       return;
835     
836     visitDeclContext(D);
837   }
838
839   // ObjCMethodDecl
840   void visitObjCMethodDeclAttrs(ObjCMethodDecl *D) {
841     // decl qualifier?
842     // implementation control?
843
844     setFlag("instance", D->isInstanceMethod());
845     setFlag("variadic", D->isVariadic());
846     setFlag("property_accessor", D->isPropertyAccessor());
847     setFlag("defined", D->isDefined());
848     setFlag("related_result_type", D->hasRelatedResultType());
849   }
850   void visitObjCMethodDeclChildren(ObjCMethodDecl *D) {
851     dispatch(D->getResultType());
852     for (ObjCMethodDecl::param_iterator
853            I = D->param_begin(), E = D->param_end(); I != E; ++I)
854       dispatch(*I);
855     if (D->isThisDeclarationADefinition())
856       dispatch(D->getBody());
857   }
858
859   // ObjCIvarDecl
860   void setAccessControl(StringRef prop, ObjCIvarDecl::AccessControl AC) {
861     switch (AC) {
862     case ObjCIvarDecl::None: return set(prop, "none");
863     case ObjCIvarDecl::Private: return set(prop, "private");
864     case ObjCIvarDecl::Protected: return set(prop, "protected");
865     case ObjCIvarDecl::Public: return set(prop, "public");
866     case ObjCIvarDecl::Package: return set(prop, "package");
867     }
868   }
869   void visitObjCIvarDeclAttrs(ObjCIvarDecl *D) {
870     setFlag("synthesize", D->getSynthesize());
871     setAccessControl("access", D->getAccessControl());
872   }
873
874   // ObjCCompatibleAliasDecl
875   void visitObjCCompatibleAliasDeclChildren(ObjCCompatibleAliasDecl *D) {
876     visitDeclRef(D->getClassInterface());
877   }
878
879   // FIXME: ObjCPropertyDecl
880   // FIXME: ObjCPropertyImplDecl
881
882   //---- Types -----------------------------------------------------//
883   void dispatch(TypeLoc TL) {
884     dispatch(TL.getType()); // for now
885   }
886
887   void dispatch(QualType T) {
888     if (T.hasLocalQualifiers()) {
889       push("QualType");
890       Qualifiers Qs = T.getLocalQualifiers();
891       setFlag("const", Qs.hasConst());
892       setFlag("volatile", Qs.hasVolatile());
893       setFlag("restrict", Qs.hasRestrict());
894       if (Qs.hasAddressSpace()) setInteger("addrspace", Qs.getAddressSpace());
895       if (Qs.hasObjCGCAttr()) {
896         switch (Qs.getObjCGCAttr()) {
897         case Qualifiers::Weak: set("gc", "weak"); break;
898         case Qualifiers::Strong: set("gc", "strong"); break;
899         case Qualifiers::GCNone: llvm_unreachable("explicit none");
900         }
901       }
902       
903       completeAttrs();
904       dispatch(QualType(T.getTypePtr(), 0));
905       pop();
906       return;
907     }
908
909     Type *Ty = const_cast<Type*>(T.getTypePtr());
910     push(getTypeKindName(Ty));
911     XMLTypeVisitor<XMLDumper>::dispatch(const_cast<Type*>(T.getTypePtr()));
912     pop();
913   }
914
915   void setCallingConv(CallingConv CC) {
916     switch (CC) {
917     case CC_Default: return;
918     case CC_C: return set("cc", "cdecl");
919     case CC_X86FastCall: return set("cc", "x86_fastcall");
920     case CC_X86StdCall: return set("cc", "x86_stdcall");
921     case CC_X86ThisCall: return set("cc", "x86_thiscall");
922     case CC_X86Pascal: return set("cc", "x86_pascal");
923     case CC_AAPCS: return set("cc", "aapcs");
924     case CC_AAPCS_VFP: return set("cc", "aapcs_vfp");
925     case CC_PnaclCall: return set("cc", "pnaclcall");
926     }
927   }
928
929   void visitTypeAttrs(Type *D) {
930     setPointer(D);
931     setFlag("dependent", D->isDependentType());
932     setFlag("variably_modified", D->isVariablyModifiedType());
933
934     setPointer("canonical", D->getCanonicalTypeInternal().getAsOpaquePtr());
935   }
936
937   void visitPointerTypeChildren(PointerType *T) {
938     dispatch(T->getPointeeType());
939   }
940   void visitReferenceTypeChildren(ReferenceType *T) {
941     dispatch(T->getPointeeType());
942   }
943   void visitObjCObjectPointerTypeChildren(ObjCObjectPointerType *T) {
944     dispatch(T->getPointeeType());
945   }
946   void visitBlockPointerTypeChildren(BlockPointerType *T) {
947     dispatch(T->getPointeeType());
948   }
949
950   // Types that just wrap declarations.
951   void visitTagTypeChildren(TagType *T) {
952     visitDeclRef(T->getDecl());
953   }
954   void visitTypedefTypeChildren(TypedefType *T) {
955     visitDeclRef(T->getDecl());
956   }
957   void visitObjCInterfaceTypeChildren(ObjCInterfaceType *T) {
958     visitDeclRef(T->getDecl());
959   }
960   void visitUnresolvedUsingTypeChildren(UnresolvedUsingType *T) {
961     visitDeclRef(T->getDecl());
962   }
963   void visitInjectedClassNameTypeChildren(InjectedClassNameType *T) {
964     visitDeclRef(T->getDecl());
965   }
966
967   void visitFunctionTypeAttrs(FunctionType *T) {
968     setFlag("noreturn", T->getNoReturnAttr());
969     setCallingConv(T->getCallConv());
970     if (T->getHasRegParm()) setInteger("regparm", T->getRegParmType());
971   }
972   void visitFunctionTypeChildren(FunctionType *T) {
973     dispatch(T->getResultType());
974   }
975
976   void visitFunctionProtoTypeAttrs(FunctionProtoType *T) {
977     setFlag("const", T->isConst());
978     setFlag("volatile", T->isVolatile());
979     setFlag("restrict", T->isRestrict());
980     switch (T->getExceptionSpecType()) {
981     case EST_None: break;
982     case EST_DynamicNone: set("exception_spec", "throw()"); break;
983     case EST_Dynamic: set("exception_spec", "throw(T)"); break;
984     case EST_MSAny: set("exception_spec", "throw(...)"); break;
985     case EST_BasicNoexcept: set("exception_spec", "noexcept"); break;
986     case EST_ComputedNoexcept: set("exception_spec", "noexcept(expr)"); break;
987     case EST_Unevaluated: set("exception_spec", "unevaluated"); break;
988     case EST_Uninstantiated: set("exception_spec", "uninstantiated"); break;
989     }
990   }
991   void visitFunctionProtoTypeChildren(FunctionProtoType *T) {
992     push("parameters");
993     setFlag("variadic", T->isVariadic());
994     completeAttrs();
995     for (FunctionProtoType::arg_type_iterator
996            I = T->arg_type_begin(), E = T->arg_type_end(); I != E; ++I)
997       dispatch(*I);
998     pop();
999
1000     if (T->hasDynamicExceptionSpec()) {
1001       push("exception_specifiers");
1002       setFlag("any", T->getExceptionSpecType() == EST_MSAny);
1003       completeAttrs();
1004       for (FunctionProtoType::exception_iterator
1005              I = T->exception_begin(), E = T->exception_end(); I != E; ++I)
1006         dispatch(*I);
1007       pop();
1008     }
1009     // FIXME: noexcept specifier
1010   }
1011
1012   void visitTemplateSpecializationTypeChildren(TemplateSpecializationType *T) {
1013     if (const RecordType *RT = T->getAs<RecordType>())
1014       visitDeclRef(RT->getDecl());
1015
1016     // TODO: TemplateName
1017
1018     push("template_arguments");
1019     completeAttrs();
1020     for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I)
1021       dispatch(T->getArg(I));
1022     pop();
1023   }
1024
1025   //---- Statements ------------------------------------------------//
1026   void dispatch(Stmt *S) {
1027     // FIXME: this is not really XML at all
1028     push("Stmt");
1029     out << ">\n";
1030     Stack.back().State = NS_Children; // explicitly become non-lazy
1031     S->dump(out, Context.getSourceManager());
1032     out << '\n';
1033     pop();
1034   }
1035 };
1036 }
1037
1038 void Decl::dumpXML() const {
1039   dumpXML(llvm::errs());
1040 }
1041
1042 void Decl::dumpXML(raw_ostream &out) const {
1043   XMLDumper(out, getASTContext()).dispatch(const_cast<Decl*>(this));
1044 }
1045
1046 #else /* ifndef NDEBUG */
1047
1048 void Decl::dumpXML() const {}
1049 void Decl::dumpXML(raw_ostream &out) const {}
1050
1051 #endif