• 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/SmallVector.h"
43 #include "llvm/ADT/StringRef.h"
44 
45 using namespace clang;
46 
47 #ifndef NDEBUG
48 
49 namespace {
50 
51 enum NodeState {
52   NS_Attrs, NS_LazyChildren, NS_Children
53 };
54 
55 struct Node {
56   llvm::StringRef Name;
57   NodeState State;
Node__anone37c897d0111::Node58   Node(llvm::StringRef name) : Name(name), State(NS_Attrs) {}
59 
isDoneWithAttrs__anone37c897d0111::Node60   bool isDoneWithAttrs() const { return State != NS_Attrs; }
61 };
62 
63 template <class Impl> struct XMLDeclVisitor {
64 #define DISPATCH(NAME, CLASS) \
65   static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(D))
66 
dispatch__anone37c897d0111::XMLDeclVisitor67   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 
dispatchDeclAttrs__anone37c897d0111::XMLDeclVisitor100   void dispatchDeclAttrs(Decl *D) {
101     DISPATCH(visitDeclAttrs, Decl);
102   }
visitDeclAttrs__anone37c897d0111::XMLDeclVisitor103   void visitDeclAttrs(Decl *D) {}
104 
dispatchDeclChildren__anone37c897d0111::XMLDeclVisitor105   void dispatchDeclChildren(Decl *D) {
106     DISPATCH(visitDeclChildren, Decl);
107   }
visitDeclChildren__anone37c897d0111::XMLDeclVisitor108   void visitDeclChildren(Decl *D) {}
109 
dispatchDeclAsContext__anone37c897d0111::XMLDeclVisitor110   void dispatchDeclAsContext(Decl *D) {
111     DISPATCH(visitDeclAsContext, Decl);
112   }
visitDeclAsContext__anone37c897d0111::XMLDeclVisitor113   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 
dispatch__anone37c897d0111::XMLTypeVisitor122   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 
dispatchTypeAttrs__anone37c897d0111::XMLTypeVisitor149   void dispatchTypeAttrs(Type *T) {
150     DISPATCH(visitTypeAttrs, Type);
151   }
visitTypeAttrs__anone37c897d0111::XMLTypeVisitor152   void visitTypeAttrs(Type *T) {}
153 
dispatchTypeChildren__anone37c897d0111::XMLTypeVisitor154   void dispatchTypeChildren(Type *T) {
155     DISPATCH(visitTypeChildren, Type);
156   }
visitTypeChildren__anone37c897d0111::XMLTypeVisitor157   void visitTypeChildren(Type *T) {}
158 
159 #undef DISPATCH
160 };
161 
getTypeKindName(Type * T)162 static 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 
173 struct 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;
XMLDumper__anone37c897d0111::XMLDumper179   explicit XMLDumper(llvm::raw_ostream &OS, ASTContext &context)
180     : out(OS), Context(context), Indent(0) {}
181 
indent__anone37c897d0111::XMLDumper182   void indent() {
183     for (unsigned I = Indent; I; --I)
184       out << ' ';
185   }
186 
187   /// Push a new node on the stack.
push__anone37c897d0111::XMLDumper188   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.
set__anone37c897d0111::XMLDumper203   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.
completeAttrs__anone37c897d0111::XMLDumper209   void completeAttrs() {
210     assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
211     Stack.back().State = NS_LazyChildren;
212   }
213 
214   /// Pop a node.
pop__anone37c897d0111::XMLDumper215   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 
setPointer__anone37c897d0111::XMLDumper229   void setPointer(llvm::StringRef prop, const 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 
setPointer__anone37c897d0111::XMLDumper237   void setPointer(void *p) {
238     setPointer("ptr", p);
239   }
240 
setInteger__anone37c897d0111::XMLDumper241   void setInteger(llvm::StringRef prop, const llvm::APSInt &v) {
242     set(prop, v.toString(10));
243   }
244 
setInteger__anone37c897d0111::XMLDumper245   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 
setFlag__anone37c897d0111::XMLDumper253   void setFlag(llvm::StringRef prop, bool flag) {
254     if (flag) set(prop, "true");
255   }
256 
setName__anone37c897d0111::XMLDumper257   void setName(DeclarationName Name) {
258     if (!Name)
259       return set("name", "");
260 
261     // Common case.
262     if (Name.isIdentifier())
263       return set("name", Name.getAsIdentifierInfo()->getName());
264 
265     set("name", Name.getAsString());
266   }
267 
268   class TemporaryContainer {
269     XMLDumper &Dumper;
270   public:
TemporaryContainer(XMLDumper & dumper,llvm::StringRef name)271     TemporaryContainer(XMLDumper &dumper, llvm::StringRef name)
272       : Dumper(dumper) {
273       Dumper.push(name);
274       Dumper.completeAttrs();
275     }
276 
~TemporaryContainer()277     ~TemporaryContainer() {
278       Dumper.pop();
279     }
280   };
281 
visitTemplateParameters__anone37c897d0111::XMLDumper282   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 
visitTemplateArguments__anone37c897d0111::XMLDumper291   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.
visitDeclRef__anone37c897d0111::XMLDumper300   void visitDeclRef(Decl *D) {
301     push(D->getDeclKindName());
302     setPointer("ref", D);
303     completeAttrs();
304     pop();
305   }
visitDeclRef__anone37c897d0111::XMLDumper306   void visitDeclRef(llvm::StringRef Name, Decl *D) {
307     TemporaryContainer C(*this, Name);
308     if (D) visitDeclRef(D);
309   }
310 
dispatch__anone37c897d0111::XMLDumper311   void dispatch(const TemplateArgument &A) {
312     switch (A.getKind()) {
313     case TemplateArgument::Null: {
314       TemporaryContainer C(*this, "null");
315       break;
316     }
317     case TemplateArgument::Type: {
318       dispatch(A.getAsType());
319       break;
320     }
321     case TemplateArgument::Template:
322     case TemplateArgument::TemplateExpansion:
323       // FIXME: Implement!
324       break;
325 
326     case TemplateArgument::Declaration: {
327       visitDeclRef(A.getAsDecl());
328       break;
329     }
330     case TemplateArgument::Integral: {
331       push("integer");
332       setInteger("value", *A.getAsIntegral());
333       completeAttrs();
334       pop();
335       break;
336     }
337     case TemplateArgument::Expression: {
338       dispatch(A.getAsExpr());
339       break;
340     }
341     case TemplateArgument::Pack: {
342       for (TemplateArgument::pack_iterator P = A.pack_begin(),
343                                         PEnd = A.pack_end();
344            P != PEnd; ++P)
345         dispatch(*P);
346       break;
347     }
348     }
349   }
350 
dispatch__anone37c897d0111::XMLDumper351   void dispatch(const TemplateArgumentLoc &A) {
352     dispatch(A.getArgument());
353   }
354 
355   //---- Declarations ------------------------------------------------//
356   // Calls are made in this order:
357   //   # Enter a new node.
358   //   push("FieldDecl")
359   //
360   //   # In this phase, attributes are set on the node.
361   //   visitDeclAttrs(D)
362   //   visitNamedDeclAttrs(D)
363   //   ...
364   //   visitFieldDeclAttrs(D)
365   //
366   //   # No more attributes after this point.
367   //   completeAttrs()
368   //
369   //   # Create "header" child nodes, i.e. those which logically
370   //   # belong to the declaration itself.
371   //   visitDeclChildren(D)
372   //   visitNamedDeclChildren(D)
373   //   ...
374   //   visitFieldDeclChildren(D)
375   //
376   //   # Create nodes for the lexical children.
377   //   visitDeclAsContext(D)
378   //   visitNamedDeclAsContext(D)
379   //   ...
380   //   visitFieldDeclAsContext(D)
381   //
382   //   # Finish the node.
383   //   pop();
dispatch__anone37c897d0111::XMLDumper384   void dispatch(Decl *D) {
385     push(D->getDeclKindName());
386     XMLDeclVisitor<XMLDumper>::dispatch(D);
387     pop();
388   }
visitDeclAttrs__anone37c897d0111::XMLDumper389   void visitDeclAttrs(Decl *D) {
390     setPointer(D);
391   }
392 
393   /// Visit all the lexical decls in the given context.
visitDeclContext__anone37c897d0111::XMLDumper394   void visitDeclContext(DeclContext *DC) {
395     for (DeclContext::decl_iterator
396            I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
397       dispatch(*I);
398 
399     // FIXME: point out visible declarations not in lexical context?
400   }
401 
402   /// Set the "access" attribute on the current node according to the
403   /// given specifier.
setAccess__anone37c897d0111::XMLDumper404   void setAccess(AccessSpecifier AS) {
405     switch (AS) {
406     case AS_public: return set("access", "public");
407     case AS_protected: return set("access", "protected");
408     case AS_private: return set("access", "private");
409     case AS_none: llvm_unreachable("explicit forbidden access");
410     }
411   }
412 
visitRedeclarableAttrs__anone37c897d0111::XMLDumper413   template <class T> void visitRedeclarableAttrs(T *D) {
414     if (T *Prev = D->getPreviousDeclaration())
415       setPointer("previous", Prev);
416   }
417 
418 
419   // TranslationUnitDecl
visitTranslationUnitDeclAsContext__anone37c897d0111::XMLDumper420   void visitTranslationUnitDeclAsContext(TranslationUnitDecl *D) {
421     visitDeclContext(D);
422   }
423 
424   // LinkageSpecDecl
visitLinkageSpecDeclAttrs__anone37c897d0111::XMLDumper425   void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) {
426     llvm::StringRef lang = "";
427     switch (D->getLanguage()) {
428     case LinkageSpecDecl::lang_c: lang = "C"; break;
429     case LinkageSpecDecl::lang_cxx: lang = "C++"; break;
430     }
431     set("lang", lang);
432   }
visitLinkageSpecDeclAsContext__anone37c897d0111::XMLDumper433   void visitLinkageSpecDeclAsContext(LinkageSpecDecl *D) {
434     visitDeclContext(D);
435   }
436 
437   // NamespaceDecl
visitNamespaceDeclAttrs__anone37c897d0111::XMLDumper438   void visitNamespaceDeclAttrs(NamespaceDecl *D) {
439     setFlag("inline", D->isInline());
440     if (!D->isOriginalNamespace())
441       setPointer("original", D->getOriginalNamespace());
442   }
visitNamespaceDeclAsContext__anone37c897d0111::XMLDumper443   void visitNamespaceDeclAsContext(NamespaceDecl *D) {
444     visitDeclContext(D);
445   }
446 
447   // NamedDecl
visitNamedDeclAttrs__anone37c897d0111::XMLDumper448   void visitNamedDeclAttrs(NamedDecl *D) {
449     setName(D->getDeclName());
450   }
451 
452   // ValueDecl
visitValueDeclChildren__anone37c897d0111::XMLDumper453   void visitValueDeclChildren(ValueDecl *D) {
454     dispatch(D->getType());
455   }
456 
457   // DeclaratorDecl
visitDeclaratorDeclChildren__anone37c897d0111::XMLDumper458   void visitDeclaratorDeclChildren(DeclaratorDecl *D) {
459     //dispatch(D->getTypeSourceInfo()->getTypeLoc());
460   }
461 
462   // VarDecl
visitVarDeclAttrs__anone37c897d0111::XMLDumper463   void visitVarDeclAttrs(VarDecl *D) {
464     visitRedeclarableAttrs(D);
465     if (D->getStorageClass() != SC_None)
466       set("storage",
467           VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
468     setFlag("directinit", D->hasCXXDirectInitializer());
469     setFlag("nrvo", D->isNRVOVariable());
470     // TODO: instantiation, etc.
471   }
visitVarDeclChildren__anone37c897d0111::XMLDumper472   void visitVarDeclChildren(VarDecl *D) {
473     if (D->hasInit()) dispatch(D->getInit());
474   }
475 
476   // ParmVarDecl?
477 
478   // FunctionDecl
visitFunctionDeclAttrs__anone37c897d0111::XMLDumper479   void visitFunctionDeclAttrs(FunctionDecl *D) {
480     visitRedeclarableAttrs(D);
481     setFlag("pure", D->isPure());
482     setFlag("trivial", D->isTrivial());
483     setFlag("returnzero", D->hasImplicitReturnZero());
484     setFlag("prototype", D->hasWrittenPrototype());
485     setFlag("deleted", D->isDeletedAsWritten());
486     if (D->getStorageClass() != SC_None)
487       set("storage",
488           VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
489     setFlag("inline", D->isInlineSpecified());
490     if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>())
491       set("asmlabel", ALA->getLabel());
492     // TODO: instantiation, etc.
493   }
visitFunctionDeclChildren__anone37c897d0111::XMLDumper494   void visitFunctionDeclChildren(FunctionDecl *D) {
495     for (FunctionDecl::param_iterator
496            I = D->param_begin(), E = D->param_end(); I != E; ++I)
497       dispatch(*I);
498     if (D->doesThisDeclarationHaveABody())
499       dispatch(D->getBody());
500   }
501 
502   // CXXMethodDecl ?
503   // CXXConstructorDecl ?
504   // CXXDestructorDecl ?
505   // CXXConversionDecl ?
506 
dispatch__anone37c897d0111::XMLDumper507   void dispatch(CXXCtorInitializer *Init) {
508     // TODO
509   }
510 
511   // FieldDecl
visitFieldDeclAttrs__anone37c897d0111::XMLDumper512   void visitFieldDeclAttrs(FieldDecl *D) {
513     setFlag("mutable", D->isMutable());
514   }
visitFieldDeclChildren__anone37c897d0111::XMLDumper515   void visitFieldDeclChildren(FieldDecl *D) {
516     if (D->isBitField()) {
517       TemporaryContainer C(*this, "bitwidth");
518       dispatch(D->getBitWidth());
519     }
520     // TODO: C++0x member initializer
521   }
522 
523   // EnumConstantDecl
visitEnumConstantDeclChildren__anone37c897d0111::XMLDumper524   void visitEnumConstantDeclChildren(EnumConstantDecl *D) {
525     // value in any case?
526     if (D->getInitExpr()) dispatch(D->getInitExpr());
527   }
528 
529   // IndirectFieldDecl
visitIndirectFieldDeclChildren__anone37c897d0111::XMLDumper530   void visitIndirectFieldDeclChildren(IndirectFieldDecl *D) {
531     for (IndirectFieldDecl::chain_iterator
532            I = D->chain_begin(), E = D->chain_end(); I != E; ++I) {
533       NamedDecl *VD = const_cast<NamedDecl*>(*I);
534       push(isa<VarDecl>(VD) ? "variable" : "field");
535       setPointer("ptr", VD);
536       completeAttrs();
537       pop();
538     }
539   }
540 
541   // TypeDecl
visitTypeDeclAttrs__anone37c897d0111::XMLDumper542   void visitTypeDeclAttrs(TypeDecl *D) {
543     setPointer("typeptr", D->getTypeForDecl());
544   }
545 
546   // TypedefDecl
visitTypedefDeclAttrs__anone37c897d0111::XMLDumper547   void visitTypedefDeclAttrs(TypedefDecl *D) {
548     visitRedeclarableAttrs<TypedefNameDecl>(D);
549   }
visitTypedefDeclChildren__anone37c897d0111::XMLDumper550   void visitTypedefDeclChildren(TypedefDecl *D) {
551     dispatch(D->getTypeSourceInfo()->getTypeLoc());
552   }
553 
554   // TypeAliasDecl
visitTypeAliasDeclAttrs__anone37c897d0111::XMLDumper555   void visitTypeAliasDeclAttrs(TypeAliasDecl *D) {
556     visitRedeclarableAttrs<TypedefNameDecl>(D);
557   }
visitTypeAliasDeclChildren__anone37c897d0111::XMLDumper558   void visitTypeAliasDeclChildren(TypeAliasDecl *D) {
559     dispatch(D->getTypeSourceInfo()->getTypeLoc());
560   }
561 
562   // TagDecl
visitTagDeclAttrs__anone37c897d0111::XMLDumper563   void visitTagDeclAttrs(TagDecl *D) {
564     visitRedeclarableAttrs(D);
565   }
visitTagDeclAsContext__anone37c897d0111::XMLDumper566   void visitTagDeclAsContext(TagDecl *D) {
567     visitDeclContext(D);
568   }
569 
570   // EnumDecl
visitEnumDeclAttrs__anone37c897d0111::XMLDumper571   void visitEnumDeclAttrs(EnumDecl *D) {
572     setFlag("scoped", D->isScoped());
573     setFlag("fixed", D->isFixed());
574   }
visitEnumDeclChildren__anone37c897d0111::XMLDumper575   void visitEnumDeclChildren(EnumDecl *D) {
576     {
577       TemporaryContainer C(*this, "promotion_type");
578       dispatch(D->getPromotionType());
579     }
580     {
581       TemporaryContainer C(*this, "integer_type");
582       dispatch(D->getIntegerType());
583     }
584   }
585 
586   // RecordDecl ?
587 
visitCXXRecordDeclChildren__anone37c897d0111::XMLDumper588   void visitCXXRecordDeclChildren(CXXRecordDecl *D) {
589     if (!D->isThisDeclarationADefinition()) return;
590 
591     for (CXXRecordDecl::base_class_iterator
592            I = D->bases_begin(), E = D->bases_end(); I != E; ++I) {
593       push("base");
594       setAccess(I->getAccessSpecifier());
595       completeAttrs();
596       dispatch(I->getTypeSourceInfo()->getTypeLoc());
597       pop();
598     }
599   }
600 
601   // ClassTemplateSpecializationDecl ?
602 
603   // FileScopeAsmDecl ?
604 
605   // BlockDecl
visitBlockDeclAttrs__anone37c897d0111::XMLDumper606   void visitBlockDeclAttrs(BlockDecl *D) {
607     setFlag("variadic", D->isVariadic());
608   }
visitBlockDeclChildren__anone37c897d0111::XMLDumper609   void visitBlockDeclChildren(BlockDecl *D) {
610     for (FunctionDecl::param_iterator
611            I = D->param_begin(), E = D->param_end(); I != E; ++I)
612       dispatch(*I);
613     dispatch(D->getBody());
614   }
615 
616   // AccessSpecDecl
visitAccessSpecDeclAttrs__anone37c897d0111::XMLDumper617   void visitAccessSpecDeclAttrs(AccessSpecDecl *D) {
618     setAccess(D->getAccess());
619   }
620 
621   // TemplateDecl
visitTemplateDeclChildren__anone37c897d0111::XMLDumper622   void visitTemplateDeclChildren(TemplateDecl *D) {
623     visitTemplateParameters(D->getTemplateParameters());
624     if (D->getTemplatedDecl())
625       dispatch(D->getTemplatedDecl());
626   }
627 
628   // FunctionTemplateDecl
visitFunctionTemplateDeclAttrs__anone37c897d0111::XMLDumper629   void visitFunctionTemplateDeclAttrs(FunctionTemplateDecl *D) {
630     visitRedeclarableAttrs(D);
631   }
visitFunctionTemplateDeclChildren__anone37c897d0111::XMLDumper632   void visitFunctionTemplateDeclChildren(FunctionTemplateDecl *D) {
633     // Mention all the specializations which don't have explicit
634     // declarations elsewhere.
635     for (FunctionTemplateDecl::spec_iterator
636            I = D->spec_begin(), E = D->spec_end(); I != E; ++I) {
637       FunctionTemplateSpecializationInfo *Info
638         = I->getTemplateSpecializationInfo();
639 
640       bool Unknown = false;
641       switch (Info->getTemplateSpecializationKind()) {
642       case TSK_ImplicitInstantiation: Unknown = false; break;
643       case TSK_Undeclared: Unknown = true; break;
644 
645       // These will be covered at their respective sites.
646       case TSK_ExplicitSpecialization: continue;
647       case TSK_ExplicitInstantiationDeclaration: continue;
648       case TSK_ExplicitInstantiationDefinition: continue;
649       }
650 
651       TemporaryContainer C(*this,
652                            Unknown ? "uninstantiated" : "instantiation");
653       visitTemplateArguments(*Info->TemplateArguments);
654       dispatch(Info->Function);
655     }
656   }
657 
658   // ClasTemplateDecl
visitClassTemplateDeclAttrs__anone37c897d0111::XMLDumper659   void visitClassTemplateDeclAttrs(ClassTemplateDecl *D) {
660     visitRedeclarableAttrs(D);
661   }
visitClassTemplateDeclChildren__anone37c897d0111::XMLDumper662   void visitClassTemplateDeclChildren(ClassTemplateDecl *D) {
663     // Mention all the specializations which don't have explicit
664     // declarations elsewhere.
665     for (ClassTemplateDecl::spec_iterator
666            I = D->spec_begin(), E = D->spec_end(); I != E; ++I) {
667 
668       bool Unknown = false;
669       switch (I->getTemplateSpecializationKind()) {
670       case TSK_ImplicitInstantiation: Unknown = false; break;
671       case TSK_Undeclared: Unknown = true; break;
672 
673       // These will be covered at their respective sites.
674       case TSK_ExplicitSpecialization: continue;
675       case TSK_ExplicitInstantiationDeclaration: continue;
676       case TSK_ExplicitInstantiationDefinition: continue;
677       }
678 
679       TemporaryContainer C(*this,
680                            Unknown ? "uninstantiated" : "instantiation");
681       visitTemplateArguments(I->getTemplateArgs());
682       dispatch(*I);
683     }
684   }
685 
686   // TemplateTypeParmDecl
visitTemplateTypeParmDeclAttrs__anone37c897d0111::XMLDumper687   void visitTemplateTypeParmDeclAttrs(TemplateTypeParmDecl *D) {
688     setInteger("depth", D->getDepth());
689     setInteger("index", D->getIndex());
690   }
visitTemplateTypeParmDeclChildren__anone37c897d0111::XMLDumper691   void visitTemplateTypeParmDeclChildren(TemplateTypeParmDecl *D) {
692     if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
693       dispatch(D->getDefaultArgumentInfo()->getTypeLoc());
694     // parameter pack?
695   }
696 
697   // NonTypeTemplateParmDecl
visitNonTypeTemplateParmDeclAttrs__anone37c897d0111::XMLDumper698   void visitNonTypeTemplateParmDeclAttrs(NonTypeTemplateParmDecl *D) {
699     setInteger("depth", D->getDepth());
700     setInteger("index", D->getIndex());
701   }
visitNonTypeTemplateParmDeclChildren__anone37c897d0111::XMLDumper702   void visitNonTypeTemplateParmDeclChildren(NonTypeTemplateParmDecl *D) {
703     if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
704       dispatch(D->getDefaultArgument());
705     // parameter pack?
706   }
707 
708   // TemplateTemplateParmDecl
visitTemplateTemplateParmDeclAttrs__anone37c897d0111::XMLDumper709   void visitTemplateTemplateParmDeclAttrs(TemplateTemplateParmDecl *D) {
710     setInteger("depth", D->getDepth());
711     setInteger("index", D->getIndex());
712   }
visitTemplateTemplateParmDeclChildren__anone37c897d0111::XMLDumper713   void visitTemplateTemplateParmDeclChildren(TemplateTemplateParmDecl *D) {
714     if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
715       dispatch(D->getDefaultArgument());
716     // parameter pack?
717   }
718 
719   // FriendDecl
visitFriendDeclChildren__anone37c897d0111::XMLDumper720   void visitFriendDeclChildren(FriendDecl *D) {
721     if (TypeSourceInfo *T = D->getFriendType())
722       dispatch(T->getTypeLoc());
723     else
724       dispatch(D->getFriendDecl());
725   }
726 
727   // UsingDirectiveDecl ?
728   // UsingDecl ?
729   // UsingShadowDecl ?
730   // NamespaceAliasDecl ?
731   // UnresolvedUsingValueDecl ?
732   // UnresolvedUsingTypenameDecl ?
733   // StaticAssertDecl ?
734 
735   // ObjCImplDecl
visitObjCImplDeclChildren__anone37c897d0111::XMLDumper736   void visitObjCImplDeclChildren(ObjCImplDecl *D) {
737     visitDeclRef(D->getClassInterface());
738   }
visitObjCImplDeclAsContext__anone37c897d0111::XMLDumper739   void visitObjCImplDeclAsContext(ObjCImplDecl *D) {
740     visitDeclContext(D);
741   }
742 
743   // ObjCClassDecl
visitObjCClassDeclChildren__anone37c897d0111::XMLDumper744   void visitObjCClassDeclChildren(ObjCClassDecl *D) {
745     for (ObjCClassDecl::iterator I = D->begin(), E = D->end(); I != E; ++I)
746       visitDeclRef(I->getInterface());
747   }
748 
749   // ObjCInterfaceDecl
visitCategoryList__anone37c897d0111::XMLDumper750   void visitCategoryList(ObjCCategoryDecl *D) {
751     if (!D) return;
752 
753     TemporaryContainer C(*this, "categories");
754     for (; D; D = D->getNextClassCategory())
755       visitDeclRef(D);
756   }
visitObjCInterfaceDeclAttrs__anone37c897d0111::XMLDumper757   void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) {
758     setPointer("typeptr", D->getTypeForDecl());
759     setFlag("forward_decl", D->isForwardDecl());
760     setFlag("implicit_interface", D->isImplicitInterfaceDecl());
761   }
visitObjCInterfaceDeclChildren__anone37c897d0111::XMLDumper762   void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) {
763     visitDeclRef("super", D->getSuperClass());
764     visitDeclRef("implementation", D->getImplementation());
765     if (D->protocol_begin() != D->protocol_end()) {
766       TemporaryContainer C(*this, "protocols");
767       for (ObjCInterfaceDecl::protocol_iterator
768              I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
769         visitDeclRef(*I);
770     }
771     visitCategoryList(D->getCategoryList());
772   }
visitObjCInterfaceDeclAsContext__anone37c897d0111::XMLDumper773   void visitObjCInterfaceDeclAsContext(ObjCInterfaceDecl *D) {
774     visitDeclContext(D);
775   }
776 
777   // ObjCCategoryDecl
visitObjCCategoryDeclAttrs__anone37c897d0111::XMLDumper778   void visitObjCCategoryDeclAttrs(ObjCCategoryDecl *D) {
779     setFlag("extension", D->IsClassExtension());
780     setFlag("synth_bitfield", D->hasSynthBitfield());
781   }
visitObjCCategoryDeclChildren__anone37c897d0111::XMLDumper782   void visitObjCCategoryDeclChildren(ObjCCategoryDecl *D) {
783     visitDeclRef("interface", D->getClassInterface());
784     visitDeclRef("implementation", D->getImplementation());
785     if (D->protocol_begin() != D->protocol_end()) {
786       TemporaryContainer C(*this, "protocols");
787       for (ObjCCategoryDecl::protocol_iterator
788              I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
789         visitDeclRef(*I);
790     }
791   }
visitObjCCategoryDeclAsContext__anone37c897d0111::XMLDumper792   void visitObjCCategoryDeclAsContext(ObjCCategoryDecl *D) {
793     visitDeclContext(D);
794   }
795 
796   // ObjCCategoryImplDecl
visitObjCCategoryImplDeclAttrs__anone37c897d0111::XMLDumper797   void visitObjCCategoryImplDeclAttrs(ObjCCategoryImplDecl *D) {
798     set("identifier", D->getName());
799   }
visitObjCCategoryImplDeclChildren__anone37c897d0111::XMLDumper800   void visitObjCCategoryImplDeclChildren(ObjCCategoryImplDecl *D) {
801     visitDeclRef(D->getCategoryDecl());
802   }
803 
804   // ObjCImplementationDecl
visitObjCImplementationDeclAttrs__anone37c897d0111::XMLDumper805   void visitObjCImplementationDeclAttrs(ObjCImplementationDecl *D) {
806     setFlag("synth_bitfield", D->hasSynthBitfield());
807     set("identifier", D->getName());
808   }
visitObjCImplementationDeclChildren__anone37c897d0111::XMLDumper809   void visitObjCImplementationDeclChildren(ObjCImplementationDecl *D) {
810     visitDeclRef("super", D->getSuperClass());
811     if (D->init_begin() != D->init_end()) {
812       TemporaryContainer C(*this, "initializers");
813       for (ObjCImplementationDecl::init_iterator
814              I = D->init_begin(), E = D->init_end(); I != E; ++I)
815         dispatch(*I);
816     }
817   }
818 
819   // ObjCForwardProtocolDecl
visitObjCForwardProtocolDeclChildren__anone37c897d0111::XMLDumper820   void visitObjCForwardProtocolDeclChildren(ObjCForwardProtocolDecl *D) {
821     for (ObjCForwardProtocolDecl::protocol_iterator
822            I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
823       visitDeclRef(*I);
824   }
825 
826   // ObjCProtocolDecl
visitObjCProtocolDeclAttrs__anone37c897d0111::XMLDumper827   void visitObjCProtocolDeclAttrs(ObjCProtocolDecl *D) {
828     setFlag("forward_decl", D->isForwardDecl());
829   }
visitObjCProtocolDeclChildren__anone37c897d0111::XMLDumper830   void visitObjCProtocolDeclChildren(ObjCProtocolDecl *D) {
831     if (D->protocol_begin() != D->protocol_end()) {
832       TemporaryContainer C(*this, "protocols");
833       for (ObjCInterfaceDecl::protocol_iterator
834              I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
835         visitDeclRef(*I);
836     }
837   }
visitObjCProtocolDeclAsContext__anone37c897d0111::XMLDumper838   void visitObjCProtocolDeclAsContext(ObjCProtocolDecl *D) {
839     visitDeclContext(D);
840   }
841 
842   // ObjCMethodDecl
visitObjCMethodDeclAttrs__anone37c897d0111::XMLDumper843   void visitObjCMethodDeclAttrs(ObjCMethodDecl *D) {
844     // decl qualifier?
845     // implementation control?
846 
847     setFlag("instance", D->isInstanceMethod());
848     setFlag("variadic", D->isVariadic());
849     setFlag("synthesized", D->isSynthesized());
850     setFlag("defined", D->isDefined());
851     setFlag("related_result_type", D->hasRelatedResultType());
852   }
visitObjCMethodDeclChildren__anone37c897d0111::XMLDumper853   void visitObjCMethodDeclChildren(ObjCMethodDecl *D) {
854     dispatch(D->getResultType());
855     for (ObjCMethodDecl::param_iterator
856            I = D->param_begin(), E = D->param_end(); I != E; ++I)
857       dispatch(*I);
858     if (D->isThisDeclarationADefinition())
859       dispatch(D->getBody());
860   }
861 
862   // ObjCIvarDecl
setAccessControl__anone37c897d0111::XMLDumper863   void setAccessControl(llvm::StringRef prop, ObjCIvarDecl::AccessControl AC) {
864     switch (AC) {
865     case ObjCIvarDecl::None: return set(prop, "none");
866     case ObjCIvarDecl::Private: return set(prop, "private");
867     case ObjCIvarDecl::Protected: return set(prop, "protected");
868     case ObjCIvarDecl::Public: return set(prop, "public");
869     case ObjCIvarDecl::Package: return set(prop, "package");
870     }
871   }
visitObjCIvarDeclAttrs__anone37c897d0111::XMLDumper872   void visitObjCIvarDeclAttrs(ObjCIvarDecl *D) {
873     setFlag("synthesize", D->getSynthesize());
874     setAccessControl("access", D->getAccessControl());
875   }
876 
877   // ObjCCompatibleAliasDecl
visitObjCCompatibleAliasDeclChildren__anone37c897d0111::XMLDumper878   void visitObjCCompatibleAliasDeclChildren(ObjCCompatibleAliasDecl *D) {
879     visitDeclRef(D->getClassInterface());
880   }
881 
882   // FIXME: ObjCPropertyDecl
883   // FIXME: ObjCPropertyImplDecl
884 
885   //---- Types -----------------------------------------------------//
dispatch__anone37c897d0111::XMLDumper886   void dispatch(TypeLoc TL) {
887     dispatch(TL.getType()); // for now
888   }
889 
dispatch__anone37c897d0111::XMLDumper890   void dispatch(QualType T) {
891     if (T.hasLocalQualifiers()) {
892       push("QualType");
893       Qualifiers Qs = T.getLocalQualifiers();
894       setFlag("const", Qs.hasConst());
895       setFlag("volatile", Qs.hasVolatile());
896       setFlag("restrict", Qs.hasRestrict());
897       if (Qs.hasAddressSpace()) setInteger("addrspace", Qs.getAddressSpace());
898       if (Qs.hasObjCGCAttr()) {
899         switch (Qs.getObjCGCAttr()) {
900         case Qualifiers::Weak: set("gc", "weak"); break;
901         case Qualifiers::Strong: set("gc", "strong"); break;
902         case Qualifiers::GCNone: llvm_unreachable("explicit none");
903         }
904       }
905 
906       completeAttrs();
907       dispatch(QualType(T.getTypePtr(), 0));
908       pop();
909       return;
910     }
911 
912     Type *Ty = const_cast<Type*>(T.getTypePtr());
913     push(getTypeKindName(Ty));
914     XMLTypeVisitor<XMLDumper>::dispatch(const_cast<Type*>(T.getTypePtr()));
915     pop();
916   }
917 
setCallingConv__anone37c897d0111::XMLDumper918   void setCallingConv(CallingConv CC) {
919     switch (CC) {
920     case CC_Default: return;
921     case CC_C: return set("cc", "cdecl");
922     case CC_X86FastCall: return set("cc", "x86_fastcall");
923     case CC_X86StdCall: return set("cc", "x86_stdcall");
924     case CC_X86ThisCall: return set("cc", "x86_thiscall");
925     case CC_X86Pascal: return set("cc", "x86_pascal");
926     case CC_AAPCS: return set("cc", "aapcs");
927     case CC_AAPCS_VFP: return set("cc", "aapcs_vfp");
928     }
929   }
930 
visitTypeAttrs__anone37c897d0111::XMLDumper931   void visitTypeAttrs(Type *D) {
932     setPointer(D);
933     setFlag("dependent", D->isDependentType());
934     setFlag("variably_modified", D->isVariablyModifiedType());
935 
936     setPointer("canonical", D->getCanonicalTypeInternal().getAsOpaquePtr());
937   }
938 
visitPointerTypeChildren__anone37c897d0111::XMLDumper939   void visitPointerTypeChildren(PointerType *T) {
940     dispatch(T->getPointeeType());
941   }
visitReferenceTypeChildren__anone37c897d0111::XMLDumper942   void visitReferenceTypeChildren(ReferenceType *T) {
943     dispatch(T->getPointeeType());
944   }
visitObjCObjectPointerTypeChildren__anone37c897d0111::XMLDumper945   void visitObjCObjectPointerTypeChildren(ObjCObjectPointerType *T) {
946     dispatch(T->getPointeeType());
947   }
visitBlockPointerTypeChildren__anone37c897d0111::XMLDumper948   void visitBlockPointerTypeChildren(BlockPointerType *T) {
949     dispatch(T->getPointeeType());
950   }
951 
952   // Types that just wrap declarations.
visitTagTypeChildren__anone37c897d0111::XMLDumper953   void visitTagTypeChildren(TagType *T) {
954     visitDeclRef(T->getDecl());
955   }
visitTypedefTypeChildren__anone37c897d0111::XMLDumper956   void visitTypedefTypeChildren(TypedefType *T) {
957     visitDeclRef(T->getDecl());
958   }
visitObjCInterfaceTypeChildren__anone37c897d0111::XMLDumper959   void visitObjCInterfaceTypeChildren(ObjCInterfaceType *T) {
960     visitDeclRef(T->getDecl());
961   }
visitUnresolvedUsingTypeChildren__anone37c897d0111::XMLDumper962   void visitUnresolvedUsingTypeChildren(UnresolvedUsingType *T) {
963     visitDeclRef(T->getDecl());
964   }
visitInjectedClassNameTypeChildren__anone37c897d0111::XMLDumper965   void visitInjectedClassNameTypeChildren(InjectedClassNameType *T) {
966     visitDeclRef(T->getDecl());
967   }
968 
visitFunctionTypeAttrs__anone37c897d0111::XMLDumper969   void visitFunctionTypeAttrs(FunctionType *T) {
970     setFlag("noreturn", T->getNoReturnAttr());
971     setCallingConv(T->getCallConv());
972     if (T->getHasRegParm()) setInteger("regparm", T->getRegParmType());
973   }
visitFunctionTypeChildren__anone37c897d0111::XMLDumper974   void visitFunctionTypeChildren(FunctionType *T) {
975     dispatch(T->getResultType());
976   }
977 
visitFunctionProtoTypeAttrs__anone37c897d0111::XMLDumper978   void visitFunctionProtoTypeAttrs(FunctionProtoType *T) {
979     setFlag("const", T->getTypeQuals() & Qualifiers::Const);
980     setFlag("volatile", T->getTypeQuals() & Qualifiers::Volatile);
981     setFlag("restrict", T->getTypeQuals() & Qualifiers::Restrict);
982   }
visitFunctionProtoTypeChildren__anone37c897d0111::XMLDumper983   void visitFunctionProtoTypeChildren(FunctionProtoType *T) {
984     push("parameters");
985     setFlag("variadic", T->isVariadic());
986     completeAttrs();
987     for (FunctionProtoType::arg_type_iterator
988            I = T->arg_type_begin(), E = T->arg_type_end(); I != E; ++I)
989       dispatch(*I);
990     pop();
991 
992     if (T->hasDynamicExceptionSpec()) {
993       push("exception_specifiers");
994       setFlag("any", T->getExceptionSpecType() == EST_MSAny);
995       completeAttrs();
996       for (FunctionProtoType::exception_iterator
997              I = T->exception_begin(), E = T->exception_end(); I != E; ++I)
998         dispatch(*I);
999       pop();
1000     }
1001     // FIXME: noexcept specifier
1002   }
1003 
visitTemplateSpecializationTypeChildren__anone37c897d0111::XMLDumper1004   void visitTemplateSpecializationTypeChildren(TemplateSpecializationType *T) {
1005     if (const RecordType *RT = T->getAs<RecordType>())
1006       visitDeclRef(RT->getDecl());
1007 
1008     // TODO: TemplateName
1009 
1010     push("template_arguments");
1011     completeAttrs();
1012     for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I)
1013       dispatch(T->getArg(I));
1014     pop();
1015   }
1016 
1017   //---- Statements ------------------------------------------------//
dispatch__anone37c897d0111::XMLDumper1018   void dispatch(Stmt *S) {
1019     // FIXME: this is not really XML at all
1020     push("Stmt");
1021     out << ">\n";
1022     Stack.back().State = NS_Children; // explicitly become non-lazy
1023     S->dump(out, Context.getSourceManager());
1024     out << '\n';
1025     pop();
1026   }
1027 };
1028 }
1029 
dumpXML() const1030 void Decl::dumpXML() const {
1031   dumpXML(llvm::errs());
1032 }
1033 
dumpXML(llvm::raw_ostream & out) const1034 void Decl::dumpXML(llvm::raw_ostream &out) const {
1035   XMLDumper(out, getASTContext()).dispatch(const_cast<Decl*>(this));
1036 }
1037 
1038 #else /* ifndef NDEBUG */
1039 
dumpXML() const1040 void Decl::dumpXML() const {}
dumpXML(llvm::raw_ostream & out) const1041 void Decl::dumpXML(llvm::raw_ostream &out) const {}
1042 
1043 #endif
1044