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