Path: blob/main/contrib/llvm-project/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp
35232 views
//===--- CreateInvocationFromCommandLine.cpp - CompilerInvocation from Args ==//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Construct a compiler invocation object for command line driver arguments9//10//===----------------------------------------------------------------------===//1112#include "clang/Basic/DiagnosticOptions.h"13#include "clang/Driver/Action.h"14#include "clang/Driver/Compilation.h"15#include "clang/Driver/Driver.h"16#include "clang/Driver/Options.h"17#include "clang/Driver/Tool.h"18#include "clang/Frontend/CompilerInstance.h"19#include "clang/Frontend/FrontendDiagnostic.h"20#include "clang/Frontend/Utils.h"21#include "llvm/ADT/STLExtras.h"22#include "llvm/ADT/StringRef.h"23#include "llvm/Option/ArgList.h"24#include "llvm/TargetParser/Host.h"25using namespace clang;26using namespace llvm::opt;2728std::unique_ptr<CompilerInvocation>29clang::createInvocation(ArrayRef<const char *> ArgList,30CreateInvocationOptions Opts) {31assert(!ArgList.empty());32auto Diags = Opts.Diags33? std::move(Opts.Diags)34: CompilerInstance::createDiagnostics(new DiagnosticOptions);3536SmallVector<const char *, 16> Args(ArgList.begin(), ArgList.end());3738// FIXME: Find a cleaner way to force the driver into restricted modes.39Args.insert(40llvm::find_if(41Args, [](const char *Elem) { return llvm::StringRef(Elem) == "--"; }),42"-fsyntax-only");4344// FIXME: We shouldn't have to pass in the path info.45driver::Driver TheDriver(Args[0], llvm::sys::getDefaultTargetTriple(), *Diags,46"clang LLVM compiler", Opts.VFS);4748// Don't check that inputs exist, they may have been remapped.49TheDriver.setCheckInputsExist(false);50TheDriver.setProbePrecompiled(Opts.ProbePrecompiled);5152std::unique_ptr<driver::Compilation> C(TheDriver.BuildCompilation(Args));53if (!C)54return nullptr;5556if (C->getArgs().hasArg(driver::options::OPT_fdriver_only))57return nullptr;5859// Just print the cc1 options if -### was present.60if (C->getArgs().hasArg(driver::options::OPT__HASH_HASH_HASH)) {61C->getJobs().Print(llvm::errs(), "\n", true);62return nullptr;63}6465// We expect to get back exactly one command job, if we didn't something66// failed. Offload compilation is an exception as it creates multiple jobs. If67// that's the case, we proceed with the first job. If caller needs a68// particular job, it should be controlled via options (e.g.69// --cuda-{host|device}-only for CUDA) passed to the driver.70const driver::JobList &Jobs = C->getJobs();71bool OffloadCompilation = false;72if (Jobs.size() > 1) {73for (auto &A : C->getActions()){74// On MacOSX real actions may end up being wrapped in BindArchAction75if (isa<driver::BindArchAction>(A))76A = *A->input_begin();77if (isa<driver::OffloadAction>(A)) {78OffloadCompilation = true;79break;80}81}82}8384bool PickFirstOfMany = OffloadCompilation || Opts.RecoverOnError;85if (Jobs.size() == 0 || (Jobs.size() > 1 && !PickFirstOfMany)) {86SmallString<256> Msg;87llvm::raw_svector_ostream OS(Msg);88Jobs.Print(OS, "; ", true);89Diags->Report(diag::err_fe_expected_compiler_job) << OS.str();90return nullptr;91}92auto Cmd = llvm::find_if(Jobs, [](const driver::Command &Cmd) {93return StringRef(Cmd.getCreator().getName()) == "clang";94});95if (Cmd == Jobs.end()) {96Diags->Report(diag::err_fe_expected_clang_command);97return nullptr;98}99100const ArgStringList &CCArgs = Cmd->getArguments();101if (Opts.CC1Args)102*Opts.CC1Args = {CCArgs.begin(), CCArgs.end()};103auto CI = std::make_unique<CompilerInvocation>();104if (!CompilerInvocation::CreateFromArgs(*CI, CCArgs, *Diags, Args[0]) &&105!Opts.RecoverOnError)106return nullptr;107return CI;108}109110111