[cfe-commits] r62136 - in /cfe/trunk/Driver: ASTConsumers.cpp ASTConsumers.h clang.cpp

Zhongxing Xu xuzhongxing at gmail.com
Mon Jan 12 17:29:25 PST 2009


Author: zhongxingxu
Date: Mon Jan 12 19:29:24 2009
New Revision: 62136

URL: http://llvm.org/viewvc/llvm-project?rev=62136&view=rev
Log:
Add an initial framework of a DeclContextPrinter. It can print DeclContext and
its Decls in indented format. An Example:

$ cat t.cpp
class A {
  int a;
  void f();
};
void A::f() {
  a = 3;
}

$ clang -print-decl-contexts t.cpp
[translation unit] 0x9754d7c
    <typedef> __builtin_va_list
    [class] A 0x9753310
        <class> A 0x975ce20
        <field> a
        <c++ method> f
        <c++ ctor> A
        <c++ ctor> A
        <c++ method> operator=
        <c++ dtor> ~A
    [c++ method] f [[0x9753310]]

Some comments: '<>' indicates a declaration, '[]' indicates a definition, '[[
]]' displays the semantic DeclContext which is different from the lexical
DeclContext.  The symbols printed can definitely be changed in the future.

Modified:
    cfe/trunk/Driver/ASTConsumers.cpp
    cfe/trunk/Driver/ASTConsumers.h
    cfe/trunk/Driver/clang.cpp

Modified: cfe/trunk/Driver/ASTConsumers.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/ASTConsumers.cpp?rev=62136&r1=62135&r2=62136&view=diff

==============================================================================
--- cfe/trunk/Driver/ASTConsumers.cpp (original)
+++ cfe/trunk/Driver/ASTConsumers.cpp Mon Jan 12 19:29:24 2009
@@ -555,6 +555,225 @@
 ASTConsumer *clang::CreateASTViewer() { return new ASTViewer(); }
 
 //===----------------------------------------------------------------------===//
+/// DeclContextPrinter - Decl and DeclContext Visualization
+
+namespace {
+
+class DeclContextPrinter : public ASTConsumer {
+  llvm::raw_ostream& Out;
+public:
+  DeclContextPrinter() : Out(llvm::errs()) {}
+
+  void HandleTranslationUnit(TranslationUnit& TU) {
+    TranslationUnitDecl* TUD = TU.getContext().getTranslationUnitDecl();
+    PrintDeclContext(TUD, 4);
+  }
+
+  void PrintDeclContext(const DeclContext* DC, unsigned Indentation);
+};
+
+void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, 
+                                          unsigned Indentation) {
+  // Print DeclContext name.
+  Decl::Kind DK = DeclContext::KindTrait<DeclContext>::getKind(DC);
+  switch (DK) {
+  case Decl::TranslationUnit:
+    Out << "[translation unit] " << DC;
+    break;
+  case Decl::Namespace: {
+    Out << "[namespace] ";
+    NamespaceDecl* ND = NamespaceDecl::castFromDeclContext(DC);
+    Out << ND->getNameAsString();
+    break;
+  }
+  case Decl::Enum:
+    Out << "[enum]";
+    break;
+  case Decl::Record: {
+    RecordDecl* RD = RecordDecl::castFromDeclContext(DC);
+    if (RD->isDefinition())
+      Out << "[struct] ";
+    else
+      Out << "<struct> ";
+    Out << RD->getNameAsString();
+    break;
+  }
+  case Decl::CXXRecord: {
+    CXXRecordDecl* RD = CXXRecordDecl::castFromDeclContext(DC);
+    if (RD->isDefinition())
+      Out << "[class] ";
+    else
+      Out << "<class> ";
+    Out << RD->getNameAsString() << " " << DC;
+    break;
+  }
+  case Decl::ObjCMethod:
+    Out << "[objc method]";
+    break;
+  case Decl::ObjCInterface:
+    Out << "[objc interface]";
+    break;
+  case Decl::ObjCCategory:
+    Out << "[objc category]";
+    break;
+  case Decl::ObjCProtocol:
+    Out << "[objc protocol]";
+    break;
+  case Decl::ObjCImplementation:
+    Out << "[objc implementation]";
+    break;
+  case Decl::ObjCCategoryImpl:
+    Out << "[objc categoryimpl]";
+    break;
+  case Decl::LinkageSpec:
+    Out << "[linkage spec]";
+    break;
+  case Decl::Block:
+    Out << "[block]";
+    break;
+  case Decl::Function: {
+    FunctionDecl* FD = FunctionDecl::castFromDeclContext(DC);
+    if (FD->isThisDeclarationADefinition())
+      Out << "[function] ";
+    else
+      Out << "<function> ";
+    Out << FD->getNameAsString();
+    break;
+  }
+  case Decl::CXXMethod: {
+    CXXMethodDecl* CMD = CXXMethodDecl::castFromDeclContext(DC);
+    if (CMD->isOutOfLineDefinition())
+      Out << "[c++ method] ";
+    else
+      Out << "<c++ method> ";
+    Out << CMD->getNameAsString();
+
+    // Check the semantic DeclContext.
+    DeclContext* SemaDC = CMD->getDeclContext();
+    DeclContext* LexicalDC = CMD->getLexicalDeclContext();
+    if (SemaDC != LexicalDC) {
+      Out << " [[" << SemaDC << "]]";
+    }
+    break;
+  }
+  case Decl::CXXConstructor: {
+    CXXConstructorDecl* CMD = CXXConstructorDecl::castFromDeclContext(DC);
+    if (CMD->isOutOfLineDefinition())
+      Out << "[c++ ctor] ";
+    else
+      Out << "<c++ ctor> ";
+    Out << CMD->getNameAsString();
+    break;
+  }
+  case Decl::CXXDestructor: {
+    CXXDestructorDecl* CMD = CXXDestructorDecl::castFromDeclContext(DC);
+    if (CMD->isOutOfLineDefinition())
+      Out << "[c++ dtor] ";
+    else
+      Out << "<c++ dtor> ";
+    Out << CMD->getNameAsString();
+    break;
+  }
+  case Decl::CXXConversion: {
+    CXXConversionDecl* CMD = CXXConversionDecl::castFromDeclContext(DC);
+    if (CMD->isOutOfLineDefinition())
+      Out << "[c++ conversion] ";
+    else
+      Out << "<c++ conversion> ";
+    Out << CMD->getNameAsString();
+    break;
+  }
+
+  default:
+    assert(0 && "a decl that inherits DeclContext isn't handled");
+  }
+
+  Out << "\n";
+
+  // Print decls in the DeclContext.
+  for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
+       I != E; ++I) {
+    for (unsigned i = 0; i < Indentation; ++i)
+      Out << " ";
+
+    Decl::Kind DK = I->getKind();
+    switch (DK) {
+    case Decl::Namespace:
+    case Decl::Enum:
+    case Decl::Record:
+    case Decl::CXXRecord:
+    case Decl::ObjCMethod:
+    case Decl::ObjCInterface:
+    case Decl::ObjCCategory: 
+    case Decl::ObjCProtocol:
+    case Decl::ObjCImplementation:
+    case Decl::ObjCCategoryImpl:
+    case Decl::LinkageSpec:
+    case Decl::Block:
+    case Decl::Function:
+    case Decl::CXXMethod:
+    case Decl::CXXConstructor:
+    case Decl::CXXDestructor:
+    case Decl::CXXConversion:
+    {
+      DeclContext* DC = Decl::castToDeclContext(*I);
+      PrintDeclContext(DC, Indentation+4);
+      break;
+    }
+    case Decl::Field: {
+      FieldDecl* FD = cast<FieldDecl>(*I);
+      Out << "<field> " << FD->getNameAsString() << "\n";
+      break;
+    }
+    case Decl::Typedef: {
+      TypedefDecl* TD = cast<TypedefDecl>(*I);
+      Out << "<typedef> " << TD->getNameAsString() << "\n";
+      break;
+    }
+    case Decl::EnumConstant: {
+      EnumConstantDecl* ECD = cast<EnumConstantDecl>(*I);
+      Out << "<enum constant> " << ECD->getNameAsString() << "\n";
+      break;
+    }
+    case Decl::Var: {
+      VarDecl* VD = cast<VarDecl>(*I);
+      Out << "<var> " << VD->getNameAsString() << "\n";
+      break;
+    }
+    case Decl::ImplicitParam: {
+      ImplicitParamDecl* IPD = cast<ImplicitParamDecl>(*I);
+      Out << "<implicit parameter> " << IPD->getNameAsString() << "\n";
+      break;
+    }
+    case Decl::CXXClassVar: {
+      CXXClassVarDecl* CVD = cast<CXXClassVarDecl>(*I);
+      Out << "<static member var> " << CVD->getNameAsString() << "\n";
+      break;
+    }
+    case Decl::ParmVar: {
+      ParmVarDecl* PVD = cast<ParmVarDecl>(*I);
+      Out << "<parameter> " << PVD->getNameAsString() << "\n";
+      break;
+    }
+    case Decl::ObjCProperty: {
+      ObjCPropertyDecl* OPD = cast<ObjCPropertyDecl>(*I);
+      Out << "<objc property> " << OPD->getNameAsString() << "\n";
+      break;
+    }
+    default:
+      fprintf(stderr, "DeclKind: %d\n", DK);
+      assert(0 && "decl unhandled");
+    }
+  }
+}
+
+}
+
+ASTConsumer *clang::CreateDeclContextPrinter() { 
+  return new DeclContextPrinter(); 
+}
+
+//===----------------------------------------------------------------------===//
 /// InheritanceViewer - C++ Inheritance Visualization
 
 namespace {

Modified: cfe/trunk/Driver/ASTConsumers.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/ASTConsumers.h?rev=62136&r1=62135&r2=62136&view=diff

==============================================================================
--- cfe/trunk/Driver/ASTConsumers.h (original)
+++ cfe/trunk/Driver/ASTConsumers.h Mon Jan 12 19:29:24 2009
@@ -38,6 +38,8 @@
 
 ASTConsumer *CreateASTViewer();
 
+ASTConsumer *CreateDeclContextPrinter();
+
 ASTConsumer *CreateCodeRewriterTest(const std::string& InFile,
                                     const std::string& OutFile,
                                     Diagnostic &Diags,

Modified: cfe/trunk/Driver/clang.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Driver/clang.cpp?rev=62136&r1=62135&r2=62136&view=diff

==============================================================================
--- cfe/trunk/Driver/clang.cpp (original)
+++ cfe/trunk/Driver/clang.cpp Mon Jan 12 19:29:24 2009
@@ -83,6 +83,7 @@
   ASTPrint,                     // Parse ASTs and print them.
   ASTDump,                      // Parse ASTs and dump them.
   ASTView,                      // Parse ASTs and view them in Graphviz.
+  PrintDeclContext,             // Print DeclContext and their Decls.
   TestSerialization,            // Run experimental serialization code.
   ParsePrintCallbacks,          // Parse and print each callback.
   ParseSyntaxOnly,              // Parse and perform semantic analysis.
@@ -122,6 +123,8 @@
                         "Build ASTs and then debug dump them"),
              clEnumValN(ASTView, "ast-view",
                         "Build ASTs and view them with GraphViz"),
+             clEnumValN(PrintDeclContext, "print-decl-contexts",
+                        "Print DeclContexts and their Decls."),
              clEnumValN(TestSerialization, "test-pickling",
                         "Run prototype serialization code"),
              clEnumValN(EmitAssembly, "S",
@@ -1245,6 +1248,9 @@
       
     case ASTView:
       return CreateASTViewer();   
+
+    case PrintDeclContext:
+      return CreateDeclContextPrinter();
       
     case EmitHTML:
       return CreateHTMLPrinter(OutputFile, Diag, PP, PPF);





More information about the cfe-commits mailing list