diff --git a/clang/include/clang/Driver/Job.h b/clang/include/clang/Driver/Job.h --- a/clang/include/clang/Driver/Job.h +++ b/clang/include/clang/Driver/Job.h @@ -122,6 +122,9 @@ /// The list of program arguments which are inputs. llvm::opt::ArgStringList InputFilenames; + /// The list of program arguments which are outputs. + std::vector OutputFilenames; + /// Response file name, if this command is set to use one, or nullptr /// otherwise const char *ResponseFile = nullptr; @@ -158,8 +161,8 @@ Command(const Action &Source, const Tool &Creator, ResponseFileSupport ResponseSupport, const char *Executable, - const llvm::opt::ArgStringList &Arguments, - ArrayRef Inputs); + const llvm::opt::ArgStringList &Arguments, ArrayRef Inputs, + ArrayRef Outputs); // FIXME: This really shouldn't be copyable, but is currently copied in some // error handling in Driver::generateCompilationDiagnostics. Command(const Command &) = default; @@ -201,6 +204,14 @@ const llvm::opt::ArgStringList &getArguments() const { return Arguments; } + const llvm::opt::ArgStringList &getInputFilenames() const { + return InputFilenames; + } + + const std::vector &getOutputFilenames() const { + return OutputFilenames; + } + protected: /// Optionally print the filenames to be compiled void PrintFileNames() const; @@ -212,7 +223,7 @@ CC1Command(const Action &Source, const Tool &Creator, ResponseFileSupport ResponseSupport, const char *Executable, const llvm::opt::ArgStringList &Arguments, - ArrayRef Inputs); + ArrayRef Inputs, ArrayRef Outputs); void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, CrashReportInfo *CrashInfo = nullptr) const override; @@ -230,7 +241,7 @@ FallbackCommand(const Action &Source_, const Tool &Creator_, ResponseFileSupport ResponseSupport, const char *Executable_, const llvm::opt::ArgStringList &Arguments_, - ArrayRef Inputs, + ArrayRef Inputs, ArrayRef Outputs, std::unique_ptr Fallback_); void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, @@ -250,7 +261,7 @@ ResponseFileSupport ResponseSupport, const char *Executable_, const llvm::opt::ArgStringList &Arguments_, - ArrayRef Inputs); + ArrayRef Inputs, ArrayRef Outputs); void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, CrashReportInfo *CrashInfo = nullptr) const override; diff --git a/clang/lib/Driver/Job.cpp b/clang/lib/Driver/Job.cpp --- a/clang/lib/Driver/Job.cpp +++ b/clang/lib/Driver/Job.cpp @@ -38,12 +38,15 @@ Command::Command(const Action &Source, const Tool &Creator, ResponseFileSupport ResponseSupport, const char *Executable, const llvm::opt::ArgStringList &Arguments, - ArrayRef Inputs) + ArrayRef Inputs, ArrayRef Outputs) : Source(Source), Creator(Creator), ResponseSupport(ResponseSupport), Executable(Executable), Arguments(Arguments) { for (const auto &II : Inputs) if (II.isFilename()) InputFilenames.push_back(II.getFilename()); + for (const auto &II : Outputs) + if (II.isFilename()) + OutputFilenames.push_back(II.getFilename()); } /// Check if the compiler flag in question should be skipped when @@ -357,8 +360,9 @@ ResponseFileSupport ResponseSupport, const char *Executable, const llvm::opt::ArgStringList &Arguments, - ArrayRef Inputs) - : Command(Source, Creator, ResponseSupport, Executable, Arguments, Inputs) { + ArrayRef Inputs, ArrayRef Outputs) + : Command(Source, Creator, ResponseSupport, Executable, Arguments, Inputs, + Outputs) { InProcess = true; } @@ -415,9 +419,10 @@ const char *Executable_, const llvm::opt::ArgStringList &Arguments_, ArrayRef Inputs, + ArrayRef Outputs, std::unique_ptr Fallback_) : Command(Source_, Creator_, ResponseSupport, Executable_, Arguments_, - Inputs), + Inputs, Outputs), Fallback(std::move(Fallback_)) {} void FallbackCommand::Print(raw_ostream &OS, const char *Terminator, @@ -456,9 +461,10 @@ ForceSuccessCommand::ForceSuccessCommand( const Action &Source_, const Tool &Creator_, ResponseFileSupport ResponseSupport, const char *Executable_, - const llvm::opt::ArgStringList &Arguments_, ArrayRef Inputs) + const llvm::opt::ArgStringList &Arguments_, ArrayRef Inputs, + ArrayRef Outputs) : Command(Source_, Creator_, ResponseSupport, Executable_, Arguments_, - Inputs) {} + Inputs, Outputs) {} void ForceSuccessCommand::Print(raw_ostream &OS, const char *Terminator, bool Quote, CrashReportInfo *CrashInfo) const { diff --git a/clang/lib/Driver/ToolChains/AIX.cpp b/clang/lib/Driver/ToolChains/AIX.cpp --- a/clang/lib/Driver/ToolChains/AIX.cpp +++ b/clang/lib/Driver/ToolChains/AIX.cpp @@ -71,7 +71,7 @@ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), - Exec, CmdArgs, Inputs)); + Exec, CmdArgs, Inputs, Output)); } void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -170,7 +170,7 @@ const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), - Exec, CmdArgs, Inputs)); + Exec, CmdArgs, Inputs, Output)); } /// AIX - AIX tool chain which can call as(1) and ld(1) directly. diff --git a/clang/lib/Driver/ToolChains/AMDGPU.cpp b/clang/lib/Driver/ToolChains/AMDGPU.cpp --- a/clang/lib/Driver/ToolChains/AMDGPU.cpp +++ b/clang/lib/Driver/ToolChains/AMDGPU.cpp @@ -356,9 +356,9 @@ CmdArgs.push_back("-shared"); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - C.addCommand( - std::make_unique(JA, *this, ResponseFileSupport::AtFileCurCP(), - Args.MakeArgString(Linker), CmdArgs, Inputs)); + C.addCommand(std::make_unique( + JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Linker), + CmdArgs, Inputs, Output)); } void amdgpu::getAMDGPUTargetFeatures(const Driver &D, diff --git a/clang/lib/Driver/ToolChains/AVR.cpp b/clang/lib/Driver/ToolChains/AVR.cpp --- a/clang/lib/Driver/ToolChains/AVR.cpp +++ b/clang/lib/Driver/ToolChains/AVR.cpp @@ -142,9 +142,9 @@ CmdArgs.push_back(Args.MakeArgString(std::string("-m") + *FamilyName)); } - C.addCommand( - std::make_unique(JA, *this, ResponseFileSupport::AtFileCurCP(), - Args.MakeArgString(Linker), CmdArgs, Inputs)); + C.addCommand(std::make_unique( + JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Linker), + CmdArgs, Inputs, Output)); } llvm::Optional AVRToolChain::findAVRLibcInstallation() const { diff --git a/clang/lib/Driver/ToolChains/Ananas.cpp b/clang/lib/Driver/ToolChains/Ananas.cpp --- a/clang/lib/Driver/ToolChains/Ananas.cpp +++ b/clang/lib/Driver/ToolChains/Ananas.cpp @@ -39,8 +39,9 @@ CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -124,8 +125,9 @@ } const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } // Ananas - Ananas tool chain which can call as(1) and ld(1) directly. diff --git a/clang/lib/Driver/ToolChains/BareMetal.cpp b/clang/lib/Driver/ToolChains/BareMetal.cpp --- a/clang/lib/Driver/ToolChains/BareMetal.cpp +++ b/clang/lib/Driver/ToolChains/BareMetal.cpp @@ -202,5 +202,5 @@ C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), Args.MakeArgString(TC.GetLinkerPath()), - CmdArgs, Inputs)); + CmdArgs, Inputs, Output)); } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4352,9 +4352,9 @@ II.getInputArg().renderAsInput(Args, CmdArgs); } - C.addCommand( - std::make_unique(JA, *this, ResponseFileSupport::AtFileUTF8(), - D.getClangProgramPath(), CmdArgs, Inputs)); + C.addCommand(std::make_unique( + JA, *this, ResponseFileSupport::AtFileUTF8(), D.getClangProgramPath(), + CmdArgs, Inputs, Output)); return; } @@ -6310,20 +6310,23 @@ getCLFallback()->GetCommand(C, JA, Output, Inputs, Args, LinkingOutput); C.addCommand(std::make_unique( JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs, - std::move(CLCommand))); + Output, std::move(CLCommand))); } else if (Args.hasArg(options::OPT__SLASH_fallback) && isa(JA)) { // In /fallback builds, run the main compilation even if the pch generation // fails, so that the main compilation's fallback to cl.exe runs. C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs)); + JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs, + Output)); } else if (D.CC1Main && !D.CCGenDiagnostics) { // Invoke the CC1 directly in this process - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileUTF8(), + Exec, CmdArgs, Inputs, Output)); } else { - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileUTF8(), + Exec, CmdArgs, Inputs, Output)); } // Make the compile command echo its inputs for /showFilenames. @@ -7070,8 +7073,9 @@ CmdArgs.push_back(Input.getFilename()); const char *Exec = getToolChain().getDriver().getClangProgramPath(); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileUTF8(), + Exec, CmdArgs, Inputs, Output)); } // Begin OffloadBundler @@ -7157,7 +7161,7 @@ C.addCommand(std::make_unique( JA, *this, ResponseFileSupport::None(), TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())), - CmdArgs, None)); + CmdArgs, None, Output)); } void OffloadBundler::ConstructJobMultipleOutputs( @@ -7223,7 +7227,7 @@ C.addCommand(std::make_unique( JA, *this, ResponseFileSupport::None(), TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())), - CmdArgs, None)); + CmdArgs, None, Outputs)); } void OffloadWrapper::ConstructJob(Compilation &C, const JobAction &JA, @@ -7253,5 +7257,5 @@ C.addCommand(std::make_unique( JA, *this, ResponseFileSupport::None(), Args.MakeArgString(getToolChain().GetProgramPath(getShortName())), - CmdArgs, Inputs)); + CmdArgs, Inputs, Output)); } diff --git a/clang/lib/Driver/ToolChains/CloudABI.cpp b/clang/lib/Driver/ToolChains/CloudABI.cpp --- a/clang/lib/Driver/ToolChains/CloudABI.cpp +++ b/clang/lib/Driver/ToolChains/CloudABI.cpp @@ -92,8 +92,9 @@ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } // CloudABI - CloudABI tool chain which can call ld(1) directly. diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -951,12 +951,13 @@ InputInfo II(types::TY_Object, Output.getFilename(), Output.getFilename()); // First extract the dwo sections. - C.addCommand(std::make_unique( - JA, T, ResponseFileSupport::AtFileCurCP(), Exec, ExtractArgs, II)); + C.addCommand(std::make_unique(JA, T, + ResponseFileSupport::AtFileCurCP(), + Exec, ExtractArgs, II, Output)); // Then remove them from the original .o file. C.addCommand(std::make_unique( - JA, T, ResponseFileSupport::AtFileCurCP(), Exec, StripArgs, II)); + JA, T, ResponseFileSupport::AtFileCurCP(), Exec, StripArgs, II, Output)); } // Claim options we don't want to warn if they are unused. We do this for diff --git a/clang/lib/Driver/ToolChains/CrossWindows.cpp b/clang/lib/Driver/ToolChains/CrossWindows.cpp --- a/clang/lib/Driver/ToolChains/CrossWindows.cpp +++ b/clang/lib/Driver/ToolChains/CrossWindows.cpp @@ -58,7 +58,7 @@ Exec = Args.MakeArgString(Assembler); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), - Exec, CmdArgs, Inputs)); + Exec, CmdArgs, Inputs, Output)); } void tools::CrossWindows::Linker::ConstructJob( @@ -203,8 +203,9 @@ Exec = Args.MakeArgString(TC.GetLinkerPath()); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileUTF8(), + Exec, CmdArgs, Inputs, Output)); } CrossWindowsToolChain::CrossWindowsToolChain(const Driver &D, diff --git a/clang/lib/Driver/ToolChains/Cuda.cpp b/clang/lib/Driver/ToolChains/Cuda.cpp --- a/clang/lib/Driver/ToolChains/Cuda.cpp +++ b/clang/lib/Driver/ToolChains/Cuda.cpp @@ -427,7 +427,7 @@ JA, *this, ResponseFileSupport{ResponseFileSupport::RF_Full, llvm::sys::WEM_UTF8, "--options-file"}, - Exec, CmdArgs, Inputs)); + Exec, CmdArgs, Inputs, Output)); } static bool shouldIncludePTX(const ArgList &Args, const char *gpu_arch) { @@ -496,7 +496,7 @@ JA, *this, ResponseFileSupport{ResponseFileSupport::RF_Full, llvm::sys::WEM_UTF8, "--options-file"}, - Exec, CmdArgs, Inputs)); + Exec, CmdArgs, Inputs, Output)); } void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA, @@ -577,7 +577,7 @@ JA, *this, ResponseFileSupport{ResponseFileSupport::RF_Full, llvm::sys::WEM_UTF8, "--options-file"}, - Exec, CmdArgs, Inputs)); + Exec, CmdArgs, Inputs, Output)); } /// CUDA toolchain. Our assembler is ptxas, and our "linker" is fatbinary, diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -149,7 +149,7 @@ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), - Exec, CmdArgs, Inputs)); + Exec, CmdArgs, Inputs, Output)); } void darwin::MachOTool::anchor() {} @@ -522,7 +522,7 @@ Args.MakeArgString(getToolChain().GetProgramPath("touch")); CmdArgs.push_back(Output.getFilename()); C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::None(), Exec, CmdArgs, None)); + JA, *this, ResponseFileSupport::None(), Exec, CmdArgs, None, Output)); return; } @@ -695,7 +695,7 @@ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); std::unique_ptr Cmd = std::make_unique( - JA, *this, ResponseSupport, Exec, CmdArgs, Inputs); + JA, *this, ResponseSupport, Exec, CmdArgs, Inputs, Output); Cmd->setInputFileList(std::move(InputFileList)); C.addCommand(std::move(Cmd)); } @@ -720,7 +720,7 @@ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo")); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), - Exec, CmdArgs, Inputs)); + Exec, CmdArgs, Inputs, Output)); } void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA, @@ -741,7 +741,7 @@ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("dsymutil")); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), - Exec, CmdArgs, Inputs)); + Exec, CmdArgs, Inputs, Output)); } void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, @@ -765,7 +765,7 @@ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump")); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), - Exec, CmdArgs, Inputs)); + Exec, CmdArgs, Inputs, Output)); } MachO::MachO(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) diff --git a/clang/lib/Driver/ToolChains/DragonFly.cpp b/clang/lib/Driver/ToolChains/DragonFly.cpp --- a/clang/lib/Driver/ToolChains/DragonFly.cpp +++ b/clang/lib/Driver/ToolChains/DragonFly.cpp @@ -45,8 +45,9 @@ CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -170,8 +171,9 @@ getToolChain().addProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } /// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly. diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp --- a/clang/lib/Driver/ToolChains/Flang.cpp +++ b/clang/lib/Driver/ToolChains/Flang.cpp @@ -72,8 +72,9 @@ // TODO: Replace flang-new with flang once the new driver replaces the // throwaway driver const char *Exec = Args.MakeArgString(D.GetProgramPath("flang-new", TC)); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileUTF8(), + Exec, CmdArgs, Inputs, Output)); } Flang::Flang(const ToolChain &TC) : Tool("flang-new", "flang frontend", TC) {} diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp --- a/clang/lib/Driver/ToolChains/FreeBSD.cpp +++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp @@ -128,8 +128,9 @@ CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -359,8 +360,9 @@ ToolChain.addProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } /// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly. diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp --- a/clang/lib/Driver/ToolChains/Fuchsia.cpp +++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp @@ -167,7 +167,7 @@ } C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), - Exec, CmdArgs, Inputs)); + Exec, CmdArgs, Inputs, Output)); } /// Fuchsia - Fuchsia tool chain which can call as(1) and ld(1) directly. diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -171,8 +171,9 @@ GCCName = "gcc"; const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } void tools::gcc::Preprocessor::RenderExtraToolArgs( @@ -364,8 +365,9 @@ } const char *Exec = Args.MakeArgString(getToolChain().GetStaticLibToolPath()); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -662,8 +664,9 @@ Args.AddAllArgs(CmdArgs, options::OPT_T); const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } void tools::gnutools::Assembler::ConstructJob(Compilation &C, @@ -930,8 +933,9 @@ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(DefaultAssembler)); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); // Handle the debug info splitting at object creation time if we're // creating an object. diff --git a/clang/lib/Driver/ToolChains/HIP.cpp b/clang/lib/Driver/ToolChains/HIP.cpp --- a/clang/lib/Driver/ToolChains/HIP.cpp +++ b/clang/lib/Driver/ToolChains/HIP.cpp @@ -98,7 +98,7 @@ LldArgs.push_back(Input.getFilename()); const char *Lld = Args.MakeArgString(getToolChain().GetProgramPath("lld")); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), - Lld, LldArgs, Inputs)); + Lld, LldArgs, Inputs, Output)); } // Construct a clang-offload-bundler command to bundle code objects for @@ -127,14 +127,16 @@ BundlerArgs.push_back(Args.MakeArgString(BundlerTargetArg)); BundlerArgs.push_back(Args.MakeArgString(BundlerInputArg)); - auto BundlerOutputArg = Args.MakeArgString( - std::string("-outputs=").append(std::string(OutputFileName))); + std::string Output = std::string(OutputFileName); + auto BundlerOutputArg = + Args.MakeArgString(std::string("-outputs=").append(Output)); BundlerArgs.push_back(BundlerOutputArg); const char *Bundler = Args.MakeArgString( T.getToolChain().GetProgramPath("clang-offload-bundler")); - C.addCommand(std::make_unique(JA, T, ResponseFileSupport::None(), - Bundler, BundlerArgs, Inputs)); + C.addCommand(std::make_unique( + JA, T, ResponseFileSupport::None(), Bundler, BundlerArgs, Inputs, + InputInfo(&JA, Args.MakeArgString(Output)))); } /// Add Generated HIP Object File which has device images embedded into the @@ -205,7 +207,7 @@ McinFile, "--filetype=obj"}; const char *Mc = Args.MakeArgString(TC.GetProgramPath("llvm-mc")); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), - Mc, McArgs, Inputs)); + Mc, McArgs, Inputs, Output)); } // For amdgcn the inputs of the linker job are device bitcode and output is diff --git a/clang/lib/Driver/ToolChains/Hexagon.cpp b/clang/lib/Driver/ToolChains/Hexagon.cpp --- a/clang/lib/Driver/ToolChains/Hexagon.cpp +++ b/clang/lib/Driver/ToolChains/Hexagon.cpp @@ -189,8 +189,9 @@ } auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName)); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA, @@ -407,8 +408,9 @@ LinkingOutput); const char *Exec = Args.MakeArgString(HTC.GetLinkerPath()); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } // Hexagon tools end. diff --git a/clang/lib/Driver/ToolChains/InterfaceStubs.cpp b/clang/lib/Driver/ToolChains/InterfaceStubs.cpp --- a/clang/lib/Driver/ToolChains/InterfaceStubs.cpp +++ b/clang/lib/Driver/ToolChains/InterfaceStubs.cpp @@ -56,7 +56,7 @@ C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), Args.MakeArgString(Merger), CmdArgs, - Inputs)); + Inputs, Output)); } } // namespace ifstool } // namespace tools diff --git a/clang/lib/Driver/ToolChains/MSP430.cpp b/clang/lib/Driver/ToolChains/MSP430.cpp --- a/clang/lib/Driver/ToolChains/MSP430.cpp +++ b/clang/lib/Driver/ToolChains/MSP430.cpp @@ -312,7 +312,7 @@ Args.AddAllArgs(CmdArgs, options::OPT_T); - C.addCommand( - std::make_unique(JA, *this, ResponseFileSupport::AtFileCurCP(), - Args.MakeArgString(Linker), CmdArgs, Inputs)); + C.addCommand(std::make_unique( + JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Linker), + CmdArgs, Inputs, Output)); } diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp --- a/clang/lib/Driver/ToolChains/MSVC.cpp +++ b/clang/lib/Driver/ToolChains/MSVC.cpp @@ -606,9 +606,9 @@ linkPath = TC.GetProgramPath(Linker.str().c_str()); } - auto LinkCmd = - std::make_unique(JA, *this, ResponseFileSupport::AtFileUTF16(), - Args.MakeArgString(linkPath), CmdArgs, Inputs); + auto LinkCmd = std::make_unique( + JA, *this, ResponseFileSupport::AtFileUTF16(), + Args.MakeArgString(linkPath), CmdArgs, Inputs, Output); if (!Environment.empty()) LinkCmd->setEnvironment(Environment); C.addCommand(std::move(LinkCmd)); @@ -748,9 +748,9 @@ CmdArgs.push_back(Fo); std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe"); - return std::make_unique(JA, *this, - ResponseFileSupport::AtFileUTF16(), - Args.MakeArgString(Exec), CmdArgs, Inputs); + return std::make_unique( + JA, *this, ResponseFileSupport::AtFileUTF16(), Args.MakeArgString(Exec), + CmdArgs, Inputs, Output); } MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple, diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -51,7 +51,7 @@ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), - Exec, CmdArgs, Inputs)); + Exec, CmdArgs, Inputs, Output)); if (Args.hasArg(options::OPT_gsplit_dwarf)) SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, @@ -167,9 +167,10 @@ // that lacks an extension. // GCC used to do this only when the compiler itself runs on windows, but // since GCC 8 it does the same when cross compiling as well. - if (!llvm::sys::path::has_extension(OutputFile)) + if (!llvm::sys::path::has_extension(OutputFile)) { CmdArgs.push_back(Args.MakeArgString(Twine(OutputFile) + ".exe")); - else + OutputFile = CmdArgs.back(); + } else CmdArgs.push_back(OutputFile); Args.AddAllArgs(CmdArgs, options::OPT_e); @@ -318,8 +319,9 @@ } } const char *Exec = Args.MakeArgString(TC.GetLinkerPath()); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileUTF8(), + Exec, CmdArgs, Inputs, Output)); } // Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple. diff --git a/clang/lib/Driver/ToolChains/Minix.cpp b/clang/lib/Driver/ToolChains/Minix.cpp --- a/clang/lib/Driver/ToolChains/Minix.cpp +++ b/clang/lib/Driver/ToolChains/Minix.cpp @@ -36,8 +36,9 @@ CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } void tools::minix::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -89,8 +90,9 @@ } const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } /// Minix - Minix tool chain which can call as(1) and ld(1) directly. diff --git a/clang/lib/Driver/ToolChains/Myriad.cpp b/clang/lib/Driver/ToolChains/Myriad.cpp --- a/clang/lib/Driver/ToolChains/Myriad.cpp +++ b/clang/lib/Driver/ToolChains/Myriad.cpp @@ -79,7 +79,7 @@ Args.MakeArgString(getToolChain().GetProgramPath("moviCompile")); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), Args.MakeArgString(Exec), CmdArgs, - Inputs)); + Inputs, Output)); } void tools::SHAVE::Assembler::ConstructJob(Compilation &C, const JobAction &JA, @@ -115,7 +115,7 @@ Args.MakeArgString(getToolChain().GetProgramPath("moviAsm")); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), Args.MakeArgString(Exec), CmdArgs, - Inputs)); + Inputs, Output)); } void tools::Myriad::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -200,9 +200,9 @@ std::string Exec = Args.MakeArgString(TC.GetProgramPath("sparc-myriad-rtems-ld")); - C.addCommand( - std::make_unique(JA, *this, ResponseFileSupport::AtFileCurCP(), - Args.MakeArgString(Exec), CmdArgs, Inputs)); + C.addCommand(std::make_unique( + JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Exec), + CmdArgs, Inputs, Output)); } MyriadToolChain::MyriadToolChain(const Driver &D, const llvm::Triple &Triple, diff --git a/clang/lib/Driver/ToolChains/NaCl.cpp b/clang/lib/Driver/ToolChains/NaCl.cpp --- a/clang/lib/Driver/ToolChains/NaCl.cpp +++ b/clang/lib/Driver/ToolChains/NaCl.cpp @@ -193,8 +193,9 @@ } const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } /// NaCl Toolchain diff --git a/clang/lib/Driver/ToolChains/NetBSD.cpp b/clang/lib/Driver/ToolChains/NetBSD.cpp --- a/clang/lib/Driver/ToolChains/NetBSD.cpp +++ b/clang/lib/Driver/ToolChains/NetBSD.cpp @@ -103,8 +103,9 @@ CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString((getToolChain().GetProgramPath("as"))); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -338,8 +339,9 @@ ToolChain.addProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } /// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly. diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp --- a/clang/lib/Driver/ToolChains/OpenBSD.cpp +++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp @@ -82,8 +82,9 @@ CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -221,8 +222,9 @@ } const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); } SanitizerMask OpenBSD::getSupportedSanitizers() const { diff --git a/clang/lib/Driver/ToolChains/PS4CPU.cpp b/clang/lib/Driver/ToolChains/PS4CPU.cpp --- a/clang/lib/Driver/ToolChains/PS4CPU.cpp +++ b/clang/lib/Driver/ToolChains/PS4CPU.cpp @@ -66,8 +66,9 @@ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("orbis-as")); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileUTF8(), + Exec, CmdArgs, Inputs, Output)); } static void AddPS4SanitizerArgs(const ToolChain &TC, ArgStringList &CmdArgs) { @@ -152,8 +153,9 @@ const char *Exec = Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld")); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileUTF8(), Exec, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileUTF8(), + Exec, CmdArgs, Inputs, Output)); } toolchains::PS4CPU::PS4CPU(const Driver &D, const llvm::Triple &Triple, diff --git a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp --- a/clang/lib/Driver/ToolChains/RISCVToolchain.cpp +++ b/clang/lib/Driver/ToolChains/RISCVToolchain.cpp @@ -191,8 +191,8 @@ CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - C.addCommand( - std::make_unique(JA, *this, ResponseFileSupport::AtFileCurCP(), - Args.MakeArgString(Linker), CmdArgs, Inputs)); + C.addCommand(std::make_unique( + JA, *this, ResponseFileSupport::AtFileCurCP(), Args.MakeArgString(Linker), + CmdArgs, Inputs, Output)); } // RISCV tools end. diff --git a/clang/lib/Driver/ToolChains/Solaris.cpp b/clang/lib/Driver/ToolChains/Solaris.cpp --- a/clang/lib/Driver/ToolChains/Solaris.cpp +++ b/clang/lib/Driver/ToolChains/Solaris.cpp @@ -42,7 +42,7 @@ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), - Exec, CmdArgs, Inputs)); + Exec, CmdArgs, Inputs, Output)); } void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -152,7 +152,7 @@ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), - Exec, CmdArgs, Inputs)); + Exec, CmdArgs, Inputs, Output)); } static StringRef getSolarisLibSuffix(const llvm::Triple &Triple) { diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp --- a/clang/lib/Driver/ToolChains/WebAssembly.cpp +++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp @@ -114,8 +114,9 @@ CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - C.addCommand(std::make_unique( - JA, *this, ResponseFileSupport::AtFileCurCP(), Linker, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Linker, CmdArgs, Inputs, Output)); // When optimizing, if wasm-opt is available, run it. if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { @@ -139,7 +140,7 @@ CmdArgs.push_back(Output.getFilename()); C.addCommand(std::make_unique( JA, *this, ResponseFileSupport::AtFileCurCP(), WasmOpt, CmdArgs, - Inputs)); + Inputs, Output)); } } } diff --git a/clang/lib/Driver/ToolChains/XCore.cpp b/clang/lib/Driver/ToolChains/XCore.cpp --- a/clang/lib/Driver/ToolChains/XCore.cpp +++ b/clang/lib/Driver/ToolChains/XCore.cpp @@ -53,7 +53,7 @@ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), - Exec, CmdArgs, Inputs)); + Exec, CmdArgs, Inputs, Output)); } void tools::XCore::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -82,7 +82,7 @@ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); C.addCommand(std::make_unique(JA, *this, ResponseFileSupport::None(), - Exec, CmdArgs, Inputs)); + Exec, CmdArgs, Inputs, Output)); } /// XCore tool chain diff --git a/clang/unittests/Driver/ToolChainTest.cpp b/clang/unittests/Driver/ToolChainTest.cpp --- a/clang/unittests/Driver/ToolChainTest.cpp +++ b/clang/unittests/Driver/ToolChainTest.cpp @@ -259,4 +259,34 @@ EXPECT_STREQ(Res.DriverMode, "--driver-mode=cl"); EXPECT_FALSE(Res.TargetIsValid); } + +TEST(ToolChainTest, CommandOutput) { + IntrusiveRefCntPtr DiagOpts = new DiagnosticOptions(); + + IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); + struct TestDiagnosticConsumer : public DiagnosticConsumer {}; + DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); + IntrusiveRefCntPtr InMemoryFileSystem( + new llvm::vfs::InMemoryFileSystem); + + Driver CCDriver("/home/test/bin/clang", "arm-linux-gnueabi", Diags, + "clang LLVM compiler", InMemoryFileSystem); + CCDriver.setCheckInputsExist(false); + std::unique_ptr CC( + CCDriver.BuildCompilation({"/home/test/bin/clang", "foo.cpp"})); + const JobList &Jobs = CC->getJobs(); + + const auto &CmdCompile = Jobs.getJobs().front(); + const auto &InFile = CmdCompile->getInputFilenames().front(); + EXPECT_STREQ(InFile, "foo.cpp"); + auto ObjFile = CmdCompile->getOutputFilenames().front(); + EXPECT_TRUE(StringRef(ObjFile).endswith(".o")); + + const auto &CmdLink = Jobs.getJobs().back(); + const auto LinkInFile = CmdLink->getInputFilenames().front(); + EXPECT_EQ(ObjFile, LinkInFile); + auto ExeFile = CmdLink->getOutputFilenames().front(); + EXPECT_EQ("a.out", ExeFile); +} + } // end anonymous namespace.