Mercurial > hg > CbC > CbC_llvm
diff clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | 0572611fdcc8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp Thu Feb 13 15:10:13 2020 +0900 @@ -0,0 +1,298 @@ +//===--- ExecuteCompilerInvocation.cpp ------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// 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/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/FrontendTool/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/BuryPointer.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/ErrorHandling.h" +using namespace clang; +using namespace llvm::opt; + +namespace clang { + +static std::unique_ptr<FrontendAction> +CreateFrontendBaseAction(CompilerInstance &CI) { + using namespace clang::frontend; + StringRef Action("unknown"); + (void)Action; + + switch (CI.getFrontendOpts().ProgramAction) { + case ASTDeclList: return std::make_unique<ASTDeclListAction>(); + case ASTDump: return std::make_unique<ASTDumpAction>(); + case ASTPrint: return std::make_unique<ASTPrintAction>(); + case ASTView: return std::make_unique<ASTViewAction>(); + case DumpCompilerOptions: + return std::make_unique<DumpCompilerOptionsAction>(); + case DumpRawTokens: return std::make_unique<DumpRawTokensAction>(); + case DumpTokens: return std::make_unique<DumpTokensAction>(); + case EmitAssembly: return std::make_unique<EmitAssemblyAction>(); + case EmitBC: return std::make_unique<EmitBCAction>(); + case EmitHTML: return std::make_unique<HTMLPrintAction>(); + case EmitLLVM: return std::make_unique<EmitLLVMAction>(); + case EmitLLVMOnly: return std::make_unique<EmitLLVMOnlyAction>(); + case EmitCodeGenOnly: return std::make_unique<EmitCodeGenOnlyAction>(); + case EmitObj: return std::make_unique<EmitObjAction>(); + case FixIt: return std::make_unique<FixItAction>(); + case GenerateModule: + return std::make_unique<GenerateModuleFromModuleMapAction>(); + case GenerateModuleInterface: + return std::make_unique<GenerateModuleInterfaceAction>(); + case GenerateHeaderModule: + return std::make_unique<GenerateHeaderModuleAction>(); + case GeneratePCH: return std::make_unique<GeneratePCHAction>(); + case GenerateInterfaceIfsExpV1: + return std::make_unique<GenerateInterfaceIfsExpV1Action>(); + case InitOnly: return std::make_unique<InitOnlyAction>(); + case ParseSyntaxOnly: return std::make_unique<SyntaxOnlyAction>(); + case ModuleFileInfo: return std::make_unique<DumpModuleInfoAction>(); + case VerifyPCH: return std::make_unique<VerifyPCHAction>(); + case TemplightDump: return std::make_unique<TemplightDumpAction>(); + + 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[std::string(it->getName())])) + return nullptr; + return std::move(P); + } + } + + CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name) + << CI.getFrontendOpts().ActionName; + return nullptr; + } + + case PrintPreamble: return std::make_unique<PrintPreambleAction>(); + case PrintPreprocessedInput: { + if (CI.getPreprocessorOutputOpts().RewriteIncludes || + CI.getPreprocessorOutputOpts().RewriteImports) + return std::make_unique<RewriteIncludesAction>(); + return std::make_unique<PrintPreprocessedAction>(); + } + + case RewriteMacros: return std::make_unique<RewriteMacrosAction>(); + case RewriteTest: return std::make_unique<RewriteTestAction>(); +#if CLANG_ENABLE_OBJC_REWRITER + case RewriteObjC: return std::make_unique<RewriteObjCAction>(); +#else + case RewriteObjC: Action = "RewriteObjC"; break; +#endif +#if CLANG_ENABLE_ARCMT + case MigrateSource: + return std::make_unique<arcmt::MigrateSourceAction>(); +#else + case MigrateSource: Action = "MigrateSource"; break; +#endif +#if CLANG_ENABLE_STATIC_ANALYZER + case RunAnalysis: return std::make_unique<ento::AnalysisAction>(); +#else + case RunAnalysis: Action = "RunAnalysis"; break; +#endif + case RunPreprocessorOnly: return std::make_unique<PreprocessOnlyAction>(); + case PrintDependencyDirectivesSourceMinimizerOutput: + return std::make_unique<PrintDependencyDirectivesSourceMinimizerAction>(); + } + +#if !CLANG_ENABLE_ARCMT || !CLANG_ENABLE_STATIC_ANALYZER \ + || !CLANG_ENABLE_OBJC_REWRITER + CI.getDiagnostics().Report(diag::err_fe_action_not_available) << Action; + return 0; +#else + llvm_unreachable("Invalid program action!"); +#endif +} + +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 = std::make_unique<FixItRecompile>(std::move(Act)); + } + +#if 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 = std::make_unique<arcmt::CheckAction>(std::move(Act)); + break; + case FrontendOptions::ARCMT_Modify: + Act = std::make_unique<arcmt::ModifyAction>(std::move(Act)); + break; + case FrontendOptions::ARCMT_Migrate: + Act = std::make_unique<arcmt::MigrateAction>(std::move(Act), + FEOpts.MTMigrateDir, + FEOpts.ARCMTMigrateReportOut, + FEOpts.ARCMTMigrateEmitARCErrors); + break; + } + + if (FEOpts.ObjCMTAction != FrontendOptions::ObjCMT_None) { + Act = std::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 = std::make_unique<ASTMergeAction>(std::move(Act), + FEOpts.ASTMergeFiles); + + return Act; +} + +bool ExecuteCompilerInvocation(CompilerInstance *Clang) { + // Honor -help. + if (Clang->getFrontendOpts().ShowHelp) { + driver::getDriverOptTable().PrintHelp( + llvm::outs(), "clang -cc1 [options] file...", + "LLVM 'Clang' Compiler: http://clang.llvm.org", + /*Include=*/driver::options::CC1Option, + /*Exclude=*/0, /*ShowAllAliases=*/false); + 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 = std::string(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 = std::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()); + } + +#if CLANG_ENABLE_STATIC_ANALYZER + // These should happen AFTER plugins have been loaded! + + AnalyzerOptions &AnOpts = *Clang->getAnalyzerOpts(); + // Honor -analyzer-checker-help and -analyzer-checker-help-hidden. + if (AnOpts.ShowCheckerHelp || AnOpts.ShowCheckerHelpAlpha || + AnOpts.ShowCheckerHelpDeveloper) { + ento::printCheckerHelp(llvm::outs(), + Clang->getFrontendOpts().Plugins, + AnOpts, + Clang->getDiagnostics(), + Clang->getLangOpts()); + return true; + } + + // Honor -analyzer-checker-option-help. + if (AnOpts.ShowCheckerOptionList || AnOpts.ShowCheckerOptionAlphaList || + AnOpts.ShowCheckerOptionDeveloperList) { + ento::printCheckerConfigList(llvm::outs(), + Clang->getFrontendOpts().Plugins, + *Clang->getAnalyzerOpts(), + Clang->getDiagnostics(), + Clang->getLangOpts()); + return true; + } + + // Honor -analyzer-list-enabled-checkers. + if (AnOpts.ShowEnabledCheckerList) { + ento::printEnabledCheckerList(llvm::outs(), + Clang->getFrontendOpts().Plugins, + AnOpts, + Clang->getDiagnostics(), + Clang->getLangOpts()); + return true; + } + + // Honor -analyzer-config-help. + if (AnOpts.ShowConfigOptionsList) { + ento::printAnalyzerConfigList(llvm::outs()); + return true; + } +#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) + llvm::BuryPointer(std::move(Act)); + return Success; +} + +} // namespace clang