From: Alexander Kornienko Date: Thu, 20 Dec 2012 02:09:13 +0000 (+0000) Subject: Implement AST dumper for Decls. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d538ed9b2a617239d5bd56357663de62f6f9224c;p=clang 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 --- 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 { + class ASTDumper + : public DeclVisitor, public StmtVisitor { 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(D)) { OS << " '"; @@ -205,9 +281,132 @@ void ASTDumper::dumpDeclRef(Decl *D) { OS << "'"; } - if (ValueDecl *VD = dyn_cast(D)) { - OS << ' '; + if (ValueDecl *VD = dyn_cast(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(D)) { - OS << "\"typedef " << localType->getUnderlyingType().getAsString() - << ' ' << *localType << '"'; - } else if (TypeAliasDecl *localType = dyn_cast(D)) { - OS << "\"using " << *localType << " = " - << localType->getUnderlyingType().getAsString() << '"'; - } else if (ValueDecl *VD = dyn_cast(D)) { - OS << "\""; - // Emit storage class for vardecls. - if (VarDecl *V = dyn_cast(VD)) { - if (V->getStorageClass() != SC_None) - OS << VarDecl::getStorageClassSpecifierString(V->getStorageClass()) - << " "; + IndentScope Indent(*this); + + if (!D) { + OS << "<<>>"; + return; + } + + OS << D->getDeclKindName() << "Decl"; + dumpPointer(D); + dumpSourceRange(D->getSourceRange()); + DeclVisitor::Visit(D); + // Decls within functions are visited by the body + if (!isa(*D) && !isa(*D)) + dumpDeclContext(dyn_cast(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::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(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(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(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 = ""; - OS << '"' << TD->getKindName() << ' ' << tagname << ";\""; - // FIXME: print tag bodies. - } else if (UsingDirectiveDecl *UD = dyn_cast(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 = ""; - OS << '"' << UD->getDeclKindName() << ns << ";\""; - } else if (UsingDecl *UD = dyn_cast(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(D)) { - OS << "label " << *LD; - } else if (StaticAssertDecl *SAD = dyn_cast(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::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(); + dumpPointer(Node); + dumpSourceRange(Node->getSourceRange()); } void ASTDumper::VisitDeclStmt(DeclStmt *Node) { VisitStmt(Node); - for (DeclStmt::decl_iterator DI = Node->decl_begin(), DE = Node->decl_end(); - DI != DE; ++DI) { - IndentScope Indent(*this); - Decl *D = *DI; - OS << (void*) D << " "; - dumpDecl(D); - } + for (DeclStmt::decl_iterator I = Node->decl_begin(), E = Node->decl_end(); + I != E; ++I) + dumpDecl(*I); } void ASTDumper::VisitLabelStmt(LabelStmt *Node) { @@ -328,8 +967,8 @@ void ASTDumper::VisitLabelStmt(LabelStmt *Node) { void ASTDumper::VisitGotoStmt(GotoStmt *Node) { VisitStmt(Node); - OS << " '" << Node->getLabel()->getName() - << "':" << (void*)Node->getLabel(); + OS << " '" << Node->getLabel()->getName() << "'"; + dumpPointer(Node->getLabel()); } //===----------------------------------------------------------------------===// @@ -338,7 +977,6 @@ void ASTDumper::VisitGotoStmt(GotoStmt *Node) { void ASTDumper::VisitExpr(Expr *Node) { VisitStmt(Node); - OS << ' '; dumpType(Node->getType()); switch (Node->getValueKind()) { @@ -405,10 +1043,10 @@ void ASTDumper::VisitDeclRefExpr(DeclRefExpr *Node) { VisitExpr(Node); OS << " "; - dumpDeclRef(Node->getDecl()); + dumpBareDeclRef(Node->getDecl()); if (Node->getDecl() != Node->getFoundDecl()) { OS << " ("; - dumpDeclRef(Node->getFoundDecl()); + dumpBareDeclRef(Node->getFoundDecl()); OS << ")"; } } @@ -425,15 +1063,15 @@ void ASTDumper::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *Node) { if (I == E) OS << " empty"; for (; I != E; ++I) - OS << " " << (void*) *I; + dumpPointer(*I); } void ASTDumper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { VisitExpr(Node); OS << " " << Node->getDecl()->getDeclKindName() - << "Decl='" << *Node->getDecl() - << "' " << (void*)Node->getDecl(); + << "Decl='" << *Node->getDecl() << "'"; + dumpPointer(Node->getDecl()); if (Node->isFreeIvar()) OS << " isFreeIvar"; } @@ -482,13 +1120,13 @@ void ASTDumper::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) { VisitExpr(Node); switch(Node->getKind()) { case UETT_SizeOf: - OS << " sizeof "; + OS << " sizeof"; break; case UETT_AlignOf: - OS << " alignof "; + OS << " alignof"; break; case UETT_VecStep: - OS << " vec_step "; + OS << " vec_step"; break; } if (Node->isArgumentType()) @@ -497,9 +1135,8 @@ void ASTDumper::VisitUnaryExprOrTypeTraitExpr(UnaryExprOrTypeTraitExpr *Node) { void ASTDumper::VisitMemberExpr(MemberExpr *Node) { VisitExpr(Node); - OS << " " << (Node->isArrow() ? "->" : ".") - << *Node->getMemberDecl() << ' ' - << (void*)Node->getMemberDecl(); + OS << " " << (Node->isArrow() ? "->" : ".") << *Node->getMemberDecl(); + dumpPointer(Node->getMemberDecl()); } void ASTDumper::VisitExtVectorElementExpr(ExtVectorElementExpr *Node) { @@ -516,36 +1153,14 @@ void ASTDumper::VisitCompoundAssignOperator(CompoundAssignOperator *Node) { VisitExpr(Node); OS << " '" << BinaryOperator::getOpcodeStr(Node->getOpcode()) << "' ComputeLHSTy="; - dumpType(Node->getComputationLHSType()); + dumpBareType(Node->getComputationLHSType()); OS << " ComputeResultTy="; - dumpType(Node->getComputationResultType()); + dumpBareType(Node->getComputationResultType()); } void ASTDumper::VisitBlockExpr(BlockExpr *Node) { VisitExpr(Node); - - BlockDecl *block = Node->getBlockDecl(); - OS << " decl=" << block; - - if (block->capturesCXXThis()) { - IndentScope Indent(*this); - OS << "capture this"; - } - for (BlockDecl::capture_iterator - i = block->capture_begin(), e = block->capture_end(); i != e; ++i) { - IndentScope Indent(*this); - OS << "capture "; - if (i->isByRef()) - OS << "byref "; - if (i->isNested()) - OS << "nested "; - if (i->getVariable()) - dumpDeclRef(i->getVariable()); - if (i->hasCopyExpr()) - dumpStmt(i->getCopyExpr()); - } - - dumpStmt(block->getBody()); + dumpDecl(Node->getBlockDecl()); } void ASTDumper::VisitOpaqueValueExpr(OpaqueValueExpr *Node) { @@ -559,8 +1174,8 @@ void ASTDumper::VisitOpaqueValueExpr(OpaqueValueExpr *Node) { void ASTDumper::VisitAddrLabelExpr(AddrLabelExpr *Node) { VisitExpr(Node); - OS << " " << Node->getLabel()->getName() - << " " << (void*)Node->getLabel(); + OS << " " << Node->getLabel()->getName(); + dumpPointer(Node->getLabel()); } //===----------------------------------------------------------------------===// @@ -610,15 +1225,14 @@ void ASTDumper::VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *Node) { void ASTDumper::VisitExprWithCleanups(ExprWithCleanups *Node) { VisitExpr(Node); - for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i) { - IndentScope Indent(*this); - OS << "cleanup "; - dumpDeclRef(Node->getObject(i)); - } + for (unsigned i = 0, e = Node->getNumObjects(); i != e; ++i) + dumpDeclRef(Node->getObject(i), "cleanup"); } void ASTDumper::dumpCXXTemporary(CXXTemporary *Temporary) { - OS << "(CXXTemporary " << (void *)Temporary << ")"; + OS << "(CXXTemporary"; + dumpPointer(Temporary); + OS << ")"; } //===----------------------------------------------------------------------===// @@ -634,7 +1248,7 @@ void ASTDumper::VisitObjCMessageExpr(ObjCMessageExpr *Node) { case ObjCMessageExpr::Class: OS << " class="; - dumpType(Node->getClassReceiver()); + dumpBareType(Node->getClassReceiver()); break; case ObjCMessageExpr::SuperInstance: @@ -654,17 +1268,14 @@ void ASTDumper::VisitObjCBoxedExpr(ObjCBoxedExpr *Node) { void ASTDumper::VisitObjCAtCatchStmt(ObjCAtCatchStmt *Node) { VisitStmt(Node); - if (VarDecl *CatchParam = Node->getCatchParamDecl()) { - OS << " catch parm = "; + if (VarDecl *CatchParam = Node->getCatchParamDecl()) dumpDecl(CatchParam); - } else { + else OS << " catch all"; - } } void ASTDumper::VisitObjCEncodeExpr(ObjCEncodeExpr *Node) { VisitExpr(Node); - OS << " "; dumpType(Node->getEncodedType()); } @@ -737,6 +1348,19 @@ void ASTDumper::VisitObjCBoolLiteralExpr(ObjCBoolLiteralExpr *Node) { OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no"); } +//===----------------------------------------------------------------------===// +// Decl method implementations +//===----------------------------------------------------------------------===// + +void Decl::dump() const { + dump(llvm::errs()); +} + +void Decl::dump(raw_ostream &OS) const { + ASTDumper P(&getASTContext().getSourceManager(), OS); + P.dumpDecl(const_cast(this)); +} + //===----------------------------------------------------------------------===// // Stmt method implementations //===----------------------------------------------------------------------===// diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 572e3d0bc7..4a7344c982 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file implements the Decl::dump method, which pretty print the +// This file implements the Decl::print method, which pretty prints the // AST back out to C/Objective-C/C++/Objective-C++ code. // //===----------------------------------------------------------------------===// @@ -176,16 +176,6 @@ void DeclContext::dumpDeclContext() const { Printer.VisitDeclContext(const_cast(this), /*Indent=*/false); } -void Decl::dump() const { - dump(llvm::errs()); -} - -void Decl::dump(raw_ostream &Out) const { - PrintingPolicy Policy = getASTContext().getPrintingPolicy(); - Policy.DumpSourceManager = &getASTContext().getSourceManager(); - print(Out, Policy, /*Indentation*/ 0, /*PrintInstantiation*/ true); -} - raw_ostream& DeclPrinter::Indent(unsigned Indentation) { for (unsigned i = 0; i != Indentation; ++i) Out << " "; @@ -242,18 +232,18 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) { if (isa(*D)) continue; - if (!Policy.DumpSourceManager) { - // Skip over implicit declarations in pretty-printing mode. - if (D->isImplicit()) continue; - // FIXME: Ugly hack so we don't pretty-print the builtin declaration - // of __builtin_va_list or __[u]int128_t. There should be some other way - // to check that. - if (NamedDecl *ND = dyn_cast(*D)) { - if (IdentifierInfo *II = ND->getIdentifier()) { - if (II->isStr("__builtin_va_list") || - II->isStr("__int128_t") || II->isStr("__uint128_t")) - continue; - } + // Skip over implicit declarations in pretty-printing mode. + if (D->isImplicit()) + continue; + + // FIXME: Ugly hack so we don't pretty-print the builtin declaration + // of __builtin_va_list or __[u]int128_t. There should be some other way + // to check that. + if (NamedDecl *ND = dyn_cast(*D)) { + if (IdentifierInfo *II = ND->getIdentifier()) { + if (II->isStr("__builtin_va_list") || + II->isStr("__int128_t") || II->isStr("__uint128_t")) + continue; } } diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 0c741495b9..f021c71dca 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -1875,11 +1875,6 @@ void Stmt::printPretty(raw_ostream &OS, return; } - if (Policy.DumpSourceManager) { - dump(OS, *Policy.DumpSourceManager); - return; - } - StmtPrinter P(OS, Helper, Policy, Indentation); P.Visit(const_cast(this)); } diff --git a/lib/AST/TemplateName.cpp b/lib/AST/TemplateName.cpp index c86fe8c270..f68dbda7c7 100644 --- a/lib/AST/TemplateName.cpp +++ b/lib/AST/TemplateName.cpp @@ -168,9 +168,13 @@ const DiagnosticBuilder &clang::operator<<(const DiagnosticBuilder &DB, return DB << NameStr; } -void TemplateName::dump() const { +void TemplateName::dump(raw_ostream &OS) const { LangOptions LO; // FIXME! LO.CPlusPlus = true; LO.Bool = true; - print(llvm::errs(), PrintingPolicy(LO)); + print(OS, PrintingPolicy(LO)); +} + +void TemplateName::dump() const { + dump(llvm::errs()); } diff --git a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp index 08d963951c..be1113d47e 100644 --- a/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp +++ b/test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp @@ -3,10 +3,10 @@ // CHECK: example0 void example0() { double d = 2.0; - // CHECK: double &rd = + // CHECK: VarDecl{{.*}}rd 'double &' // CHECK-NEXT: DeclRefExpr double &rd = d; - // CHECK: const double &rcd = + // CHECK: VarDecl{{.*}}rcd 'const double &' // CHECK-NEXT: ImplicitCastExpr{{.*}}'const double' lvalue const double &rcd = d; } @@ -16,10 +16,10 @@ struct B : A { } b; // CHECK: example1 void example1() { - // CHECK: A &ra = + // CHECK: VarDecl{{.*}}ra 'struct A &' // CHECK: ImplicitCastExpr{{.*}}'struct A' lvalue A &ra = b; - // CHECK: const A &rca = + // CHECK: VarDecl{{.*}}rca 'const struct A &' // CHECK: ImplicitCastExpr{{.*}}'const struct A' lvalue // CHECK: ImplicitCastExpr{{.*}}'struct A' lvalue const A& rca = b; @@ -33,12 +33,12 @@ struct X { // CHECK: example2 void example2() { - // CHECK: const A &rca = + // CHECK: VarDecl{{.*}}rca 'const struct A &' // CHECK: ImplicitCastExpr{{.*}}'const struct A' // CHECK: ImplicitCastExpr{{.*}}'struct A' // CHECK: CallExpr{{.*}}B const A &rca = f(); - // CHECK: const A &r = + // CHECK: VarDecl{{.*}}r 'const struct A &' // CHECK: ImplicitCastExpr{{.*}}'const struct A' // CHECK: ImplicitCastExpr{{.*}}'struct A' // CHECK: CXXMemberCallExpr{{.*}}'struct B' @@ -47,7 +47,7 @@ void example2() { // CHECK: example3 void example3() { - // CHECK: const double &rcd2 = + // CHECK: VarDecl{{.*}}rcd2 'const double &' // CHECK: ImplicitCastExpr{{.*}} const double& rcd2 = 2; } diff --git a/test/CodeGen/bitfield-2.c b/test/CodeGen/bitfield-2.c index fc85a8080a..867ed8c2ce 100644 --- a/test/CodeGen/bitfield-2.c +++ b/test/CodeGen/bitfield-2.c @@ -9,7 +9,7 @@ // PR6176 // CHECK-RECORD: *** Dumping IRgen Record Layout -// CHECK-RECORD: Record: struct s0 +// CHECK-RECORD: Record: (RecordDecl{{.*}}s0 // CHECK-RECORD: Layout: // CHECK-RECORD: IsZeroInitializable:1 @@ -49,7 +49,7 @@ unsigned long long test_0() { // PR5591 // CHECK-RECORD: *** Dumping IRgen Record Layout -// CHECK-RECORD: Record: struct s1 +// CHECK-RECORD: Record: (RecordDecl{{.*}}s1 // CHECK-RECORD: Layout: // CHECK-RECORD: IsZeroInitializable:1 @@ -97,7 +97,7 @@ unsigned long long test_1() { // PR5567 // CHECK-RECORD: *** Dumping IRgen Record Layout -// CHECK-RECORD: Record: union u2 +// CHECK-RECORD: Record: (RecordDecl{{.*}}u2 // CHECK-RECORD: Layout: // CHECK-RECORD: IsZeroInitializable:1 @@ -269,7 +269,7 @@ _Bool test_6() { // Check that we compute the best alignment possible for each access. // // CHECK-RECORD: *** Dumping IRgen Record Layout -// CHECK-RECORD: Record: struct s7 +// CHECK-RECORD: Record: (RecordDecl{{.*}}s7 // CHECK-RECORD: Layout: TestLocation + +struct TestIndent { + int x; +}; +// CHECK: {{^\(RecordDecl.*TestIndent[^()]*$}} +// CHECK-NEXT: {{^ \(FieldDecl.*x[^()]*\)\)$}} + +struct TestChildren { + int x; + struct y { + int z; + }; +}; +// CHECK: RecordDecl{{.*}}TestChildren +// CHECK-NEXT: FieldDecl{{.*}}x +// CHECK-NEXT: RecordDecl{{.*}}y +// CHECK-NEXT: FieldDecl{{.*}}z + +// CHECK-TU: TranslationUnitDecl + +void testLabelDecl() { + __label__ TestLabelDecl; + TestLabelDecl: goto TestLabelDecl; +} +// CHECK: LabelDecl{{.*}} TestLabelDecl + +typedef int TestTypedefDecl; +// CHECK: TypedefDecl{{.*}} TestTypedefDecl 'int' + +__module_private__ typedef int TestTypedefDeclPrivate; +// CHECK: TypedefDecl{{.*}} TestTypedefDeclPrivate 'int' __module_private__ + +enum TestEnumDecl { + testEnumDecl +}; +// CHECK: EnumDecl{{.*}} TestEnumDecl +// CHECK-NEXT: EnumConstantDecl{{.*}} testEnumDecl + +struct TestEnumDeclAnon { + enum { + testEnumDeclAnon + } e; +}; +// CHECK: RecordDecl{{.*}} TestEnumDeclAnon +// CHECK-NEXT: EnumDecl{{.*>$}} + +enum TestEnumDeclForward; +// CHECK: EnumDecl{{.*}} TestEnumDeclForward + +__module_private__ enum TestEnumDeclPrivate; +// CHECK: EnumDecl{{.*}} TestEnumDeclPrivate __module_private__ + +struct TestRecordDecl { + int i; +}; +// CHECK: RecordDecl{{.*}} struct TestRecordDecl +// CHECK-NEXT: FieldDecl + +struct TestRecordDeclEmpty { +}; +// CHECK: RecordDecl{{.*}} struct TestRecordDeclEmpty + +struct TestRecordDeclAnon1 { + struct { + } testRecordDeclAnon1; +}; +// CHECK: RecordDecl{{.*}} struct TestRecordDeclAnon1 +// CHECK-NEXT: RecordDecl{{.*}} struct + +struct TestRecordDeclAnon2 { + struct { + }; +}; +// CHECK: RecordDecl{{.*}} struct TestRecordDeclAnon2 +// CHECK-NEXT: RecordDecl{{.*}} struct + +struct TestRecordDeclForward; +// CHECK: RecordDecl{{.*}} struct TestRecordDeclForward + +__module_private__ struct TestRecordDeclPrivate; +// CHECK: RecordDecl{{.*}} struct TestRecordDeclPrivate __module_private__ + +enum testEnumConstantDecl { + TestEnumConstantDecl, + TestEnumConstantDeclInit = 1 +}; +// CHECK: EnumConstantDecl{{.*}} TestEnumConstantDecl 'int' +// CHECK: EnumConstantDecl{{.*}} TestEnumConstantDeclInit 'int' +// CHECK-NEXT: IntegerLiteral + +struct testIndirectFieldDecl { + struct { + int TestIndirectFieldDecl; + }; +}; +// CHECK: IndirectFieldDecl{{.*}} TestIndirectFieldDecl 'int' +// CHECK-NEXT: Field{{.*}} '' +// CHECK-NEXT: Field{{.*}} 'TestIndirectFieldDecl' + +int TestFunctionDecl(int x, enum { e } y) { + return x; +} +// CHECK: FunctionDecl{{.*}} TestFunctionDecl 'int (int, enum {{.*}})' +// CHECK-NEXT: EnumDecl +// CHECK-NEXT: EnumConstantDecl{{.*}} e +// CHECK-NEXT: ParmVarDecl{{.*}} x +// CHECK-NEXT: ParmVarDecl{{.*}} y +// CHECK-NEXT: CompoundStmt + +int TestFunctionDeclProto(int x); +// CHECK: FunctionDecl{{.*}} TestFunctionDeclProto 'int (int)' +// CHECK-NEXT: ParmVarDecl{{.*}} x + +extern int TestFunctionDeclSC(); +// CHECK: FunctionDecl{{.*}} TestFunctionDeclSC 'int ()' extern + +inline int TestFunctionDeclInline(); +// CHECK: FunctionDecl{{.*}} TestFunctionDeclInline 'int ()' inline + +struct testFieldDecl { + int TestFieldDecl; + int TestFieldDeclWidth : 1; + __module_private__ int TestFieldDeclPrivate; +}; +// CHECK: FieldDecl{{.*}} TestFieldDecl 'int' +// CHECK: FieldDecl{{.*}} TestFieldDeclWidth 'int' +// CHECK-NEXT: IntegerLiteral +// CHECK: FieldDecl{{.*}} TestFieldDeclPrivate 'int' __module_private__ + +int TestVarDecl; +// CHECK: VarDecl{{.*}} TestVarDecl 'int' + +extern int TestVarDeclSC; +// CHECK: VarDecl{{.*}} TestVarDeclSC 'int' extern + +__thread int TestVarDeclThread; +// CHECK: VarDecl{{.*}} TestVarDeclThread 'int' __thread + +__module_private__ int TestVarDeclPrivate; +// CHECK: VarDecl{{.*}} TestVarDeclPrivate 'int' __module_private__ + +int TestVarDeclInit = 0; +// CHECK: VarDecl{{.*}} TestVarDeclInit 'int' +// CHECK-NEXT: IntegerLiteral + +void testParmVarDecl(int TestParmVarDecl); +// CHECK: ParmVarDecl{{.*}} TestParmVarDecl 'int' diff --git a/test/Misc/ast-dump-decl.cpp b/test/Misc/ast-dump-decl.cpp new file mode 100644 index 0000000000..ab847cac6f --- /dev/null +++ b/test/Misc/ast-dump-decl.cpp @@ -0,0 +1,405 @@ +// RUN: %clang_cc1 -std=c++11 -fms-extensions -ast-dump -ast-dump-filter Test %s | FileCheck -check-prefix CHECK -strict-whitespace %s + +class testEnumDecl { + enum class TestEnumDeclScoped; + enum TestEnumDeclFixed : int; +}; +// CHECK: EnumDecl{{.*}} class TestEnumDeclScoped 'int' +// CHECK: EnumDecl{{.*}} TestEnumDeclFixed 'int' + +class testFieldDecl { + int TestFieldDeclInit = 0; +}; +// CHECK: FieldDecl{{.*}} TestFieldDeclInit 'int' +// CHECK-NEXT: IntegerLiteral + +namespace testVarDeclNRVO { + class A { }; + A foo() { + A TestVarDeclNRVO; + return TestVarDeclNRVO; + } +} +// CHECK: VarDecl{{.*}} TestVarDeclNRVO 'class testVarDeclNRVO::A' nrvo + +void testParmVarDeclInit(int TestParmVarDeclInit = 0); +// CHECK: ParmVarDecl{{.*}} TestParmVarDeclInit 'int' +// CHECK-NEXT: IntegerLiteral{{.*}} + +namespace TestNamespaceDecl { + int i; +} +// CHECK: NamespaceDecl{{.*}} TestNamespaceDecl +// CHECK-NEXT: VarDecl + +namespace TestNamespaceDecl { + int j; +} +// CHECK: NamespaceDecl{{.*}} TestNamespaceDecl +// CHECK-NEXT: original Namespace +// CHECK-NEXT: VarDecl + +inline namespace TestNamespaceDeclInline { +} +// CHECK: NamespaceDecl{{.*}} TestNamespaceDeclInline inline + +namespace testUsingDirectiveDecl { + namespace A { + } +} +namespace TestUsingDirectiveDecl { + using namespace testUsingDirectiveDecl::A; +} +// CHECK: NamespaceDecl{{.*}} TestUsingDirectiveDecl +// CHECK-NEXT: UsingDirectiveDecl{{.*}} Namespace{{.*}} 'A' + +namespace testNamespaceAlias { + namespace A { + } +} +namespace TestNamespaceAlias = testNamespaceAlias::A; +// CHECK: NamespaceAliasDecl{{.*}} TestNamespaceAlias +// CHECK-NEXT: Namespace{{.*}} 'A' + +using TestTypeAliasDecl = int; +// CHECK: TypeAliasDecl{{.*}} TestTypeAliasDecl 'int' + +namespace testTypeAliasTemplateDecl { + template class A; + template using TestTypeAliasTemplateDecl = A; +} +// CHECK: TypeAliasTemplateDecl{{.*}} TestTypeAliasTemplateDecl +// CHECK-NEXT: TemplateTypeParmDecl +// CHECK-NEXT: TypeAliasDecl{{.*}} TestTypeAliasTemplateDecl 'A' + +namespace testCXXRecordDecl { + class A { }; + class B { }; + class TestCXXRecordDecl : virtual A, public B { + int i; + }; +} +// CHECK: CXXRecordDecl{{.*}} class TestCXXRecordDecl +// CHECK-NEXT: virtual private 'class testCXXRecordDecl::A' +// CHECK-NEXT: public 'class testCXXRecordDecl::B' +// CHECK-NEXT: CXXRecordDecl{{.*}} class TestCXXRecordDecl +// CHECK-NEXT: FieldDecl + +template +class TestCXXRecordDeclPack : public T... { +}; +// CHECK: CXXRecordDecl{{.*}} class TestCXXRecordDeclPack +// CHECK-NEXT: public 'T'... +// CHECK-NEXT: CXXRecordDecl{{.*}} class TestCXXRecordDeclPack + +__module_private__ class TestCXXRecordDeclPrivate; +// CHECK: CXXRecordDecl{{.*}} class TestCXXRecordDeclPrivate __module_private__ + +class testCXXMethodDecl { + __module_private__ void TestCXXMethodDeclPrivate(); + virtual void TestCXXMethodDeclPure() = 0; + void TestCXXMethodDeclDelete() = delete; + void TestCXXMethodDeclThrow() throw(); + void TestCXXMethodDeclThrowType() throw(int); +}; +// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclPrivate 'void (void)' __module_private__ +// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclPure 'void (void)' virtual pure +// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclDelete 'void (void)' delete +// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclThrow 'void (void) throw()' +// CHECK: CXXMethodDecl{{.*}} TestCXXMethodDeclThrowType 'void (void) throw(int)' + +namespace testCXXConstructorDecl { + class A { }; + class TestCXXConstructorDecl : public A { + int I; + TestCXXConstructorDecl(A &a, int i) : A(a), I(i) { } + }; +} +// CHECK: CXXConstructorDecl{{.*}} TestCXXConstructorDecl 'void {{.*}}' +// CHECK-NEXT: ParmVarDecl{{.*}} a +// CHECK-NEXT: ParmVarDecl{{.*}} i +// CHECK-NEXT: CXXCtorInitializer{{.*}}A +// CHECK-NEXT: Expr +// CHECK: CXXCtorInitializer{{.*}}I +// CHECK-NEXT: Expr +// CHECK: CompoundStmt + +class TestCXXDestructorDecl { + ~TestCXXDestructorDecl() { } +}; +// CHECK: CXXDestructorDecl{{.*}} ~TestCXXDestructorDecl 'void (void) noexcept' +// CHECK-NEXT: CompoundStmt + +class TestCXXConversionDecl { + operator int() { return 0; } +}; +// CHECK: CXXConversionDecl{{.*}} operator int 'int (void)' +// CHECK-NEXT: CompoundStmt + +namespace TestStaticAssertDecl { + static_assert(true, "msg"); +} +// CHECK: NamespaceDecl{{.*}} TestStaticAssertDecl +// CHECK-NEXT: StaticAssertDecl{{.*>$}} +// CHECK-NEXT: CXXBoolLiteralExpr +// CHECK-NEXT: StringLiteral + +namespace testFunctionTemplateDecl { + class A { }; + class B { }; + class C { }; + class D { }; + template void TestFunctionTemplate(T) { } + + // implicit instantiation + void bar(A a) { TestFunctionTemplate(a); } + + // explicit specialization + template<> void TestFunctionTemplate(B); + + // explicit instantiation declaration + extern template void TestFunctionTemplate(C); + + // explicit instantiation definition + template void TestFunctionTemplate(D); +} +// CHECK: FunctionTemplateDecl{{.*}} TestFunctionTemplate +// CHECK-NEXT: TemplateTypeParmDecl +// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate 'void (T)' +// CHECK-NEXT: ParmVarDecl{{.*}} 'T' +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}A +// CHECK-NEXT: TemplateArgument +// CHECK-NEXT: ParmVarDecl +// CHECK-NEXT: CompoundStmt +// CHECK-NEXT: Function{{.*}} 'TestFunctionTemplate' {{.*}}B +// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}C +// CHECK-NEXT: TemplateArgument +// CHECK-NEXT: ParmVarDecl +// CHECK-NEXT: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}D +// CHECK-NEXT: TemplateArgument +// CHECK-NEXT: ParmVarDecl +// CHECK-NEXT: CompoundStmt +// CHECK: FunctionDecl{{.*}} TestFunctionTemplate {{.*}}B +// CHECK-NEXT: TemplateArgument +// CHECK-NEXT: ParmVarDecl + +namespace testClassTemplateDecl { + class A { }; + class B { }; + class C { }; + class D { }; + + template class TestClassTemplate { + int i; + }; + + // implicit instantiation + TestClassTemplate a; + + // explicit specialization + template<> class TestClassTemplate { + int j; + }; + + // explicit instantiation declaration + extern template class TestClassTemplate; + + // explicit instantiation definition + template class TestClassTemplate; + + // partial explicit specialization + template class TestClassTemplatePartial { + int i; + }; + template class TestClassTemplatePartial { + int j; + }; +} +// CHECK: ClassTemplateDecl{{.*}} TestClassTemplate +// CHECK-NEXT: TemplateTypeParmDecl +// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate +// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate +// CHECK-NEXT: FieldDecl{{.*}} i +// CHECK-NEXT: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate +// CHECK-NEXT: TemplateArgument{{.*}}A +// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate +// CHECK-NEXT: FieldDecl{{.*}} i +// CHECK: ClassTemplateSpecialization{{.*}} 'TestClassTemplate' +// CHECK-NEXT: ClassTemplateSpecialization{{.*}} 'TestClassTemplate' +// CHECK-NEXT: ClassTemplateSpecialization{{.*}} 'TestClassTemplate' + +// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate +// CHECK-NEXT: TemplateArgument{{.*}}B +// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate +// CHECK-NEXT: FieldDecl{{.*}} j + +// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate +// CHECK-NEXT: TemplateArgument{{.*}}C +// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate +// CHECK-NEXT: FieldDecl{{.*}} i + +// CHECK: ClassTemplateSpecializationDecl{{.*}} class TestClassTemplate +// CHECK-NEXT: TemplateArgument{{.*}}D +// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplate +// CHECK-NEXT: FieldDecl{{.*}} i + +// CHECK: ClassTemplatePartialSpecializationDecl{{.*}} class TestClassTemplatePartial +// CHECK-NEXT: TemplateArgument +// CHECK-NEXT: TemplateArgument{{.*}}A +// CHECK-NEXT: TemplateTypeParmDecl +// CHECK-NEXT: CXXRecordDecl{{.*}} class TestClassTemplatePartial +// CHECK-NEXT: FieldDecl{{.*}} j + +template +class TestClassScopeFunctionSpecialization { + template void foo(U a) { } + template<> void foo(int a) { } +}; +// CHECK: ClassScopeFunctionSpecializationDecl +// CHECK-NEXT: CXXMethod{{.*}} 'foo' 'void (int)' +// CHECK-NEXT: TemplateArgument{{.*}} 'int' + +namespace TestTemplateTypeParmDecl { + template void foo(); +} +// CHECK: NamespaceDecl{{.*}} TestTemplateTypeParmDecl +// CHECK-NEXT: FunctionTemplateDecl +// CHECK-NEXT: TemplateTypeParmDecl{{.*}} typename ... T +// CHECK-NEXT: TemplateTypeParmDecl{{.*}} class U 'int' + +namespace TestNonTypeTemplateParmDecl { + template void foo(); +} +// CHECK: NamespaceDecl{{.*}} TestNonTypeTemplateParmDecl +// CHECK-NEXT: FunctionTemplateDecl +// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' I +// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 1 +// CHECK-NEXT: NonTypeTemplateParmDecl{{.*}} 'int' ... J + +namespace TestTemplateTemplateParmDecl { + template class A; + template