From 071e4da10b07ca5278a7ce9dcabd853e0d57e5a4 Mon Sep 17 00:00:00 2001 From: Mike Stump Date: Tue, 10 Feb 2009 20:16:46 +0000 Subject: [PATCH] Fixup -ast-print so that: We handle indentation of decls better. We Indent extern "C" { } stuff better. We print out structure contents more often. We handle pass indentation information into the statement printer, so that nested things come out more indented. We print out FieldDecls. We print out Vars. We print out namespaces. We indent functions better. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64232 91177308-0d34-0410-b5e6-96231b3b80d8 --- Driver/ASTConsumers.cpp | 99 ++++++++++++++++++++++++++++++++++++---- include/clang/AST/Stmt.h | 3 +- lib/AST/StmtPrinter.cpp | 37 ++++++++++----- 3 files changed, 117 insertions(+), 22 deletions(-) diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp index 78b199680a..c504f0fc9a 100644 --- a/Driver/ASTConsumers.cpp +++ b/Driver/ASTConsumers.cpp @@ -34,12 +34,26 @@ namespace { class DeclPrinter { public: llvm::raw_ostream& Out; + unsigned Indentation; - DeclPrinter(llvm::raw_ostream* out) : Out(out ? *out : llvm::errs()) {} - DeclPrinter() : Out(llvm::errs()) {} + DeclPrinter(llvm::raw_ostream* out) : Out(out ? *out : llvm::errs()), + Indentation(0) {} + DeclPrinter() : Out(llvm::errs()), Indentation(0) {} virtual ~DeclPrinter(); + void ChangeIndent(int I) { + Indentation += I; + } + + llvm::raw_ostream& Indent() { + for (unsigned i = 0; i < Indentation; ++i) + Out << " "; + return Out; + } + void PrintDecl(Decl *D); + void Print(NamedDecl *ND); + void Print(NamespaceDecl *NS); void PrintFunctionDeclStart(FunctionDecl *FD); void PrintTypeDefDecl(TypedefDecl *TD); void PrintLinkageSpec(LinkageSpecDecl *LS); @@ -62,12 +76,13 @@ DeclPrinter::~DeclPrinter() { } void DeclPrinter:: PrintDecl(Decl *D) { + Indent(); if (FunctionDecl *FD = dyn_cast(D)) { PrintFunctionDeclStart(FD); if (FD->getBody()) { Out << ' '; - FD->getBody()->printPretty(Out); + FD->getBody()->printPretty(Out, 0, Indentation, true); Out << '\n'; } } else if (isa(D)) { @@ -117,7 +132,23 @@ void DeclPrinter:: PrintDecl(Decl *D) { Out << " " << (*E)->getNameAsString() << ",\n"; Out << "};\n"; } else if (TagDecl *TD = dyn_cast(D)) { - Out << "Read top-level tag decl: '" << TD->getNameAsString() << "'\n"; + // print a free standing tag decl (e.g. "struct x;"). + Out << TD->getKindName(); + Out << " "; + if (const IdentifierInfo *II = TD->getIdentifier()) + Out << II->getName(); + + Out << " {\n"; + ChangeIndent(1); + for (DeclContext::decl_iterator i = TD->decls_begin(); + i != TD->decls_end(); + ++i) + PrintDecl(*i); + ChangeIndent(-1); + Indent(); + Out << "}"; + + Out << "\n"; } else if (TemplateDecl *TempD = dyn_cast(D)) { PrintTemplateDecl(TempD); } else if (LinkageSpecDecl *LSD = dyn_cast(D)) { @@ -127,17 +158,61 @@ void DeclPrinter:: PrintDecl(Decl *D) { AD->getAsmString()->printPretty(Out); Out << ")\n"; } else if (NamedDecl *ND = dyn_cast(D)) { - Out << "Read top-level variable decl: '" << ND->getNameAsString() << "'\n"; + Print(ND); } else { assert(0 && "Unknown decl type!"); } } +void DeclPrinter::Print(NamedDecl *ND) { + switch (ND->getKind()) { + default: + // FIXME: Handle the rest of the NamedDecls. + Out << "### NamedDecl " << ND->getNameAsString() << "\n"; + break; + case Decl::Field: + case Decl::Var: { + // Emit storage class for vardecls. + if (VarDecl *V = dyn_cast(ND)) { + switch (V->getStorageClass()) { + default: assert(0 && "Unknown storage class!"); + case VarDecl::None: break; + case VarDecl::Extern: Out << "extern "; break; + case VarDecl::Static: Out << "static "; break; + case VarDecl::Auto: Out << "auto "; break; + case VarDecl::Register: Out << "register "; break; + } + } + std::string Name = ND->getNameAsString(); + // This forms: "int a". + dyn_cast(ND)->getType().getAsStringInternal(Name); + Out << Name << ";\n"; + break; + } + case Decl::Namespace: + Print(dyn_cast(ND)); + break; + } +} + +void DeclPrinter::Print(NamespaceDecl *NS) { + Out << "namespace " << NS->getNameAsString() << " {\n"; + ChangeIndent(1); + for (DeclContext::decl_iterator i = NS->decls_begin(); + i != NS->decls_end(); + ++i) + PrintDecl(*i); + ChangeIndent(-1); + Indent(); + Out << "}\n"; +} + void DeclPrinter::PrintFunctionDeclStart(FunctionDecl *FD) { bool HasBody = FD->getBody(); Out << '\n'; + Indent(); switch (FD->getStorageClass()) { default: assert(0 && "Unknown storage class"); case FunctionDecl::None: break; @@ -198,16 +273,20 @@ void DeclPrinter::PrintLinkageSpec(LinkageSpecDecl *LS) { } Out << "extern \"" << l << "\" "; - if (LS->hasBraces()) + if (LS->hasBraces()) { Out << "{\n"; + ChangeIndent(1); + } for (LinkageSpecDecl::decl_iterator D = LS->decls_begin(), DEnd = LS->decls_end(); D != DEnd; ++D) PrintDecl(*D); - if (LS->hasBraces()) - Out << "}"; + if (LS->hasBraces()) { + ChangeIndent(-1); + Indent() << "}"; + } Out << "\n"; } @@ -774,7 +853,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) { for (unsigned i = 0; i < Indentation; ++i) - Out << " "; + Out << " "; Decl::Kind DK = I->getKind(); switch (DK) { @@ -797,7 +876,7 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, case Decl::CXXConversion: { DeclContext* DC = Decl::castToDeclContext(*I); - PrintDeclContext(DC, Indentation+4); + PrintDeclContext(DC, Indentation+2); break; } case Decl::Field: { diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 3f76c95fb5..ae7596a106 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -176,7 +176,8 @@ public: /// dumpPretty/printPretty - These two methods do a "pretty print" of the AST /// back to its original source language syntax. void dumpPretty() const; - void printPretty(llvm::raw_ostream &OS, PrinterHelper* = NULL) const; + void printPretty(llvm::raw_ostream &OS, PrinterHelper* = NULL, unsigned = 0, + bool NoIndent=false) const; /// viewAST - Visualize an AST rooted at this Stmt* using GraphViz. Only /// works on systems with GraphViz (Mac OS X) or dot+gv installed. diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp index 49292afe67..cc32fa23d9 100644 --- a/lib/AST/StmtPrinter.cpp +++ b/lib/AST/StmtPrinter.cpp @@ -29,10 +29,12 @@ namespace { class VISIBILITY_HIDDEN StmtPrinter : public StmtVisitor { llvm::raw_ostream &OS; unsigned IndentLevel; + bool NoIndent; clang::PrinterHelper* Helper; public: - StmtPrinter(llvm::raw_ostream &os, PrinterHelper* helper) : - OS(os), IndentLevel(0), Helper(helper) {} + StmtPrinter(llvm::raw_ostream &os, PrinterHelper* helper, unsigned I=0, + bool noIndent=false) : + OS(os), IndentLevel(I), NoIndent(noIndent), Helper(helper) {} void PrintStmt(Stmt *S, int SubIndent = 1) { IndentLevel += SubIndent; @@ -52,6 +54,7 @@ namespace { void PrintRawCompoundStmt(CompoundStmt *S); void PrintRawDecl(Decl *D); void PrintRawDeclStmt(DeclStmt *S); + void PrintFieldDecl(FieldDecl *FD); void PrintRawIfStmt(IfStmt *If); void PrintRawCXXCatchStmt(CXXCatchStmt *Catch); @@ -62,9 +65,11 @@ namespace { OS << ""; } - llvm::raw_ostream &Indent(int Delta = 0) const { - for (int i = 0, e = IndentLevel+Delta; i < e; ++i) - OS << " "; + llvm::raw_ostream &Indent(int Delta = 0) { + if (!NoIndent) { + for (int i = 0, e = IndentLevel+Delta; i < e; ++i) + OS << " "; + } else NoIndent = false; return OS; } @@ -139,16 +144,25 @@ void StmtPrinter::PrintRawDecl(Decl *D) { OS << " "; if (const IdentifierInfo *II = TD->getIdentifier()) OS << II->getName(); - else - OS << ""; - // FIXME: print tag bodies. + if (RecordDecl *RD = dyn_cast(TD)) { + OS << "{\n"; + IndentLevel += 1; + for (RecordDecl::field_iterator i = RD->field_begin(); i != RD->field_end(); ++i) { + PrintFieldDecl(*i); + IndentLevel -= 1; + } + } } else { assert(0 && "Unexpected decl"); } } +void StmtPrinter::PrintFieldDecl(FieldDecl *FD) { + Indent() << FD->getNameAsString() << "\n"; +} + void StmtPrinter::PrintRawDeclStmt(DeclStmt *S) { - bool isFirst = false; + bool isFirst = true; for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end(); I != E; ++I) { @@ -1222,13 +1236,14 @@ void Stmt::dumpPretty() const { OS.flush(); } -void Stmt::printPretty(llvm::raw_ostream &OS, PrinterHelper* Helper) const { +void Stmt::printPretty(llvm::raw_ostream &OS, PrinterHelper* Helper, + unsigned I, bool NoIndent) const { if (this == 0) { OS << ""; return; } - StmtPrinter P(OS, Helper); + StmtPrinter P(OS, Helper, I, NoIndent); P.Visit(const_cast(this)); } -- 2.50.1