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