]> granicus.if.org Git - clang/commitdiff
Add an initial framework of a DeclContextPrinter. It can print DeclContext and
authorZhongxing Xu <xuzhongxing@gmail.com>
Tue, 13 Jan 2009 01:29:24 +0000 (01:29 +0000)
committerZhongxing Xu <xuzhongxing@gmail.com>
Tue, 13 Jan 2009 01:29:24 +0000 (01:29 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62136 91177308-0d34-0410-b5e6-96231b3b80d8

Driver/ASTConsumers.cpp
Driver/ASTConsumers.h
Driver/clang.cpp

index a8fcf00999e7faf2147cd8f4b51ee7cdfc96a83e..17763f63bdd62762978e2a24cea4326faaa51bab 100644 (file)
@@ -554,6 +554,225 @@ namespace {
 
 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
 
index 97adfb30c829f34d87f7a76e444916449874f821..0093a7046acc1fcf1d984cd62adb6418bd450c72 100644 (file)
@@ -38,6 +38,8 @@ ASTConsumer *CreateASTDumper();
 
 ASTConsumer *CreateASTViewer();
 
+ASTConsumer *CreateDeclContextPrinter();
+
 ASTConsumer *CreateCodeRewriterTest(const std::string& InFile,
                                     const std::string& OutFile,
                                     Diagnostic &Diags,
index 51b1335f9c43b2426ab97a25a0140416805ea158..5f3a554dbb37b6992ef5a0b6d0e00d6b18e4a2c5 100644 (file)
@@ -83,6 +83,7 @@ enum ProgActions {
   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 @@ ProgAction(llvm::cl::desc("Choose output type:"), llvm::cl::ZeroOrMore,
                         "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 @@ static ASTConsumer* CreateASTConsumer(const std::string& InFile,
       
     case ASTView:
       return CreateASTViewer();   
+
+    case PrintDeclContext:
+      return CreateDeclContextPrinter();
       
     case EmitHTML:
       return CreateHTMLPrinter(OutputFile, Diag, PP, PPF);