diff options
Diffstat (limited to 'clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp')
| -rw-r--r-- | clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp | 296 | 
1 files changed, 296 insertions, 0 deletions
| diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp new file mode 100644 index 0000000000000..9bf70b793d9b8 --- /dev/null +++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -0,0 +1,296 @@ +//===--- 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[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 = 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 | 
