From 0fe8a165046cc3298f113b54ed6863f486714c20 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 31 Oct 2019 22:31:03 -0700 Subject: [PATCH] Infer -target and --driver-mode from argv[0] Fix #511 --- src/clang_tu.cc | 71 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 60 insertions(+), 11 deletions(-) diff --git a/src/clang_tu.cc b/src/clang_tu.cc index e6e4e03d..5042714f 100644 --- a/src/clang_tu.cc +++ b/src/clang_tu.cc @@ -7,6 +7,10 @@ #include "platform.hh" #include +#include +#include +#include +#include #include #include #include @@ -77,21 +81,66 @@ buildCompilerInvocation(const std::string &main, std::vector args, IntrusiveRefCntPtr 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 diags( CompilerInstance::createDiagnostics(new DiagnosticOptions, new IgnoringDiagConsumer, true)); - std::unique_ptr 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 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(a)) + a = *a->input_begin(); + if (isa(a)) { + offload_compilation = true; + break; + } + } + if (!offload_compilation) + return nullptr; } + if (jobs.size() == 0 || !isa(*jobs.begin())) + return nullptr; + + const driver::Command &cmd = cast(*jobs.begin()); + if (StringRef(cmd.getCreator().getName()) != "clang") + return nullptr; + const llvm::opt::ArgStringList &cc_args = cmd.getArguments(); + auto ci = std::make_unique(); +#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; }