diff options
Diffstat (limited to 'clang/lib/Frontend/CreateInvocationFromCommandLine.cpp')
| -rw-r--r-- | clang/lib/Frontend/CreateInvocationFromCommandLine.cpp | 105 | 
1 files changed, 105 insertions, 0 deletions
diff --git a/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp b/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp new file mode 100644 index 000000000000..b62416ffd9e7 --- /dev/null +++ b/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp @@ -0,0 +1,105 @@ +//===--- CreateInvocationFromCommandLine.cpp - CompilerInvocation from Args ==// +// +// 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 +// +//===----------------------------------------------------------------------===// +// +// Construct a compiler invocation object for command line driver arguments +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/Utils.h" +#include "clang/Basic/DiagnosticOptions.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/Action.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/Tool.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendDiagnostic.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Support/Host.h" +using namespace clang; +using namespace llvm::opt; + +/// createInvocationFromCommandLine - Construct a compiler invocation object for +/// a command line argument vector. +/// +/// \return A CompilerInvocation, or 0 if none was built for the given +/// argument vector. +std::unique_ptr<CompilerInvocation> clang::createInvocationFromCommandLine( +    ArrayRef<const char *> ArgList, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, +    IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS) { +  if (!Diags.get()) { +    // No diagnostics engine was provided, so create our own diagnostics object +    // with the default options. +    Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions); +  } + +  SmallVector<const char *, 16> Args(ArgList.begin(), ArgList.end()); + +  // FIXME: Find a cleaner way to force the driver into restricted modes. +  Args.push_back("-fsyntax-only"); + +  // FIXME: We shouldn't have to pass in the path info. +  driver::Driver TheDriver(Args[0], llvm::sys::getDefaultTargetTriple(), +                           *Diags, VFS); + +  // Don't check that inputs exist, they may have been remapped. +  TheDriver.setCheckInputsExist(false); + +  std::unique_ptr<driver::Compilation> C(TheDriver.BuildCompilation(Args)); +  if (!C) +    return nullptr; + +  // Just print the cc1 options if -### was present. +  if (C->getArgs().hasArg(driver::options::OPT__HASH_HASH_HASH)) { +    C->getJobs().Print(llvm::errs(), "\n", true); +    return nullptr; +  } + +  // We expect to get back exactly one command job, if we didn't something +  // failed. Offload compilation is an exception as it creates multiple jobs. If +  // that's the case, we proceed with the first job. If caller needs a +  // particular job, it should be controlled via options (e.g. +  // --cuda-{host|device}-only for CUDA) passed to the driver. +  const driver::JobList &Jobs = C->getJobs(); +  bool OffloadCompilation = false; +  if (Jobs.size() > 1) { +    for (auto &A : C->getActions()){ +      // On MacOSX real actions may end up being wrapped in BindArchAction +      if (isa<driver::BindArchAction>(A)) +        A = *A->input_begin(); +      if (isa<driver::OffloadAction>(A)) { +        OffloadCompilation = true; +        break; +      } +    } +  } +  if (Jobs.size() == 0 || !isa<driver::Command>(*Jobs.begin()) || +      (Jobs.size() > 1 && !OffloadCompilation)) { +    SmallString<256> Msg; +    llvm::raw_svector_ostream OS(Msg); +    Jobs.Print(OS, "; ", true); +    Diags->Report(diag::err_fe_expected_compiler_job) << OS.str(); +    return nullptr; +  } + +  const driver::Command &Cmd = cast<driver::Command>(*Jobs.begin()); +  if (StringRef(Cmd.getCreator().getName()) != "clang") { +    Diags->Report(diag::err_fe_expected_clang_command); +    return nullptr; +  } + +  const ArgStringList &CCArgs = Cmd.getArguments(); +  auto CI = llvm::make_unique<CompilerInvocation>(); +  if (!CompilerInvocation::CreateFromArgs(*CI, +                                     const_cast<const char **>(CCArgs.data()), +                                     const_cast<const char **>(CCArgs.data()) + +                                     CCArgs.size(), +                                     *Diags)) +    return nullptr; +  return CI; +}  | 
