forked from OSchip/llvm-project
cc1: Factor out CompilerInstance::ExecuteAction which has the majority of the
clang -cc1 logic for running an action against a set of options. - This should make it easier to build tools that have a clang -cc1 like interface, but aren't actually part of clang -cc1. llvm-svn: 93282
This commit is contained in:
parent
7d38d4da61
commit
4f2bc55d4e
|
@ -32,6 +32,7 @@ class Diagnostic;
|
|||
class DiagnosticClient;
|
||||
class ExternalASTSource;
|
||||
class FileManager;
|
||||
class FrontendAction;
|
||||
class Preprocessor;
|
||||
class Source;
|
||||
class SourceManager;
|
||||
|
@ -103,6 +104,42 @@ public:
|
|||
bool _OwnsLLVMContext = true);
|
||||
~CompilerInstance();
|
||||
|
||||
/// @name High-Level Operations
|
||||
/// {
|
||||
|
||||
/// ExecuteAction - Execute the provided action against the compiler's
|
||||
/// CompilerInvocation object.
|
||||
///
|
||||
/// This function makes the following assumptions:
|
||||
///
|
||||
/// - The invocation options should be initialized. This function does not
|
||||
/// handle the '-help' or '-version' options, clients should handle those
|
||||
/// directly.
|
||||
///
|
||||
/// - The diagnostics engine should have already been created by the client.
|
||||
///
|
||||
/// - No other CompilerInstance state should have been initialized (this is
|
||||
/// an unchecked error).
|
||||
///
|
||||
/// - Clients should have initialized any LLVM target features that may be
|
||||
/// required.
|
||||
///
|
||||
/// - Clients should eventually call llvm_shutdown() upon the completion of
|
||||
/// this routine to ensure that any managed objects are properly destroyed.
|
||||
///
|
||||
/// Note that this routine may write output to 'stderr'.
|
||||
///
|
||||
/// \param Act - The action to execute.
|
||||
/// \return - True on success.
|
||||
//
|
||||
// FIXME: This function should take the stream to write any debugging /
|
||||
// verbose output to as an argument.
|
||||
//
|
||||
// FIXME: Eliminate the llvm_shutdown requirement, that should either be part
|
||||
// of the context or else not CompilerInstance specific.
|
||||
bool ExecuteAction(FrontendAction &Act);
|
||||
|
||||
/// }
|
||||
/// @name LLVM Context
|
||||
/// {
|
||||
|
||||
|
|
|
@ -14,10 +14,12 @@
|
|||
#include "clang/Basic/FileManager.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/Basic/Version.h"
|
||||
#include "clang/Lex/HeaderSearch.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Lex/PTHManager.h"
|
||||
#include "clang/Frontend/ChainedDiagnosticClient.h"
|
||||
#include "clang/Frontend/FrontendAction.h"
|
||||
#include "clang/Frontend/PCHReader.h"
|
||||
#include "clang/Frontend/FrontendDiagnostic.h"
|
||||
#include "clang/Frontend/TextDiagnosticPrinter.h"
|
||||
|
@ -28,6 +30,7 @@
|
|||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/Timer.h"
|
||||
#include "llvm/System/Host.h"
|
||||
#include "llvm/System/Path.h"
|
||||
#include "llvm/System/Program.h"
|
||||
using namespace clang;
|
||||
|
@ -409,3 +412,87 @@ bool CompilerInstance::InitializeSourceManager(llvm::StringRef InputFile,
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
// High-Level Operations
|
||||
|
||||
bool CompilerInstance::ExecuteAction(FrontendAction &Act) {
|
||||
assert(hasDiagnostics() && "Diagnostics engine is not initialized!");
|
||||
assert(!getFrontendOpts().ShowHelp && "Client must handle '-help'!");
|
||||
assert(!getFrontendOpts().ShowVersion && "Client must handle '-version'!");
|
||||
|
||||
// FIXME: Take this as an argument, once all the APIs we used have moved to
|
||||
// taking it as an input instead of hard-coding llvm::errs.
|
||||
llvm::raw_ostream &OS = llvm::errs();
|
||||
|
||||
// Create the target instance.
|
||||
setTarget(TargetInfo::CreateTargetInfo(getDiagnostics(), getTargetOpts()));
|
||||
if (!hasTarget())
|
||||
return false;
|
||||
|
||||
// Inform the target of the language options.
|
||||
//
|
||||
// FIXME: We shouldn't need to do this, the target should be immutable once
|
||||
// created. This complexity should be lifted elsewhere.
|
||||
getTarget().setForcedLangOptions(getLangOpts());
|
||||
|
||||
// Validate/process some options.
|
||||
if (getHeaderSearchOpts().Verbose)
|
||||
OS << "clang -cc1 version " CLANG_VERSION_STRING
|
||||
<< " based upon " << PACKAGE_STRING
|
||||
<< " hosted on " << llvm::sys::getHostTriple() << "\n";
|
||||
|
||||
if (getFrontendOpts().ShowTimers)
|
||||
createFrontendTimer();
|
||||
|
||||
for (unsigned i = 0, e = getFrontendOpts().Inputs.size(); i != e; ++i) {
|
||||
const std::string &InFile = getFrontendOpts().Inputs[i].second;
|
||||
|
||||
// If we aren't using an AST file, setup the file and source managers and
|
||||
// the preprocessor.
|
||||
bool IsAST = getFrontendOpts().Inputs[i].first == FrontendOptions::IK_AST;
|
||||
if (!IsAST) {
|
||||
if (!i) {
|
||||
// Create a file manager object to provide access to and cache the
|
||||
// filesystem.
|
||||
createFileManager();
|
||||
|
||||
// Create the source manager.
|
||||
createSourceManager();
|
||||
} else {
|
||||
// Reset the ID tables if we are reusing the SourceManager.
|
||||
getSourceManager().clearIDTables();
|
||||
}
|
||||
|
||||
// Create the preprocessor.
|
||||
createPreprocessor();
|
||||
}
|
||||
|
||||
if (Act.BeginSourceFile(*this, InFile, IsAST)) {
|
||||
Act.Execute();
|
||||
Act.EndSourceFile();
|
||||
}
|
||||
}
|
||||
|
||||
if (getDiagnosticOpts().ShowCarets)
|
||||
if (unsigned NumDiagnostics = getDiagnostics().getNumDiagnostics())
|
||||
OS << NumDiagnostics << " diagnostic"
|
||||
<< (NumDiagnostics == 1 ? "" : "s")
|
||||
<< " generated.\n";
|
||||
|
||||
if (getFrontendOpts().ShowStats) {
|
||||
getFileManager().PrintStats();
|
||||
OS << "\n";
|
||||
}
|
||||
|
||||
// Return the appropriate status when verifying diagnostics.
|
||||
//
|
||||
// FIXME: If we could make getNumErrors() do the right thing, we wouldn't need
|
||||
// this.
|
||||
if (getDiagnosticOpts().VerifyDiagnostics)
|
||||
return !static_cast<VerifyDiagnosticsClient&>(
|
||||
getDiagnosticClient()).HadErrors();
|
||||
|
||||
return !getDiagnostics().getNumErrors();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,10 +14,6 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Basic/Diagnostic.h"
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "clang/Basic/Version.h"
|
||||
#include "clang/Driver/Arg.h"
|
||||
#include "clang/Driver/ArgList.h"
|
||||
#include "clang/Driver/CC1Options.h"
|
||||
|
@ -30,7 +26,6 @@
|
|||
#include "clang/Frontend/FrontendPluginRegistry.h"
|
||||
#include "clang/Frontend/TextDiagnosticBuffer.h"
|
||||
#include "clang/Frontend/TextDiagnosticPrinter.h"
|
||||
#include "clang/Frontend/VerifyDiagnosticsClient.h"
|
||||
#include "llvm/LLVMContext.h"
|
||||
#include "llvm/ADT/OwningPtr.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
@ -38,8 +33,6 @@
|
|||
#include "llvm/Support/PrettyStackTrace.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/System/DynamicLibrary.h"
|
||||
#include "llvm/System/Host.h"
|
||||
#include "llvm/System/Path.h"
|
||||
#include "llvm/System/Signals.h"
|
||||
#include "llvm/Target/TargetSelect.h"
|
||||
#include <cstdio>
|
||||
|
@ -207,13 +200,13 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,
|
|||
Diags);
|
||||
|
||||
// Infer the builtin include path if unspecified.
|
||||
if (Clang.getInvocation().getHeaderSearchOpts().UseBuiltinIncludes &&
|
||||
Clang.getInvocation().getHeaderSearchOpts().ResourceDir.empty())
|
||||
Clang.getInvocation().getHeaderSearchOpts().ResourceDir =
|
||||
if (Clang.getHeaderSearchOpts().UseBuiltinIncludes &&
|
||||
Clang.getHeaderSearchOpts().ResourceDir.empty())
|
||||
Clang.getHeaderSearchOpts().ResourceDir =
|
||||
CompilerInvocation::GetResourcesPath(Argv0, MainAddr);
|
||||
|
||||
// Honor -help.
|
||||
if (Clang.getInvocation().getFrontendOpts().ShowHelp) {
|
||||
if (Clang.getFrontendOpts().ShowHelp) {
|
||||
llvm::OwningPtr<driver::OptTable> Opts(driver::createCC1OptTable());
|
||||
Opts->PrintHelp(llvm::outs(), "clang -cc1",
|
||||
"LLVM 'Clang' Compiler: http://clang.llvm.org");
|
||||
|
@ -223,7 +216,7 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,
|
|||
// Honor -version.
|
||||
//
|
||||
// FIXME: Use a better -version message?
|
||||
if (Clang.getInvocation().getFrontendOpts().ShowVersion) {
|
||||
if (Clang.getFrontendOpts().ShowVersion) {
|
||||
llvm::cl::PrintVersionMessage();
|
||||
return 0;
|
||||
}
|
||||
|
@ -249,85 +242,18 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,
|
|||
Diags.Report(diag::err_fe_unable_to_load_plugin) << Path << Error;
|
||||
}
|
||||
|
||||
// Create the frontend action.
|
||||
llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang));
|
||||
|
||||
// If there were any errors in processing arguments, exit now.
|
||||
if (!Act || Clang.getDiagnostics().getNumErrors())
|
||||
return 1;
|
||||
|
||||
// Create the target instance.
|
||||
Clang.setTarget(TargetInfo::CreateTargetInfo(Clang.getDiagnostics(),
|
||||
Clang.getTargetOpts()));
|
||||
if (!Clang.hasTarget())
|
||||
return 1;
|
||||
|
||||
// Inform the target of the language options.
|
||||
//
|
||||
// FIXME: We shouldn't need to do this, the target should be immutable once
|
||||
// created. This complexity should be lifted elsewhere.
|
||||
Clang.getTarget().setForcedLangOptions(Clang.getLangOpts());
|
||||
|
||||
// Validate/process some options.
|
||||
if (Clang.getHeaderSearchOpts().Verbose)
|
||||
llvm::errs() << "clang -cc1 version " CLANG_VERSION_STRING
|
||||
<< " based upon " << PACKAGE_STRING
|
||||
<< " hosted on " << llvm::sys::getHostTriple() << "\n";
|
||||
|
||||
if (Clang.getFrontendOpts().ShowTimers)
|
||||
Clang.createFrontendTimer();
|
||||
|
||||
for (unsigned i = 0, e = Clang.getFrontendOpts().Inputs.size(); i != e; ++i) {
|
||||
const std::string &InFile = Clang.getFrontendOpts().Inputs[i].second;
|
||||
|
||||
// If we aren't using an AST file, setup the file and source managers and
|
||||
// the preprocessor.
|
||||
bool IsAST =
|
||||
Clang.getFrontendOpts().Inputs[i].first == FrontendOptions::IK_AST;
|
||||
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();
|
||||
}
|
||||
|
||||
if (Act->BeginSourceFile(Clang, InFile, IsAST)) {
|
||||
Act->Execute();
|
||||
Act->EndSourceFile();
|
||||
}
|
||||
// If there were errors in processing arguments, don't do anything else.
|
||||
bool Success = false;
|
||||
if (!Clang.getDiagnostics().getNumErrors()) {
|
||||
// Create and execute the frontend action.
|
||||
llvm::OwningPtr<FrontendAction> Act(CreateFrontendAction(Clang));
|
||||
if (Act)
|
||||
Success = Clang.ExecuteAction(*Act);
|
||||
}
|
||||
|
||||
if (Clang.getDiagnosticOpts().ShowCarets)
|
||||
if (unsigned NumDiagnostics = Clang.getDiagnostics().getNumDiagnostics())
|
||||
fprintf(stderr, "%d diagnostic%s generated.\n", NumDiagnostics,
|
||||
(NumDiagnostics == 1 ? "" : "s"));
|
||||
|
||||
if (Clang.getFrontendOpts().ShowStats) {
|
||||
Clang.getFileManager().PrintStats();
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
// Return the appropriate status when verifying diagnostics.
|
||||
//
|
||||
// FIXME: If we could make getNumErrors() do the right thing, we wouldn't need
|
||||
// this.
|
||||
if (Clang.getDiagnosticOpts().VerifyDiagnostics)
|
||||
return static_cast<VerifyDiagnosticsClient&>(
|
||||
Clang.getDiagnosticClient()).HadErrors();
|
||||
|
||||
// Managed static deconstruction. Useful for making things like
|
||||
// -time-passes usable.
|
||||
llvm::llvm_shutdown();
|
||||
|
||||
return (Clang.getDiagnostics().getNumErrors() != 0);
|
||||
return !Success;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue