clang API Documentation
00001 //===--- DumpXML.cpp - Detailed XML dumping ---------------------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the Decl::dumpXML() method, a debugging tool to 00011 // print a detailed graph of an AST in an unspecified XML format. 00012 // 00013 // There is no guarantee of stability for this format. 00014 // 00015 //===----------------------------------------------------------------------===// 00016 00017 // Only pay for this in code size in assertions-enabled builds. 00018 00019 #include "clang/AST/ASTContext.h" 00020 #include "clang/AST/Decl.h" 00021 #include "clang/AST/DeclCXX.h" 00022 #include "clang/AST/DeclFriend.h" 00023 #include "clang/AST/DeclObjC.h" 00024 #include "clang/AST/DeclTemplate.h" 00025 #include "clang/AST/DeclVisitor.h" 00026 #include "clang/AST/Expr.h" 00027 #include "clang/AST/ExprCXX.h" 00028 #include "clang/AST/ExprObjC.h" 00029 #include "clang/AST/NestedNameSpecifier.h" 00030 #include "clang/AST/Stmt.h" 00031 #include "clang/AST/StmtCXX.h" 00032 #include "clang/AST/StmtObjC.h" 00033 #include "clang/AST/StmtVisitor.h" 00034 #include "clang/AST/TemplateBase.h" 00035 #include "clang/AST/TemplateName.h" 00036 #include "clang/AST/Type.h" 00037 #include "clang/AST/TypeLoc.h" 00038 #include "clang/AST/TypeLocVisitor.h" 00039 #include "clang/AST/TypeVisitor.h" 00040 #include "clang/AST/Expr.h" 00041 #include "clang/AST/ExprCXX.h" 00042 #include "llvm/ADT/SmallString.h" 00043 00044 using namespace clang; 00045 00046 #ifndef NDEBUG 00047 00048 namespace { 00049 00050 enum NodeState { 00051 NS_Attrs, NS_LazyChildren, NS_Children 00052 }; 00053 00054 struct Node { 00055 StringRef Name; 00056 NodeState State; 00057 Node(StringRef name) : Name(name), State(NS_Attrs) {} 00058 00059 bool isDoneWithAttrs() const { return State != NS_Attrs; } 00060 }; 00061 00062 template <class Impl> struct XMLDeclVisitor { 00063 #define DISPATCH(NAME, CLASS) \ 00064 static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(D)) 00065 00066 void dispatch(Decl *D) { 00067 switch (D->getKind()) { 00068 #define DECL(DERIVED, BASE) \ 00069 case Decl::DERIVED: \ 00070 DISPATCH(dispatch##DERIVED##DeclAttrs, DERIVED##Decl); \ 00071 static_cast<Impl*>(this)->completeAttrs(); \ 00072 DISPATCH(dispatch##DERIVED##DeclChildren, DERIVED##Decl); \ 00073 DISPATCH(dispatch##DERIVED##DeclAsContext, DERIVED##Decl); \ 00074 break; 00075 #define ABSTRACT_DECL(DECL) 00076 #include "clang/AST/DeclNodes.inc" 00077 } 00078 } 00079 00080 #define DECL(DERIVED, BASE) \ 00081 void dispatch##DERIVED##DeclAttrs(DERIVED##Decl *D) { \ 00082 DISPATCH(dispatch##BASE##Attrs, BASE); \ 00083 DISPATCH(visit##DERIVED##DeclAttrs, DERIVED##Decl); \ 00084 } \ 00085 void visit##DERIVED##DeclAttrs(DERIVED##Decl *D) {} \ 00086 void dispatch##DERIVED##DeclChildren(DERIVED##Decl *D) { \ 00087 DISPATCH(dispatch##BASE##Children, BASE); \ 00088 DISPATCH(visit##DERIVED##DeclChildren, DERIVED##Decl); \ 00089 } \ 00090 void visit##DERIVED##DeclChildren(DERIVED##Decl *D) {} \ 00091 void dispatch##DERIVED##DeclAsContext(DERIVED##Decl *D) { \ 00092 DISPATCH(dispatch##BASE##AsContext, BASE); \ 00093 DISPATCH(visit##DERIVED##DeclAsContext, DERIVED##Decl); \ 00094 } \ 00095 void visit##DERIVED##DeclAsContext(DERIVED##Decl *D) {} 00096 #include "clang/AST/DeclNodes.inc" 00097 00098 void dispatchDeclAttrs(Decl *D) { 00099 DISPATCH(visitDeclAttrs, Decl); 00100 } 00101 void visitDeclAttrs(Decl *D) {} 00102 00103 void dispatchDeclChildren(Decl *D) { 00104 DISPATCH(visitDeclChildren, Decl); 00105 } 00106 void visitDeclChildren(Decl *D) {} 00107 00108 void dispatchDeclAsContext(Decl *D) { 00109 DISPATCH(visitDeclAsContext, Decl); 00110 } 00111 void visitDeclAsContext(Decl *D) {} 00112 00113 #undef DISPATCH 00114 }; 00115 00116 template <class Impl> struct XMLTypeVisitor { 00117 #define DISPATCH(NAME, CLASS) \ 00118 static_cast<Impl*>(this)->NAME(static_cast<CLASS*>(T)) 00119 00120 void dispatch(Type *T) { 00121 switch (T->getTypeClass()) { 00122 #define TYPE(DERIVED, BASE) \ 00123 case Type::DERIVED: \ 00124 DISPATCH(dispatch##DERIVED##TypeAttrs, DERIVED##Type); \ 00125 static_cast<Impl*>(this)->completeAttrs(); \ 00126 DISPATCH(dispatch##DERIVED##TypeChildren, DERIVED##Type); \ 00127 break; 00128 #define ABSTRACT_TYPE(DERIVED, BASE) 00129 #include "clang/AST/TypeNodes.def" 00130 } 00131 } 00132 00133 #define TYPE(DERIVED, BASE) \ 00134 void dispatch##DERIVED##TypeAttrs(DERIVED##Type *T) { \ 00135 DISPATCH(dispatch##BASE##Attrs, BASE); \ 00136 DISPATCH(visit##DERIVED##TypeAttrs, DERIVED##Type); \ 00137 } \ 00138 void visit##DERIVED##TypeAttrs(DERIVED##Type *T) {} \ 00139 void dispatch##DERIVED##TypeChildren(DERIVED##Type *T) { \ 00140 DISPATCH(dispatch##BASE##Children, BASE); \ 00141 DISPATCH(visit##DERIVED##TypeChildren, DERIVED##Type); \ 00142 } \ 00143 void visit##DERIVED##TypeChildren(DERIVED##Type *T) {} 00144 #include "clang/AST/TypeNodes.def" 00145 00146 void dispatchTypeAttrs(Type *T) { 00147 DISPATCH(visitTypeAttrs, Type); 00148 } 00149 void visitTypeAttrs(Type *T) {} 00150 00151 void dispatchTypeChildren(Type *T) { 00152 DISPATCH(visitTypeChildren, Type); 00153 } 00154 void visitTypeChildren(Type *T) {} 00155 00156 #undef DISPATCH 00157 }; 00158 00159 static StringRef getTypeKindName(Type *T) { 00160 switch (T->getTypeClass()) { 00161 #define TYPE(DERIVED, BASE) case Type::DERIVED: return #DERIVED "Type"; 00162 #define ABSTRACT_TYPE(DERIVED, BASE) 00163 #include "clang/AST/TypeNodes.def" 00164 } 00165 00166 llvm_unreachable("unknown type kind!"); 00167 } 00168 00169 struct XMLDumper : public XMLDeclVisitor<XMLDumper>, 00170 public XMLTypeVisitor<XMLDumper> { 00171 raw_ostream &out; 00172 ASTContext &Context; 00173 SmallVector<Node, 16> Stack; 00174 unsigned Indent; 00175 explicit XMLDumper(raw_ostream &OS, ASTContext &context) 00176 : out(OS), Context(context), Indent(0) {} 00177 00178 void indent() { 00179 for (unsigned I = Indent; I; --I) 00180 out << ' '; 00181 } 00182 00183 /// Push a new node on the stack. 00184 void push(StringRef name) { 00185 if (!Stack.empty()) { 00186 assert(Stack.back().isDoneWithAttrs()); 00187 if (Stack.back().State == NS_LazyChildren) { 00188 Stack.back().State = NS_Children; 00189 out << ">\n"; 00190 } 00191 Indent++; 00192 indent(); 00193 } 00194 Stack.push_back(Node(name)); 00195 out << '<' << name; 00196 } 00197 00198 /// Set the given attribute to the given value. 00199 void set(StringRef attr, StringRef value) { 00200 assert(!Stack.empty() && !Stack.back().isDoneWithAttrs()); 00201 out << ' ' << attr << '=' << '"' << value << '"'; // TODO: quotation 00202 } 00203 00204 /// Finish attributes. 00205 void completeAttrs() { 00206 assert(!Stack.empty() && !Stack.back().isDoneWithAttrs()); 00207 Stack.back().State = NS_LazyChildren; 00208 } 00209 00210 /// Pop a node. 00211 void pop() { 00212 assert(!Stack.empty() && Stack.back().isDoneWithAttrs()); 00213 if (Stack.back().State == NS_LazyChildren) { 00214 out << "/>\n"; 00215 } else { 00216 indent(); 00217 out << "</" << Stack.back().Name << ">\n"; 00218 } 00219 if (Stack.size() > 1) Indent--; 00220 Stack.pop_back(); 00221 } 00222 00223 //---- General utilities -------------------------------------------// 00224 00225 void setPointer(StringRef prop, const void *p) { 00226 SmallString<10> buffer; 00227 llvm::raw_svector_ostream os(buffer); 00228 os << p; 00229 os.flush(); 00230 set(prop, buffer); 00231 } 00232 00233 void setPointer(void *p) { 00234 setPointer("ptr", p); 00235 } 00236 00237 void setInteger(StringRef prop, const llvm::APSInt &v) { 00238 set(prop, v.toString(10)); 00239 } 00240 00241 void setInteger(StringRef prop, unsigned n) { 00242 SmallString<10> buffer; 00243 llvm::raw_svector_ostream os(buffer); 00244 os << n; 00245 os.flush(); 00246 set(prop, buffer); 00247 } 00248 00249 void setFlag(StringRef prop, bool flag) { 00250 if (flag) set(prop, "true"); 00251 } 00252 00253 void setName(DeclarationName Name) { 00254 if (!Name) 00255 return set("name", ""); 00256 00257 // Common case. 00258 if (Name.isIdentifier()) 00259 return set("name", Name.getAsIdentifierInfo()->getName()); 00260 00261 set("name", Name.getAsString()); 00262 } 00263 00264 class TemporaryContainer { 00265 XMLDumper &Dumper; 00266 public: 00267 TemporaryContainer(XMLDumper &dumper, StringRef name) 00268 : Dumper(dumper) { 00269 Dumper.push(name); 00270 Dumper.completeAttrs(); 00271 } 00272 00273 ~TemporaryContainer() { 00274 Dumper.pop(); 00275 } 00276 }; 00277 00278 void visitTemplateParameters(TemplateParameterList *L) { 00279 push("template_parameters"); 00280 completeAttrs(); 00281 for (TemplateParameterList::iterator 00282 I = L->begin(), E = L->end(); I != E; ++I) 00283 dispatch(*I); 00284 pop(); 00285 } 00286 00287 void visitTemplateArguments(const TemplateArgumentList &L) { 00288 push("template_arguments"); 00289 completeAttrs(); 00290 for (unsigned I = 0, E = L.size(); I != E; ++I) 00291 dispatch(L[I]); 00292 pop(); 00293 } 00294 00295 /// Visits a reference to the given declaration. 00296 void visitDeclRef(Decl *D) { 00297 push(D->getDeclKindName()); 00298 setPointer("ref", D); 00299 completeAttrs(); 00300 pop(); 00301 } 00302 void visitDeclRef(StringRef Name, Decl *D) { 00303 TemporaryContainer C(*this, Name); 00304 if (D) visitDeclRef(D); 00305 } 00306 00307 void dispatch(const TemplateArgument &A) { 00308 switch (A.getKind()) { 00309 case TemplateArgument::Null: { 00310 TemporaryContainer C(*this, "null"); 00311 break; 00312 } 00313 case TemplateArgument::Type: { 00314 dispatch(A.getAsType()); 00315 break; 00316 } 00317 case TemplateArgument::Template: 00318 case TemplateArgument::TemplateExpansion: 00319 // FIXME: Implement! 00320 break; 00321 00322 case TemplateArgument::Declaration: { 00323 if (Decl *D = A.getAsDecl()) 00324 visitDeclRef(D); 00325 break; 00326 } 00327 case TemplateArgument::Integral: { 00328 push("integer"); 00329 setInteger("value", *A.getAsIntegral()); 00330 completeAttrs(); 00331 pop(); 00332 break; 00333 } 00334 case TemplateArgument::Expression: { 00335 dispatch(A.getAsExpr()); 00336 break; 00337 } 00338 case TemplateArgument::Pack: { 00339 for (TemplateArgument::pack_iterator P = A.pack_begin(), 00340 PEnd = A.pack_end(); 00341 P != PEnd; ++P) 00342 dispatch(*P); 00343 break; 00344 } 00345 } 00346 } 00347 00348 void dispatch(const TemplateArgumentLoc &A) { 00349 dispatch(A.getArgument()); 00350 } 00351 00352 //---- Declarations ------------------------------------------------// 00353 // Calls are made in this order: 00354 // # Enter a new node. 00355 // push("FieldDecl") 00356 // 00357 // # In this phase, attributes are set on the node. 00358 // visitDeclAttrs(D) 00359 // visitNamedDeclAttrs(D) 00360 // ... 00361 // visitFieldDeclAttrs(D) 00362 // 00363 // # No more attributes after this point. 00364 // completeAttrs() 00365 // 00366 // # Create "header" child nodes, i.e. those which logically 00367 // # belong to the declaration itself. 00368 // visitDeclChildren(D) 00369 // visitNamedDeclChildren(D) 00370 // ... 00371 // visitFieldDeclChildren(D) 00372 // 00373 // # Create nodes for the lexical children. 00374 // visitDeclAsContext(D) 00375 // visitNamedDeclAsContext(D) 00376 // ... 00377 // visitFieldDeclAsContext(D) 00378 // 00379 // # Finish the node. 00380 // pop(); 00381 void dispatch(Decl *D) { 00382 push(D->getDeclKindName()); 00383 XMLDeclVisitor<XMLDumper>::dispatch(D); 00384 pop(); 00385 } 00386 void visitDeclAttrs(Decl *D) { 00387 setPointer(D); 00388 } 00389 00390 /// Visit all the lexical decls in the given context. 00391 void visitDeclContext(DeclContext *DC) { 00392 for (DeclContext::decl_iterator 00393 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) 00394 dispatch(*I); 00395 00396 // FIXME: point out visible declarations not in lexical context? 00397 } 00398 00399 /// Set the "access" attribute on the current node according to the 00400 /// given specifier. 00401 void setAccess(AccessSpecifier AS) { 00402 switch (AS) { 00403 case AS_public: return set("access", "public"); 00404 case AS_protected: return set("access", "protected"); 00405 case AS_private: return set("access", "private"); 00406 case AS_none: llvm_unreachable("explicit forbidden access"); 00407 } 00408 } 00409 00410 template <class T> void visitRedeclarableAttrs(T *D) { 00411 if (T *Prev = D->getPreviousDecl()) 00412 setPointer("previous", Prev); 00413 } 00414 00415 00416 // TranslationUnitDecl 00417 void visitTranslationUnitDeclAsContext(TranslationUnitDecl *D) { 00418 visitDeclContext(D); 00419 } 00420 00421 // LinkageSpecDecl 00422 void visitLinkageSpecDeclAttrs(LinkageSpecDecl *D) { 00423 StringRef lang = ""; 00424 switch (D->getLanguage()) { 00425 case LinkageSpecDecl::lang_c: lang = "C"; break; 00426 case LinkageSpecDecl::lang_cxx: lang = "C++"; break; 00427 } 00428 set("lang", lang); 00429 } 00430 void visitLinkageSpecDeclAsContext(LinkageSpecDecl *D) { 00431 visitDeclContext(D); 00432 } 00433 00434 // NamespaceDecl 00435 void visitNamespaceDeclAttrs(NamespaceDecl *D) { 00436 setFlag("inline", D->isInline()); 00437 if (!D->isOriginalNamespace()) 00438 setPointer("original", D->getOriginalNamespace()); 00439 } 00440 void visitNamespaceDeclAsContext(NamespaceDecl *D) { 00441 visitDeclContext(D); 00442 } 00443 00444 // NamedDecl 00445 void visitNamedDeclAttrs(NamedDecl *D) { 00446 setName(D->getDeclName()); 00447 } 00448 00449 // ValueDecl 00450 void visitValueDeclChildren(ValueDecl *D) { 00451 dispatch(D->getType()); 00452 } 00453 00454 // DeclaratorDecl 00455 void visitDeclaratorDeclChildren(DeclaratorDecl *D) { 00456 //dispatch(D->getTypeSourceInfo()->getTypeLoc()); 00457 } 00458 00459 // VarDecl 00460 void visitVarDeclAttrs(VarDecl *D) { 00461 visitRedeclarableAttrs(D); 00462 if (D->getStorageClass() != SC_None) 00463 set("storage", 00464 VarDecl::getStorageClassSpecifierString(D->getStorageClass())); 00465 StringRef initStyle = ""; 00466 switch (D->getInitStyle()) { 00467 case VarDecl::CInit: initStyle = "c"; break; 00468 case VarDecl::CallInit: initStyle = "call"; break; 00469 case VarDecl::ListInit: initStyle = "list"; break; 00470 } 00471 set("initstyle", initStyle); 00472 setFlag("nrvo", D->isNRVOVariable()); 00473 // TODO: instantiation, etc. 00474 } 00475 void visitVarDeclChildren(VarDecl *D) { 00476 if (D->hasInit()) dispatch(D->getInit()); 00477 } 00478 00479 // ParmVarDecl? 00480 00481 // FunctionDecl 00482 void visitFunctionDeclAttrs(FunctionDecl *D) { 00483 visitRedeclarableAttrs(D); 00484 setFlag("pure", D->isPure()); 00485 setFlag("trivial", D->isTrivial()); 00486 setFlag("returnzero", D->hasImplicitReturnZero()); 00487 setFlag("prototype", D->hasWrittenPrototype()); 00488 setFlag("deleted", D->isDeletedAsWritten()); 00489 if (D->getStorageClass() != SC_None) 00490 set("storage", 00491 VarDecl::getStorageClassSpecifierString(D->getStorageClass())); 00492 setFlag("inline", D->isInlineSpecified()); 00493 if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) 00494 set("asmlabel", ALA->getLabel()); 00495 // TODO: instantiation, etc. 00496 } 00497 void visitFunctionDeclChildren(FunctionDecl *D) { 00498 for (FunctionDecl::param_iterator 00499 I = D->param_begin(), E = D->param_end(); I != E; ++I) 00500 dispatch(*I); 00501 for (llvm::ArrayRef<NamedDecl*>::iterator 00502 I = D->getDeclsInPrototypeScope().begin(), E = D->getDeclsInPrototypeScope().end(); 00503 I != E; ++I) 00504 dispatch(*I); 00505 if (D->doesThisDeclarationHaveABody()) 00506 dispatch(D->getBody()); 00507 } 00508 00509 // CXXMethodDecl ? 00510 // CXXConstructorDecl ? 00511 // CXXDestructorDecl ? 00512 // CXXConversionDecl ? 00513 00514 void dispatch(CXXCtorInitializer *Init) { 00515 // TODO 00516 } 00517 00518 // FieldDecl 00519 void visitFieldDeclAttrs(FieldDecl *D) { 00520 setFlag("mutable", D->isMutable()); 00521 } 00522 void visitFieldDeclChildren(FieldDecl *D) { 00523 if (D->isBitField()) { 00524 TemporaryContainer C(*this, "bitwidth"); 00525 dispatch(D->getBitWidth()); 00526 } 00527 // TODO: C++0x member initializer 00528 } 00529 00530 // EnumConstantDecl 00531 void visitEnumConstantDeclChildren(EnumConstantDecl *D) { 00532 // value in any case? 00533 if (D->getInitExpr()) dispatch(D->getInitExpr()); 00534 } 00535 00536 // IndirectFieldDecl 00537 void visitIndirectFieldDeclChildren(IndirectFieldDecl *D) { 00538 for (IndirectFieldDecl::chain_iterator 00539 I = D->chain_begin(), E = D->chain_end(); I != E; ++I) { 00540 NamedDecl *VD = const_cast<NamedDecl*>(*I); 00541 push(isa<VarDecl>(VD) ? "variable" : "field"); 00542 setPointer("ptr", VD); 00543 completeAttrs(); 00544 pop(); 00545 } 00546 } 00547 00548 // TypeDecl 00549 void visitTypeDeclAttrs(TypeDecl *D) { 00550 setPointer("typeptr", D->getTypeForDecl()); 00551 } 00552 00553 // TypedefDecl 00554 void visitTypedefDeclAttrs(TypedefDecl *D) { 00555 visitRedeclarableAttrs<TypedefNameDecl>(D); 00556 } 00557 void visitTypedefDeclChildren(TypedefDecl *D) { 00558 dispatch(D->getTypeSourceInfo()->getTypeLoc()); 00559 } 00560 00561 // TypeAliasDecl 00562 void visitTypeAliasDeclAttrs(TypeAliasDecl *D) { 00563 visitRedeclarableAttrs<TypedefNameDecl>(D); 00564 } 00565 void visitTypeAliasDeclChildren(TypeAliasDecl *D) { 00566 dispatch(D->getTypeSourceInfo()->getTypeLoc()); 00567 } 00568 00569 // TagDecl 00570 void visitTagDeclAttrs(TagDecl *D) { 00571 visitRedeclarableAttrs(D); 00572 } 00573 void visitTagDeclAsContext(TagDecl *D) { 00574 visitDeclContext(D); 00575 } 00576 00577 // EnumDecl 00578 void visitEnumDeclAttrs(EnumDecl *D) { 00579 setFlag("scoped", D->isScoped()); 00580 setFlag("fixed", D->isFixed()); 00581 } 00582 void visitEnumDeclChildren(EnumDecl *D) { 00583 { 00584 TemporaryContainer C(*this, "promotion_type"); 00585 dispatch(D->getPromotionType()); 00586 } 00587 { 00588 TemporaryContainer C(*this, "integer_type"); 00589 dispatch(D->getIntegerType()); 00590 } 00591 } 00592 00593 // RecordDecl ? 00594 00595 void visitCXXRecordDeclChildren(CXXRecordDecl *D) { 00596 if (!D->isThisDeclarationADefinition()) return; 00597 00598 for (CXXRecordDecl::base_class_iterator 00599 I = D->bases_begin(), E = D->bases_end(); I != E; ++I) { 00600 push("base"); 00601 setAccess(I->getAccessSpecifier()); 00602 completeAttrs(); 00603 dispatch(I->getTypeSourceInfo()->getTypeLoc()); 00604 pop(); 00605 } 00606 } 00607 00608 // ClassTemplateSpecializationDecl ? 00609 00610 // FileScopeAsmDecl ? 00611 00612 // BlockDecl 00613 void visitBlockDeclAttrs(BlockDecl *D) { 00614 setFlag("variadic", D->isVariadic()); 00615 } 00616 void visitBlockDeclChildren(BlockDecl *D) { 00617 for (FunctionDecl::param_iterator 00618 I = D->param_begin(), E = D->param_end(); I != E; ++I) 00619 dispatch(*I); 00620 dispatch(D->getBody()); 00621 } 00622 00623 // AccessSpecDecl 00624 void visitAccessSpecDeclAttrs(AccessSpecDecl *D) { 00625 setAccess(D->getAccess()); 00626 } 00627 00628 // TemplateDecl 00629 void visitTemplateDeclChildren(TemplateDecl *D) { 00630 visitTemplateParameters(D->getTemplateParameters()); 00631 if (D->getTemplatedDecl()) 00632 dispatch(D->getTemplatedDecl()); 00633 } 00634 00635 // FunctionTemplateDecl 00636 void visitFunctionTemplateDeclAttrs(FunctionTemplateDecl *D) { 00637 visitRedeclarableAttrs(D); 00638 } 00639 void visitFunctionTemplateDeclChildren(FunctionTemplateDecl *D) { 00640 // Mention all the specializations which don't have explicit 00641 // declarations elsewhere. 00642 for (FunctionTemplateDecl::spec_iterator 00643 I = D->spec_begin(), E = D->spec_end(); I != E; ++I) { 00644 FunctionTemplateSpecializationInfo *Info 00645 = I->getTemplateSpecializationInfo(); 00646 00647 bool Unknown = false; 00648 switch (Info->getTemplateSpecializationKind()) { 00649 case TSK_ImplicitInstantiation: Unknown = false; break; 00650 case TSK_Undeclared: Unknown = true; break; 00651 00652 // These will be covered at their respective sites. 00653 case TSK_ExplicitSpecialization: continue; 00654 case TSK_ExplicitInstantiationDeclaration: continue; 00655 case TSK_ExplicitInstantiationDefinition: continue; 00656 } 00657 00658 TemporaryContainer C(*this, 00659 Unknown ? "uninstantiated" : "instantiation"); 00660 visitTemplateArguments(*Info->TemplateArguments); 00661 dispatch(Info->Function); 00662 } 00663 } 00664 00665 // ClasTemplateDecl 00666 void visitClassTemplateDeclAttrs(ClassTemplateDecl *D) { 00667 visitRedeclarableAttrs(D); 00668 } 00669 void visitClassTemplateDeclChildren(ClassTemplateDecl *D) { 00670 // Mention all the specializations which don't have explicit 00671 // declarations elsewhere. 00672 for (ClassTemplateDecl::spec_iterator 00673 I = D->spec_begin(), E = D->spec_end(); I != E; ++I) { 00674 00675 bool Unknown = false; 00676 switch (I->getTemplateSpecializationKind()) { 00677 case TSK_ImplicitInstantiation: Unknown = false; break; 00678 case TSK_Undeclared: Unknown = true; break; 00679 00680 // These will be covered at their respective sites. 00681 case TSK_ExplicitSpecialization: continue; 00682 case TSK_ExplicitInstantiationDeclaration: continue; 00683 case TSK_ExplicitInstantiationDefinition: continue; 00684 } 00685 00686 TemporaryContainer C(*this, 00687 Unknown ? "uninstantiated" : "instantiation"); 00688 visitTemplateArguments(I->getTemplateArgs()); 00689 dispatch(*I); 00690 } 00691 } 00692 00693 // TemplateTypeParmDecl 00694 void visitTemplateTypeParmDeclAttrs(TemplateTypeParmDecl *D) { 00695 setInteger("depth", D->getDepth()); 00696 setInteger("index", D->getIndex()); 00697 } 00698 void visitTemplateTypeParmDeclChildren(TemplateTypeParmDecl *D) { 00699 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) 00700 dispatch(D->getDefaultArgumentInfo()->getTypeLoc()); 00701 // parameter pack? 00702 } 00703 00704 // NonTypeTemplateParmDecl 00705 void visitNonTypeTemplateParmDeclAttrs(NonTypeTemplateParmDecl *D) { 00706 setInteger("depth", D->getDepth()); 00707 setInteger("index", D->getIndex()); 00708 } 00709 void visitNonTypeTemplateParmDeclChildren(NonTypeTemplateParmDecl *D) { 00710 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) 00711 dispatch(D->getDefaultArgument()); 00712 // parameter pack? 00713 } 00714 00715 // TemplateTemplateParmDecl 00716 void visitTemplateTemplateParmDeclAttrs(TemplateTemplateParmDecl *D) { 00717 setInteger("depth", D->getDepth()); 00718 setInteger("index", D->getIndex()); 00719 } 00720 void visitTemplateTemplateParmDeclChildren(TemplateTemplateParmDecl *D) { 00721 if (D->hasDefaultArgument() && !D->defaultArgumentWasInherited()) 00722 dispatch(D->getDefaultArgument()); 00723 // parameter pack? 00724 } 00725 00726 // FriendDecl 00727 void visitFriendDeclChildren(FriendDecl *D) { 00728 if (TypeSourceInfo *T = D->getFriendType()) 00729 dispatch(T->getTypeLoc()); 00730 else 00731 dispatch(D->getFriendDecl()); 00732 } 00733 00734 // UsingDirectiveDecl ? 00735 // UsingDecl ? 00736 // UsingShadowDecl ? 00737 // NamespaceAliasDecl ? 00738 // UnresolvedUsingValueDecl ? 00739 // UnresolvedUsingTypenameDecl ? 00740 // StaticAssertDecl ? 00741 00742 // ObjCImplDecl 00743 void visitObjCImplDeclChildren(ObjCImplDecl *D) { 00744 visitDeclRef(D->getClassInterface()); 00745 } 00746 void visitObjCImplDeclAsContext(ObjCImplDecl *D) { 00747 visitDeclContext(D); 00748 } 00749 00750 // ObjCInterfaceDecl 00751 void visitCategoryList(ObjCCategoryDecl *D) { 00752 if (!D) return; 00753 00754 TemporaryContainer C(*this, "categories"); 00755 for (; D; D = D->getNextClassCategory()) 00756 visitDeclRef(D); 00757 } 00758 void visitObjCInterfaceDeclAttrs(ObjCInterfaceDecl *D) { 00759 setPointer("typeptr", D->getTypeForDecl()); 00760 setFlag("forward_decl", !D->isThisDeclarationADefinition()); 00761 setFlag("implicit_interface", D->isImplicitInterfaceDecl()); 00762 } 00763 void visitObjCInterfaceDeclChildren(ObjCInterfaceDecl *D) { 00764 visitDeclRef("super", D->getSuperClass()); 00765 visitDeclRef("implementation", D->getImplementation()); 00766 if (D->protocol_begin() != D->protocol_end()) { 00767 TemporaryContainer C(*this, "protocols"); 00768 for (ObjCInterfaceDecl::protocol_iterator 00769 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) 00770 visitDeclRef(*I); 00771 } 00772 visitCategoryList(D->getCategoryList()); 00773 } 00774 void visitObjCInterfaceDeclAsContext(ObjCInterfaceDecl *D) { 00775 visitDeclContext(D); 00776 } 00777 00778 // ObjCCategoryDecl 00779 void visitObjCCategoryDeclAttrs(ObjCCategoryDecl *D) { 00780 setFlag("extension", D->IsClassExtension()); 00781 setFlag("synth_bitfield", D->hasSynthBitfield()); 00782 } 00783 void visitObjCCategoryDeclChildren(ObjCCategoryDecl *D) { 00784 visitDeclRef("interface", D->getClassInterface()); 00785 visitDeclRef("implementation", D->getImplementation()); 00786 if (D->protocol_begin() != D->protocol_end()) { 00787 TemporaryContainer C(*this, "protocols"); 00788 for (ObjCCategoryDecl::protocol_iterator 00789 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) 00790 visitDeclRef(*I); 00791 } 00792 } 00793 void visitObjCCategoryDeclAsContext(ObjCCategoryDecl *D) { 00794 visitDeclContext(D); 00795 } 00796 00797 // ObjCCategoryImplDecl 00798 void visitObjCCategoryImplDeclAttrs(ObjCCategoryImplDecl *D) { 00799 set("identifier", D->getName()); 00800 } 00801 void visitObjCCategoryImplDeclChildren(ObjCCategoryImplDecl *D) { 00802 visitDeclRef(D->getCategoryDecl()); 00803 } 00804 00805 // ObjCImplementationDecl 00806 void visitObjCImplementationDeclAttrs(ObjCImplementationDecl *D) { 00807 setFlag("synth_bitfield", D->hasSynthBitfield()); 00808 set("identifier", D->getName()); 00809 } 00810 void visitObjCImplementationDeclChildren(ObjCImplementationDecl *D) { 00811 visitDeclRef("super", D->getSuperClass()); 00812 if (D->init_begin() != D->init_end()) { 00813 TemporaryContainer C(*this, "initializers"); 00814 for (ObjCImplementationDecl::init_iterator 00815 I = D->init_begin(), E = D->init_end(); I != E; ++I) 00816 dispatch(*I); 00817 } 00818 } 00819 00820 // ObjCProtocolDecl 00821 void visitObjCProtocolDeclChildren(ObjCProtocolDecl *D) { 00822 if (!D->isThisDeclarationADefinition()) 00823 return; 00824 00825 if (D->protocol_begin() != D->protocol_end()) { 00826 TemporaryContainer C(*this, "protocols"); 00827 for (ObjCInterfaceDecl::protocol_iterator 00828 I = D->protocol_begin(), E = D->protocol_end(); I != E; ++I) 00829 visitDeclRef(*I); 00830 } 00831 } 00832 void visitObjCProtocolDeclAsContext(ObjCProtocolDecl *D) { 00833 if (!D->isThisDeclarationADefinition()) 00834 return; 00835 00836 visitDeclContext(D); 00837 } 00838 00839 // ObjCMethodDecl 00840 void visitObjCMethodDeclAttrs(ObjCMethodDecl *D) { 00841 // decl qualifier? 00842 // implementation control? 00843 00844 setFlag("instance", D->isInstanceMethod()); 00845 setFlag("variadic", D->isVariadic()); 00846 setFlag("synthesized", D->isSynthesized()); 00847 setFlag("defined", D->isDefined()); 00848 setFlag("related_result_type", D->hasRelatedResultType()); 00849 } 00850 void visitObjCMethodDeclChildren(ObjCMethodDecl *D) { 00851 dispatch(D->getResultType()); 00852 for (ObjCMethodDecl::param_iterator 00853 I = D->param_begin(), E = D->param_end(); I != E; ++I) 00854 dispatch(*I); 00855 if (D->isThisDeclarationADefinition()) 00856 dispatch(D->getBody()); 00857 } 00858 00859 // ObjCIvarDecl 00860 void setAccessControl(StringRef prop, ObjCIvarDecl::AccessControl AC) { 00861 switch (AC) { 00862 case ObjCIvarDecl::None: return set(prop, "none"); 00863 case ObjCIvarDecl::Private: return set(prop, "private"); 00864 case ObjCIvarDecl::Protected: return set(prop, "protected"); 00865 case ObjCIvarDecl::Public: return set(prop, "public"); 00866 case ObjCIvarDecl::Package: return set(prop, "package"); 00867 } 00868 } 00869 void visitObjCIvarDeclAttrs(ObjCIvarDecl *D) { 00870 setFlag("synthesize", D->getSynthesize()); 00871 setAccessControl("access", D->getAccessControl()); 00872 } 00873 00874 // ObjCCompatibleAliasDecl 00875 void visitObjCCompatibleAliasDeclChildren(ObjCCompatibleAliasDecl *D) { 00876 visitDeclRef(D->getClassInterface()); 00877 } 00878 00879 // FIXME: ObjCPropertyDecl 00880 // FIXME: ObjCPropertyImplDecl 00881 00882 //---- Types -----------------------------------------------------// 00883 void dispatch(TypeLoc TL) { 00884 dispatch(TL.getType()); // for now 00885 } 00886 00887 void dispatch(QualType T) { 00888 if (T.hasLocalQualifiers()) { 00889 push("QualType"); 00890 Qualifiers Qs = T.getLocalQualifiers(); 00891 setFlag("const", Qs.hasConst()); 00892 setFlag("volatile", Qs.hasVolatile()); 00893 setFlag("restrict", Qs.hasRestrict()); 00894 if (Qs.hasAddressSpace()) setInteger("addrspace", Qs.getAddressSpace()); 00895 if (Qs.hasObjCGCAttr()) { 00896 switch (Qs.getObjCGCAttr()) { 00897 case Qualifiers::Weak: set("gc", "weak"); break; 00898 case Qualifiers::Strong: set("gc", "strong"); break; 00899 case Qualifiers::GCNone: llvm_unreachable("explicit none"); 00900 } 00901 } 00902 00903 completeAttrs(); 00904 dispatch(QualType(T.getTypePtr(), 0)); 00905 pop(); 00906 return; 00907 } 00908 00909 Type *Ty = const_cast<Type*>(T.getTypePtr()); 00910 push(getTypeKindName(Ty)); 00911 XMLTypeVisitor<XMLDumper>::dispatch(const_cast<Type*>(T.getTypePtr())); 00912 pop(); 00913 } 00914 00915 void setCallingConv(CallingConv CC) { 00916 switch (CC) { 00917 case CC_Default: return; 00918 case CC_C: return set("cc", "cdecl"); 00919 case CC_X86FastCall: return set("cc", "x86_fastcall"); 00920 case CC_X86StdCall: return set("cc", "x86_stdcall"); 00921 case CC_X86ThisCall: return set("cc", "x86_thiscall"); 00922 case CC_X86Pascal: return set("cc", "x86_pascal"); 00923 case CC_AAPCS: return set("cc", "aapcs"); 00924 case CC_AAPCS_VFP: return set("cc", "aapcs_vfp"); 00925 } 00926 } 00927 00928 void visitTypeAttrs(Type *D) { 00929 setPointer(D); 00930 setFlag("dependent", D->isDependentType()); 00931 setFlag("variably_modified", D->isVariablyModifiedType()); 00932 00933 setPointer("canonical", D->getCanonicalTypeInternal().getAsOpaquePtr()); 00934 } 00935 00936 void visitPointerTypeChildren(PointerType *T) { 00937 dispatch(T->getPointeeType()); 00938 } 00939 void visitReferenceTypeChildren(ReferenceType *T) { 00940 dispatch(T->getPointeeType()); 00941 } 00942 void visitObjCObjectPointerTypeChildren(ObjCObjectPointerType *T) { 00943 dispatch(T->getPointeeType()); 00944 } 00945 void visitBlockPointerTypeChildren(BlockPointerType *T) { 00946 dispatch(T->getPointeeType()); 00947 } 00948 00949 // Types that just wrap declarations. 00950 void visitTagTypeChildren(TagType *T) { 00951 visitDeclRef(T->getDecl()); 00952 } 00953 void visitTypedefTypeChildren(TypedefType *T) { 00954 visitDeclRef(T->getDecl()); 00955 } 00956 void visitObjCInterfaceTypeChildren(ObjCInterfaceType *T) { 00957 visitDeclRef(T->getDecl()); 00958 } 00959 void visitUnresolvedUsingTypeChildren(UnresolvedUsingType *T) { 00960 visitDeclRef(T->getDecl()); 00961 } 00962 void visitInjectedClassNameTypeChildren(InjectedClassNameType *T) { 00963 visitDeclRef(T->getDecl()); 00964 } 00965 00966 void visitFunctionTypeAttrs(FunctionType *T) { 00967 setFlag("noreturn", T->getNoReturnAttr()); 00968 setCallingConv(T->getCallConv()); 00969 if (T->getHasRegParm()) setInteger("regparm", T->getRegParmType()); 00970 } 00971 void visitFunctionTypeChildren(FunctionType *T) { 00972 dispatch(T->getResultType()); 00973 } 00974 00975 void visitFunctionProtoTypeAttrs(FunctionProtoType *T) { 00976 setFlag("const", T->getTypeQuals() & Qualifiers::Const); 00977 setFlag("volatile", T->getTypeQuals() & Qualifiers::Volatile); 00978 setFlag("restrict", T->getTypeQuals() & Qualifiers::Restrict); 00979 } 00980 void visitFunctionProtoTypeChildren(FunctionProtoType *T) { 00981 push("parameters"); 00982 setFlag("variadic", T->isVariadic()); 00983 completeAttrs(); 00984 for (FunctionProtoType::arg_type_iterator 00985 I = T->arg_type_begin(), E = T->arg_type_end(); I != E; ++I) 00986 dispatch(*I); 00987 pop(); 00988 00989 if (T->hasDynamicExceptionSpec()) { 00990 push("exception_specifiers"); 00991 setFlag("any", T->getExceptionSpecType() == EST_MSAny); 00992 completeAttrs(); 00993 for (FunctionProtoType::exception_iterator 00994 I = T->exception_begin(), E = T->exception_end(); I != E; ++I) 00995 dispatch(*I); 00996 pop(); 00997 } 00998 // FIXME: noexcept specifier 00999 } 01000 01001 void visitTemplateSpecializationTypeChildren(TemplateSpecializationType *T) { 01002 if (const RecordType *RT = T->getAs<RecordType>()) 01003 visitDeclRef(RT->getDecl()); 01004 01005 // TODO: TemplateName 01006 01007 push("template_arguments"); 01008 completeAttrs(); 01009 for (unsigned I = 0, E = T->getNumArgs(); I != E; ++I) 01010 dispatch(T->getArg(I)); 01011 pop(); 01012 } 01013 01014 //---- Statements ------------------------------------------------// 01015 void dispatch(Stmt *S) { 01016 // FIXME: this is not really XML at all 01017 push("Stmt"); 01018 out << ">\n"; 01019 Stack.back().State = NS_Children; // explicitly become non-lazy 01020 S->dump(out, Context.getSourceManager()); 01021 out << '\n'; 01022 pop(); 01023 } 01024 }; 01025 } 01026 01027 void Decl::dumpXML() const { 01028 dumpXML(llvm::errs()); 01029 } 01030 01031 void Decl::dumpXML(raw_ostream &out) const { 01032 XMLDumper(out, getASTContext()).dispatch(const_cast<Decl*>(this)); 01033 } 01034 01035 #else /* ifndef NDEBUG */ 01036 01037 void Decl::dumpXML() const {} 01038 void Decl::dumpXML(raw_ostream &out) const {} 01039 01040 #endif