]> git.proxmox.com Git - rustc.git/blame - src/llvm/tools/clang/lib/AST/DumpXML.cpp
Imported Upstream version 0.6
[rustc.git] / src / llvm / tools / clang / lib / AST / DumpXML.cpp
CommitLineData
223e47cc
LB
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
44using namespace clang;
45
46#ifndef NDEBUG
47
48namespace {
49
50enum NodeState {
51 NS_Attrs, NS_LazyChildren, NS_Children
52};
53
54struct 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
62template <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 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
98 void dispatchDeclAttrs(Decl *D) {
99 DISPATCH(visitDeclAttrs, Decl);
100 }
101 void visitDeclAttrs(Decl *D) {}
102
103 void dispatchDeclChildren(Decl *D) {
104 DISPATCH(visitDeclChildren, Decl);
105 }
106 void visitDeclChildren(Decl *D) {}
107
108 void dispatchDeclAsContext(Decl *D) {
109 DISPATCH(visitDeclAsContext, Decl);
110 }
111 void visitDeclAsContext(Decl *D) {}
112
113#undef DISPATCH
114};
115
116template <class Impl> struct XMLTypeVisitor {
117#define DISPATCH(NAME, CLASS) \
118 static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(T))
119
120 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
146 void dispatchTypeAttrs(Type *T) {
147 DISPATCH(visitTypeAttrs, Type);
148 }
149 void visitTypeAttrs(Type *T) {}
150
151 void dispatchTypeChildren(Type *T) {
152 DISPATCH(visitTypeChildren, Type);
153 }
154 void visitTypeChildren(Type *T) {}
155
156#undef DISPATCH
157};
158
159static 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
169struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
170 public XMLTypeVisitor<XMLDumper> {
171 raw_ostream &out;
172 ASTContext &Context;
173 SmallVector<Node, 16> Stack;
174 unsigned Indent;
175 explicit XMLDumper(raw_ostream &OS, ASTContext &context)
176 : out(OS), Context(context), Indent(0) {}
177
178 void indent() {
179 for (unsigned I = Indent; I; --I)
180 out << ' ';
181 }
182
183 /// Push a new node on the stack.
184 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.
199 void set(StringRef attr, StringRef value) {
200 assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
201 out << ' ' << attr << '=' << '"' << value << '"'; // TODO: quotation
202 }
203
204 /// Finish attributes.
205 void completeAttrs() {
206 assert(!Stack.empty() && !Stack.back().isDoneWithAttrs());
207 Stack.back().State = NS_LazyChildren;
208 }
209
210 /// Pop a node.
211 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
225 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
233 void setPointer(void *p) {
234 setPointer("ptr", p);
235 }
236
237 void setInteger(StringRef prop, const llvm::APSInt &v) {
238 set(prop, v.toString(10));
239 }
240
241 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
249 void setFlag(StringRef prop, bool flag) {
250 if (flag) set(prop, "true");
251 }
252
253 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:
267 TemporaryContainer(XMLDumper &dumper, StringRef name)
268 : Dumper(dumper) {
269 Dumper.push(name);
270 Dumper.completeAttrs();
271 }
272
273 ~TemporaryContainer() {
274 Dumper.pop();
275 }
276 };
277
278 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
287 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.
296 void visitDeclRef(Decl *D) {
297 push(D->getDeclKindName());
298 setPointer("ref", D);
299 completeAttrs();
300 pop();
301 }
302 void visitDeclRef(StringRef Name, Decl *D) {
303 TemporaryContainer C(*this, Name);
304 if (D) visitDeclRef(D);
305 }
306
307 void dispatch(const TemplateArgument &A) {
308 switch (A.getKind()) {
309 case TemplateArgument::Null: {
310 TemporaryContainer C(*this, "null");
311 break;
312 }
313 case TemplateArgument::Type: {
314 dispatch(A.getAsType());
315 break;
316 }
317 case TemplateArgument::Template:
318 case TemplateArgument::TemplateExpansion:
319 case TemplateArgument::NullPtr:
320 // FIXME: Implement!
321 break;
322
323 case TemplateArgument::Declaration: {
324 visitDeclRef(A.getAsDecl());
325 break;
326 }
327 case TemplateArgument::Integral: {
328 push("integer");
329 setInteger("value", A.getAsIntegral());
330 completeAttrs();
331 pop();
332 break;
333 }
334 case TemplateArgument::Expression: {
335 dispatch(A.getAsExpr());
336 break;
337 }
338 case TemplateArgument::Pack: {
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
348 void dispatch(const TemplateArgumentLoc &A) {
349 dispatch(A.getArgument());
350 }
351
352 //---- Declarations ------------------------------------------------//
353 // Calls are made in this order:
354 // # Enter a new node.
355 // push("FieldDecl")
356 //
357 // # In this phase, attributes are set on the node.
358 // visitDeclAttrs(D)
359 // visitNamedDeclAttrs(D)
360 // ...
361 // visitFieldDeclAttrs(D)
362 //
363 // # No more attributes after this point.
364 // completeAttrs()
365 //
366 // # Create "header" child nodes, i.e. those which logically
367 // # belong to the declaration itself.
368 // visitDeclChildren(D)
369 // visitNamedDeclChildren(D)
370 // ...
371 // visitFieldDeclChildren(D)
372 //
373 // # Create nodes for the lexical children.
374 // visitDeclAsContext(D)
375 // visitNamedDeclAsContext(D)
376 // ...
377 // visitFieldDeclAsContext(D)
378 //
379 // # Finish the node.
380 // pop();
381 void dispatch(Decl *D) {
382 push(D->getDeclKindName());
383 XMLDeclVisitor<XMLDumper>::dispatch(D);
384 pop();
385 }
386 void visitDeclAttrs(Decl *D) {
387 setPointer(D);
388 }
389
390 /// Visit all the lexical decls in the given context.
391 void visitDeclContext(DeclContext *DC) {
392 for (DeclContext::decl_iterator
393 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
394 dispatch(*I);
395
396 // FIXME: point out visible declarations not in lexical context?
397 }
398
399 /// Set the "access" attribute on the current node according to the
400 /// given specifier.
401 void setAccess(AccessSpecifier AS) {
402 switch (AS) {
403 case AS_public: return set("access", "public");
404 case AS_protected: return set("access", "protected");
405 case AS_private: return set("access", "private");
406 case AS_none: llvm_unreachable("explicit forbidden access");
407 }
408 }
409
410 template <class T> void visitRedeclarableAttrs(T *D) {
411 if (T *Prev = D->getPreviousDecl())
412 setPointer("previous", Prev);
413 }
414
415
416 // TranslationUnitDecl
417 void visitTranslationUnitDeclAsContext(TranslationUnitDecl *D) {
418 visitDeclContext(D);
419 }
420
421 // LinkageSpecDecl
422 void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) {
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 }
430 void visitLinkageSpecDeclAsContext(LinkageSpecDecl *D) {
431 visitDeclContext(D);
432 }
433
434 // NamespaceDecl
435 void visitNamespaceDeclAttrs(NamespaceDecl *D) {
436 setFlag("inline", D->isInline());
437 if (!D->isOriginalNamespace())
438 setPointer("original", D->getOriginalNamespace());
439 }
440 void visitNamespaceDeclAsContext(NamespaceDecl *D) {
441 visitDeclContext(D);
442 }
443
444 // NamedDecl
445 void visitNamedDeclAttrs(NamedDecl *D) {
446 setName(D->getDeclName());
447 }
448
449 // ValueDecl
450 void visitValueDeclChildren(ValueDecl *D) {
451 dispatch(D->getType());
452 }
453
454 // DeclaratorDecl
455 void visitDeclaratorDeclChildren(DeclaratorDecl *D) {
456 //dispatch(D->getTypeSourceInfo()->getTypeLoc());
457 }
458
459 // VarDecl
460 void visitVarDeclAttrs(VarDecl *D) {
461 visitRedeclarableAttrs(D);
462 if (D->getStorageClass() != SC_None)
463 set("storage",
464 VarDecl::getStorageClassSpecifierString(D->getStorageClass()));
465 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 }
475 void visitVarDeclChildren(VarDecl *D) {
476 if (D->hasInit()) dispatch(D->getInit());
477 }
478
479 // ParmVarDecl?
480
481 // FunctionDecl
482 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 }
497 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
514 void dispatch(CXXCtorInitializer *Init) {
515 // TODO
516 }
517
518 // FieldDecl
519 void visitFieldDeclAttrs(FieldDecl *D) {
520 setFlag("mutable", D->isMutable());
521 }
522 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
531 void visitEnumConstantDeclChildren(EnumConstantDecl *D) {
532 // value in any case?
533 if (D->getInitExpr()) dispatch(D->getInitExpr());
534 }
535
536 // IndirectFieldDecl
537 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
549 void visitTypeDeclAttrs(TypeDecl *D) {
550 setPointer("typeptr", D->getTypeForDecl());
551 }
552
553 // TypedefDecl
554 void visitTypedefDeclAttrs(TypedefDecl *D) {
555 visitRedeclarableAttrs<TypedefNameDecl>(D);
556 }
557 void visitTypedefDeclChildren(TypedefDecl *D) {
558 dispatch(D->getTypeSourceInfo()->getTypeLoc());
559 }
560
561 // TypeAliasDecl
562 void visitTypeAliasDeclAttrs(TypeAliasDecl *D) {
563 visitRedeclarableAttrs<TypedefNameDecl>(D);
564 }
565 void visitTypeAliasDeclChildren(TypeAliasDecl *D) {
566 dispatch(D->getTypeSourceInfo()->getTypeLoc());
567 }
568
569 // TagDecl
570 void visitTagDeclAttrs(TagDecl *D) {
571 visitRedeclarableAttrs(D);
572 }
573 void visitTagDeclAsContext(TagDecl *D) {
574 visitDeclContext(D);
575 }
576
577 // EnumDecl
578 void visitEnumDeclAttrs(EnumDecl *D) {
579 setFlag("scoped", D->isScoped());
580 setFlag("fixed", D->isFixed());
581 }
582 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
595 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
613 void visitBlockDeclAttrs(BlockDecl *D) {
614 setFlag("variadic", D->isVariadic());
615 }
616 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
624 void visitAccessSpecDeclAttrs(AccessSpecDecl *D) {
625 setAccess(D->getAccess());
626 }
627
628 // TemplateDecl
629 void visitTemplateDeclChildren(TemplateDecl *D) {
630 visitTemplateParameters(D->getTemplateParameters());
631 if (D->getTemplatedDecl())
632 dispatch(D->getTemplatedDecl());
633 }
634
635 // FunctionTemplateDecl
636 void visitFunctionTemplateDeclAttrs(FunctionTemplateDecl *D) {
637 visitRedeclarableAttrs(D);
638 }
639 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
666 void visitClassTemplateDeclAttrs(ClassTemplateDecl *D) {
667 visitRedeclarableAttrs(D);
668 }
669 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
694 void visitTemplateTypeParmDeclAttrs(TemplateTypeParmDecl *D) {
695 setInteger("depth", D->getDepth());
696 setInteger("index", D->getIndex());
697 }
698 void visitTemplateTypeParmDeclChildren(TemplateTypeParmDecl *D) {
699 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
700 dispatch(D->getDefaultArgumentInfo()->getTypeLoc());
701 // parameter pack?
702 }
703
704 // NonTypeTemplateParmDecl
705 void visitNonTypeTemplateParmDeclAttrs(NonTypeTemplateParmDecl *D) {
706 setInteger("depth", D->getDepth());
707 setInteger("index", D->getIndex());
708 }
709 void visitNonTypeTemplateParmDeclChildren(NonTypeTemplateParmDecl *D) {
710 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
711 dispatch(D->getDefaultArgument());
712 // parameter pack?
713 }
714
715 // TemplateTemplateParmDecl
716 void visitTemplateTemplateParmDeclAttrs(TemplateTemplateParmDecl *D) {
717 setInteger("depth", D->getDepth());
718 setInteger("index", D->getIndex());
719 }
720 void visitTemplateTemplateParmDeclChildren(TemplateTemplateParmDecl *D) {
721 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited())
722 dispatch(D->getDefaultArgument());
723 // parameter pack?
724 }
725
726 // FriendDecl
727 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
743 void visitObjCImplDeclChildren(ObjCImplDecl *D) {
744 visitDeclRef(D->getClassInterface());
745 }
746 void visitObjCImplDeclAsContext(ObjCImplDecl *D) {
747 visitDeclContext(D);
748 }
749
750 // ObjCInterfaceDecl
751 void visitCategoryList(ObjCCategoryDecl *D) {
752 if (!D) return;
753
754 TemporaryContainer C(*this, "categories");
755 for (; D; D = D->getNextClassCategory())
756 visitDeclRef(D);
757 }
758 void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) {
759 setPointer("typeptr", D->getTypeForDecl());
760 setFlag("forward_decl", !D->isThisDeclarationADefinition());
761 setFlag("implicit_interface", D->isImplicitInterfaceDecl());
762 }
763 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 }
774 void visitObjCInterfaceDeclAsContext(ObjCInterfaceDecl *D) {
775 visitDeclContext(D);
776 }
777
778 // ObjCCategoryDecl
779 void visitObjCCategoryDeclAttrs(ObjCCategoryDecl *D) {
780 setFlag("extension", D->IsClassExtension());
781 }
782 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 }
792 void visitObjCCategoryDeclAsContext(ObjCCategoryDecl *D) {
793 visitDeclContext(D);
794 }
795
796 // ObjCCategoryImplDecl
797 void visitObjCCategoryImplDeclAttrs(ObjCCategoryImplDecl *D) {
798 set("identifier", D->getName());
799 }
800 void visitObjCCategoryImplDeclChildren(ObjCCategoryImplDecl *D) {
801 visitDeclRef(D->getCategoryDecl());
802 }
803
804 // ObjCImplementationDecl
805 void visitObjCImplementationDeclAttrs(ObjCImplementationDecl *D) {
806 set("identifier", D->getName());
807 }
808 void visitObjCImplementationDeclChildren(ObjCImplementationDecl *D) {
809 visitDeclRef("super", D->getSuperClass());
810 if (D->init_begin() != D->init_end()) {
811 TemporaryContainer C(*this, "initializers");
812 for (ObjCImplementationDecl::init_iterator
813 I = D->init_begin(), E = D->init_end(); I != E; ++I)
814 dispatch(*I);
815 }
816 }
817
818 // ObjCProtocolDecl
819 void visitObjCProtocolDeclChildren(ObjCProtocolDecl *D) {
820 if (!D->isThisDeclarationADefinition())
821 return;
822
823 if (D->protocol_begin() != D->protocol_end()) {
824 TemporaryContainer C(*this, "protocols");
825 for (ObjCInterfaceDecl::protocol_iterator
826 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I)
827 visitDeclRef(*I);
828 }
829 }
830 void visitObjCProtocolDeclAsContext(ObjCProtocolDecl *D) {
831 if (!D->isThisDeclarationADefinition())
832 return;
833
834 visitDeclContext(D);
835 }
836
837 // ObjCMethodDecl
838 void visitObjCMethodDeclAttrs(ObjCMethodDecl *D) {
839 // decl qualifier?
840 // implementation control?
841
842 setFlag("instance", D->isInstanceMethod());
843 setFlag("variadic", D->isVariadic());
844 setFlag("synthesized", D->isSynthesized());
845 setFlag("defined", D->isDefined());
846 setFlag("related_result_type", D->hasRelatedResultType());
847 }
848 void visitObjCMethodDeclChildren(ObjCMethodDecl *D) {
849 dispatch(D->getResultType());
850 for (ObjCMethodDecl::param_iterator
851 I = D->param_begin(), E = D->param_end(); I != E; ++I)
852 dispatch(*I);
853 if (D->isThisDeclarationADefinition())
854 dispatch(D->getBody());
855 }
856
857 // ObjCIvarDecl
858 void setAccessControl(StringRef prop, ObjCIvarDecl::AccessControl AC) {
859 switch (AC) {
860 case ObjCIvarDecl::None: return set(prop, "none");
861 case ObjCIvarDecl::Private: return set(prop, "private");
862 case ObjCIvarDecl::Protected: return set(prop, "protected");
863 case ObjCIvarDecl::Public: return set(prop, "public");
864 case ObjCIvarDecl::Package: return set(prop, "package");
865 }
866 }
867 void visitObjCIvarDeclAttrs(ObjCIvarDecl *D) {
868 setFlag("synthesize", D->getSynthesize());
869 setAccessControl("access", D->getAccessControl());
870 }
871
872 // ObjCCompatibleAliasDecl
873 void visitObjCCompatibleAliasDeclChildren(ObjCCompatibleAliasDecl *D) {
874 visitDeclRef(D->getClassInterface());
875 }
876
877 // FIXME: ObjCPropertyDecl
878 // FIXME: ObjCPropertyImplDecl
879
880 //---- Types -----------------------------------------------------//
881 void dispatch(TypeLoc TL) {
882 dispatch(TL.getType()); // for now
883 }
884
885 void dispatch(QualType T) {
886 if (T.hasLocalQualifiers()) {
887 push("QualType");
888 Qualifiers Qs = T.getLocalQualifiers();
889 setFlag("const", Qs.hasConst());
890 setFlag("volatile", Qs.hasVolatile());
891 setFlag("restrict", Qs.hasRestrict());
892 if (Qs.hasAddressSpace()) setInteger("addrspace", Qs.getAddressSpace());
893 if (Qs.hasObjCGCAttr()) {
894 switch (Qs.getObjCGCAttr()) {
895 case Qualifiers::Weak: set("gc", "weak"); break;
896 case Qualifiers::Strong: set("gc", "strong"); break;
897 case Qualifiers::GCNone: llvm_unreachable("explicit none");
898 }
899 }
900
901 completeAttrs();
902 dispatch(QualType(T.getTypePtr(), 0));
903 pop();
904 return;
905 }
906
907 Type *Ty = const_cast<Type*>(T.getTypePtr());
908 push(getTypeKindName(Ty));
909 XMLTypeVisitor<XMLDumper>::dispatch(const_cast<Type*>(T.getTypePtr()));
910 pop();
911 }
912
913 void setCallingConv(CallingConv CC) {
914 switch (CC) {
915 case CC_Default: return;
916 case CC_C: return set("cc", "cdecl");
917 case CC_X86FastCall: return set("cc", "x86_fastcall");
918 case CC_X86StdCall: return set("cc", "x86_stdcall");
919 case CC_X86ThisCall: return set("cc", "x86_thiscall");
920 case CC_X86Pascal: return set("cc", "x86_pascal");
921 case CC_AAPCS: return set("cc", "aapcs");
922 case CC_AAPCS_VFP: return set("cc", "aapcs_vfp");
923 }
924 }
925
926 void visitTypeAttrs(Type *D) {
927 setPointer(D);
928 setFlag("dependent", D->isDependentType());
929 setFlag("variably_modified", D->isVariablyModifiedType());
930
931 setPointer("canonical", D->getCanonicalTypeInternal().getAsOpaquePtr());
932 }
933
934 void visitPointerTypeChildren(PointerType *T) {
935 dispatch(T->getPointeeType());
936 }
937 void visitReferenceTypeChildren(ReferenceType *T) {
938 dispatch(T->getPointeeType());
939 }
940 void visitObjCObjectPointerTypeChildren(ObjCObjectPointerType *T) {
941 dispatch(T->getPointeeType());
942 }
943 void visitBlockPointerTypeChildren(BlockPointerType *T) {
944 dispatch(T->getPointeeType());
945 }
946
947 // Types that just wrap declarations.
948 void visitTagTypeChildren(TagType *T) {
949 visitDeclRef(T->getDecl());
950 }
951 void visitTypedefTypeChildren(TypedefType *T) {
952 visitDeclRef(T->getDecl());
953 }
954 void visitObjCInterfaceTypeChildren(ObjCInterfaceType *T) {
955 visitDeclRef(T->getDecl());
956 }
957 void visitUnresolvedUsingTypeChildren(UnresolvedUsingType *T) {
958 visitDeclRef(T->getDecl());
959 }
960 void visitInjectedClassNameTypeChildren(InjectedClassNameType *T) {
961 visitDeclRef(T->getDecl());
962 }
963
964 void visitFunctionTypeAttrs(FunctionType *T) {
965 setFlag("noreturn", T->getNoReturnAttr());
966 setCallingConv(T->getCallConv());
967 if (T->getHasRegParm()) setInteger("regparm", T->getRegParmType());
968 }
969 void visitFunctionTypeChildren(FunctionType *T) {
970 dispatch(T->getResultType());
971 }
972
973 void visitFunctionProtoTypeAttrs(FunctionProtoType *T) {
974 setFlag("const", T->isConst());
975 setFlag("volatile", T->isVolatile());
976 setFlag("restrict", T->isRestrict());
977 }
978 void visitFunctionProtoTypeChildren(FunctionProtoType *T) {
979 push("parameters");
980 setFlag("variadic", T->isVariadic());
981 completeAttrs();
982 for (FunctionProtoType::arg_type_iterator
983 I = T->arg_type_begin(), E = T->arg_type_end(); I != E; ++I)
984 dispatch(*I);
985 pop();
986
987 if (T->hasDynamicExceptionSpec()) {
988 push("exception_specifiers");
989 setFlag("any", T->getExceptionSpecType() == EST_MSAny);
990 completeAttrs();
991 for (FunctionProtoType::exception_iterator
992 I = T->exception_begin(), E = T->exception_end(); I != E; ++I)
993 dispatch(*I);
994 pop();
995 }
996 // FIXME: noexcept specifier
997 }
998
999 void visitTemplateSpecializationTypeChildren(TemplateSpecializationType *T) {
1000 if (const RecordType *RT = T->getAs<RecordType>())
1001 visitDeclRef(RT->getDecl());
1002
1003 // TODO: TemplateName
1004
1005 push("template_arguments");
1006 completeAttrs();
1007 for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I)
1008 dispatch(T->getArg(I));
1009 pop();
1010 }
1011
1012 //---- Statements ------------------------------------------------//
1013 void dispatch(Stmt *S) {
1014 // FIXME: this is not really XML at all
1015 push("Stmt");
1016 out << ">\n";
1017 Stack.back().State = NS_Children; // explicitly become non-lazy
1018 S->dump(out, Context.getSourceManager());
1019 out << '\n';
1020 pop();
1021 }
1022};
1023}
1024
1025void Decl::dumpXML() const {
1026 dumpXML(llvm::errs());
1027}
1028
1029void Decl::dumpXML(raw_ostream &out) const {
1030 XMLDumper(out, getASTContext()).dispatch(const_cast<Decl*>(this));
1031}
1032
1033#else /* ifndef NDEBUG */
1034
1035void Decl::dumpXML() const {}
1036void Decl::dumpXML(raw_ostream &out) const {}
1037
1038#endif