Infer -target and --driver-mode from argv[0]

Fix #511
This commit is contained in:
Fangrui Song 2019-10-31 22:31:03 -07:00
parent 5935db10fd
commit 0fe8a16504

View File

@ -7,6 +7,10 @@
#include "platform.hh"
#include <clang/AST/Type.h>
#include <clang/Driver/Action.h>
#include <clang/Driver/Compilation.h>
#include <clang/Driver/Driver.h>
#include <clang/Driver/Tool.h>
#include <clang/Lex/Lexer.h>
#include <llvm/Support/Host.h>
#include <llvm/Support/Path.h>
@ -77,21 +81,66 @@ buildCompilerInvocation(const std::string &main, std::vector<const char *> args,
IntrusiveRefCntPtr<llvm::vfs::FileSystem> vfs) {
std::string save = "-resource-dir=" + g_config->clang.resourceDir;
args.push_back(save.c_str());
args.push_back("-fsyntax-only");
// Similar to clang/tools/driver/driver.cpp:insertTargetAndModeArgs but don't
// require llvm::InitializeAllTargetInfos().
auto target_and_mode =
driver::ToolChain::getTargetAndModeFromProgramName(args[0]);
if (target_and_mode.DriverMode)
args.insert(args.begin() + 1, target_and_mode.DriverMode);
if (!target_and_mode.TargetPrefix.empty()) {
const char *arr[] = {"-target", target_and_mode.TargetPrefix.c_str()};
args.insert(args.begin() + 1, std::begin(arr), std::end(arr));
}
IntrusiveRefCntPtr<DiagnosticsEngine> diags(
CompilerInstance::createDiagnostics(new DiagnosticOptions,
new IgnoringDiagConsumer, true));
std::unique_ptr<CompilerInvocation> ci =
createInvocationFromCommandLine(args, diags, vfs);
if (ci) {
ci->getDiagnosticOpts().IgnoreWarnings = true;
ci->getFrontendOpts().DisableFree = false;
// Enable IndexFrontendAction::shouldSkipFunctionBody.
ci->getFrontendOpts().SkipFunctionBodies = true;
ci->getLangOpts()->SpellChecking = false;
auto &isec = ci->getFrontendOpts().Inputs;
if (isec.size())
isec[0] = FrontendInputFile(main, isec[0].getKind(), isec[0].isSystem());
driver::Driver d(args[0], llvm::sys::getDefaultTargetTriple(), *diags, vfs);
d.setCheckInputsExist(false);
std::unique_ptr<driver::Compilation> comp(d.BuildCompilation(args));
if (!comp)
return nullptr;
const driver::JobList &jobs = comp->getJobs();
bool offload_compilation = false;
if (jobs.size() > 1) {
for (auto &a : comp->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)) {
offload_compilation = true;
break;
}
}
if (!offload_compilation)
return nullptr;
}
if (jobs.size() == 0 || !isa<driver::Command>(*jobs.begin()))
return nullptr;
const driver::Command &cmd = cast<driver::Command>(*jobs.begin());
if (StringRef(cmd.getCreator().getName()) != "clang")
return nullptr;
const llvm::opt::ArgStringList &cc_args = cmd.getArguments();
auto ci = std::make_unique<CompilerInvocation>();
#if LLVM_VERSION_MAJOR >= 10 // rC370122
if (!CompilerInvocation::CreateFromArgs(*ci, cc_args, *diags))
#else
if (!CompilerInvocation::CreateFromArgs(
*ci, cc_args.data(), cc_args.data() + cc_args.size(), *diags))
#endif
return nullptr;
ci->getDiagnosticOpts().IgnoreWarnings = true;
ci->getFrontendOpts().DisableFree = false;
// Enable IndexFrontendAction::shouldSkipFunctionBody.
ci->getFrontendOpts().SkipFunctionBodies = true;
ci->getLangOpts()->SpellChecking = false;
auto &isec = ci->getFrontendOpts().Inputs;
if (isec.size())
isec[0] = FrontendInputFile(main, isec[0].getKind(), isec[0].isSystem());
return ci;
}