diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/FrontendTool')
-rw-r--r-- | contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp new file mode 100644 index 000000000000..166631558806 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -0,0 +1,255 @@ +//===--- ExecuteCompilerInvocation.cpp ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file holds ExecuteCompilerInvocation(). It is split into its own file to +// minimize the impact of pulling in essentially everything else in Clang. +// +//===----------------------------------------------------------------------===// + +#include "clang/FrontendTool/Utils.h" +#include "clang/ARCMigrate/ARCMTActions.h" +#include "clang/CodeGen/CodeGenAction.h" +#include "clang/Config/config.h" +#include "clang/Driver/Options.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/FrontendActions.h" +#include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include "clang/Frontend/Utils.h" +#include "clang/Rewrite/Frontend/FrontendActions.h" +#include "clang/StaticAnalyzer/Frontend/FrontendActions.h" +#include "llvm/Option/OptTable.h" +#include "llvm/Option/Option.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/ErrorHandling.h" +using namespace clang; +using namespace llvm::opt; + +static std::unique_ptr<FrontendAction> +CreateFrontendBaseAction(CompilerInstance &CI) { + using namespace clang::frontend; + StringRef Action("unknown"); + (void)Action; + + switch (CI.getFrontendOpts().ProgramAction) { + case ASTDeclList: return llvm::make_unique<ASTDeclListAction>(); + case ASTDump: return llvm::make_unique<ASTDumpAction>(); + case ASTPrint: return llvm::make_unique<ASTPrintAction>(); + case ASTView: return llvm::make_unique<ASTViewAction>(); + case DumpRawTokens: return llvm::make_unique<DumpRawTokensAction>(); + case DumpTokens: return llvm::make_unique<DumpTokensAction>(); + case EmitAssembly: return llvm::make_unique<EmitAssemblyAction>(); + case EmitBC: return llvm::make_unique<EmitBCAction>(); + case EmitHTML: return llvm::make_unique<HTMLPrintAction>(); + case EmitLLVM: return llvm::make_unique<EmitLLVMAction>(); + case EmitLLVMOnly: return llvm::make_unique<EmitLLVMOnlyAction>(); + case EmitCodeGenOnly: return llvm::make_unique<EmitCodeGenOnlyAction>(); + case EmitObj: return llvm::make_unique<EmitObjAction>(); + case FixIt: return llvm::make_unique<FixItAction>(); + case GenerateModule: + return llvm::make_unique<GenerateModuleFromModuleMapAction>(); + case GenerateModuleInterface: + return llvm::make_unique<GenerateModuleInterfaceAction>(); + case GeneratePCH: return llvm::make_unique<GeneratePCHAction>(); + case GeneratePTH: return llvm::make_unique<GeneratePTHAction>(); + case InitOnly: return llvm::make_unique<InitOnlyAction>(); + case ParseSyntaxOnly: return llvm::make_unique<SyntaxOnlyAction>(); + case ModuleFileInfo: return llvm::make_unique<DumpModuleInfoAction>(); + case VerifyPCH: return llvm::make_unique<VerifyPCHAction>(); + + case PluginAction: { + for (FrontendPluginRegistry::iterator it = + FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end(); + it != ie; ++it) { + if (it->getName() == CI.getFrontendOpts().ActionName) { + std::unique_ptr<PluginASTAction> P(it->instantiate()); + if ((P->getActionType() != PluginASTAction::ReplaceAction && + P->getActionType() != PluginASTAction::Cmdline) || + !P->ParseArgs(CI, CI.getFrontendOpts().PluginArgs[it->getName()])) + return nullptr; + return std::move(P); + } + } + + CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name) + << CI.getFrontendOpts().ActionName; + return nullptr; + } + + case PrintDeclContext: return llvm::make_unique<DeclContextPrintAction>(); + case PrintPreamble: return llvm::make_unique<PrintPreambleAction>(); + case PrintPreprocessedInput: { + if (CI.getPreprocessorOutputOpts().RewriteIncludes || + CI.getPreprocessorOutputOpts().RewriteImports) + return llvm::make_unique<RewriteIncludesAction>(); + return llvm::make_unique<PrintPreprocessedAction>(); + } + + case RewriteMacros: return llvm::make_unique<RewriteMacrosAction>(); + case RewriteTest: return llvm::make_unique<RewriteTestAction>(); +#ifdef CLANG_ENABLE_OBJC_REWRITER + case RewriteObjC: return llvm::make_unique<RewriteObjCAction>(); +#else + case RewriteObjC: Action = "RewriteObjC"; break; +#endif +#ifdef CLANG_ENABLE_ARCMT + case MigrateSource: + return llvm::make_unique<arcmt::MigrateSourceAction>(); +#else + case MigrateSource: Action = "MigrateSource"; break; +#endif +#ifdef CLANG_ENABLE_STATIC_ANALYZER + case RunAnalysis: return llvm::make_unique<ento::AnalysisAction>(); +#else + case RunAnalysis: Action = "RunAnalysis"; break; +#endif + case RunPreprocessorOnly: return llvm::make_unique<PreprocessOnlyAction>(); + } + +#if !defined(CLANG_ENABLE_ARCMT) || !defined(CLANG_ENABLE_STATIC_ANALYZER) \ + || !defined(CLANG_ENABLE_OBJC_REWRITER) + CI.getDiagnostics().Report(diag::err_fe_action_not_available) << Action; + return 0; +#else + llvm_unreachable("Invalid program action!"); +#endif +} + +static std::unique_ptr<FrontendAction> +CreateFrontendAction(CompilerInstance &CI) { + // Create the underlying action. + std::unique_ptr<FrontendAction> Act = CreateFrontendBaseAction(CI); + if (!Act) + return nullptr; + + const FrontendOptions &FEOpts = CI.getFrontendOpts(); + + if (FEOpts.FixAndRecompile) { + Act = llvm::make_unique<FixItRecompile>(std::move(Act)); + } + +#ifdef CLANG_ENABLE_ARCMT + if (CI.getFrontendOpts().ProgramAction != frontend::MigrateSource && + CI.getFrontendOpts().ProgramAction != frontend::GeneratePCH) { + // Potentially wrap the base FE action in an ARC Migrate Tool action. + switch (FEOpts.ARCMTAction) { + case FrontendOptions::ARCMT_None: + break; + case FrontendOptions::ARCMT_Check: + Act = llvm::make_unique<arcmt::CheckAction>(std::move(Act)); + break; + case FrontendOptions::ARCMT_Modify: + Act = llvm::make_unique<arcmt::ModifyAction>(std::move(Act)); + break; + case FrontendOptions::ARCMT_Migrate: + Act = llvm::make_unique<arcmt::MigrateAction>(std::move(Act), + FEOpts.MTMigrateDir, + FEOpts.ARCMTMigrateReportOut, + FEOpts.ARCMTMigrateEmitARCErrors); + break; + } + + if (FEOpts.ObjCMTAction != FrontendOptions::ObjCMT_None) { + Act = llvm::make_unique<arcmt::ObjCMigrateAction>(std::move(Act), + FEOpts.MTMigrateDir, + FEOpts.ObjCMTAction); + } + } +#endif + + // If there are any AST files to merge, create a frontend action + // adaptor to perform the merge. + if (!FEOpts.ASTMergeFiles.empty()) + Act = llvm::make_unique<ASTMergeAction>(std::move(Act), + FEOpts.ASTMergeFiles); + + return Act; +} + +bool clang::ExecuteCompilerInvocation(CompilerInstance *Clang) { + // Honor -help. + if (Clang->getFrontendOpts().ShowHelp) { + std::unique_ptr<OptTable> Opts = driver::createDriverOptTable(); + Opts->PrintHelp(llvm::outs(), "clang -cc1", + "LLVM 'Clang' Compiler: http://clang.llvm.org", + /*Include=*/ driver::options::CC1Option, /*Exclude=*/ 0); + return true; + } + + // Honor -version. + // + // FIXME: Use a better -version message? + if (Clang->getFrontendOpts().ShowVersion) { + llvm::cl::PrintVersionMessage(); + return true; + } + + // Load any requested plugins. + for (unsigned i = 0, + e = Clang->getFrontendOpts().Plugins.size(); i != e; ++i) { + const std::string &Path = Clang->getFrontendOpts().Plugins[i]; + std::string Error; + if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(Path.c_str(), &Error)) + Clang->getDiagnostics().Report(diag::err_fe_unable_to_load_plugin) + << Path << Error; + } + + // Check if any of the loaded plugins replaces the main AST action + for (FrontendPluginRegistry::iterator it = FrontendPluginRegistry::begin(), + ie = FrontendPluginRegistry::end(); + it != ie; ++it) { + std::unique_ptr<PluginASTAction> P(it->instantiate()); + if (P->getActionType() == PluginASTAction::ReplaceAction) { + Clang->getFrontendOpts().ProgramAction = clang::frontend::PluginAction; + Clang->getFrontendOpts().ActionName = it->getName(); + break; + } + } + + // Honor -mllvm. + // + // FIXME: Remove this, one day. + // This should happen AFTER plugins have been loaded! + if (!Clang->getFrontendOpts().LLVMArgs.empty()) { + unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size(); + auto Args = llvm::make_unique<const char*[]>(NumArgs + 2); + Args[0] = "clang (LLVM option parsing)"; + for (unsigned i = 0; i != NumArgs; ++i) + Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str(); + Args[NumArgs + 1] = nullptr; + llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get()); + } + +#ifdef CLANG_ENABLE_STATIC_ANALYZER + // Honor -analyzer-checker-help. + // This should happen AFTER plugins have been loaded! + if (Clang->getAnalyzerOpts()->ShowCheckerHelp) { + ento::printCheckerHelp(llvm::outs(), Clang->getFrontendOpts().Plugins); + return true; + } + if (Clang->getAnalyzerOpts()->ShowEnabledCheckerList) { + ento::printEnabledCheckerList(llvm::outs(), + Clang->getFrontendOpts().Plugins, + *Clang->getAnalyzerOpts()); + } +#endif + + // If there were errors in processing arguments, don't do anything else. + if (Clang->getDiagnostics().hasErrorOccurred()) + return false; + // Create and execute the frontend action. + std::unique_ptr<FrontendAction> Act(CreateFrontendAction(*Clang)); + if (!Act) + return false; + bool Success = Clang->ExecuteAction(*Act); + if (Clang->getFrontendOpts().DisableFree) + BuryPointer(std::move(Act)); + return Success; +} |