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 @@ -55,6 +55,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; @@ -90,8 +93,8 @@ bool InProcess = false; Command(const Action &Source, const Tool &Creator, 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; @@ -128,6 +131,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; @@ -138,7 +149,7 @@ public: CC1Command(const Action &Source, const Tool &Creator, 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; @@ -156,7 +167,7 @@ FallbackCommand(const Action &Source_, const Tool &Creator_, 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, @@ -175,7 +186,7 @@ ForceSuccessCommand(const Action &Source_, const Tool &Creator_, 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, const char *Executable, const llvm::opt::ArgStringList &Arguments, - ArrayRef Inputs) + ArrayRef Inputs, ArrayRef Outputs) : Source(Source), Creator(Creator), 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 @@ -356,8 +359,8 @@ CC1Command::CC1Command(const Action &Source, const Tool &Creator, const char *Executable, const llvm::opt::ArgStringList &Arguments, - ArrayRef Inputs) - : Command(Source, Creator, Executable, Arguments, Inputs) { + ArrayRef Inputs, ArrayRef Outputs) + : Command(Source, Creator, Executable, Arguments, Inputs, Outputs) { InProcess = true; } @@ -413,8 +416,9 @@ const char *Executable_, const llvm::opt::ArgStringList &Arguments_, ArrayRef Inputs, + ArrayRef Outputs, std::unique_ptr Fallback_) - : Command(Source_, Creator_, Executable_, Arguments_, Inputs), + : Command(Source_, Creator_, Executable_, Arguments_, Inputs, Outputs), Fallback(std::move(Fallback_)) {} void FallbackCommand::Print(raw_ostream &OS, const char *Terminator, @@ -452,8 +456,9 @@ ForceSuccessCommand::ForceSuccessCommand( const Action &Source_, const Tool &Creator_, const char *Executable_, - const llvm::opt::ArgStringList &Arguments_, ArrayRef Inputs) - : Command(Source_, Creator_, Executable_, Arguments_, Inputs) {} + const llvm::opt::ArgStringList &Arguments_, ArrayRef Inputs, + ArrayRef Outputs) + : Command(Source_, Creator_, Executable_, Arguments_, 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 @@ -73,7 +73,8 @@ CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -152,7 +153,8 @@ } const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, 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 @@ -252,7 +252,7 @@ CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); C.addCommand(std::make_unique(JA, *this, Args.MakeArgString(Linker), - CmdArgs, Inputs)); + 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 @@ -152,7 +152,7 @@ } C.addCommand(std::make_unique(JA, *this, Args.MakeArgString(Linker), - CmdArgs, Inputs)); + 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,7 +39,8 @@ CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } void ananas::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -123,7 +124,8 @@ } const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, 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 @@ -192,6 +192,6 @@ CmdArgs.push_back(Output.getFilename()); C.addCommand(std::make_unique(JA, *this, - Args.MakeArgString(TC.GetLinkerPath()), - CmdArgs, Inputs)); + Args.MakeArgString(TC.GetLinkerPath()), + 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 @@ -4323,7 +4323,7 @@ } C.addCommand(std::make_unique(JA, *this, D.getClangProgramPath(), - CmdArgs, Inputs)); + CmdArgs, Inputs, Output)); return; } @@ -6231,19 +6231,20 @@ auto CLCommand = getCLFallback()->GetCommand(C, JA, Output, Inputs, Args, LinkingOutput); C.addCommand(std::make_unique( - JA, *this, Exec, CmdArgs, Inputs, std::move(CLCommand))); + JA, *this, Exec, CmdArgs, Inputs, 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, Exec, - CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, + Inputs, Output)); } else if (D.CC1Main && !D.CCGenDiagnostics) { // Invoke the CC1 directly in this process C.addCommand( - std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } else { - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } // Make the compile command echo its inputs for /showFilenames. @@ -6981,7 +6982,8 @@ CmdArgs.push_back(Input.getFilename()); const char *Exec = getToolChain().getDriver().getClangProgramPath(); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } // Begin OffloadBundler @@ -7067,7 +7069,7 @@ C.addCommand(std::make_unique( JA, *this, TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())), - CmdArgs, None)); + CmdArgs, None, Output)); } void OffloadBundler::ConstructJobMultipleOutputs( @@ -7133,7 +7135,7 @@ C.addCommand(std::make_unique( JA, *this, TCArgs.MakeArgString(getToolChain().GetProgramPath(getShortName())), - CmdArgs, None)); + CmdArgs, None, Outputs)); } void OffloadWrapper::ConstructJob(Compilation &C, const JobAction &JA, @@ -7163,5 +7165,5 @@ C.addCommand(std::make_unique( JA, *this, 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,7 +92,8 @@ CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtend.o"))); const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, 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 @@ -862,10 +862,10 @@ InputInfo II(types::TY_Object, Output.getFilename(), Output.getFilename()); // First extract the dwo sections. - C.addCommand(std::make_unique(JA, T, Exec, ExtractArgs, II)); + C.addCommand(std::make_unique(JA, T, Exec, ExtractArgs, II, Output)); // Then remove them from the original .o file. - C.addCommand(std::make_unique(JA, T, Exec, StripArgs, II)); + C.addCommand(std::make_unique(JA, T, 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 @@ -57,7 +57,8 @@ const std::string Assembler = TC.GetProgramPath("as"); Exec = Args.MakeArgString(Assembler); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } void tools::CrossWindows::Linker::ConstructJob( @@ -202,7 +203,8 @@ Exec = Args.MakeArgString(TC.GetLinkerPath()); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, 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 @@ -423,7 +423,8 @@ Exec = A->getValue(); else Exec = Args.MakeArgString(TC.GetProgramPath("ptxas")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } static bool shouldIncludePTX(const ArgList &Args, const char *gpu_arch) { @@ -488,7 +489,8 @@ CmdArgs.push_back(Args.MakeArgString(A)); const char *Exec = Args.MakeArgString(TC.GetProgramPath("fatbinary")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } void NVPTX::OpenMPLinker::ConstructJob(Compilation &C, const JobAction &JA, @@ -565,7 +567,8 @@ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("nvlink")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, 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 @@ -148,7 +148,8 @@ // asm_final spec is empty. const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } void darwin::MachOTool::anchor() {} @@ -525,7 +526,8 @@ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("touch")); CmdArgs.push_back(Output.getFilename()); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, None)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, None, Output)); return; } @@ -684,7 +686,7 @@ const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); std::unique_ptr Cmd = - std::make_unique(JA, *this, Exec, CmdArgs, Inputs); + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output); Cmd->setInputFileList(std::move(InputFileList)); C.addCommand(std::move(Cmd)); } @@ -708,7 +710,8 @@ } const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("lipo")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } void darwin::Dsymutil::ConstructJob(Compilation &C, const JobAction &JA, @@ -728,7 +731,8 @@ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("dsymutil")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, @@ -751,7 +755,8 @@ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("dwarfdump")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, None)); } 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,7 +45,8 @@ CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -169,7 +170,8 @@ getToolChain().addProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, 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 @@ -70,7 +70,8 @@ const auto& D = C.getDriver(); const char* Exec = Args.MakeArgString(D.GetProgramPath("flang", TC)); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } Flang::Flang(const ToolChain &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,7 +128,8 @@ CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -358,7 +359,8 @@ ToolChain.addProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, 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 @@ -164,7 +164,8 @@ CmdArgs.push_back("-lc"); } - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, 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 @@ -190,7 +190,8 @@ GCCName = "gcc"; const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } void tools::gcc::Preprocessor::RenderExtraToolArgs( @@ -632,7 +633,8 @@ Args.AddAllArgs(CmdArgs, options::OPT_T); const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } void tools::gnutools::Assembler::ConstructJob(Compilation &C, @@ -895,7 +897,8 @@ CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, 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 @@ -68,7 +68,8 @@ for (auto Input : Inputs) LldArgs.push_back(Input.getFilename()); const char *Lld = Args.MakeArgString(getToolChain().GetProgramPath("lld")); - C.addCommand(std::make_unique(JA, *this, Lld, LldArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Lld, LldArgs, Inputs, Output)); } // Construct a clang-offload-bundler command to bundle code objects for @@ -101,7 +102,9 @@ const char *Bundler = Args.MakeArgString( T.getToolChain().GetProgramPath("clang-offload-bundler")); - C.addCommand(std::make_unique(JA, T, Bundler, BundlerArgs, Inputs)); + C.addCommand( + std::make_unique(JA, T, Bundler, BundlerArgs, Inputs, + InputInfo(&JA, OutputFileName.str().c_str()))); } // 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,7 +189,8 @@ } auto *Exec = Args.MakeArgString(HTC.GetProgramPath(AsName)); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } void hexagon::Linker::RenderExtraToolArgs(const JobAction &JA, @@ -406,7 +407,8 @@ LinkingOutput); const char *Exec = Args.MakeArgString(HTC.GetLinkerPath()); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, 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 @@ -54,8 +54,9 @@ CmdArgs.push_back(Args.MakeArgString(InputFilename.c_str())); } - C.addCommand(std::make_unique(JA, *this, Args.MakeArgString(Merger), - CmdArgs, Inputs)); + C.addCommand(std::make_unique( + JA, *this, Args.MakeArgString(Merger), CmdArgs, Inputs, + InputInfo(&JA, OutputFilename.c_str()))); } } // 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 @@ -228,5 +228,5 @@ CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); C.addCommand(std::make_unique(JA, *this, Args.MakeArgString(Linker), - CmdArgs, Inputs)); + 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 @@ -593,7 +593,7 @@ } auto LinkCmd = std::make_unique( - JA, *this, Args.MakeArgString(linkPath), CmdArgs, Inputs); + JA, *this, Args.MakeArgString(linkPath), CmdArgs, Inputs, Output); if (!Environment.empty()) LinkCmd->setEnvironment(Environment); C.addCommand(std::move(LinkCmd)); @@ -733,8 +733,8 @@ CmdArgs.push_back(Fo); std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe"); - return std::make_unique(JA, *this, Args.MakeArgString(Exec), - CmdArgs, Inputs); + return std::make_unique(JA, *this, 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 @@ -50,7 +50,8 @@ CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); if (Args.hasArg(options::OPT_gsplit_dwarf)) SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, @@ -167,9 +168,10 @@ // running on windows, not when operating as a cross compiler. As some users // have come to rely on this behaviour, try to replicate it. #ifdef _WIN32 - 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); #else CmdArgs.push_back(OutputFile); @@ -321,7 +323,8 @@ } } const char *Exec = Args.MakeArgString(TC.GetLinkerPath()); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, 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,7 +36,8 @@ CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } void tools::minix::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -88,7 +89,8 @@ } const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, 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 @@ -78,7 +78,7 @@ std::string Exec = Args.MakeArgString(getToolChain().GetProgramPath("moviCompile")); C.addCommand(std::make_unique(JA, *this, Args.MakeArgString(Exec), - CmdArgs, Inputs)); + CmdArgs, Inputs, Output)); } void tools::SHAVE::Assembler::ConstructJob(Compilation &C, const JobAction &JA, @@ -113,7 +113,7 @@ std::string Exec = Args.MakeArgString(getToolChain().GetProgramPath("moviAsm")); C.addCommand(std::make_unique(JA, *this, Args.MakeArgString(Exec), - CmdArgs, Inputs)); + CmdArgs, Inputs, Output)); } void tools::Myriad::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -199,7 +199,7 @@ std::string Exec = Args.MakeArgString(TC.GetProgramPath("sparc-myriad-rtems-ld")); C.addCommand(std::make_unique(JA, *this, Args.MakeArgString(Exec), - CmdArgs, Inputs)); + 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,7 +193,8 @@ } const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, 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,7 +103,8 @@ CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString((getToolChain().GetProgramPath("as"))); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -337,7 +338,8 @@ ToolChain.addProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, 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 @@ -89,7 +89,8 @@ CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -227,7 +228,8 @@ } const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath()); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, 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,7 +66,8 @@ const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("orbis-as")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } static void AddPS4SanitizerArgs(const ToolChain &TC, ArgStringList &CmdArgs) { @@ -151,7 +152,8 @@ const char *Exec = Args.MakeArgString(ToolChain.GetProgramPath("orbis-ld")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, 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 @@ -192,6 +192,6 @@ CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); C.addCommand(std::make_unique(JA, *this, Args.MakeArgString(Linker), - CmdArgs, Inputs)); + 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 @@ -41,7 +41,8 @@ CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -150,7 +151,8 @@ getToolChain().addProfileRTLibs(Args, CmdArgs); const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, 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 @@ -108,7 +108,8 @@ CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - C.addCommand(std::make_unique(JA, *this, Linker, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Linker, CmdArgs, Inputs, Output)); // When optimizing, if wasm-opt is available, run it. if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { @@ -130,7 +131,8 @@ CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-O") + OOpt)); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); - C.addCommand(std::make_unique(JA, *this, WasmOpt, CmdArgs, Inputs)); + C.addCommand(std::make_unique(JA, *this, WasmOpt, CmdArgs, + 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 @@ -52,7 +52,8 @@ CmdArgs.push_back(II.getFilename()); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, Exec, CmdArgs, Inputs, Output)); } void tools::XCore::Linker::ConstructJob(Compilation &C, const JobAction &JA, @@ -80,7 +81,8 @@ AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs, JA); const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("xcc")); - C.addCommand(std::make_unique(JA, *this, Exec, CmdArgs, Inputs)); + C.addCommand( + std::make_unique(JA, *this, 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, + InMemoryFileSystem); + CCDriver.setCheckInputsExist(false); + std::unique_ptr CC( + CCDriver.BuildCompilation({"/home/test/bin/clang", "foo.cpp"})); + const JobList &Jobs = CC->getJobs(); + + auto &CmdCompile = Jobs.getJobs().front(); + auto InFile = CmdCompile->getInputFilenames().front(); + EXPECT_STREQ(InFile, "foo.cpp"); + auto ObjFile = CmdCompile->getOutputFilenames().front(); + EXPECT_TRUE(StringRef(ObjFile).endswith(".o")); + + auto &CmdLink = Jobs.getJobs().back(); + auto LinkInFile = CmdLink->getInputFilenames().front(); + EXPECT_EQ(ObjFile, LinkInFile); + auto ExeFile = CmdLink->getOutputFilenames().front(); + EXPECT_EQ("a.out", ExeFile); +} + } // end anonymous namespace.