diff --git a/clang/include/clang/Driver/Compilation.h b/clang/include/clang/Driver/Compilation.h --- a/clang/include/clang/Driver/Compilation.h +++ b/clang/include/clang/Driver/Compilation.h @@ -295,16 +295,22 @@ /// /// \param FailingCommand - For non-zero results, this will be set to the /// Command which failed, if any. + /// \param LogOnly - When true, only tries to log the command, not actually + /// execute it. /// \return The result code of the subprocess. - int ExecuteCommand(const Command &C, const Command *&FailingCommand) const; + int ExecuteCommand(const Command &C, const Command *&FailingCommand, + bool LogOnly = false) const; /// ExecuteJob - Execute a single job. /// /// \param FailingCommands - For non-zero results, this will be a vector of /// failing commands and their associated result code. - void ExecuteJobs( - const JobList &Jobs, - SmallVectorImpl> &FailingCommands) const; + /// \param LogOnly - When true, only tries to log the command, not actually + /// execute it. + void + ExecuteJobs(const JobList &Jobs, + SmallVectorImpl> &FailingCommands, + bool LogOnly = false) const; /// initCompilationForDiagnostics - Remove stale state and suppress output /// so compilation can be reexecuted to generate additional diagnostic diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -2751,6 +2751,8 @@ " overwriting polymorphic C++ objects">, NegFlag>; def fstrict_overflow : Flag<["-"], "fstrict-overflow">, Group; +def fdriver_only : Flag<["-"], "fdriver-only">, Flags<[NoXarchOption, CoreOption]>, + Group, HelpText<"Only run the driver.">; def fsyntax_only : Flag<["-"], "fsyntax-only">, Flags<[NoXarchOption,CoreOption,CC1Option,FC1Option]>, Group; def ftabstop_EQ : Joined<["-"], "ftabstop=">, Group; diff --git a/clang/lib/Driver/Compilation.cpp b/clang/lib/Driver/Compilation.cpp --- a/clang/lib/Driver/Compilation.cpp +++ b/clang/lib/Driver/Compilation.cpp @@ -162,7 +162,8 @@ } int Compilation::ExecuteCommand(const Command &C, - const Command *&FailingCommand) const { + const Command *&FailingCommand, + bool LogOnly) const { if ((getDriver().CCPrintOptions || getArgs().hasArg(options::OPT_v)) && !getDriver().CCGenDiagnostics) { raw_ostream *OS = &llvm::errs(); @@ -191,6 +192,9 @@ C.Print(*OS, "\n", /*Quote=*/getDriver().CCPrintOptions); } + if (LogOnly) + return 0; + std::string Error; bool ExecutionFailed; int Res = C.Execute(Redirects, &Error, &ExecutionFailed); @@ -237,7 +241,8 @@ } void Compilation::ExecuteJobs(const JobList &Jobs, - FailingCommandList &FailingCommands) const { + FailingCommandList &FailingCommands, + bool LogOnly) const { // According to UNIX standard, driver need to continue compiling all the // inputs on the command line even one of them failed. // In all but CLMode, execute all the jobs unless the necessary inputs for the @@ -246,7 +251,7 @@ if (!InputsOk(Job, FailingCommands)) continue; const Command *FailingCommand = nullptr; - if (int Res = ExecuteCommand(Job, FailingCommand)) { + if (int Res = ExecuteCommand(Job, FailingCommand, LogOnly)) { FailingCommands.push_back(std::make_pair(Res, FailingCommand)); // Bail as soon as one command fails in cl driver mode. if (TheDriver.IsCLMode()) diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1689,6 +1689,19 @@ int Driver::ExecuteCompilation( Compilation &C, SmallVectorImpl> &FailingCommands) { + if (C.getArgs().hasArg(options::OPT_fdriver_only)) { + if (C.getArgs().hasArg(options::OPT_v)) + C.getJobs().Print(llvm::errs(), "\n", true); + + C.ExecuteJobs(C.getJobs(), FailingCommands, /*LogOnly=*/true); + + // If there were errors building the compilation, quit now. + if (!FailingCommands.empty() || Diags.hasErrorOccurred()) + return 1; + + return 0; + } + // Just print if -### was present. if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) { C.getJobs().Print(llvm::errs(), "\n", true); @@ -4761,6 +4774,8 @@ C.getArgs().hasArg(options::OPT_Qunused_arguments)) return; + // Claim -fdriver-only here. + (void)C.getArgs().hasArg(options::OPT_fdriver_only); // Claim -### here. (void)C.getArgs().hasArg(options::OPT__HASH_HASH_HASH); diff --git a/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp b/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp --- a/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp +++ b/clang/lib/Frontend/CreateInvocationFromCommandLine.cpp @@ -54,6 +54,9 @@ if (!C) return nullptr; + if (C->getArgs().hasArg(driver::options::OPT_fdriver_only)) + 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); diff --git a/clang/test/Driver/cc-print-options.c b/clang/test/Driver/cc-print-options.c --- a/clang/test/Driver/cc-print-options.c +++ b/clang/test/Driver/cc-print-options.c @@ -1,8 +1,14 @@ +// RUN: rm -f %t.log // RUN: env CC_PRINT_OPTIONS=1 \ // RUN: CC_PRINT_OPTIONS_FILE=%t.log \ // RUN: %clang -S -o %t.s %s // RUN: FileCheck %s < %t.log -// CHECK: [Logging clang options] -// CHECK: {{.*}} "-S" +// RUN: rm -f %t.log +// RUN: env CC_PRINT_OPTIONS=1 \ +// RUN: CC_PRINT_OPTIONS_FILE=%t.log \ +// RUN: %clang -fdriver-only -o %t.s %s +// RUN: FileCheck %s < %t.log +// CHECK: [Logging clang options] +// CHECK: {{.*}} "-cc1" diff --git a/clang/test/Driver/driver-only.c b/clang/test/Driver/driver-only.c new file mode 100644 --- /dev/null +++ b/clang/test/Driver/driver-only.c @@ -0,0 +1,19 @@ +// RUN: rm -rf %t +// RUN: mkdir %t + +// Check that -fdriver-only doesn't actually run the generated -cc1 job. +// +// RUN: %clang -c %s -o %t/a.o -fdriver-only +// RUN: not cat %t/a.o + +// Check that -fdriver-only respects errors. +// +// RUN: not %clang -c %s -fdriver-only -target i386-apple-darwin9 -m32 -Xarch_i386 -o + +// Check that -fdriver-only respects -v. +// +// RUN: %clang -c %s -fdriver-only -v 2>&1 | FileCheck %s --check-prefix=CHECK-V +// CHECK-V: {{.*}} "-cc1" +// +// RUN: %clang -c %s -fdriver-only 2>&1 | FileCheck %s --check-prefix=CHECK-NO-V --allow-empty +// CHECK-NO-V-NOT: {{.*}} "-cc1"