teak-llvm/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp
Serge Pavlov c46064c2a9 Method loadFromCommandLine should be able to report errors
Now FixedCompilationDatabase::loadFromCommandLine has no means to report
which error occurred if it fails to create compilation object. This is
a block for implementing D33013, because after that change driver will
refuse to create compilation if command line contains erroneous options.

This change adds additional argument to loadFromCommandLine, which is
assigned error message text if compilation object was not created. This is
the same way as other methods of CompilationDatabase report failure.

Differential Revision: https://reviews.llvm.org/D33272

llvm-svn: 303741
2017-05-24 11:57:37 +00:00

107 lines
3.9 KiB
C++

//===--- CreateInvocationFromCommandLine.cpp - CompilerInvocation from Args ==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// 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) {
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);
// 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;
}