diff options
author | Alexander Kornienko <alexfh@google.com> | 2012-12-20 02:09:13 +0000 |
---|---|---|
committer | Alexander Kornienko <alexfh@google.com> | 2012-12-20 02:09:13 +0000 |
commit | d538ed9b2a617239d5bd56357663de62f6f9224c (patch) | |
tree | 4d89b1886df14de8f283d0916da56ee1c0b2c3c0 | |
parent | bf53dfac8195835028bd6347433f7dbebcc29fc1 (diff) |
Implement AST dumper for Decls.
http://llvm-reviews.chandlerc.com/D52
Patch by Philip Craig!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@170634 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/PrettyPrinter.h | 9 | ||||
-rw-r--r-- | include/clang/AST/TemplateName.h | 3 | ||||
-rw-r--r-- | lib/AST/ASTDumper.cpp | 898 | ||||
-rw-r--r-- | lib/AST/DeclPrinter.cpp | 36 | ||||
-rw-r--r-- | lib/AST/StmtPrinter.cpp | 5 | ||||
-rw-r--r-- | lib/AST/TemplateName.cpp | 8 | ||||
-rw-r--r-- | test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp | 14 | ||||
-rw-r--r-- | test/CodeGen/bitfield-2.c | 8 | ||||
-rw-r--r-- | test/Misc/ast-dump-decl.c | 152 | ||||
-rw-r--r-- | test/Misc/ast-dump-decl.cpp | 405 | ||||
-rw-r--r-- | test/Misc/ast-dump-decl.m | 136 | ||||
-rw-r--r-- | test/Misc/ast-dump-decl.mm | 23 | ||||
-rw-r--r-- | test/Misc/ast-dump-stmt.c | 24 | ||||
-rw-r--r-- | test/Misc/ast-dump-stmt.m | 14 | ||||
-rw-r--r-- | test/Misc/ast-dump-templates.cpp | 6 | ||||
-rw-r--r-- | test/Misc/ast-dump-wchar.cpp | 8 | ||||
-rw-r--r-- | test/PCH/objc_stmts.m | 10 | ||||
-rw-r--r-- | test/SemaTemplate/default-expr-arguments-2.cpp | 4 | ||||
-rw-r--r-- | test/Tooling/clang-check-ast-dump.cpp | 19 |
19 files changed, 1556 insertions, 226 deletions
diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index 10354034a5..e3c09e7b41 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -40,8 +40,7 @@ struct PrintingPolicy { SuppressUnwrittenScope(false), SuppressInitializers(false), ConstantArraySizeAsWritten(false), AnonymousTagLocations(true), SuppressStrongLifetime(false), Bool(LO.Bool), - TerseOutput(false), PolishForDeclaration(false), - DumpSourceManager(0) { } + TerseOutput(false), PolishForDeclaration(false) { } /// \brief What language we're printing. LangOptions LangOpts; @@ -147,12 +146,6 @@ struct PrintingPolicy { /// declaration tag; such as, do not print attributes attached to the declaration. /// unsigned PolishForDeclaration : 1; - - /// \brief If we are "dumping" rather than "pretty-printing", this points to - /// a SourceManager which will be used to dump SourceLocations. Dumping - /// involves printing the internal details of the AST and pretty-printing - /// involves printing something similar to source code. - SourceManager *DumpSourceManager; }; } // end namespace clang diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h index 28aee84c2e..174b451b2b 100644 --- a/include/clang/AST/TemplateName.h +++ b/include/clang/AST/TemplateName.h @@ -308,6 +308,9 @@ public: void print(raw_ostream &OS, const PrintingPolicy &Policy, bool SuppressNNS = false) const; + /// \brief Debugging aid that dumps the template name. + void dump(raw_ostream &OS) const; + /// \brief Debugging aid that dumps the template name to standard /// error. void dump() const; diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 51d0f26c56..31331f1f9d 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -12,11 +12,12 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/PrettyPrinter.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclVisitor.h" #include "clang/AST/StmtVisitor.h" +#include "clang/Basic/Module.h" #include "clang/Basic/SourceManager.h" #include "llvm/Support/raw_ostream.h" using namespace clang; @@ -26,7 +27,8 @@ using namespace clang; //===----------------------------------------------------------------------===// namespace { - class ASTDumper : public StmtVisitor<ASTDumper> { + class ASTDumper + : public DeclVisitor<ASTDumper>, public StmtVisitor<ASTDumper> { SourceManager *SM; raw_ostream &OS; unsigned IndentLevel; @@ -63,10 +65,78 @@ namespace { // Utilities void indent(); void unindent(); - void dumpSourceRange(const Stmt *Node); + void dumpPointer(const void *Ptr); + void dumpSourceRange(SourceRange R); void dumpLocation(SourceLocation Loc); + void dumpBareType(QualType T); void dumpType(QualType T); - void dumpDeclRef(Decl *node); + void dumpBareDeclRef(Decl *node); + void dumpDeclRef(Decl *node, const char *Label = NULL); + void dumpName(NamedDecl *D); + void dumpDeclContext(DeclContext *DC); + + // C++ Utilities + void dumpAccessSpecifier(AccessSpecifier AS); + void dumpCXXCtorInitializer(CXXCtorInitializer *Init); + void dumpTemplateParameters(TemplateParameterList *TPL); + void dumpTemplateArgumentListInfo(const TemplateArgumentListInfo &TALI); + void dumpTemplateArgumentLoc(const TemplateArgumentLoc &A); + void dumpTemplateArgumentList(const TemplateArgumentList &TAL); + void dumpTemplateArgument(const TemplateArgument &A, + SourceRange R = SourceRange()); + + // Decls + void VisitLabelDecl(LabelDecl *D); + void VisitTypedefDecl(TypedefDecl *D); + void VisitEnumDecl(EnumDecl *D); + void VisitRecordDecl(RecordDecl *D); + void VisitEnumConstantDecl(EnumConstantDecl *D); + void VisitIndirectFieldDecl(IndirectFieldDecl *D); + void VisitFunctionDecl(FunctionDecl *D); + void VisitFieldDecl(FieldDecl *D); + void VisitVarDecl(VarDecl *D); + void VisitFileScopeAsmDecl(FileScopeAsmDecl *D); + void VisitImportDecl(ImportDecl *D); + + // C++ Decls + void VisitNamespaceDecl(NamespaceDecl *D); + void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); + void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); + void VisitTypeAliasDecl(TypeAliasDecl *D); + void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D); + void VisitCXXRecordDecl(CXXRecordDecl *D); + void VisitStaticAssertDecl(StaticAssertDecl *D); + void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); + void VisitClassTemplateDecl(ClassTemplateDecl *D); + void VisitClassTemplateSpecializationDecl( + ClassTemplateSpecializationDecl *D); + void VisitClassTemplatePartialSpecializationDecl( + ClassTemplatePartialSpecializationDecl *D); + void VisitClassScopeFunctionSpecializationDecl( + ClassScopeFunctionSpecializationDecl *D); + void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); + void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); + void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); + void VisitUsingDecl(UsingDecl *D); + void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); + void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); + void VisitUsingShadowDecl(UsingShadowDecl *D); + void VisitLinkageSpecDecl(LinkageSpecDecl *D); + void VisitAccessSpecDecl(AccessSpecDecl *D); + void VisitFriendDecl(FriendDecl *D); + + // ObjC Decls + void VisitObjCIvarDecl(ObjCIvarDecl *D); + void VisitObjCMethodDecl(ObjCMethodDecl *D); + void VisitObjCCategoryDecl(ObjCCategoryDecl *D); + void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); + void VisitObjCProtocolDecl(ObjCProtocolDecl *D); + void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); + void VisitObjCImplementationDecl(ObjCImplementationDecl *D); + void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); + void VisitObjCPropertyDecl(ObjCPropertyDecl *D); + void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); + void VisitBlockDecl(BlockDecl *D); // Stmts. void VisitStmt(Stmt *Node); @@ -137,6 +207,10 @@ void ASTDumper::unindent() { IndentLevel--; } +void ASTDumper::dumpPointer(const void *Ptr) { + OS << ' ' << Ptr; +} + void ASTDumper::dumpLocation(SourceLocation Loc) { SourceLocation SpellingLoc = SM->getSpellingLoc(Loc); @@ -163,15 +237,11 @@ void ASTDumper::dumpLocation(SourceLocation Loc) { } } -void ASTDumper::dumpSourceRange(const Stmt *Node) { +void ASTDumper::dumpSourceRange(SourceRange R) { // Can't translate locations if a SourceManager isn't available. if (!SM) return; - // TODO: If the parent expression is available, we can print a delta vs its - // location. - SourceRange R = Node->getSourceRange(); - OS << " <"; dumpLocation(R.getBegin()); if (R.getBegin() != R.getEnd()) { @@ -184,7 +254,7 @@ void ASTDumper::dumpSourceRange(const Stmt *Node) { } -void ASTDumper::dumpType(QualType T) { +void ASTDumper::dumpBareType(QualType T) { SplitQualType T_split = T.split(); OS << "'" << QualType::getAsString(T_split) << "'"; @@ -196,8 +266,14 @@ void ASTDumper::dumpType(QualType T) { } } -void ASTDumper::dumpDeclRef(Decl *D) { - OS << D->getDeclKindName() << ' ' << (void*) D; +void ASTDumper::dumpType(QualType T) { + OS << ' '; + dumpBareType(T); +} + +void ASTDumper::dumpBareDeclRef(Decl *D) { + OS << D->getDeclKindName(); + dumpPointer(D); if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) { OS << " '"; @@ -205,9 +281,132 @@ void ASTDumper::dumpDeclRef(Decl *D) { OS << "'"; } - if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) { - OS << ' '; + if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) dumpType(VD->getType()); +} + +void ASTDumper::dumpDeclRef(Decl *D, const char *Label) { + if (!D) + return; + + IndentScope Indent(*this); + if (Label) + OS << Label << ' '; + dumpBareDeclRef(D); +} + +void ASTDumper::dumpName(NamedDecl *ND) { + if (ND->getDeclName()) + OS << ' ' << ND->getNameAsString(); +} + +void ASTDumper::dumpDeclContext(DeclContext *DC) { + if (!DC) + return; + for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end(); + I != E; ++I) + dumpDecl(*I); +} + +//===----------------------------------------------------------------------===// +// C++ Utilities +//===----------------------------------------------------------------------===// + +void ASTDumper::dumpAccessSpecifier(AccessSpecifier AS) { + switch (AS) { + case AS_none: + break; + case AS_public: + OS << "public"; + break; + case AS_protected: + OS << "protected"; + break; + case AS_private: + OS << "private"; + break; + } +} + +void ASTDumper::dumpCXXCtorInitializer(CXXCtorInitializer *Init) { + IndentScope Indent(*this); + OS << "CXXCtorInitializer"; + if (Init->isAnyMemberInitializer()) { + OS << ' '; + dumpBareDeclRef(Init->getAnyMember()); + } else { + dumpType(QualType(Init->getBaseClass(), 0)); + } + dumpStmt(Init->getInit()); +} + +void ASTDumper::dumpTemplateParameters(TemplateParameterList *TPL) { + if (!TPL) + return; + + for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); + I != E; ++I) + dumpDecl(*I); +} + +void ASTDumper::dumpTemplateArgumentListInfo( + const TemplateArgumentListInfo &TALI) { + for (unsigned i = 0, e = TALI.size(); i < e; ++i) + dumpTemplateArgumentLoc(TALI[i]); +} + +void ASTDumper::dumpTemplateArgumentLoc(const TemplateArgumentLoc &A) { + dumpTemplateArgument(A.getArgument(), A.getSourceRange()); +} + +void ASTDumper::dumpTemplateArgumentList(const TemplateArgumentList &TAL) { + for (unsigned i = 0, e = TAL.size(); i < e; ++i) + dumpTemplateArgument(TAL[i]); +} + +void ASTDumper::dumpTemplateArgument(const TemplateArgument &A, SourceRange R) { + IndentScope Indent(*this); + OS << "TemplateArgument"; + if (R.isValid()) + dumpSourceRange(R); + + switch (A.getKind()) { + case TemplateArgument::Null: + OS << " null"; + break; + case TemplateArgument::Type: + OS << " type"; + dumpType(A.getAsType()); + break; + case TemplateArgument::Declaration: + OS << " decl"; + dumpDeclRef(A.getAsDecl()); + break; + case TemplateArgument::NullPtr: + OS << " nullptr"; + break; + case TemplateArgument::Integral: + OS << " integral"; + OS << ' ' << A.getAsIntegral(); + break; + case TemplateArgument::Template: + OS << " template "; + A.getAsTemplate().dump(OS); + break; + case TemplateArgument::TemplateExpansion: + OS << " template expansion"; + A.getAsTemplateOrTemplatePattern().dump(OS); + break; + case TemplateArgument::Expression: + OS << " expr"; + dumpStmt(A.getAsExpr()); + break; + case TemplateArgument::Pack: + OS << " pack"; + for (TemplateArgument::pack_iterator I = A.pack_begin(), E = A.pack_end(); + I != E; ++I) + dumpTemplateArgument(*I); + break; } } @@ -216,71 +415,514 @@ void ASTDumper::dumpDeclRef(Decl *D) { //===----------------------------------------------------------------------===// void ASTDumper::dumpDecl(Decl *D) { - // FIXME: Need to complete/beautify this... this code simply shows the - // nodes are where they need to be. - if (TypedefDecl *localType = dyn_cast<TypedefDecl>(D)) { - OS << "\"typedef " << localType->getUnderlyingType().getAsString() - << ' ' << *localType << '"'; - } else if (TypeAliasDecl *localType = dyn_cast<TypeAliasDecl>(D)) { - OS << "\"using " << *localType << " = " - << localType->getUnderlyingType().getAsString() << '"'; - } else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) { - OS << "\""; - // Emit storage class for vardecls. - if (VarDecl *V = dyn_cast<VarDecl>(VD)) { - if (V->getStorageClass() != SC_None) - OS << VarDecl::getStorageClassSpecifierString(V->getStorageClass()) - << " "; + IndentScope Indent(*this); + + if (!D) { + OS << "<<<NULL>>>"; + return; + } + + OS << D->getDeclKindName() << "Decl"; + dumpPointer(D); + dumpSourceRange(D->getSourceRange()); + DeclVisitor<ASTDumper>::Visit(D); + // Decls within functions are visited by the body + if (!isa<FunctionDecl>(*D) && !isa<ObjCMethodDecl>(*D)) + dumpDeclContext(dyn_cast<DeclContext>(D)); +} + +void ASTDumper::VisitLabelDecl(LabelDecl *D) { + dumpName(D); +} + +void ASTDumper::VisitTypedefDecl(TypedefDecl *D) { + dumpName(D); + dumpType(D->getUnderlyingType()); + if (D->isModulePrivate()) + OS << " __module_private__"; +} + +void ASTDumper::VisitEnumDecl(EnumDecl *D) { + if (D->isScoped()) { + if (D->isScopedUsingClassTag()) + OS << " class"; + else + OS << " struct"; + } + dumpName(D); + if (D->isModulePrivate()) + OS << " __module_private__"; + if (D->isFixed()) + dumpType(D->getIntegerType()); +} + +void ASTDumper::VisitRecordDecl(RecordDecl *D) { + OS << ' ' << D->getKindName(); + dumpName(D); + if (D->isModulePrivate()) + OS << " __module_private__"; +} + +void ASTDumper::VisitEnumConstantDecl(EnumConstantDecl *D) { + dumpName(D); + dumpType(D->getType()); + if (Expr *Init = D->getInitExpr()) + dumpStmt(Init); +} + +void ASTDumper::VisitIndirectFieldDecl(IndirectFieldDecl *D) { + dumpName(D); + dumpType(D->getType()); + for (IndirectFieldDecl::chain_iterator I = D->chain_begin(), + E = D->chain_end(); I != E; ++I) + dumpDeclRef(*I); +} + +void ASTDumper::VisitFunctionDecl(FunctionDecl *D) { + dumpName(D); + dumpType(D->getType()); + + StorageClass SC = D->getStorageClassAsWritten(); + if (SC != SC_None) + OS << ' ' << VarDecl::getStorageClassSpecifierString(SC); + if (D->isInlineSpecified()) + OS << " inline"; + if (D->isVirtualAsWritten()) + OS << " virtual"; + if (D->isModulePrivate()) + OS << " __module_private__"; + + if (D->isPure()) + OS << " pure"; + else if (D->isDeletedAsWritten()) + OS << " delete"; + + if (const FunctionTemplateSpecializationInfo *FTSI = + D->getTemplateSpecializationInfo()) + dumpTemplateArgumentList(*FTSI->TemplateArguments); + + for (llvm::ArrayRef<NamedDecl*>::iterator + I = D->getDeclsInPrototypeScope().begin(), + E = D->getDeclsInPrototypeScope().end(); I != E; ++I) + dumpDecl(*I); + + for (FunctionDecl::param_iterator I = D->param_begin(), E = D->param_end(); + I != E; ++I) + dumpDecl(*I); + + if (CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(D)) + for (CXXConstructorDecl::init_const_iterator I = C->init_begin(), + E = C->init_end(); I != E; ++I) + dumpCXXCtorInitializer(*I); + + if (D->doesThisDeclarationHaveABody()) + dumpStmt(D->getBody()); +} + +void ASTDumper::VisitFieldDecl(FieldDecl *D) { + dumpName(D); + dumpType(D->getType()); + if (D->isMutable()) + OS << " mutable"; + if (D->isModulePrivate()) + OS << " __module_private__"; + if (D->isBitField()) + dumpStmt(D->getBitWidth()); + if (Expr *Init = D->getInClassInitializer()) + dumpStmt(Init); +} + +void ASTDumper::VisitVarDecl(VarDecl *D) { + dumpName(D); + dumpType(D->getType()); + StorageClass SC = D->getStorageClassAsWritten(); + if (SC != SC_None) + OS << ' ' << VarDecl::getStorageClassSpecifierString(SC); + if (D->isThreadSpecified()) + OS << " __thread"; + if (D->isModulePrivate()) + OS << " __module_private__"; + if (D->isNRVOVariable()) + OS << " nrvo"; + if (D->hasInit()) + dumpStmt(D->getInit()); +} + +void ASTDumper::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { + dumpStmt(D->getAsmString()); +} + +void ASTDumper::VisitImportDecl(ImportDecl *D) { + OS << ' ' << D->getImportedModule()->getFullModuleName(); +} + +//===----------------------------------------------------------------------===// +// C++ Declarations +//===----------------------------------------------------------------------===// + +void ASTDumper::VisitNamespaceDecl(NamespaceDecl *D) { + dumpName(D); + if (D->isInline()) + OS << " inline"; + if (!D->isOriginalNamespace()) + dumpDeclRef(D->getOriginalNamespace(), "original"); +} + +void ASTDumper::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { + OS << ' '; + dumpBareDeclRef(D->getNominatedNamespace()); +} + +void ASTDumper::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { + dumpName(D); + dumpDeclRef(D->getAliasedNamespace()); +} + +void ASTDumper::VisitTypeAliasDecl(TypeAliasDecl *D) { + dumpName(D); + dumpType(D->getUnderlyingType()); +} + +void ASTDumper::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { + dumpName(D); + dumpTemplateParameters(D->getTemplateParameters()); + dumpDecl(D->getTemplatedDecl()); +} + +void ASTDumper::VisitCXXRecordDecl(CXXRecordDecl *D) { + VisitRecordDecl(D); + if (!D->isCompleteDefinition()) + return; + + for (CXXRecordDecl::base_class_iterator I = D->bases_begin(), + E = D->bases_end(); I != E; ++I) { + IndentScope Indent(*this); + if (I->isVirtual()) + OS << "virtual "; + dumpAccessSpecifier(I->getAccessSpecifier()); + dumpType(I->getType()); + if (I->isPackExpansion()) + OS << "..."; + } +} + +void ASTDumper::VisitStaticAssertDecl(StaticAssertDecl *D) { + dumpStmt(D->getAssertExpr()); + dumpStmt(D->getMessage()); +} + +void ASTDumper::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { + dumpName(D); + dumpTemplateParameters(D->getTemplateParameters()); + dumpDecl(D->getTemplatedDecl()); + for (FunctionTemplateDecl::spec_iterator I = D->spec_begin(), + E = D->spec_end(); I != E; ++I) { + switch (I->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + dumpDecl(*I); + break; + case TSK_ExplicitSpecialization: + dumpDeclRef(*I); + break; + } + } +} + +void ASTDumper::VisitClassTemplateDecl(ClassTemplateDecl *D) { + dumpName(D); + dumpTemplateParameters(D->getTemplateParameters()); + dumpDecl(D->getTemplatedDecl()); + for (ClassTemplateDecl::spec_iterator I = D->spec_begin(), E = D->spec_end(); + I != E; ++I) { + switch (I->getTemplateSpecializationKind()) { + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + dumpDecl(*I); + break; + case TSK_ExplicitSpecialization: + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + dumpDeclRef(*I); + break; } + } +} - std::string Name = VD->getNameAsString(); - VD->getType().getAsStringInternal(Name, - PrintingPolicy(VD->getASTContext().getLangOpts())); - OS << Name; +void ASTDumper::VisitClassTemplateSpecializationDecl( + ClassTemplateSpecializationDecl *D) { + VisitCXXRecordDecl(D); + dumpTemplateArgumentList(D->getTemplateArgs()); +} - // If this is a vardecl with an initializer, emit it. - if (VarDecl *V = dyn_cast<VarDecl>(VD)) { - if (V->getInit()) { - OS << " ="; - dumpStmt(V->getInit()); - } +void ASTDumper::VisitClassTemplatePartialSpecializationDecl( + ClassTemplatePartialSpecializationDecl *D) { + VisitClassTemplateSpecializationDecl(D); + dumpTemplateParameters(D->getTemplateParameters()); +} + +void ASTDumper::VisitClassScopeFunctionSpecializationDecl( + ClassScopeFunctionSpecializationDecl *D) { + dumpDeclRef(D->getSpecialization()); + if (D->hasExplicitTemplateArgs()) + dumpTemplateArgumentListInfo(D->templateArgs()); +} + +void ASTDumper::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { + if (D->wasDeclaredWithTypename()) + OS << " typename"; + else + OS << " class"; + if (D->isParameterPack()) + OS << " ..."; + dumpName(D); + if (D->hasDefaultArgument()) + dumpType(D->getDefaultArgument()); +} + +void ASTDumper::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { + dumpType(D->getType()); + if (D->isParameterPack()) + OS << " ..."; + dumpName(D); + if (D->hasDefaultArgument()) + dumpStmt(D->getDefaultArgument()); +} + +void ASTDumper::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { + if (D->isParameterPack()) + OS << " ..."; + dumpName(D); + dumpTemplateParameters(D->getTemplateParameters()); + if (D->hasDefaultArgument()) + dumpTemplateArgumentLoc(D->getDefaultArgument()); +} + +void ASTDumper::VisitUsingDecl(UsingDecl *D) { + OS << ' '; + D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); + OS << D->getNameAsString(); +} + +void +ASTDumper::VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D) { + OS << ' '; + D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); + OS << D->getNameAsString(); +} + +void ASTDumper::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { + OS << ' '; + D->getQualifier()->print(OS, D->getASTContext().getPrintingPolicy()); + OS << D->getNameAsString(); + dumpType(D->getType()); +} + +void ASTDumper::VisitUsingShadowDecl(UsingShadowDecl *D) { + OS << ' '; + dumpBareDeclRef(D->getTargetDecl()); +} + +void ASTDumper::VisitLinkageSpecDecl(LinkageSpecDecl *D) { + switch (D->getLanguage()) { + case LinkageSpecDecl::lang_c: OS << " C"; break; + case LinkageSpecDecl::lang_cxx: OS << " C++"; break; + } +} + +void ASTDumper::VisitAccessSpecDecl(AccessSpecDecl *D) { + OS << ' '; + dumpAccessSpecifier(D->getAccess()); +} + +void ASTDumper::VisitFriendDecl(FriendDecl *D) { + if (TypeSourceInfo *T = D->getFriendType()) + dumpType(T->getType()); + else + dumpDecl(D->getFriendDecl()); +} + +//===----------------------------------------------------------------------===// +// Obj-C Declarations +//===----------------------------------------------------------------------===// + +void ASTDumper::VisitObjCIvarDecl(ObjCIvarDecl *D) { + dumpName(D); + dumpType(D->getType()); + if (D->getSynthesize()) + OS << " synthesize"; + + switch (D->getAccessControl()) { + case ObjCIvarDecl::None: + OS << " none"; + break; + case ObjCIvarDecl::Private: + OS << " private"; + break; + case ObjCIvarDecl::Protected: + OS << " protected"; + break; + case ObjCIvarDecl::Public: + OS << " public"; + break; + case ObjCIvarDecl::Package: + OS << " package"; + break; + } +} + +void ASTDumper::VisitObjCMethodDecl(ObjCMethodDecl *D) { + if (D->isInstanceMethod()) + OS << " -"; + else + OS << " +"; + dumpName(D); + dumpType(D->getResultType()); + + if (D->isThisDeclarationADefinition()) + dumpDeclContext(D); + else { + for (ObjCMethodDecl::param_iterator I = D->param_begin(), + E = D->param_end(); I != E; ++I) { + dumpDecl(*I); } - OS << '"'; - } else if (TagDecl *TD = dyn_cast<TagDecl>(D)) { - // print a free standing tag decl (e.g. "struct x;"). - const char *tagname; - if (const IdentifierInfo *II = TD->getIdentifier()) - tagname = II->getNameStart(); - else - tagname = "<anonymous>"; - OS << '"' << TD->getKindName() << ' ' << tagname << ";\""; - // FIXME: print tag bodies. - } else if (UsingDirectiveDecl *UD = dyn_cast<UsingDirectiveDecl>(D)) { - // print using-directive decl (e.g. "using namespace x;") - const char *ns; - if (const IdentifierInfo *II = UD->getNominatedNamespace()->getIdentifier()) - ns = II->getNameStart(); - else - ns = "<anonymous>"; - OS << '"' << UD->getDeclKindName() << ns << ";\""; - } else if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) { - // print using decl (e.g. "using std::string;") - const char *tn = UD->isTypeName() ? "typename " : ""; - OS << '"' << UD->getDeclKindName() << tn; - UD->getQualifier()->print(OS, - PrintingPolicy(UD->getASTContext().getLangOpts())); - OS << ";\""; - } else if (LabelDecl *LD = dyn_cast<LabelDecl>(D)) { - OS << "label " << *LD; - } else if (StaticAssertDecl *SAD = dyn_cast<StaticAssertDecl>(D)) { - OS << "\"static_assert("; - dumpStmt(SAD->getAssertExpr()); - OS << ","; - dumpStmt(SAD->getMessage()); - OS << ");\""; - } else { - llvm_unreachable("Unexpected decl"); } + + if (D->isVariadic()) { + IndentScope Indent(*this); + OS << "..."; + } + + if (D->hasBody()) + dumpStmt(D->getBody()); +} + +void ASTDumper::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { + dumpName(D); + dumpDeclRef(D->getClassInterface()); + dumpDeclRef(D->getImplementation()); + for (ObjCCategoryDecl::protocol_iterator I = D->protocol_begin(), + E = D->protocol_end(); I != E; ++I) + dumpDeclRef(*I); +} + +void ASTDumper::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { + dumpName(D); + dumpDeclRef(D->getClassInterface()); + dumpDeclRef(D->getCategoryDecl()); +} + +void ASTDumper::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { + dumpName(D); + for (ObjCProtocolDecl::protocol_iterator I = D->protocol_begin(), + E = D->protocol_end(); I != E; ++I) + dumpDeclRef(*I); +} + +void ASTDumper::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { + dumpName(D); + dumpDeclRef(D->getSuperClass(), "super"); + dumpDeclRef(D->getImplementation()); + for (ObjCInterfaceDecl::protocol_iterator I = D->protocol_begin(), + E = D->protocol_end(); I != E; ++I) + dumpDeclRef(*I); +} + +void ASTDumper::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { + dumpName(D); + dumpDeclRef(D->getSuperClass(), "super"); + dumpDeclRef(D->getClassInterface()); + for (ObjCImplementationDecl::init_iterator I = D->init_begin(), + E = D->init_end(); I != E; ++I) + dumpCXXCtorInitializer(*I); +} + +void ASTDumper::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) { + dumpName(D); + dumpDeclRef(D->getClassInterface()); +} + +void ASTDumper::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { + dumpName(D); + dumpType(D->getType()); + + if (D->getPropertyImplementation() == ObjCPropertyDecl::Required) + OS << " required"; + else if (D->getPropertyImplementation() == ObjCPropertyDecl::Optional) + OS << " optional"; + + ObjCPropertyDecl::PropertyAttributeKind Attrs = D->getPropertyAttributes(); + if (Attrs != ObjCPropertyDecl::OBJC_PR_noattr) { + if (Attrs & ObjCPropertyDecl::OBJC_PR_readonly) + OS << " readonly"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_assign) + OS << " assign"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_readwrite) + OS << " readwrite"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_retain) + OS << " retain"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_copy) + OS << " copy"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_nonatomic) + OS << " nonatomic"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_atomic) + OS << " atomic"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_weak) + OS << " weak"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_strong) + OS << " strong"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_unsafe_unretained) + OS << " unsafe_unretained"; + if (Attrs & ObjCPropertyDecl::OBJC_PR_getter) + dumpDeclRef(D->getGetterMethodDecl(), "getter"); + if (Attrs & ObjCPropertyDecl::OBJC_PR_setter) + dumpDeclRef(D->getSetterMethodDecl(), "setter"); + } +} + +void ASTDumper::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { + dumpName(D->getPropertyDecl()); + if (D->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) + OS << " synthesize"; + else + OS << " dynamic"; + dumpDeclRef(D->getPropertyDecl()); + dumpDeclRef(D->getPropertyIvarDecl()); +} + +void ASTDumper::VisitBlockDecl(BlockDecl *D) { + for (BlockDecl::param_iterator I = D->param_begin(), E = D->param_end(); + I != E; ++I) + dumpDecl(*I); + + if (D->isVariadic()) { + IndentScope Indent(*this); + OS << "..."; + } + + if (D->capturesCXXThis()) { + IndentScope Indent(*this); + OS << "capture this"; + } + for (BlockDecl::capture_iterator I = D->capture_begin(), + E = D->capture_end(); I != E; ++I) { + IndentScope Indent(*this); + OS << "capture"; + if (I->isByRef()) + OS << " byref"; + if (I->isNested()) + OS << " nested"; + if (I->getVariable()) { + OS << ' '; + dumpBareDeclRef(I->getVariable()); + } + if (I->hasCopyExpr()) + dumpStmt(I->getCopyExpr()); + } + + dumpStmt(D->getBody()); } //===----------------------------------------------------------------------===// @@ -300,25 +942,22 @@ void ASTDumper::dumpStmt(Stmt *S) { return; } - Visit(S); + StmtVisitor<ASTDumper>::Visit(S); for (Stmt::child_range CI = S->children(); CI; ++CI) dumpStmt(*CI); } void ASTDumper::VisitStmt(Stmt *Node) { - OS << Node->getStmtClassName() << " " << (const void *)Node; - dumpSourceRange(Node); + OS << Node->getStmtClassName(); + |