From: Zhongxing Xu Date: Tue, 13 Jan 2009 01:29:24 +0000 (+0000) Subject: Add an initial framework of a DeclContextPrinter. It can print DeclContext and X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2d75d6f56c2937d67aecb6008793694f9eb51349;p=clang 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 __builtin_va_list [class] A 0x9753310 A 0x975ce20 a f A A operator= ~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 --- diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp index a8fcf00999..17763f63bd 100644 --- a/Driver/ASTConsumers.cpp +++ b/Driver/ASTConsumers.cpp @@ -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::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 << " "; + Out << RD->getNameAsString(); + break; + } + case Decl::CXXRecord: { + CXXRecordDecl* RD = CXXRecordDecl::castFromDeclContext(DC); + if (RD->isDefinition()) + Out << "[class] "; + else + Out << " "; + 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 << " "; + Out << FD->getNameAsString(); + break; + } + case Decl::CXXMethod: { + CXXMethodDecl* CMD = CXXMethodDecl::castFromDeclContext(DC); + if (CMD->isOutOfLineDefinition()) + Out << "[c++ method] "; + else + Out << " "; + 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 << " "; + Out << CMD->getNameAsString(); + break; + } + case Decl::CXXDestructor: { + CXXDestructorDecl* CMD = CXXDestructorDecl::castFromDeclContext(DC); + if (CMD->isOutOfLineDefinition()) + Out << "[c++ dtor] "; + else + Out << " "; + Out << CMD->getNameAsString(); + break; + } + case Decl::CXXConversion: { + CXXConversionDecl* CMD = CXXConversionDecl::castFromDeclContext(DC); + if (CMD->isOutOfLineDefinition()) + Out << "[c++ conversion] "; + else + Out << " "; + 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(*I); + Out << " " << FD->getNameAsString() << "\n"; + break; + } + case Decl::Typedef: { + TypedefDecl* TD = cast(*I); + Out << " " << TD->getNameAsString() << "\n"; + break; + } + case Decl::EnumConstant: { + EnumConstantDecl* ECD = cast(*I); + Out << " " << ECD->getNameAsString() << "\n"; + break; + } + case Decl::Var: { + VarDecl* VD = cast(*I); + Out << " " << VD->getNameAsString() << "\n"; + break; + } + case Decl::ImplicitParam: { + ImplicitParamDecl* IPD = cast(*I); + Out << " " << IPD->getNameAsString() << "\n"; + break; + } + case Decl::CXXClassVar: { + CXXClassVarDecl* CVD = cast(*I); + Out << " " << CVD->getNameAsString() << "\n"; + break; + } + case Decl::ParmVar: { + ParmVarDecl* PVD = cast(*I); + Out << " " << PVD->getNameAsString() << "\n"; + break; + } + case Decl::ObjCProperty: { + ObjCPropertyDecl* OPD = cast(*I); + Out << " " << 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 diff --git a/Driver/ASTConsumers.h b/Driver/ASTConsumers.h index 97adfb30c8..0093a7046a 100644 --- a/Driver/ASTConsumers.h +++ b/Driver/ASTConsumers.h @@ -38,6 +38,8 @@ ASTConsumer *CreateASTDumper(); ASTConsumer *CreateASTViewer(); +ASTConsumer *CreateDeclContextPrinter(); + ASTConsumer *CreateCodeRewriterTest(const std::string& InFile, const std::string& OutFile, Diagnostic &Diags, diff --git a/Driver/clang.cpp b/Driver/clang.cpp index 51b1335f9c..5f3a554dbb 100644 --- a/Driver/clang.cpp +++ b/Driver/clang.cpp @@ -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);