• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===--- 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/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;
Node__anonf6b4be7e0111::Node57   Node(StringRef name) : Name(name), State(NS_Attrs) {}
58 
isDoneWithAttrs__anonf6b4be7e0111::Node59   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 
dispatch__anonf6b4be7e0111::XMLDeclVisitor66   void dispatch(Decl *D) {
67     switch (D->getKind()) {
68 #define DECL(DERIVED, BASE) \
69       case Decl::DERIVED: \
70         DISPATCH(dispatch##DERIVED##DeclAttrs, DERIVED##Decl); \
71         static_cast<Impl*>(this)->completeAttrs(); \
72         DISPATCH(dispatch##DERIVED##DeclChildren, DERIVED##Decl); \
73         DISPATCH(dispatch##DERIVED##DeclAsContext, DERIVED##Decl); \
74         break;
75 #define ABSTRACT_DECL(DECL)
76 #include "clang/AST/DeclNodes.inc"
77     }
78   }
79 
80 #define DECL(DERIVED, BASE) \
81   void dispatch##DERIVED##DeclAttrs(DERIVED##Decl *D) { \
82     DISPATCH(dispatch##BASE##Attrs, BASE); \
83     DISPATCH(visit##DERIVED##DeclAttrs, DERIVED##Decl); \
84   } \
85   void visit##DERIVED##DeclAttrs(DERIVED##Decl *D) {} \
86   void dispatch##DERIVED##DeclChildren(DERIVED##Decl *D) { \
87     DISPATCH(dispatch##BASE##Children, BASE); \
88     DISPATCH(visit##DERIVED##DeclChildren, DERIVED##Decl); \
89   } \
90   void visit##DERIVED##DeclChildren(DERIVED##Decl *D) {} \
91   void dispatch##DERIVED##DeclAsContext(DERIVED##Decl *D) { \
92     DISPATCH(dispatch##BASE##AsContext, BASE); \
93     DISPATCH(visit##DERIVED##DeclAsContext, DERIVED##Decl); \
94   } \
95   void visit##DERIVED##DeclAsContext(DERIVED##Decl *D) {}
96 #include "clang/AST/DeclNodes.inc"
97 
dispatchDeclAttrs__anonf6b4be7e0111::XMLDeclVisitor98   void dispatchDeclAttrs(Decl *D) {
99     DISPATCH(visitDeclAttrs, Decl);
100   }
visitDeclAttrs__anonf6b4be7e0111::XMLDeclVisitor101   void visitDeclAttrs(Decl *D) {}
102 
dispatchDeclChildren__anonf6b4be7e0111::XMLDeclVisitor103   void dispatchDeclChildren(Decl *D) {
104     DISPATCH(visitDeclChildren, Decl);
105   }
visitDeclChildren__anonf6b4be7e0111::XMLDeclVisitor106   void visitDeclChildren(Decl *D) {}
107 
dispatchDeclAsContext__anonf6b4be7e0111::XMLDeclVisitor108   void dispatchDeclAsContext(Decl *D) {
109     DISPATCH(visitDeclAsContext, Decl);
110   }
visitDeclAsContext__anonf6b4be7e0111::XMLDeclVisitor111   void visitDeclAsContext(Decl *D) {}
112 
113 #undef DISPATCH
114 };
115 
116 template <class Impl> struct XMLTypeVisitor {
117 #define DISPATCH(NAME, CLASS) \
118   static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(T))
119 
dispatch__anonf6b4be7e0111::XMLTypeVisitor120   void dispatch(Type *T) {
121     switch (T->getTypeClass()) {
122 #define TYPE(DERIVED, BASE) \
123       case Type::DERIVED: \
124         DISPATCH(dispatch##DERIVED##TypeAttrs, DERIVED##Type); \
125         static_cast<Impl*>(this)->completeAttrs(); \
126         DISPATCH(dispatch##DERIVED##TypeChildren, DERIVED##Type); \
127         break;
128 #define ABSTRACT_TYPE(DERIVED, BASE)
129 #include "clang/AST/TypeNodes.def"
130     }
131   }
132 
133 #define TYPE(DERIVED, BASE) \
134   void dispatch##DERIVED##TypeAttrs(DERIVED##Type *T) { \
135     DISPATCH(dispatch##BASE##Attrs, BASE); \
136     DISPATCH(visit##DERIVED##TypeAttrs, DERIVED##Type); \
137   } \
138   void visit##DERIVED##TypeAttrs(DERIVED##Type *T) {} \
139   void dispatch##DERIVED##TypeChildren(DERIVED##Type *T) { \
140     DISPATCH(dispatch##BASE##Children, BASE); \
141     DISPATCH(visit##DERIVED##TypeChildren, DERIVED##Type); \
142   } \
143   void visit##DERIVED##TypeChildren(DERIVED##Type *T) {}
144 #include "clang/AST/TypeNodes.def"
145 
dispatchTypeAttrs__anonf6b4be7e0111::XMLTypeVisitor146   void dispatchTypeAttrs(Type *T) {
147     DISPATCH(visitTypeAttrs, Type);
148   }
visitTypeAttrs__anonf6b4be7e0111::XMLTypeVisitor149   void visitTypeAttrs(Type *T) {}
150 
dispatchTypeChildren__anonf6b4be7e0111::XMLTypeVisitor151   void dispatchTypeChildren(Type *T) {
152     DISPATCH(visitTypeChildren, Type);
153   }
visitTypeChildren__anonf6b4be7e0111::XMLTypeVisitor154   void visitTypeChildren(Type *T) {}
155 
156 #undef DISPATCH
157 };
158 
getTypeKindName(Type * T)159 static StringRef getTypeKindName(Type *T) {
160   switch (T->getTypeClass()) {
161 #define TYPE(DERIVED, BASE) case Type::DERIVED: return #DERIVED "Type";
162 #define ABSTRACT_TYPE(DERIVED, BASE)
163 #include "clang/AST/TypeNodes.def"
164   }
165 
166   llvm_unreachable("unknown type kind!");
167 }
168 
169 struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
170                    public XMLTypeVisitor<XMLDumper> {
171   raw_ostream &out;
172   ASTContext &Context;
173   SmallVector<Node, 16> Stack;
174   unsigned Indent;
XMLDumper__anonf6b4be7e0111::XMLDumper175   explicit XMLDumper(raw_ostream &OS, ASTContext &context)
176     : out(OS), Context(context), Indent(0) {}
177 
indent__anonf6b4be7e0111::XMLDumper178   void indent() {
179     for (unsigned I = Indent; I; --I)
180       out << ' ';
181   }
182 
183   /// Push a new node on the stack.
push__anonf6b4be7e0111::XMLDumper184   void push(StringRef name) {
185     if (!Stack.empty()) {
186       assert(Stack.back().isDoneWithAttrs());
187       if (Stack.back().State == NS_LazyChildren) {
188         Stack.back().State = NS_Children;
189         out << ">\n";
190       }
191       Indent++;
192       indent();
193     }
194     Stack.push_back(Node(name));
195     out << '<' << name;
196   }
197 
198   /// Set the given attribute to the given value.
set__anonf6b4be7e0111::XMLDumper199   void set(StringRef attr, StringRef value) {
200     assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
201     out << ' ' << attr << '=' << '"' << value << '"'; // TODO: quotation
202   }
203 
204   /// Finish attributes.
completeAttrs__anonf6b4be7e0111::XMLDumper205   void completeAttrs() {
206     assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
207     Stack.back().State = NS_LazyChildren;
208   }
209 
210   /// Pop a node.
pop__anonf6b4be7e0111::XMLDumper211   void pop() {
212     assert(!Stack.empty() && Stack.back().isDoneWithAttrs());
213     if (Stack.back().State == NS_LazyChildren) {
214       out << "/>\n";
215     } else {
216       indent();
217       out << "</" << Stack.back().Name << ">\n";
218     }
219     if (Stack.size() > 1) Indent--;
220     Stack.pop_back();
221   }
222 
223   //---- General utilities -------------------------------------------//
224 
setPointer__anonf6b4be7e0111::XMLDumper225   void setPointer(StringRef prop, const void *p) {
226     SmallString<10> buffer;
227     llvm::raw_svector_ostream os(buffer);
228     os << p;
229     os.flush();
230     set(prop, buffer);
231   }
232 
setPointer__anonf6b4be7e0111::XMLDumper233   void setPointer(void *p) {
234     setPointer("ptr", p);
235   }
236 
setInteger__anonf6b4be7e0111::XMLDumper237   void setInteger(StringRef prop, const llvm::APSInt &v) {
238     set(prop, v.toString(10));
239   }
240 
setInteger__anonf6b4be7e0111::XMLDumper241   void setInteger(StringRef prop, unsigned n) {
242     SmallString<10> buffer;
243     llvm::raw_svector_ostream os(buffer);
244     os << n;
245     os.flush();
246     set(prop, buffer);
247   }
248 
setFlag__anonf6b4be7e0111::XMLDumper249   void setFlag(StringRef prop, bool flag) {
250     if (flag) set(prop, "true");
251   }
252 
setName__anonf6b4be7e0111::XMLDumper253   void setName(DeclarationName Name) {
254     if (!Name)
255       return set("name", "");
256 
257     // Common case.
258     if (Name.isIdentifier())
259       return set("name", Name.getAsIdentifierInfo()->getName());
260 
261     set("name", Name.getAsString());
262   }
263 
264   class TemporaryContainer {
265     XMLDumper &Dumper;
266   public:
TemporaryContainer(XMLDumper & dumper,StringRef name)267     TemporaryContainer(XMLDumper &dumper, StringRef name)
268       : Dumper(dumper) {
269       Dumper.push(name);
270       Dumper.completeAttrs();
271     }
272 
~TemporaryContainer()273     ~TemporaryContainer() {
274       Dumper.pop();
275     }
276   };
277 
visitTemplateParameters__anonf6b4be7e0111::XMLDumper278   void visitTemplateParameters(TemplateParameterList *L) {
279     push("template_parameters");
280     completeAttrs();
281     for (TemplateParameterList::iterator
282            I = L->begin(), E = L->end(); I != E; ++I)
283       dispatch(*I);
284     pop();
285   }
286 
visitTemplateArguments__anonf6b4be7e0111::XMLDumper287   void visitTemplateArguments(const TemplateArgumentList &L) {
288     push("template_arguments");
289     completeAttrs();
290     for (unsigned I = 0, E = L.size(); I != E; ++I)
291       dispatch(L[I]);
292     pop();
293   }
294 
295   /// Visits a reference to the given declaration.
visitDeclRef__anonf6b4be7e0111::XMLDumper296   void visitDeclRef(Decl *D) {
297     push(D->getDeclKindName());
298     setPointer("ref", D);
299     completeAttrs();
300     pop();
301   }
visitDeclRef__anonf6b4be7e0111::XMLDumper302   void visitDeclRef(StringRef Name, Decl *D) {
303     TemporaryContainer C(*this, Name);
304     if (D) visitDeclRef(D);
305   }
306 
dispatch__anonf6b4be7e0111::XMLDumper307   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::TemplateExpansion:
319       // FIXME: Implement!
320       break;
321 
322     case TemplateArgument::Declaration: {
323       if (Decl *D = A.getAsDecl())
324         visitDeclRef(D);
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: {
339       for (TemplateArgument::pack_iterator P = A.pack_begin(),
340                                         PEnd = A.pack_end();
341            P != PEnd; ++P)
342         dispatch(*P);
343       break;
344     }
345     }
346   }
347 
dispatch__anonf6b4be7e0111::XMLDumper348   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();
dispatch__anonf6b4be7e0111::XMLDumper381   void dispatch(Decl *D) {
382     push(D->getDeclKindName());
383     XMLDeclVisitor<XMLDumper>::dispatch(D);
384     pop();
385   }
visitDeclAttrs__anonf6b4be7e0111::XMLDumper386   void visitDeclAttrs(Decl *D) {
387     setPointer(D);
388   }
389 
390   /// Visit all the lexical decls in the given context.
visitDeclContext__anonf6b4be7e0111::XMLDumper391   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.
setAccess__anonf6b4be7e0111::XMLDumper401   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 
visitRedeclarableAttrs__anonf6b4be7e0111::XMLDumper410   template <class T> void visitRedeclarableAttrs(T *D) {
411     if (T *Prev = D->getPreviousDecl())
412       setPointer("previous", Prev);
413   }
414 
415 
416   // TranslationUnitDecl
visitTranslationUnitDeclAsContext__anonf6b4be7e0111::XMLDumper417   void visitTranslationUnitDeclAsContext(TranslationUnitDecl *D) {
418     visitDeclContext(D);
419   }
420 
421   // LinkageSpecDecl
visitLinkageSpecDeclAttrs__anonf6b4be7e0111::XMLDumper422   void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) {
423     StringRef lang = "";
424     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   }
visitLinkageSpecDeclAsContext__anonf6b4be7e0111::XMLDumper430   void visitLinkageSpecDeclAsContext(LinkageSpecDecl *D) {
431     visitDeclContext(D);
432   }
433 
434   // NamespaceDecl
visitNamespaceDeclAttrs__anonf6b4be7e0111::XMLDumper435   void visitNamespaceDeclAttrs(NamespaceDecl *D) {
436     setFlag("inline", D->isInline());
437     if (!D->isOriginalNamespace())
438       setPointer("original", D->getOriginalNamespace());
439   }
visitNamespaceDeclAsContext__anonf6b4be7e0111::XMLDumper440   void visitNamespaceDeclAsContext(NamespaceDecl *D) {
441     visitDeclContext(D);
442   }
443 
444   // NamedDecl
visitNamedDeclAttrs__anonf6b4be7e0111::XMLDumper445   void visitNamedDeclAttrs(NamedDecl *D) {
446     setName(D->getDeclName());
447   }
448 
449   // ValueDecl
visitValueDeclChildren__anonf6b4be7e0111::XMLDumper450   void visitValueDeclChildren(ValueDecl *D) {
451     dispatch(D->getType());
452   }
453 
454   // DeclaratorDecl
visitDeclaratorDeclChildren__anonf6b4be7e0111::XMLDumper455   void visitDeclaratorDeclChildren(DeclaratorDecl *D) {
456     //dispatch(D->getTypeSourceInfo()->getTypeLoc());
457   }
458 
459   // VarDecl
visitVarDeclAttrs__anonf6b4be7e0111::XMLDumper460   void visitVarDeclAttrs(VarDecl *D) {
461     visitRedeclarableAttrs(D);
462     if (D->getStorageClass() != SC_None)
463       set("storage",
464           VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
465     StringRef initStyle = "";
466     switch (D->getInitStyle()) {
467     case VarDecl::CInit: initStyle = "c"; break;
468     case VarDecl::CallInit: initStyle = "call"; break;
469     case VarDecl::ListInit: initStyle = "list"; break;
470     }
471     set("initstyle", initStyle);
472     setFlag("nrvo", D->isNRVOVariable());
473     // TODO: instantiation, etc.
474   }
visitVarDeclChildren__anonf6b4be7e0111::XMLDumper475   void visitVarDeclChildren(VarDecl *D) {
476     if (D->hasInit()) dispatch(D->getInit());
477   }
478 
479   // ParmVarDecl?
480 
481   // FunctionDecl
visitFunctionDeclAttrs__anonf6b4be7e0111::XMLDumper482   void visitFunctionDeclAttrs(FunctionDecl *D) {
483     visitRedeclarableAttrs(D);
484     setFlag("pure", D->isPure());
485     setFlag("trivial", D->isTrivial());
486     setFlag("returnzero", D->hasImplicitReturnZero());
487     setFlag("prototype", D->hasWrittenPrototype());
488     setFlag("deleted", D->isDeletedAsWritten());
489     if (D->getStorageClass() != SC_None)
490       set("storage",
491           VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
492     setFlag("inline", D->isInlineSpecified());
493     if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>())
494       set("asmlabel", ALA->getLabel());
495     // TODO: instantiation, etc.
496   }
visitFunctionDeclChildren__anonf6b4be7e0111::XMLDumper497   void visitFunctionDeclChildren(FunctionDecl *D) {
498     for (FunctionDecl::param_iterator
499            I = D->param_begin(), E = D->param_end(); I != E; ++I)
500       dispatch(*I);
501     for (llvm::ArrayRef<NamedDecl*>::iterator
502            I = D->getDeclsInPrototypeScope().begin(), E = D->getDeclsInPrototypeScope().end();
503          I != E; ++I)
504       dispatch(*I);
505     if (D->doesThisDeclarationHaveABody())
506       dispatch(D->getBody());
507   }
508 
509   // CXXMethodDecl ?
510   // CXXConstructorDecl ?
511   // CXXDestructorDecl ?
512   // CXXConversionDecl ?
513 
dispatch__anonf6b4be7e0111::XMLDumper514   void dispatch(CXXCtorInitializer *Init) {
515     // TODO
516   }
517 
518   // FieldDecl
visitFieldDeclAttrs__anonf6b4be7e0111::XMLDumper519   void visitFieldDeclAttrs(FieldDecl *D) {
520     setFlag("mutable", D->isMutable());
521   }
visitFieldDeclChildren__anonf6b4be7e0111::XMLDumper522   void visitFieldDeclChildren(FieldDecl *D) {
523     if (D->isBitField()) {
524       TemporaryContainer C(*this, "bitwidth");
525       dispatch(D->getBitWidth());
526     }
527     // TODO: C++0x member initializer
528   }
529 
530   // EnumConstantDecl
visitEnumConstantDeclChildren__anonf6b4be7e0111::XMLDumper531   void visitEnumConstantDeclChildren(EnumConstantDecl *D) {
532     // value in any case?
533     if (D->getInitExpr()) dispatch(D->getInitExpr());
534   }
535 
536   // IndirectFieldDecl
visitIndirectFieldDeclChildren__anonf6b4be7e0111::XMLDumper537   void visitIndirectFieldDeclChildren(IndirectFieldDecl *D) {
538     for (IndirectFieldDecl::chain_iterator
539            I = D->chain_begin(), E = D->chain_end(); I != E; ++I) {
540       NamedDecl *VD = const_cast<NamedDecl*>(*I);
541       push(isa<VarDecl>(VD) ? "variable" : "field");
542       setPointer("ptr", VD);
543       completeAttrs();
544       pop();
545     }
546   }
547 
548   // TypeDecl
visitTypeDeclAttrs__anonf6b4be7e0111::XMLDumper549   void visitTypeDeclAttrs(TypeDecl *D) {
550     setPointer("typeptr", D->getTypeForDecl());
551   }
552 
553   // TypedefDecl
visitTypedefDeclAttrs__anonf6b4be7e0111::XMLDumper554   void visitTypedefDeclAttrs(TypedefDecl *D) {
555     visitRedeclarableAttrs<TypedefNameDecl>(D);
556   }
visitTypedefDeclChildren__anonf6b4be7e0111::XMLDumper557   void visitTypedefDeclChildren(TypedefDecl *D) {
558     dispatch(D->getTypeSourceInfo()->getTypeLoc());
559   }
560 
561   // TypeAliasDecl
visitTypeAliasDeclAttrs__anonf6b4be7e0111::XMLDumper562   void visitTypeAliasDeclAttrs(TypeAliasDecl *D) {
563     visitRedeclarableAttrs<TypedefNameDecl>(D);
564   }
visitTypeAliasDeclChildren__anonf6b4be7e0111::XMLDumper565   void visitTypeAliasDeclChildren(TypeAliasDecl *D) {
566     dispatch(D->getTypeSourceInfo()->getTypeLoc());
567   }
568 
569   // TagDecl
visitTagDeclAttrs__anonf6b4be7e0111::XMLDumper570   void visitTagDeclAttrs(TagDecl *D) {
571     visitRedeclarableAttrs(D);
572   }
visitTagDeclAsContext__anonf6b4be7e0111::XMLDumper573   void visitTagDeclAsContext(TagDecl *D) {
574     visitDeclContext(D);
575   }
576 
577   // EnumDecl
visitEnumDeclAttrs__anonf6b4be7e0111::XMLDumper578   void visitEnumDeclAttrs(EnumDecl *D) {
579     setFlag("scoped", D->isScoped());
580     setFlag("fixed", D->isFixed());
581   }
visitEnumDeclChildren__anonf6b4be7e0111::XMLDumper582   void visitEnumDeclChildren(EnumDecl *D) {
583     {
584       TemporaryContainer C(*this, "promotion_type");
585       dispatch(D->getPromotionType());
586     }
587     {
588       TemporaryContainer C(*this, "integer_type");
589       dispatch(D->getIntegerType());
590     }
591   }
592 
593   // RecordDecl ?
594 
visitCXXRecordDeclChildren__anonf6b4be7e0111::XMLDumper595   void visitCXXRecordDeclChildren(CXXRecordDecl *D) {
596     if (!D->isThisDeclarationADefinition()) return;
597 
598     for (CXXRecordDecl::base_class_iterator
599            I = D->bases_begin(), E = D->bases_end(); I != E; ++I) {
600       push("base");
601       setAccess(I->getAccessSpecifier());
602       completeAttrs();
603       dispatch(I->getTypeSourceInfo()->getTypeLoc());
604       pop();
605     }
606   }
607 
608   // ClassTemplateSpecializationDecl ?
609 
610   // FileScopeAsmDecl ?
611 
612   // BlockDecl
visitBlockDeclAttrs__anonf6b4be7e0111::XMLDumper613   void visitBlockDeclAttrs(BlockDecl *D) {
614     setFlag("variadic", D->isVariadic());
615   }
visitBlockDeclChildren__anonf6b4be7e0111::XMLDumper616   void visitBlockDeclChildren(BlockDecl *D) {
617     for (FunctionDecl::param_iterator
618            I = D->param_begin(), E = D->param_end(); I != E; ++I)
619       dispatch(*I);
620     dispatch(D->getBody());
621   }
622 
623   // AccessSpecDecl
visitAccessSpecDeclAttrs__anonf6b4be7e0111::XMLDumper624   void visitAccessSpecDeclAttrs(AccessSpecDecl *D) {
625     setAccess(D->getAccess());
626   }
627 
628   // TemplateDecl
visitTemplateDeclChildren__anonf6b4be7e0111::XMLDumper629   void visitTemplateDeclChildren(TemplateDecl *D) {
630     visitTemplateParameters(D->getTemplateParameters());
631     if (D->getTemplatedDecl())
632       dispatch(D->getTemplatedDecl());
633   }
634 
635   // FunctionTemplateDecl
visitFunctionTemplateDeclAttrs__anonf6b4be7e0111::XMLDumper636   void visitFunctionTemplateDeclAttrs(FunctionTemplateDecl *D) {
637     visitRedeclarableAttrs(D);
638   }
visitFunctionTemplateDeclChildren__anonf6b4be7e0111::XMLDumper639   void visitFunctionTemplateDeclChildren(FunctionTemplateDecl *D) {
640     // Mention all the specializations which don't have explicit
641     // declarations elsewhere.
642     for (FunctionTemplateDecl::spec_iterator
643            I = D->spec_begin(), E = D->spec_end(); I != E; ++I) {
644       FunctionTemplateSpecializationInfo *Info
645         = I->getTemplateSpecializationInfo();
646 
647       bool Unknown = false;
648       switch (Info->getTemplateSpecializationKind()) {
649       case TSK_ImplicitInstantiation: Unknown = false; break;
650       case TSK_Undeclared: Unknown = true; break;
651 
652       // These will be covered at their respective sites.
653       case TSK_ExplicitSpecialization: continue;
654       case TSK_ExplicitInstantiationDeclaration: continue;
655       case TSK_ExplicitInstantiationDefinition: continue;
656       }
657 
658       TemporaryContainer C(*this,
659                            Unknown ? "uninstantiated" : "instantiation");
660       visitTemplateArguments(*Info->TemplateArguments);
661       dispatch(Info->Function);
662     }
663   }
664 
665   // ClasTemplateDecl
visitClassTemplateDeclAttrs__anonf6b4be7e0111::XMLDumper666   void visitClassTemplateDeclAttrs(ClassTemplateDecl *D) {
667     visitRedeclarableAttrs(D);
668   }
visitClassTemplateDeclChildren__anonf6b4be7e0111::XMLDumper669   void visitClassTemplateDeclChildren(ClassTemplateDecl *D) {
670     // Mention all the specializations which don't have explicit
671     // declarations elsewhere.
672     for (ClassTemplateDecl::spec_iterator
673            I = D->spec_begin(), E = D->spec_end(); I != E; ++I) {
674 
675       bool Unknown = false;
676       switch (I->getTemplateSpecializationKind()) {
677       case TSK_ImplicitInstantiation: Unknown = false; break;
678       case TSK_Undeclared: Unknown = true; break;
679 
680       // These will be covered at their respective sites.
681       case TSK_ExplicitSpecialization: continue;
682       case TSK_ExplicitInstantiationDeclaration: continue;
683       case TSK_ExplicitInstantiationDefinition: continue;
684       }
685 
686       TemporaryContainer C(*this,
687                            Unknown ? "uninstantiated" : "instantiation");
688       visitTemplateArguments(I->getTemplateArgs());
689       dispatch(*I);
690     }
691   }
692 
693   // TemplateTypeParmDecl
visitTemplateTypeParmDeclAttrs__anonf6b4be7e0111::XMLDumper694   void visitTemplateTypeParmDeclAttrs(TemplateTypeParmDecl *D) {
695     setInteger("depth", D->getDepth());
696     setInteger("index", D->getIndex());
697   }
visitTemplateTypeParmDeclChildren__anonf6b4be7e0111::XMLDumper698   void visitTemplateTypeParmDeclChildren(TemplateTypeParmDecl *D) {
699     if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
700       dispatch(D->getDefaultArgumentInfo()->getTypeLoc());
701     // parameter pack?
702   }
703 
704   // NonTypeTemplateParmDecl
visitNonTypeTemplateParmDeclAttrs__anonf6b4be7e0111::XMLDumper705   void visitNonTypeTemplateParmDeclAttrs(NonTypeTemplateParmDecl *D) {
706     setInteger("depth", D->getDepth());
707     setInteger("index", D->getIndex());
708   }
visitNonTypeTemplateParmDeclChildren__anonf6b4be7e0111::XMLDumper709   void visitNonTypeTemplateParmDeclChildren(NonTypeTemplateParmDecl *D) {
710     if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
711       dispatch(D->getDefaultArgument());
712     // parameter pack?
713   }
714 
715   // TemplateTemplateParmDecl
visitTemplateTemplateParmDeclAttrs__anonf6b4be7e0111::XMLDumper716   void visitTemplateTemplateParmDeclAttrs(TemplateTemplateParmDecl *D) {
717     setInteger("depth", D->getDepth());
718     setInteger("index", D->getIndex());
719   }
visitTemplateTemplateParmDeclChildren__anonf6b4be7e0111::XMLDumper720   void visitTemplateTemplateParmDeclChildren(TemplateTemplateParmDecl *D) {
721     if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
722       dispatch(D->getDefaultArgument());
723     // parameter pack?
724   }
725 
726   // FriendDecl
visitFriendDeclChildren__anonf6b4be7e0111::XMLDumper727   void visitFriendDeclChildren(FriendDecl *D) {
728     if (TypeSourceInfo *T = D->getFriendType())
729       dispatch(T->getTypeLoc());
730     else
731       dispatch(D->getFriendDecl());
732   }
733 
734   // UsingDirectiveDecl ?
735   // UsingDecl ?
736   // UsingShadowDecl ?
737   // NamespaceAliasDecl ?
738   // UnresolvedUsingValueDecl ?
739   // UnresolvedUsingTypenameDecl ?
740   // StaticAssertDecl ?
741 
742   // ObjCImplDecl
visitObjCImplDeclChildren__anonf6b4be7e0111::XMLDumper743   void visitObjCImplDeclChildren(ObjCImplDecl *D) {
744     visitDeclRef(D->getClassInterface());
745   }
visitObjCImplDeclAsContext__anonf6b4be7e0111::XMLDumper746   void visitObjCImplDeclAsContext(ObjCImplDecl *D) {
747     visitDeclContext(D);
748   }
749 
750   // ObjCInterfaceDecl
visitCategoryList__anonf6b4be7e0111::XMLDumper751   void visitCategoryList(ObjCCategoryDecl *D) {
752     if (!D) return;
753 
754     TemporaryContainer C(*this, "categories");
755     for (; D; D = D->getNextClassCategory())
756       visitDeclRef(D);
757   }
visitObjCInterfaceDeclAttrs__anonf6b4be7e0111::XMLDumper758   void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) {
759     setPointer("typeptr", D->getTypeForDecl());
760     setFlag("forward_decl", !D->isThisDeclarationADefinition());
761     setFlag("implicit_interface", D->isImplicitInterfaceDecl());
762   }
visitObjCInterfaceDeclChildren__anonf6b4be7e0111::XMLDumper763   void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) {
764     visitDeclRef("super", D->getSuperClass());
765     visitDeclRef("implementation", D->getImplementation());
766     if (D->protocol_begin() != D->protocol_end()) {
767       TemporaryContainer C(*this, "protocols");
768       for (ObjCInterfaceDecl::protocol_iterator
769              I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
770         visitDeclRef(*I);
771     }
772     visitCategoryList(D->getCategoryList());
773   }
visitObjCInterfaceDeclAsContext__anonf6b4be7e0111::XMLDumper774   void visitObjCInterfaceDeclAsContext(ObjCInterfaceDecl *D) {
775     visitDeclContext(D);
776   }
777 
778   // ObjCCategoryDecl
visitObjCCategoryDeclAttrs__anonf6b4be7e0111::XMLDumper779   void visitObjCCategoryDeclAttrs(ObjCCategoryDecl *D) {
780     setFlag("extension", D->IsClassExtension());
781     setFlag("synth_bitfield", D->hasSynthBitfield());
782   }
visitObjCCategoryDeclChildren__anonf6b4be7e0111::XMLDumper783   void visitObjCCategoryDeclChildren(ObjCCategoryDecl *D) {
784     visitDeclRef("interface", D->getClassInterface());
785     visitDeclRef("implementation", D->getImplementation());
786     if (D->protocol_begin() != D->protocol_end()) {
787       TemporaryContainer C(*this, "protocols");
788       for (ObjCCategoryDecl::protocol_iterator
789              I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
790         visitDeclRef(*I);
791     }
792   }
visitObjCCategoryDeclAsContext__anonf6b4be7e0111::XMLDumper793   void visitObjCCategoryDeclAsContext(ObjCCategoryDecl *D) {
794     visitDeclContext(D);
795   }
796 
797   // ObjCCategoryImplDecl
visitObjCCategoryImplDeclAttrs__anonf6b4be7e0111::XMLDumper798   void visitObjCCategoryImplDeclAttrs(ObjCCategoryImplDecl *D) {
799     set("identifier", D->getName());
800   }
visitObjCCategoryImplDeclChildren__anonf6b4be7e0111::XMLDumper801   void visitObjCCategoryImplDeclChildren(ObjCCategoryImplDecl *D) {
802     visitDeclRef(D->getCategoryDecl());
803   }
804 
805   // ObjCImplementationDecl
visitObjCImplementationDeclAttrs__anonf6b4be7e0111::XMLDumper806   void visitObjCImplementationDeclAttrs(ObjCImplementationDecl *D) {
807     setFlag("synth_bitfield", D->hasSynthBitfield());
808     set("identifier", D->getName());
809   }
visitObjCImplementationDeclChildren__anonf6b4be7e0111::XMLDumper810   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
visitObjCProtocolDeclChildren__anonf6b4be7e0111::XMLDumper821   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   }
visitObjCProtocolDeclAsContext__anonf6b4be7e0111::XMLDumper832   void visitObjCProtocolDeclAsContext(ObjCProtocolDecl *D) {
833     if (!D->isThisDeclarationADefinition())
834       return;
835 
836     visitDeclContext(D);
837   }
838 
839   // ObjCMethodDecl
visitObjCMethodDeclAttrs__anonf6b4be7e0111::XMLDumper840   void visitObjCMethodDeclAttrs(ObjCMethodDecl *D) {
841     // decl qualifier?
842     // implementation control?
843 
844     setFlag("instance", D->isInstanceMethod());
845     setFlag("variadic", D->isVariadic());
846     setFlag("synthesized", D->isSynthesized());
847     setFlag("defined", D->isDefined());
848     setFlag("related_result_type", D->hasRelatedResultType());
849   }
visitObjCMethodDeclChildren__anonf6b4be7e0111::XMLDumper850   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
setAccessControl__anonf6b4be7e0111::XMLDumper860   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   }
visitObjCIvarDeclAttrs__anonf6b4be7e0111::XMLDumper869   void visitObjCIvarDeclAttrs(ObjCIvarDecl *D) {
870     setFlag("synthesize", D->getSynthesize());
871     setAccessControl("access", D->getAccessControl());
872   }
873 
874   // ObjCCompatibleAliasDecl
visitObjCCompatibleAliasDeclChildren__anonf6b4be7e0111::XMLDumper875   void visitObjCCompatibleAliasDeclChildren(ObjCCompatibleAliasDecl *D) {
876     visitDeclRef(D->getClassInterface());
877   }
878 
879   // FIXME: ObjCPropertyDecl
880   // FIXME: ObjCPropertyImplDecl
881 
882   //---- Types -----------------------------------------------------//
dispatch__anonf6b4be7e0111::XMLDumper883   void dispatch(TypeLoc TL) {
884     dispatch(TL.getType()); // for now
885   }
886 
dispatch__anonf6b4be7e0111::XMLDumper887   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 
setCallingConv__anonf6b4be7e0111::XMLDumper915   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     }
926   }
927 
visitTypeAttrs__anonf6b4be7e0111::XMLDumper928   void visitTypeAttrs(Type *D) {
929     setPointer(D);
930     setFlag("dependent", D->isDependentType());
931     setFlag("variably_modified", D->isVariablyModifiedType());
932 
933     setPointer("canonical", D->getCanonicalTypeInternal().getAsOpaquePtr());
934   }
935 
visitPointerTypeChildren__anonf6b4be7e0111::XMLDumper936   void visitPointerTypeChildren(PointerType *T) {
937     dispatch(T->getPointeeType());
938   }
visitReferenceTypeChildren__anonf6b4be7e0111::XMLDumper939   void visitReferenceTypeChildren(ReferenceType *T) {
940     dispatch(T->getPointeeType());
941   }
visitObjCObjectPointerTypeChildren__anonf6b4be7e0111::XMLDumper942   void visitObjCObjectPointerTypeChildren(ObjCObjectPointerType *T) {
943     dispatch(T->getPointeeType());
944   }
visitBlockPointerTypeChildren__anonf6b4be7e0111::XMLDumper945   void visitBlockPointerTypeChildren(BlockPointerType *T) {
946     dispatch(T->getPointeeType());
947   }
948 
949   // Types that just wrap declarations.
visitTagTypeChildren__anonf6b4be7e0111::XMLDumper950   void visitTagTypeChildren(TagType *T) {
951     visitDeclRef(T->getDecl());
952   }
visitTypedefTypeChildren__anonf6b4be7e0111::XMLDumper953   void visitTypedefTypeChildren(TypedefType *T) {
954     visitDeclRef(T->getDecl());
955   }
visitObjCInterfaceTypeChildren__anonf6b4be7e0111::XMLDumper956   void visitObjCInterfaceTypeChildren(ObjCInterfaceType *T) {
957     visitDeclRef(T->getDecl());
958   }
visitUnresolvedUsingTypeChildren__anonf6b4be7e0111::XMLDumper959   void visitUnresolvedUsingTypeChildren(UnresolvedUsingType *T) {
960     visitDeclRef(T->getDecl());
961   }
visitInjectedClassNameTypeChildren__anonf6b4be7e0111::XMLDumper962   void visitInjectedClassNameTypeChildren(InjectedClassNameType *T) {
963     visitDeclRef(T->getDecl());
964   }
965 
visitFunctionTypeAttrs__anonf6b4be7e0111::XMLDumper966   void visitFunctionTypeAttrs(FunctionType *T) {
967     setFlag("noreturn", T->getNoReturnAttr());
968     setCallingConv(T->getCallConv());
969     if (T->getHasRegParm()) setInteger("regparm", T->getRegParmType());
970   }
visitFunctionTypeChildren__anonf6b4be7e0111::XMLDumper971   void visitFunctionTypeChildren(FunctionType *T) {
972     dispatch(T->getResultType());
973   }
974 
visitFunctionProtoTypeAttrs__anonf6b4be7e0111::XMLDumper975   void visitFunctionProtoTypeAttrs(FunctionProtoType *T) {
976     setFlag("const", T->getTypeQuals() & Qualifiers::Const);
977     setFlag("volatile", T->getTypeQuals() & Qualifiers::Volatile);
978     setFlag("restrict", T->getTypeQuals() & Qualifiers::Restrict);
979   }
visitFunctionProtoTypeChildren__anonf6b4be7e0111::XMLDumper980   void visitFunctionProtoTypeChildren(FunctionProtoType *T) {
981     push("parameters");
982     setFlag("variadic", T->isVariadic());
983     completeAttrs();
984     for (FunctionProtoType::arg_type_iterator
985            I = T->arg_type_begin(), E = T->arg_type_end(); I != E; ++I)
986       dispatch(*I);
987     pop();
988 
989     if (T->hasDynamicExceptionSpec()) {
990       push("exception_specifiers");
991       setFlag("any", T->getExceptionSpecType() == EST_MSAny);
992       completeAttrs();
993       for (FunctionProtoType::exception_iterator
994              I = T->exception_begin(), E = T->exception_end(); I != E; ++I)
995         dispatch(*I);
996       pop();
997     }
998     // FIXME: noexcept specifier
999   }
1000 
visitTemplateSpecializationTypeChildren__anonf6b4be7e0111::XMLDumper1001   void visitTemplateSpecializationTypeChildren(TemplateSpecializationType *T) {
1002     if (const RecordType *RT = T->getAs<RecordType>())
1003       visitDeclRef(RT->getDecl());
1004 
1005     // TODO: TemplateName
1006 
1007     push("template_arguments");
1008     completeAttrs();
1009     for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I)
1010       dispatch(T->getArg(I));
1011     pop();
1012   }
1013 
1014   //---- Statements ------------------------------------------------//
dispatch__anonf6b4be7e0111::XMLDumper1015   void dispatch(Stmt *S) {
1016     // FIXME: this is not really XML at all
1017     push("Stmt");
1018     out << ">\n";
1019     Stack.back().State = NS_Children; // explicitly become non-lazy
1020     S->dump(out, Context.getSourceManager());
1021     out << '\n';
1022     pop();
1023   }
1024 };
1025 }
1026 
dumpXML() const1027 void Decl::dumpXML() const {
1028   dumpXML(llvm::errs());
1029 }
1030 
dumpXML(raw_ostream & out) const1031 void Decl::dumpXML(raw_ostream &out) const {
1032   XMLDumper(out, getASTContext()).dispatch(const_cast<Decl*>(this));
1033 }
1034 
1035 #else /* ifndef NDEBUG */
1036 
dumpXML() const1037 void Decl::dumpXML() const {}
dumpXML(raw_ostream & out) const1038 void Decl::dumpXML(raw_ostream &out) const {}
1039 
1040 #endif
1041