From: Douglas Gregor Date: Tue, 27 Mar 2012 18:06:49 +0000 (+0000) Subject: Introduce a -cc1-level option -pubnames-dump, which simply dumps the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=978fc9c485d21ee89b4f0bc77ce1ea55c65c7f12;p=clang Introduce a -cc1-level option -pubnames-dump, which simply dumps the list of identifiers that that 'public' names at the end of the translation unit, e.g., defined macros or identifiers with top-level names, in sorted order. Meant to support . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153522 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index afbe9f36f4..e8ec822715 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -422,6 +422,9 @@ def ast_view : Flag<"-ast-view">, HelpText<"Build ASTs and view them with GraphViz">; def print_decl_contexts : Flag<"-print-decl-contexts">, HelpText<"Print DeclContexts and their Decls">; +def pubnames_dump : Flag<"-pubnames-dump">, + HelpText<"Print all of the public (global) names in the source, e.g., the " + "names of all global declarations and macros">; def emit_module : Flag<"-emit-module">, HelpText<"Generate pre-compiled module file from a module map">; def emit_pth : Flag<"-emit-pth">, diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h index 8f7fe87ee6..8817c5af56 100644 --- a/include/clang/Frontend/FrontendActions.h +++ b/include/clang/Frontend/FrontendActions.h @@ -173,6 +173,15 @@ protected: virtual bool usesPreprocessorOnly() const { return true; } }; +class PubnamesDumpAction : public ASTFrontendAction { +protected: + virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile); + +public: + virtual bool hasCodeCompletionSupport() const { return false; } +}; + //===----------------------------------------------------------------------===// // Preprocessor Actions //===----------------------------------------------------------------------===// diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index 0ec2f6b1ef..49a9ec189d 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -42,6 +42,7 @@ namespace frontend { PrintDeclContext, ///< Print DeclContext and their Decls. PrintPreamble, ///< Print the "preamble" of the input file PrintPreprocessedInput, ///< -E mode. + PubnamesDump, ///< Print all of the "public" names in the source. RewriteMacros, ///< Expand macros but not #includes. RewriteObjC, ///< ObjC->C Rewriter. RewriteTest, ///< Rewriter playground diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 973c5a42a5..1dd501e982 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -425,6 +425,7 @@ static const char *getActionName(frontend::ActionKind Kind) { case frontend::PrintDeclContext: return "-print-decl-contexts"; case frontend::PrintPreamble: return "-print-preamble"; case frontend::PrintPreprocessedInput: return "-E"; + case frontend::PubnamesDump: return "-pubnames-dump"; case frontend::RewriteMacros: return "-rewrite-macros"; case frontend::RewriteObjC: return "-rewrite-objc"; case frontend::RewriteTest: return "-rewrite-test"; @@ -1360,6 +1361,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::PrintPreamble; break; case OPT_E: Opts.ProgramAction = frontend::PrintPreprocessedInput; break; + case OPT_pubnames_dump: + Opts.ProgramAction = frontend::PubnamesDump; break; case OPT_rewrite_macros: Opts.ProgramAction = frontend::RewriteMacros; break; case OPT_rewrite_objc: diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 737ee4a098..b4a439d423 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -25,6 +25,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" +#include using namespace clang; @@ -354,6 +355,77 @@ ASTConsumer *SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI, return new ASTConsumer(); } +namespace { + class PubnamesDumpConsumer : public ASTConsumer { + Preprocessor &PP; + + /// \brief Determine whether the given identifier provides a 'public' name. + bool isPublicName(IdentifierInfo *II) { + // If there are any top-level declarations associated with this + // identifier, it is a public name. + if (II->getFETokenInfo()) + return true; + + // If this identifier is the name of a non-builtin macro that isn't + // defined on the command line or implicitly by the front end, it is a + // public name. + if (II->hasMacroDefinition()) { + if (MacroInfo *M = PP.getMacroInfo(II)) + if (!M->isBuiltinMacro()) { + SourceLocation Loc = M->getDefinitionLoc(); + FileID File = PP.getSourceManager().getFileID(Loc); + if (PP.getSourceManager().getFileEntryForID(File)) + return true; + } + } + + return false; + } + + public: + PubnamesDumpConsumer(Preprocessor &PP) : PP(PP) { } + + virtual void HandleTranslationUnit(ASTContext &Ctx) { + std::set Pubnames; + + // Add the names of any non-builtin macros. + for (IdentifierTable::iterator I = Ctx.Idents.begin(), + IEnd = Ctx.Idents.end(); + I != IEnd; ++I) { + if (isPublicName(I->second)) + Pubnames.insert(I->first()); + } + + // If there is an external identifier lookup source, consider those + // identifiers as well. + if (IdentifierInfoLookup *External + = Ctx.Idents.getExternalIdentifierLookup()) { + OwningPtr Iter(External->getIdentifiers()); + do { + StringRef Name = Iter->Next(); + if (Name.empty()) + break; + + if (isPublicName(PP.getIdentifierInfo(Name))) + Pubnames.insert(Name); + } while (true); + } + + // Print the names, in lexicographical order. + for (std::set::iterator N = Pubnames.begin(), + NEnd = Pubnames.end(); + N != NEnd; ++N) { + llvm::outs() << *N << '\n'; + } + } + }; +} + +ASTConsumer *PubnamesDumpAction::CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) { + return new PubnamesDumpConsumer(CI.getPreprocessor()); +} + //===----------------------------------------------------------------------===// // Preprocessor Actions //===----------------------------------------------------------------------===// diff --git a/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/lib/FrontendTool/ExecuteCompilerInvocation.cpp index 07d2b8d19f..2066505180 100644 --- a/lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ b/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -72,6 +72,7 @@ static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) { case PrintDeclContext: return new DeclContextPrintAction(); case PrintPreamble: return new PrintPreambleAction(); case PrintPreprocessedInput: return new PrintPreprocessedAction(); + case PubnamesDump: return new PubnamesDumpAction(); case RewriteMacros: return new RewriteMacrosAction(); case RewriteObjC: return new RewriteObjCAction(); case RewriteTest: return new RewriteTestAction(); diff --git a/test/Misc/pubnames.c b/test/Misc/pubnames.c new file mode 100644 index 0000000000..03048972c0 --- /dev/null +++ b/test/Misc/pubnames.c @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -pubnames-dump %s | FileCheck %s +#define FOO +#define BAR +#undef FOO +#define WIBBLE + +int foo(); +int bar(float); +int wibble; + +// CHECK: BAR +// CHECK-NOT: FOO +// CHECK: WIBBLE +// CHECK-NOT: __clang_major__ +// CHECK: bar +// CHECK: foo +// CHECK: wibble + +