clang API Documentation

DumpXML.cpp
Go to the documentation of this file.
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