aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Stump <mrs@apple.com>2009-02-10 20:16:46 +0000
committerMike Stump <mrs@apple.com>2009-02-10 20:16:46 +0000
commit071e4da10b07ca5278a7ce9dcabd853e0d57e5a4 (patch)
tree0d36f64e728435a129ccf19071475a56d9cb1fed
parent080cc35364d5bc03885ab0920528e9880f6b439d (diff)
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
-rw-r--r--Driver/ASTConsumers.cpp99
-rw-r--r--include/clang/AST/Stmt.h3
-rw-r--r--lib/AST/StmtPrinter.cpp37
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));
}