aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Kornienko <alexfh@google.com>2012-12-20 02:09:13 +0000
committerAlexander Kornienko <alexfh@google.com>2012-12-20 02:09:13 +0000
commitd538ed9b2a617239d5bd56357663de62f6f9224c (patch)
tree4d89b1886df14de8f283d0916da56ee1c0b2c3c0
parentbf53dfac8195835028bd6347433f7dbebcc29fc1 (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.h9
-rw-r--r--include/clang/AST/TemplateName.h3
-rw-r--r--lib/AST/ASTDumper.cpp898
-rw-r--r--lib/AST/DeclPrinter.cpp36
-rw-r--r--lib/AST/StmtPrinter.cpp5
-rw-r--r--lib/AST/TemplateName.cpp8
-rw-r--r--test/CXX/dcl.decl/dcl.init/dcl.init.ref/p5-examples.cpp14
-rw-r--r--test/CodeGen/bitfield-2.c8
-rw-r--r--test/Misc/ast-dump-decl.c152
-rw-r--r--test/Misc/ast-dump-decl.cpp405
-rw-r--r--test/Misc/ast-dump-decl.m136
-rw-r--r--test/Misc/ast-dump-decl.mm23
-rw-r--r--test/Misc/ast-dump-stmt.c24
-rw-r--r--test/Misc/ast-dump-stmt.m14
-rw-r--r--test/Misc/ast-dump-templates.cpp6
-rw-r--r--test/Misc/ast-dump-wchar.cpp8
-rw-r--r--test/PCH/objc_stmts.m10
-rw-r--r--test/SemaTemplate/default-expr-arguments-2.cpp4
-rw-r--r--test/Tooling/clang-check-ast-dump.cpp19
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();
+