diff options
-rw-r--r-- | Driver/ASTConsumers.cpp | 99 | ||||
-rw-r--r-- | include/clang/AST/Stmt.h | 3 | ||||
-rw-r--r-- | 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<FunctionDecl>(D)) { PrintFunctionDeclStart(FD); if (FD->getBody()) { Out << ' '; - FD->getBody()->printPretty(Out); + FD->getBody()->printPretty(Out, 0, Indentation, true); Out << '\n'; } } else if (isa<ObjCMethodDecl>(D)) { @@ -117,7 +132,23 @@ void DeclPrinter:: PrintDecl(Decl *D) { Out << " " << (*E)->getNameAsString() << ",\n"; Out << "};\n"; } else if (TagDecl *TD = dyn_cast<TagDecl>(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<TemplateDecl>(D)) { PrintTemplateDecl(TempD); } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) { @@ -127,17 +158,61 @@ void DeclPrinter:: PrintDecl(Decl *D) { AD->getAsmString()->printPretty(Out); Out << ")\n"; } else if (NamedDecl *ND = dyn_cast<NamedDecl>(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<VarDecl>(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<ValueDecl>(ND)->getType().getAsStringInternal(Name); + Out << Name << ";\n"; + break; + } + case Decl::Namespace: + Print(dyn_cast<NamespaceDecl>(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<StmtPrinter> { 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 << "<null expr>"; } - 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 << "<anonymous>"; - // FIXME: print tag bodies. + if (RecordDecl *RD = dyn_cast<RecordDecl>(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 << "<NULL>"; return; } - StmtPrinter P(OS, Helper); + StmtPrinter P(OS, Helper, I, NoIndent); P.Visit(const_cast<Stmt*>(this)); } |