[llvm] 3e57aa3 - [llvm-driver] Reinvoke clang as described by llvm driver extra args
Alex Brachet via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 10 11:42:46 PST 2023
Author: Alex Brachet
Date: 2023-02-10T19:42:32Z
New Revision: 3e57aa304f15a0821e5bcc90bd346529fed6658d
URL: https://github.com/llvm/llvm-project/commit/3e57aa304f15a0821e5bcc90bd346529fed6658d
DIFF: https://github.com/llvm/llvm-project/commit/3e57aa304f15a0821e5bcc90bd346529fed6658d.diff
LOG: [llvm-driver] Reinvoke clang as described by llvm driver extra args
Differential Revision: https://reviews.llvm.org/D137800
Added:
Modified:
clang/include/clang/Driver/Driver.h
clang/include/clang/Driver/Job.h
clang/lib/Driver/Driver.cpp
clang/lib/Driver/Job.cpp
clang/lib/Driver/ToolChains/Clang.cpp
clang/test/Analysis/scan-build/lit.local.cfg
clang/test/CodeGen/debug-info-codeview-buildinfo.c
clang/test/Driver/check-time-trace.cpp
clang/tools/driver/cc1gen_reproducer_main.cpp
clang/tools/driver/driver.cpp
clang/tools/scan-build/libexec/ccc-analyzer
llvm/cmake/modules/llvm-driver-template.cpp.in
llvm/include/llvm/Support/LLVMDriver.h
llvm/lib/Support/Path.cpp
llvm/lib/Support/Unix/Path.inc
llvm/lib/Support/Windows/Path.inc
llvm/tools/llvm-driver/llvm-driver.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index 4bbb113b6cf59..c9136ec4ae690 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -21,6 +21,7 @@
#include "clang/Driver/Types.h"
#include "clang/Driver/Util.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Option/Arg.h"
@@ -261,7 +262,8 @@ class Driver {
/// When the clangDriver lib is used through clang.exe, this provides a
/// shortcut for executing the -cc1 command-line directly, in the same
/// process.
- typedef int (*CC1ToolFunc)(SmallVectorImpl<const char *> &ArgV);
+ using CC1ToolFunc =
+ llvm::function_ref<int(SmallVectorImpl<const char *> &ArgV)>;
CC1ToolFunc CC1Main = nullptr;
private:
@@ -286,6 +288,12 @@ class Driver {
/// Arguments originated from command line.
std::unique_ptr<llvm::opt::InputArgList> CLOptions;
+ /// If this is non-null, the driver will prepend this argument before
+ /// reinvoking clang. This is useful for the llvm-driver where clang's
+ /// realpath will be to the llvm binary and not clang, so it must pass
+ /// "clang" as it's first argument.
+ const char *PrependArg;
+
/// Whether to check that input files exist when constructing compilation
/// jobs.
unsigned CheckInputsExist : 1;
@@ -383,6 +391,9 @@ class Driver {
bool getProbePrecompiled() const { return ProbePrecompiled; }
void setProbePrecompiled(bool Value) { ProbePrecompiled = Value; }
+ const char *getPrependArg() const { return PrependArg; }
+ void setPrependArg(const char *Value) { PrependArg = Value; }
+
void setTargetAndMode(const ParsedClangName &TM) { ClangNameParts = TM; }
const std::string &getTitle() { return DriverTitle; }
diff --git a/clang/include/clang/Driver/Job.h b/clang/include/clang/Driver/Job.h
index e3fa92d6ad5fd..e866679dc1a91 100644
--- a/clang/include/clang/Driver/Job.h
+++ b/clang/include/clang/Driver/Job.h
@@ -116,6 +116,9 @@ class Command {
/// The executable to run.
const char *Executable;
+ /// Optional argument to prepend.
+ const char *PrependArg;
+
/// The list of program arguments (not including the implicit first
/// argument, which will be the executable).
llvm::opt::ArgStringList Arguments;
@@ -169,7 +172,8 @@ class Command {
Command(const Action &Source, const Tool &Creator,
ResponseFileSupport ResponseSupport, const char *Executable,
const llvm::opt::ArgStringList &Arguments, ArrayRef<InputInfo> Inputs,
- ArrayRef<InputInfo> Outputs = std::nullopt);
+ ArrayRef<InputInfo> Outputs = std::nullopt,
+ const char *PrependArg = nullptr);
// FIXME: This really shouldn't be copyable, but is currently copied in some
// error handling in Driver::generateCompilationDiagnostics.
Command(const Command &) = default;
@@ -242,7 +246,8 @@ class CC1Command : public Command {
ResponseFileSupport ResponseSupport, const char *Executable,
const llvm::opt::ArgStringList &Arguments,
ArrayRef<InputInfo> Inputs,
- ArrayRef<InputInfo> Outputs = std::nullopt);
+ ArrayRef<InputInfo> Outputs = std::nullopt,
+ const char *PrependArg = nullptr);
void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
CrashReportInfo *CrashInfo = nullptr) const override;
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 8d8bd55cabae6..0567441225d0c 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -200,7 +200,7 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple,
DriverTitle(Title), CCCPrintBindings(false), CCPrintOptions(false),
CCLogDiagnostics(false), CCGenDiagnostics(false),
CCPrintProcessStats(false), TargetTriple(TargetTriple), Saver(Alloc),
- CheckInputsExist(true), ProbePrecompiled(true),
+ PrependArg(nullptr), CheckInputsExist(true), ProbePrecompiled(true),
SuppressMissingInputWarning(false) {
// Provide a sane fallback if no VFS is specified.
if (!this->VFS)
diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp
index ec355ceb84a9c..f85f55cd1ff54 100644
--- a/clang/lib/Driver/Job.cpp
+++ b/clang/lib/Driver/Job.cpp
@@ -38,9 +38,10 @@ using namespace driver;
Command::Command(const Action &Source, const Tool &Creator,
ResponseFileSupport ResponseSupport, const char *Executable,
const llvm::opt::ArgStringList &Arguments,
- ArrayRef<InputInfo> Inputs, ArrayRef<InputInfo> Outputs)
+ ArrayRef<InputInfo> Inputs, ArrayRef<InputInfo> Outputs,
+ const char *PrependArg)
: Source(Source), Creator(Creator), ResponseSupport(ResponseSupport),
- Executable(Executable), Arguments(Arguments) {
+ Executable(Executable), PrependArg(PrependArg), Arguments(Arguments) {
for (const auto &II : Inputs)
if (II.isFilename())
InputInfoList.push_back(II);
@@ -144,6 +145,10 @@ void Command::buildArgvForResponseFile(
for (const auto *InputName : InputFileList)
Inputs.insert(InputName);
Out.push_back(Executable);
+
+ if (PrependArg)
+ Out.push_back(PrependArg);
+
// In a file list, build args vector ignoring parameters that will go in the
// response file (elements of the InputFileList vector)
bool FirstInput = true;
@@ -209,6 +214,9 @@ void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
if (ResponseFile != nullptr) {
buildArgvForResponseFile(ArgsRespFile);
Args = ArrayRef<const char *>(ArgsRespFile).slice(1); // no executable name
+ } else if (PrependArg) {
+ OS << ' ';
+ llvm::sys::printArg(OS, PrependArg, /*Quote=*/true);
}
bool HaveCrashVFS = CrashInfo && !CrashInfo->VFSPath.empty();
@@ -321,6 +329,8 @@ int Command::Execute(ArrayRef<std::optional<StringRef>> Redirects,
SmallVector<const char *, 128> Argv;
if (ResponseFile == nullptr) {
Argv.push_back(Executable);
+ if (PrependArg)
+ Argv.push_back(PrependArg);
Argv.append(Arguments.begin(), Arguments.end());
Argv.push_back(nullptr);
} else {
@@ -382,9 +392,10 @@ CC1Command::CC1Command(const Action &Source, const Tool &Creator,
ResponseFileSupport ResponseSupport,
const char *Executable,
const llvm::opt::ArgStringList &Arguments,
- ArrayRef<InputInfo> Inputs, ArrayRef<InputInfo> Outputs)
+ ArrayRef<InputInfo> Inputs, ArrayRef<InputInfo> Outputs,
+ const char *PrependArg)
: Command(Source, Creator, ResponseSupport, Executable, Arguments, Inputs,
- Outputs) {
+ Outputs, PrependArg) {
InProcess = true;
}
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 6000b11a28474..c97856a47686a 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -4979,7 +4979,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
C.addCommand(std::make_unique<Command>(
JA, *this, ResponseFileSupport::AtFileUTF8(), D.getClangProgramPath(),
- CmdArgs, Inputs, Output));
+ CmdArgs, Inputs, Output, D.getPrependArg()));
return;
}
@@ -7408,13 +7408,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
if (D.CC1Main && !D.CCGenDiagnostics) {
// Invoke the CC1 directly in this process
- C.addCommand(std::make_unique<CC1Command>(JA, *this,
- ResponseFileSupport::AtFileUTF8(),
- Exec, CmdArgs, Inputs, Output));
+ C.addCommand(std::make_unique<CC1Command>(
+ JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs,
+ Output, D.getPrependArg()));
} else {
- C.addCommand(std::make_unique<Command>(JA, *this,
- ResponseFileSupport::AtFileUTF8(),
- Exec, CmdArgs, Inputs, Output));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs,
+ Output, D.getPrependArg()));
}
// Make the compile command echo its inputs for /showFilenames.
@@ -8173,13 +8173,13 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA,
const char *Exec = getToolChain().getDriver().getClangProgramPath();
if (D.CC1Main && !D.CCGenDiagnostics) {
// Invoke cc1as directly in this process.
- C.addCommand(std::make_unique<CC1Command>(JA, *this,
- ResponseFileSupport::AtFileUTF8(),
- Exec, CmdArgs, Inputs, Output));
+ C.addCommand(std::make_unique<CC1Command>(
+ JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs,
+ Output, D.getPrependArg()));
} else {
- C.addCommand(std::make_unique<Command>(JA, *this,
- ResponseFileSupport::AtFileUTF8(),
- Exec, CmdArgs, Inputs, Output));
+ C.addCommand(std::make_unique<Command>(
+ JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs,
+ Output, D.getPrependArg()));
}
}
diff --git a/clang/test/Analysis/scan-build/lit.local.cfg b/clang/test/Analysis/scan-build/lit.local.cfg
index 09ed921714786..0c28dc63b5e81 100644
--- a/clang/test/Analysis/scan-build/lit.local.cfg
+++ b/clang/test/Analysis/scan-build/lit.local.cfg
@@ -7,6 +7,8 @@ import os
use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL")
config.test_format = lit.formats.ShTest(use_lit_shell == "0")
+clang_path = config.clang if config.have_llvm_driver else os.path.realpath(config.clang)
+
config.substitutions.append(('%scan-build',
'\'%s\' --use-analyzer=%s ' % (
lit.util.which('scan-build',
@@ -15,4 +17,4 @@ config.substitutions.append(('%scan-build',
'tools',
'scan-build',
'bin')),
- os.path.realpath(config.clang))))
+ clang_path)))
diff --git a/clang/test/CodeGen/debug-info-codeview-buildinfo.c b/clang/test/CodeGen/debug-info-codeview-buildinfo.c
index e1c6f3655f379..4096fac5f7437 100644
--- a/clang/test/CodeGen/debug-info-codeview-buildinfo.c
+++ b/clang/test/CodeGen/debug-info-codeview-buildinfo.c
@@ -19,7 +19,7 @@ int main(void) { return 42; }
// CHECK: 0x[[PWD:.+]] | LF_STRING_ID [size = {{.+}}] ID: <no type>, String: [[PWDVAL:.+]]
// CHECK: 0x[[FILEPATH:.+]] | LF_STRING_ID [size = {{.+}}] ID: <no type>, String: [[FILEPATHVAL:.+[\\/]debug-info-codeview-buildinfo.c]]
// CHECK: 0x[[ZIPDB:.+]] | LF_STRING_ID [size = {{.+}}] ID: <no type>, String:
-// CHECK: 0x[[TOOL:.+]] | LF_STRING_ID [size = {{.+}}] ID: <no type>, String: [[TOOLVAL:.+[\\/]clang.*]]
+// CHECK: 0x[[TOOL:.+]] | LF_STRING_ID [size = {{.+}}] ID: <no type>, String: [[TOOLVAL:.+[\\/][clang|llvm].*]]
// CHECK: 0x[[CMDLINE:.+]] | LF_STRING_ID [size = {{.+}}] ID: <no type>, String: "-cc1
// CHECK: 0x{{.+}} | LF_BUILDINFO [size = {{.+}}]
// CHECK-NEXT: 0x[[PWD]]: `[[PWDVAL]]`
diff --git a/clang/test/Driver/check-time-trace.cpp b/clang/test/Driver/check-time-trace.cpp
index 52b3e71394fba..32940500db1bc 100644
--- a/clang/test/Driver/check-time-trace.cpp
+++ b/clang/test/Driver/check-time-trace.cpp
@@ -27,7 +27,7 @@
// CHECK-NEXT: "pid":
// CHECK-NEXT: "tid":
// CHECK-NEXT: "ts":
-// CHECK: "name": "clang{{.*}}"
+// CHECK: "name": "{{clang|llvm}}{{.*}}"
// CHECK: "name": "process_name"
// CHECK: "name": "thread_name"
diff --git a/clang/tools/driver/cc1gen_reproducer_main.cpp b/clang/tools/driver/cc1gen_reproducer_main.cpp
index f9d9cab3fab19..e97fa3d277566 100644
--- a/clang/tools/driver/cc1gen_reproducer_main.cpp
+++ b/clang/tools/driver/cc1gen_reproducer_main.cpp
@@ -18,6 +18,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/LLVMDriver.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/YAMLTraits.h"
@@ -111,7 +112,8 @@ static std::string generateReproducerMetaInfo(const ClangInvocationInfo &Info) {
/// Generates a reproducer for a set of arguments from a specific invocation.
static std::optional<driver::Driver::CompilationDiagnosticReport>
generateReproducerForInvocationArguments(ArrayRef<const char *> Argv,
- const ClangInvocationInfo &Info) {
+ const ClangInvocationInfo &Info,
+ const llvm::ToolContext &ToolContext) {
using namespace driver;
auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(Argv[0]);
@@ -120,8 +122,11 @@ generateReproducerForInvocationArguments(ArrayRef<const char *> Argv,
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
DiagnosticsEngine Diags(DiagID, &*DiagOpts, new IgnoringDiagConsumer());
ProcessWarningOptions(Diags, *DiagOpts, /*ReportDiags=*/false);
- Driver TheDriver(Argv[0], llvm::sys::getDefaultTargetTriple(), Diags);
+ Driver TheDriver(ToolContext.Path, llvm::sys::getDefaultTargetTriple(),
+ Diags);
TheDriver.setTargetAndMode(TargetAndMode);
+ if (ToolContext.NeedsPrependArg)
+ TheDriver.setPrependArg(ToolContext.PrependArg);
std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(Argv));
if (C && !C->containsError()) {
@@ -155,7 +160,8 @@ static void printReproducerInformation(
}
int cc1gen_reproducer_main(ArrayRef<const char *> Argv, const char *Argv0,
- void *MainAddr) {
+ void *MainAddr,
+ const llvm::ToolContext &ToolContext) {
if (Argv.size() < 1) {
llvm::errs() << "error: missing invocation file\n";
return 1;
@@ -182,7 +188,8 @@ int cc1gen_reproducer_main(ArrayRef<const char *> Argv, const char *Argv0,
std::string Path = GetExecutablePath(Argv0, /*CanonicalPrefixes=*/true);
DriverArgs[0] = Path.c_str();
std::optional<driver::Driver::CompilationDiagnosticReport> Report =
- generateReproducerForInvocationArguments(DriverArgs, InvocationInfo);
+ generateReproducerForInvocationArguments(DriverArgs, InvocationInfo,
+ ToolContext);
// Emit the information about the reproduce files to stdout.
int Result = 1;
diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp
index 7124742795501..52d391fc69712 100644
--- a/clang/tools/driver/driver.cpp
+++ b/clang/tools/driver/driver.cpp
@@ -211,7 +211,8 @@ extern int cc1_main(ArrayRef<const char *> Argv, const char *Argv0,
extern int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0,
void *MainAddr);
extern int cc1gen_reproducer_main(ArrayRef<const char *> Argv,
- const char *Argv0, void *MainAddr);
+ const char *Argv0, void *MainAddr,
+ const llvm::ToolContext &);
static void insertTargetAndModeArgs(const ParsedClangName &NameParts,
SmallVectorImpl<const char *> &ArgVector,
@@ -342,7 +343,8 @@ static void SetInstallDir(SmallVectorImpl<const char *> &argv,
TheDriver.setInstalledDir(InstalledPathParent);
}
-static int ExecuteCC1Tool(SmallVectorImpl<const char *> &ArgV) {
+static int ExecuteCC1Tool(SmallVectorImpl<const char *> &ArgV,
+ const llvm::ToolContext &ToolContext) {
// If we call the cc1 tool from the clangDriver library (through
// Driver::CC1Main), we need to clean up the options usage count. The options
// are currently global, and they might have been used previously by the
@@ -363,14 +365,14 @@ static int ExecuteCC1Tool(SmallVectorImpl<const char *> &ArgV) {
return cc1as_main(ArrayRef(ArgV).slice(2), ArgV[0], GetExecutablePathVP);
if (Tool == "-cc1gen-reproducer")
return cc1gen_reproducer_main(ArrayRef(ArgV).slice(2), ArgV[0],
- GetExecutablePathVP);
+ GetExecutablePathVP, ToolContext);
// Reject unknown tools.
llvm::errs() << "error: unknown integrated tool '" << Tool << "'. "
<< "Valid tools include '-cc1' and '-cc1as'.\n";
return 1;
}
-int clang_main(int Argc, char **Argv, const llvm::ToolContext &) {
+int clang_main(int Argc, char **Argv, const llvm::ToolContext &ToolContext) {
noteBottomOfStack();
llvm::InitLLVM X(Argc, Argv);
llvm::setBugReportMsg("PLEASE submit a bug report to " BUG_REPORT_URL
@@ -386,15 +388,18 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &) {
llvm::BumpPtrAllocator A;
llvm::StringSaver Saver(A);
+ const char *ProgName =
+ ToolContext.NeedsPrependArg ? ToolContext.PrependArg : ToolContext.Path;
+
// Parse response files using the GNU syntax, unless we're in CL mode. There
- // are two ways to put clang in CL compatibility mode: Args[0] is either
+ // are two ways to put clang in CL compatibility mode: ProgName is either
// clang-cl or cl, or --driver-mode=cl is on the command line. The normal
// command line parsing can't happen until after response file parsing, so we
// have to manually search for a --driver-mode=cl argument the hard way.
// Finally, our -cc1 tools don't care which tokenization mode we use because
// response files written by clang will tokenize the same way in either mode.
bool ClangCLMode =
- IsClangCL(getDriverMode(Args[0], llvm::ArrayRef(Args).slice(1)));
+ IsClangCL(getDriverMode(ProgName, llvm::ArrayRef(Args).slice(1)));
enum { Default, POSIX, Windows } RSPQuoting = Default;
for (const char *F : Args) {
if (strcmp(F, "--rsp-quoting=posix") == 0)
@@ -433,7 +438,7 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &) {
auto newEnd = std::remove(Args.begin(), Args.end(), nullptr);
Args.resize(newEnd - Args.begin());
}
- return ExecuteCC1Tool(Args);
+ return ExecuteCC1Tool(Args, ToolContext);
}
// Handle options that need handling before the real command line parsing in
@@ -480,7 +485,7 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &) {
ApplyQAOverride(Args, OverrideStr, SavedStrings);
}
- std::string Path = GetExecutablePath(Args[0], CanonicalPrefixes);
+ std::string Path = GetExecutablePath(ToolContext.Path, CanonicalPrefixes);
// Whether the cc1 tool should be called inside the current process, or if we
// should spawn a new clang subprocess (old behavior).
@@ -498,7 +503,7 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &) {
TextDiagnosticPrinter *DiagClient
= new TextDiagnosticPrinter(llvm::errs(), &*DiagOpts);
- FixupDiagPrefixExeName(DiagClient, Path);
+ FixupDiagPrefixExeName(DiagClient, ProgName);
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
@@ -516,8 +521,15 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &) {
Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags);
SetInstallDir(Args, TheDriver, CanonicalPrefixes);
- auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(Args[0]);
+ auto TargetAndMode = ToolChain::getTargetAndModeFromProgramName(ProgName);
TheDriver.setTargetAndMode(TargetAndMode);
+ // If -canonical-prefixes is set, GetExecutablePath will have resolved Path
+ // to the llvm driver binary, not clang. In this case, we need to use
+ // PrependArg which should be clang-*. Checking just CanonicalPrefixes is
+ // safe even in the normal case because PrependArg will be null so
+ // setPrependArg will be a no-op.
+ if (ToolContext.NeedsPrependArg || CanonicalPrefixes)
+ TheDriver.setPrependArg(ToolContext.PrependArg);
insertTargetAndModeArgs(TargetAndMode, Args, SavedStrings);
@@ -525,7 +537,9 @@ int clang_main(int Argc, char **Argv, const llvm::ToolContext &) {
return 1;
if (!UseNewCC1Process) {
- TheDriver.CC1Main = &ExecuteCC1Tool;
+ TheDriver.CC1Main = [&ToolContext](SmallVectorImpl<const char *> &ArgV) {
+ return ExecuteCC1Tool(ArgV, ToolContext);
+ };
// Ensure the CC1Command actually catches cc1 crashes
llvm::CrashRecoveryContext::Enable();
}
diff --git a/clang/tools/scan-build/libexec/ccc-analyzer b/clang/tools/scan-build/libexec/ccc-analyzer
index 0c900293956f6..60796a543fcd0 100755
--- a/clang/tools/scan-build/libexec/ccc-analyzer
+++ b/clang/tools/scan-build/libexec/ccc-analyzer
@@ -201,7 +201,13 @@ sub GetCCArgs {
$line =~ s/^\s+|\s+$//g;
my @items = quotewords('\s+', 0, $line);
my $cmd = shift @items;
- die "cannot find 'clang' in 'clang' command\n" if (!($cmd =~ /clang/));
+ die "cannot find 'clang' in 'clang' command\n" if (!($cmd =~ /clang/ || basename($cmd) =~ /llvm/));
+ # If this is the llvm-driver the internal command will look like "llvm clang ...".
+ # Later this will be invoked like "clang clang ...", so skip over it.
+ if (basename($cmd) =~ /llvm/) {
+ die "Expected first arg to llvm driver to be 'clang'" if $items[0] ne "clang";
+ shift @items;
+ }
return \@items;
}
diff --git a/llvm/cmake/modules/llvm-driver-template.cpp.in b/llvm/cmake/modules/llvm-driver-template.cpp.in
index a828b6dadfbde..16c4fb3471463 100644
--- a/llvm/cmake/modules/llvm-driver-template.cpp.in
+++ b/llvm/cmake/modules/llvm-driver-template.cpp.in
@@ -11,4 +11,6 @@
int @TOOL_NAME at _main(int argc, char **, const llvm::ToolContext &);
-int main(int argc, char **argv) { return @TOOL_NAME at _main(argc, argv, {}); }
+int main(int argc, char **argv) {
+ return @TOOL_NAME at _main(argc, argv, {argv[0], nullptr, false});
+}
diff --git a/llvm/include/llvm/Support/LLVMDriver.h b/llvm/include/llvm/Support/LLVMDriver.h
index 1e00c056ec4d1..1c68f50707770 100644
--- a/llvm/include/llvm/Support/LLVMDriver.h
+++ b/llvm/include/llvm/Support/LLVMDriver.h
@@ -9,9 +9,20 @@
#ifndef LLVM_SUPPORT_LLVMDRIVER_H
#define LLVM_SUPPORT_LLVMDRIVER_H
+#include "llvm/ADT/SmallVector.h"
+
namespace llvm {
-struct ToolContext {};
+struct ToolContext {
+ const char *Path;
+ const char *PrependArg;
+ // PrependArg will be added unconditionally by the llvm-driver, but
+ // NeedsPrependArg will be false if Path is adequate to reinvoke the tool.
+ // This is useful if realpath is ever called on Path, in which case it will
+ // point to the llvm-driver executable, where PrependArg will be needed to
+ // invoke the correct tool.
+ bool NeedsPrependArg;
+};
} // namespace llvm
diff --git a/llvm/lib/Support/Path.cpp b/llvm/lib/Support/Path.cpp
index 152d902f52e67..d08d451b5a4e8 100644
--- a/llvm/lib/Support/Path.cpp
+++ b/llvm/lib/Support/Path.cpp
@@ -1202,18 +1202,10 @@ Error readNativeFileToEOF(file_t FileHandle, SmallVectorImpl<char> &Buffer,
#include "Windows/Path.inc"
#endif
-bool IsLLVMDriver = false;
-
namespace llvm {
namespace sys {
namespace fs {
-std::string getMainExecutable(const char *Argv0, void *MainAddr) {
- if (IsLLVMDriver)
- return sys::path::stem(Argv0).str();
- return getMainExecutableImpl(Argv0, MainAddr);
-}
-
TempFile::TempFile(StringRef Name, int FD)
: TmpName(std::string(Name)), FD(FD) {}
TempFile::TempFile(TempFile &&Other) { *this = std::move(Other); }
diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc
index 3efcad4f2bed4..e2aece49cbc52 100644
--- a/llvm/lib/Support/Unix/Path.inc
+++ b/llvm/lib/Support/Unix/Path.inc
@@ -190,7 +190,7 @@ static char *getprogpath(char ret[PATH_MAX], const char *bin) {
/// GetMainExecutable - Return the path to the main executable, given the
/// value of argv[0] from program startup.
-std::string getMainExecutableImpl(const char *argv0, void *MainAddr) {
+std::string getMainExecutable(const char *argv0, void *MainAddr) {
#if defined(__APPLE__)
// On OS X the executable path is saved to the stack by dyld. Reading it
// from there is much faster than calling dladdr, especially for large
diff --git a/llvm/lib/Support/Windows/Path.inc b/llvm/lib/Support/Windows/Path.inc
index 92cf4fcda5a68..45f0e95c87fe4 100644
--- a/llvm/lib/Support/Windows/Path.inc
+++ b/llvm/lib/Support/Windows/Path.inc
@@ -130,7 +130,7 @@ namespace fs {
const file_t kInvalidFile = INVALID_HANDLE_VALUE;
-std::string getMainExecutableImpl(const char *argv0, void *MainExecAddr) {
+std::string getMainExecutable(const char *argv0, void *MainExecAddr) {
SmallVector<wchar_t, MAX_PATH> PathName;
PathName.resize_for_overwrite(PathName.capacity());
DWORD Size = ::GetModuleFileNameW(NULL, PathName.data(), PathName.size());
diff --git a/llvm/tools/llvm-driver/llvm-driver.cpp b/llvm/tools/llvm-driver/llvm-driver.cpp
index 653c2adee26e5..01c27618945ce 100644
--- a/llvm/tools/llvm-driver/llvm-driver.cpp
+++ b/llvm/tools/llvm-driver/llvm-driver.cpp
@@ -36,7 +36,7 @@ static void printHelpMessage() {
<< "OPTIONS:\n\n --help - Display this message";
}
-static int findTool(int Argc, char **Argv) {
+static int findTool(int Argc, char **Argv, const char *Argv0) {
if (!Argc) {
printHelpMessage();
return 1;
@@ -62,21 +62,22 @@ static int findTool(int Argc, char **Argv) {
return false;
};
+ auto MakeDriverArgs = [=]() -> llvm::ToolContext {
+ if (ToolName != Argv0)
+ return {Argv0, ToolName.data(), true};
+ return {Argv0, sys::path::filename(Argv0).data(), false};
+ };
+
#define LLVM_DRIVER_TOOL(tool, entry) \
if (Is(tool)) \
- return entry##_main(Argc, Argv, {});
+ return entry##_main(Argc, Argv, MakeDriverArgs());
#include "LLVMDriverTools.def"
if (Is("llvm"))
- return findTool(Argc - 1, Argv + 1);
+ return findTool(Argc - 1, Argv + 1, Argv0);
printHelpMessage();
return 1;
}
-extern bool IsLLVMDriver;
-
-int main(int Argc, char **Argv) {
- IsLLVMDriver = true;
- return findTool(Argc, Argv);
-}
+int main(int Argc, char **Argv) { return findTool(Argc, Argv, Argv[0]); }
More information about the llvm-commits
mailing list