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