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 <rdar://problem/10921596>.

llvm-svn: 153522
This commit is contained in:
Douglas Gregor 2012-03-27 18:06:49 +00:00
parent 8e6dbccd03
commit 41ab2899b2
7 changed files with 108 additions and 0 deletions

View File

@ -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">,

View File

@ -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
//===----------------------------------------------------------------------===//

View File

@ -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

View File

@ -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:

View File

@ -25,6 +25,7 @@
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
#include <set>
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<void>())
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<StringRef> 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<IdentifierIterator> 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<StringRef>::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
//===----------------------------------------------------------------------===//

View File

@ -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();

View File

@ -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