]> granicus.if.org Git - clang/commitdiff
Fixup -ast-print so that:
authorMike Stump <mrs@apple.com>
Tue, 10 Feb 2009 20:16:46 +0000 (20:16 +0000)
committerMike Stump <mrs@apple.com>
Tue, 10 Feb 2009 20:16:46 +0000 (20:16 +0000)
  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
include/clang/AST/Stmt.h
lib/AST/StmtPrinter.cpp

index 78b199680ae2d606868a70b7f2ed6e5e5087d0cd..c504f0fc9ae3c3221c9822abeb1df4994cc7f1fa 100644 (file)
@@ -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: {
index 3f76c95fb569096efdc9dd6aff57f2f7c83113e0..ae7596a1063607a3a2e922e8db83992c0fdbb05d 100644 (file)
@@ -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.
index 49292afe67e3479ae1d43dd5705f5873ab3a87ad..cc32fa23d9c223fa9c0db48b2e80234a786cf433 100644 (file)
@@ -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));
 }