[cfe-commits] r88776 - /cfe/trunk/tools/clang-cc/clang-cc.cpp
Daniel Dunbar
daniel at zuster.org
Sat Nov 14 02:53:49 PST 2009
Author: ddunbar
Date: Sat Nov 14 04:53:49 2009
New Revision: 88776
URL: http://llvm.org/viewvc/llvm-project?rev=88776&view=rev
Log:
clang-cc: Switch to using FrontendAction. Whee.
Please report any discrepancies you see in clang-cc, I'm not confident that our regression tests cover all the fun ways one can use clang-cc.
Modified:
cfe/trunk/tools/clang-cc/clang-cc.cpp
Modified: cfe/trunk/tools/clang-cc/clang-cc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-cc/clang-cc.cpp?rev=88776&r1=88775&r2=88776&view=diff
==============================================================================
--- cfe/trunk/tools/clang-cc/clang-cc.cpp (original)
+++ cfe/trunk/tools/clang-cc/clang-cc.cpp Sat Nov 14 04:53:49 2009
@@ -8,50 +8,32 @@
//===----------------------------------------------------------------------===//
//
// This utility may be invoked in the following manner:
-// clang --help - Output help info.
-// clang [options] - Read from stdin.
-// clang [options] file - Read from "file".
-// clang [options] file1 file2 - Read these files.
+// clang-cc --help - Output help info.
+// clang-cc [options] - Read from stdin.
+// clang-cc [options] file - Read from "file".
+// clang-cc [options] file1 file2 - Read these files.
//
//===----------------------------------------------------------------------===//
#include "Options.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/Version.h"
-#include "clang/CodeGen/ModuleBuilder.h"
-#include "clang/Frontend/ASTConsumers.h"
-#include "clang/Frontend/ASTUnit.h"
-#include "clang/Frontend/AnalysisConsumer.h"
-#include "clang/Frontend/CommandLineSourceLoc.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/CompilerInvocation.h"
-#include "clang/Frontend/DependencyOutputOptions.h"
-#include "clang/Frontend/FixItRewriter.h"
+#include "clang/Frontend/FrontendActions.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/PathDiagnosticClients.h"
#include "clang/Frontend/PreprocessorOptions.h"
#include "clang/Frontend/PreprocessorOutputOptions.h"
-#include "clang/Frontend/Utils.h"
#include "clang/Frontend/VerifyDiagnosticsClient.h"
-#include "clang/Lex/HeaderSearch.h"
-#include "clang/Lex/LexDiagnostic.h"
-#include "clang/Parse/Parser.h"
-#include "clang/Sema/CodeCompleteConsumer.h"
-#include "clang/Sema/ParseAST.h"
-#include "clang/Sema/SemaDiagnostic.h"
-#include "llvm/LLVMContext.h"
#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/Config/config.h"
+#include "llvm/LLVMContext.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/PluginLoader.h"
#include "llvm/Support/PrettyStackTrace.h"
#include "llvm/Support/Timer.h"
@@ -184,19 +166,6 @@
}
//===----------------------------------------------------------------------===//
-// Basic Parser driver
-//===----------------------------------------------------------------------===//
-
-static void ParseFile(Preprocessor &PP, MinimalAction *PA) {
- Parser P(PP, *PA);
- PP.EnterMainSourceFile();
-
- // Parsing the specified input file.
- P.ParseTranslationUnit();
- delete PA;
-}
-
-//===----------------------------------------------------------------------===//
// Main driver
//===----------------------------------------------------------------------===//
@@ -205,361 +174,39 @@
/// anything.
llvm::Timer *ClangFrontendTimer = 0;
-/// AddFixItLocations - Add any individual user specified "fix-it" locations,
-/// and return true on success.
-static bool AddFixItLocations(CompilerInstance &CI,
- FixItRewriter &FixItRewrite) {
- const std::vector<ParsedSourceLocation> &Locs =
- CI.getFrontendOpts().FixItLocations;
- for (unsigned i = 0, e = Locs.size(); i != e; ++i) {
- const FileEntry *File = CI.getFileManager().getFile(Locs[i].FileName);
- if (!File) {
- CI.getDiagnostics().Report(diag::err_fe_unable_to_find_fixit_file)
- << Locs[i].FileName;
- return false;
- }
-
- RequestedSourceLocation Requested;
- Requested.File = File;
- Requested.Line = Locs[i].Line;
- Requested.Column = Locs[i].Column;
- FixItRewrite.addFixItLocation(Requested);
- }
-
- return true;
-}
-
-static ASTConsumer *CreateConsumerAction(CompilerInstance &CI,
- Preprocessor &PP,
- const std::string &InFile,
- ProgActions PA) {
- const FrontendOptions &FEOpts = CI.getFrontendOpts();
-
+static FrontendAction *CreateFrontendAction(ProgActions PA) {
switch (PA) {
- default:
- return 0;
-
- case ASTPrint:
- return CreateASTPrinter(CI.createDefaultOutputFile(false, InFile));
-
- case ASTPrintXML:
- return CreateASTPrinterXML(CI.createDefaultOutputFile(false, InFile,
- "xml"));
-
- case ASTDump:
- return CreateASTDumper();
-
- case ASTView:
- return CreateASTViewer();
-
- case DumpRecordLayouts:
- return CreateRecordLayoutDumper();
-
- case InheritanceView:
- return CreateInheritanceViewer(FEOpts.ViewClassInheritance);
-
- case EmitAssembly:
- case EmitLLVM:
- case EmitBC:
- case EmitLLVMOnly: {
- BackendAction Act;
- llvm::OwningPtr<llvm::raw_ostream> OS;
- if (ProgAction == EmitAssembly) {
- Act = Backend_EmitAssembly;
- OS.reset(CI.createDefaultOutputFile(false, InFile, "s"));
- } else if (ProgAction == EmitLLVM) {
- Act = Backend_EmitLL;
- OS.reset(CI.createDefaultOutputFile(false, InFile, "ll"));
- } else if (ProgAction == EmitLLVMOnly) {
- Act = Backend_EmitNothing;
- } else {
- Act = Backend_EmitBC;
- OS.reset(CI.createDefaultOutputFile(true, InFile, "bc"));
- }
-
- return CreateBackendConsumer(Act, PP.getDiagnostics(), PP.getLangOptions(),
- CI.getCodeGenOpts(), InFile, OS.take(),
- CI.getLLVMContext());
- }
-
- case RewriteObjC:
- return CreateObjCRewriter(InFile,
- CI.createDefaultOutputFile(true, InFile, "cpp"),
- PP.getDiagnostics(), PP.getLangOptions(),
- CI.getDiagnosticOpts().NoRewriteMacros);
-
- case RewriteBlocks:
- return CreateBlockRewriter(InFile, PP.getDiagnostics(),
- PP.getLangOptions());
-
- case FixIt:
- return new ASTConsumer();
-
- case ParseSyntaxOnly:
- return new ASTConsumer();
-
- case PrintDeclContext:
- return CreateDeclContextPrinter();
+ default: return 0;
+ case ASTDump: return new ASTDumpAction();
+ case ASTPrint: return new ASTPrintAction();
+ case ASTPrintXML: return new ASTPrintXMLAction();
+ case ASTView: return new ASTViewAction();
+ case DumpRawTokens: return new DumpRawTokensAction();
+ case DumpRecordLayouts: return new DumpRecordAction();
+ case DumpTokens: return new DumpTokensAction();
+ case EmitAssembly: return new EmitAssemblyAction();
+ case EmitBC: return new EmitBCAction();
+ case EmitHTML: return new HTMLPrintAction();
+ case EmitLLVM: return new EmitLLVMAction();
+ case EmitLLVMOnly: return new EmitLLVMOnlyAction();
+ case FixIt: return new FixItAction();
+ case GeneratePCH: return new GeneratePCHAction();
+ case GeneratePTH: return new GeneratePTHAction();
+ case InheritanceView: return new InheritanceViewAction();
+ case ParseNoop: return new ParseOnlyAction();
+ case ParsePrintCallbacks: return new PrintParseAction();
+ case ParseSyntaxOnly: return new SyntaxOnlyAction();
+ case PrintDeclContext: return new DeclContextPrintAction();
+ case PrintPreprocessedInput: return new PrintPreprocessedAction();
+ case RewriteBlocks: return new RewriteBlocksAction();
+ case RewriteMacros: return new RewriteMacrosAction();
+ case RewriteObjC: return new RewriteObjCAction();
+ case RewriteTest: return new RewriteTestAction();
+ case RunAnalysis: return new AnalysisAction();
+ case RunPreprocessorOnly: return new PreprocessOnlyAction();
}
}
-/// ProcessInputFile - Process a single input file with the specified state.
-static void ProcessInputFile(CompilerInstance &CI, const std::string &InFile,
- ProgActions PA) {
- Preprocessor &PP = CI.getPreprocessor();
- const FrontendOptions &FEOpts = CI.getFrontendOpts();
- llvm::OwningPtr<ASTConsumer> Consumer;
- llvm::OwningPtr<FixItRewriter> FixItRewrite;
- bool CompleteTranslationUnit = true;
-
- switch (PA) {
- default:
- Consumer.reset(CreateConsumerAction(CI, PP, InFile, PA));
- if (!Consumer.get()) {
- PP.getDiagnostics().Report(diag::err_fe_invalid_ast_action);
- return;
- }
- break;
-
- case EmitHTML:
- Consumer.reset(CreateHTMLPrinter(CI.createDefaultOutputFile(false, InFile),
- PP));
- break;
-
- case RunAnalysis:
- Consumer.reset(CreateAnalysisConsumer(PP, FEOpts.OutputFile,
- CI.getAnalyzerOpts()));
- break;
-
- case GeneratePCH: {
- const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot;
- bool Relocatable = FEOpts.RelocatablePCH;
- if (Relocatable && Sysroot.empty()) {
- PP.Diag(SourceLocation(), diag::err_relocatable_without_without_isysroot);
- Relocatable = false;
- }
-
- llvm::raw_ostream *OS = CI.createDefaultOutputFile(true, InFile);
- if (Relocatable)
- Consumer.reset(CreatePCHGenerator(PP, OS, Sysroot.c_str()));
- else
- Consumer.reset(CreatePCHGenerator(PP, OS));
- CompleteTranslationUnit = false;
- break;
- }
-
- // Do any necessary set up for non-consumer actions.
- case DumpRawTokens:
- case DumpTokens:
- case RunPreprocessorOnly:
- case ParseNoop:
- case GeneratePTH:
- case PrintPreprocessedInput:
- case ParsePrintCallbacks:
- case RewriteMacros:
- case RewriteTest:
- break; // No setup.
- }
-
- // Check if we want a fix-it rewriter.
- if (PA == FixIt) {
- FixItRewrite.reset(new FixItRewriter(PP.getDiagnostics(),
- PP.getSourceManager(),
- PP.getLangOptions()));
- if (!AddFixItLocations(CI, *FixItRewrite))
- return;
- }
-
- if (Consumer) {
- // Create the ASTContext.
- CI.createASTContext();
-
- // Create the external AST source when using PCH.
- const std::string &ImplicitPCHInclude =
- CI.getPreprocessorOpts().getImplicitPCHInclude();
- if (!ImplicitPCHInclude.empty()) {
- CI.createPCHExternalASTSource(ImplicitPCHInclude);
- if (!CI.getASTContext().getExternalSource())
- return;
- }
- }
-
- // Initialize builtin info as long as we aren't using an external AST
- // source.
- if (!CI.hasASTContext() || !CI.getASTContext().getExternalSource())
- PP.getBuiltinInfo().InitializeBuiltins(PP.getIdentifierTable(),
- PP.getLangOptions().NoBuiltin);
-
- // Initialize the main file entry. This needs to be delayed until after PCH
- // has loaded.
- if (!CI.InitializeSourceManager(InFile))
- return;
-
- if (Consumer) {
- // FIXME: Move the truncation aspect of this into Sema.
- if (!FEOpts.CodeCompletionAt.FileName.empty())
- CI.createCodeCompletionConsumer();
-
- // Run the AST consumer action.
- CodeCompleteConsumer *CompletionConsumer =
- CI.hasCodeCompletionConsumer() ? &CI.getCodeCompletionConsumer() : 0;
- ParseAST(PP, Consumer.get(), CI.getASTContext(), FEOpts.ShowStats,
- CompleteTranslationUnit, CompletionConsumer);
- } else {
- // Run the preprocessor actions.
- llvm::TimeRegion Timer(ClangFrontendTimer);
- switch (PA) {
- default:
- assert(0 && "unexpected program action");
-
- case DumpRawTokens: {
- SourceManager &SM = PP.getSourceManager();
- // Start lexing the specified input file.
- Lexer RawLex(SM.getMainFileID(), SM, PP.getLangOptions());
- RawLex.SetKeepWhitespaceMode(true);
-
- Token RawTok;
- RawLex.LexFromRawLexer(RawTok);
- while (RawTok.isNot(tok::eof)) {
- PP.DumpToken(RawTok, true);
- fprintf(stderr, "\n");
- RawLex.LexFromRawLexer(RawTok);
- }
- break;
- }
-
- case DumpTokens: {
- Token Tok;
- // Start preprocessing the specified input file.
- PP.EnterMainSourceFile();
- do {
- PP.Lex(Tok);
- PP.DumpToken(Tok, true);
- fprintf(stderr, "\n");
- } while (Tok.isNot(tok::eof));
- break;
- }
-
- case GeneratePTH:
- if (FEOpts.OutputFile.empty() || FEOpts.OutputFile == "-") {
- // FIXME: Don't fail this way.
- // FIXME: Verify that we can actually seek in the given file.
- llvm::errs() << "ERROR: PTH requires an seekable file for output!\n";
- ::exit(1);
- }
- CacheTokens(PP, CI.createDefaultOutputFile(true, InFile));
- break;
-
- case ParseNoop:
- ParseFile(PP, new MinimalAction(PP));
- break;
-
- case ParsePrintCallbacks: {
- llvm::raw_ostream *OS = CI.createDefaultOutputFile(false, InFile);
- ParseFile(PP, CreatePrintParserActionsAction(PP, OS));
- break;
- }
- case PrintPreprocessedInput:
- DoPrintPreprocessedInput(PP, CI.createDefaultOutputFile(false, InFile),
- CI.getPreprocessorOutputOpts());
- break;
-
- case RewriteMacros:
- RewriteMacrosInInput(PP, CI.createDefaultOutputFile(true, InFile));
- break;
-
- case RewriteTest:
- DoRewriteTest(PP, CI.createDefaultOutputFile(false, InFile));
- break;
-
- case RunPreprocessorOnly: { // Just lex as fast as we can, no output.
- Token Tok;
- // Start parsing the specified input file.
- PP.EnterMainSourceFile();
- do {
- PP.Lex(Tok);
- } while (Tok.isNot(tok::eof));
- break;
- }
- }
- }
-
- if (FixItRewrite)
- FixItRewrite->WriteFixedFile(InFile, FEOpts.OutputFile);
-
- // Release the consumer and the AST, in that order since the consumer may
- // perform actions in its destructor which require the context.
- if (FEOpts.DisableFree) {
- Consumer.take();
- CI.takeASTContext();
- } else {
- Consumer.reset();
- CI.setASTContext(0);
- }
-
- if (FEOpts.ShowStats) {
- fprintf(stderr, "\nSTATISTICS FOR '%s':\n", InFile.c_str());
- PP.PrintStats();
- PP.getIdentifierTable().PrintStats();
- PP.getHeaderSearchInfo().PrintStats();
- PP.getSourceManager().PrintStats();
- fprintf(stderr, "\n");
- }
-
- // Cleanup the output streams, and erase the output files if we encountered an
- // error.
- CI.ClearOutputFiles(/*EraseFiles=*/PP.getDiagnostics().getNumErrors());
-}
-
-/// ProcessASTInputFile - Process a single AST input file with the specified
-/// state.
-static void ProcessASTInputFile(CompilerInstance &CI, const std::string &InFile,
- ProgActions PA) {
- std::string Error;
- llvm::OwningPtr<ASTUnit> AST(ASTUnit::LoadFromPCHFile(InFile, &Error));
- if (!AST) {
- CI.getDiagnostics().Report(diag::err_fe_invalid_ast_file) << Error;
- return;
- }
-
- Preprocessor &PP = AST->getPreprocessor();
- llvm::OwningPtr<ASTConsumer> Consumer(CreateConsumerAction(CI, PP,
- InFile, PA));
- if (!Consumer.get()) {
- CI.getDiagnostics().Report(diag::err_fe_invalid_ast_action);
- return;
- }
-
- // Set the main file ID to an empty file.
- //
- // FIXME: We probably shouldn't need this, but for now this is the simplest
- // way to reuse the logic in ParseAST.
- const char *EmptyStr = "";
- llvm::MemoryBuffer *SB =
- llvm::MemoryBuffer::getMemBuffer(EmptyStr, EmptyStr, "<dummy input>");
- AST->getSourceManager().createMainFileIDForMemBuffer(SB);
-
- // Stream the input AST to the consumer.
- CI.getDiagnostics().getClient()->BeginSourceFile(PP.getLangOptions(), &PP);
- ParseAST(PP, Consumer.get(), AST->getASTContext(),
- CI.getFrontendOpts().ShowStats);
- CI.getDiagnostics().getClient()->EndSourceFile();
-
- // Release the consumer and the AST, in that order since the consumer may
- // perform actions in its destructor which require the context.
- if (CI.getFrontendOpts().DisableFree) {
- Consumer.take();
- AST.take();
- } else {
- Consumer.reset();
- AST.reset();
- }
-
- // Cleanup the output streams, and erase the output files if we encountered an
- // error.
- CI.ClearOutputFiles(/*EraseFiles=*/PP.getDiagnostics().getNumErrors());
-}
-
static void LLVMErrorHandler(void *UserData, const std::string &Message) {
Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);
@@ -701,33 +348,35 @@
if (!Clang.getFrontendOpts().FixItLocations.empty())
ProgAction = FixIt;
- // Create the source manager.
- Clang.createSourceManager();
-
- // Create a file manager object to provide access to and cache the filesystem.
- Clang.createFileManager();
-
for (unsigned i = 0, e = Clang.getFrontendOpts().Inputs.size(); i != e; ++i) {
const std::string &InFile = Clang.getFrontendOpts().Inputs[i].second;
- // AST inputs are handled specially.
- if (IsAST) {
- ProcessASTInputFile(Clang, InFile, ProgAction);
- continue;
+ // If we aren't using an AST file, setup the file and source managers and
+ // the preprocessor.
+ if (!IsAST) {
+ if (!i) {
+ // Create a file manager object to provide access to and cache the
+ // filesystem.
+ Clang.createFileManager();
+
+ // Create the source manager.
+ Clang.createSourceManager();
+ } else {
+ // Reset the ID tables if we are reusing the SourceManager.
+ Clang.getSourceManager().clearIDTables();
+ }
+
+ // Create the preprocessor.
+ Clang.createPreprocessor();
}
- // Reset the ID tables if we are reusing the SourceManager.
- if (i)
- Clang.getSourceManager().clearIDTables();
-
- // Create the preprocessor.
- Clang.createPreprocessor();
-
- // Process the source file.
- Clang.getDiagnostics().getClient()->BeginSourceFile(Clang.getLangOpts(),
- &Clang.getPreprocessor());
- ProcessInputFile(Clang, InFile, ProgAction);
- Clang.getDiagnostics().getClient()->EndSourceFile();
+ llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(ProgAction));
+ assert(Act && "Invalid program action!");
+ Act->setCurrentTimer(ClangFrontendTimer);
+ if (Act->BeginSourceFile(Clang, InFile, IsAST)) {
+ Act->Execute();
+ Act->EndSourceFile();
+ }
}
if (Clang.getDiagnosticOpts().ShowCarets)
More information about the cfe-commits
mailing list