diff --git a/clang/test/Modules/reproducer-with-module-dependencies.c b/clang/test/Modules/reproducer-with-module-dependencies.c index a3700baac8d0b..0552f93f46e17 100644 --- a/clang/test/Modules/reproducer-with-module-dependencies.c +++ b/clang/test/Modules/reproducer-with-module-dependencies.c @@ -67,6 +67,7 @@ void test(void) { //--- script-expectations.txt CHECK: CLANG:-clang-executable +CHECK: "-o" "reproducer.cache/reproducer.o" CHECK: -fmodule-file=Test=reproducer.cache/explicitly-built-modules/Test-{{.*}}.pcm Verify the reproducer VFS overlay is added before the existing overlay provided on a command line. CHECK: -ivfsoverlay "reproducer.cache/vfs/vfs.yaml" diff --git a/clang/tools/libclang/CDependencies.cpp b/clang/tools/libclang/CDependencies.cpp index 7b5721df4b560..63b29446c4281 100644 --- a/clang/tools/libclang/CDependencies.cpp +++ b/clang/tools/libclang/CDependencies.cpp @@ -835,7 +835,8 @@ enum CXErrorCode clang_experimental_DependencyScanner_generateReproducer( std::string ReproExecutable = "\"${CLANG:-" + Opts.BuildArgs.front() + "}\""; auto PrintArguments = [&ReproExecutable, &FileCacheName, &ClangOpts](llvm::raw_fd_ostream &OS, - ArrayRef Arguments) { + ArrayRef Arguments, + bool RedirectOutput) { std::vector CharArgs(Arguments.size()); for (const std::string &Arg : Arguments) CharArgs.push_back(Arg.c_str()); @@ -853,11 +854,19 @@ enum CXErrorCode clang_experimental_DependencyScanner_generateReproducer( DidAddVFSOverlay = true; } } + bool IsOutputArg = Arg->getOption().matches(options::OPT_o); llvm::opt::ArgStringList OutArgs; Arg->render(ParsedArgs, OutArgs); + bool IsArgValue = false; for (const auto &OutArg : OutArgs) { OS << ' '; - llvm::sys::printArg(OS, OutArg, /*Quote=*/true); + if (RedirectOutput && IsOutputArg && IsArgValue) { + StringRef OutputFileName = llvm::sys::path::filename(OutArg); + OS << " \"" << FileCacheName << '/' << OutputFileName << '"'; + } else { + llvm::sys::printArg(OS, OutArg, /*Quote=*/true); + } + IsArgValue = true; } } if (!DidAddVFSOverlay) { @@ -866,11 +875,13 @@ enum CXErrorCode clang_experimental_DependencyScanner_generateReproducer( } OS << '\n'; }; + // Redirect the output to keep reproducers relocatable. But don't redirect + // modules as they are already in the appropriate place (see `LookupOutput`). for (ModuleDeps &Dep : TU.ModuleGraph) - PrintArguments(ScriptOS, Dep.getBuildArguments()); + PrintArguments(ScriptOS, Dep.getBuildArguments(), /*RedirectOutput=*/false); ScriptOS << "\n# Translation unit:\n"; for (const Command &BuildCommand : TU.Commands) - PrintArguments(ScriptOS, BuildCommand.Arguments); + PrintArguments(ScriptOS, BuildCommand.Arguments, /*RedirectOutput=*/true); auto RealFS = llvm::vfs::getRealFileSystem(); RealFS->setCurrentWorkingDirectory(*Opts.WorkingDirectory);