Bigcheese created this revision. Bigcheese added reviewers: dexonsmith, arphaman, jkorous. Herald added a project: clang.
Currently the `-working-directory` option does not actually impact the working directory for all of the clang driver, it only impacts how files are looked up to make sure they exist. This means that that clang passes the wrong paths to -fdebug-compilation-dir and -coverage-notes-file. This patch fixes that by changing all the places in the driver where we convert to absolute paths to use the VFS, and then calling setCurrentWorkingDirectory on the VFS. This also changes the default VFS for `Driver` to use a virtualized working directory, instead of changing the process's working directory. Repository: rC Clang https://reviews.llvm.org/D62271 Files: include/clang/Basic/DiagnosticDriverKinds.td lib/Driver/Driver.cpp lib/Driver/ToolChains/Clang.cpp test/Driver/working-directory.c
Index: test/Driver/working-directory.c =================================================================== --- test/Driver/working-directory.c +++ test/Driver/working-directory.c @@ -1,3 +1,11 @@ // RUN: %clang -### -working-directory /no/such/dir/ input 2>&1 | FileCheck %s +// RUN: %clang -### -working-directory %p/Inputs no_such_file.cpp -c 2>&1 | FileCheck %s --check-prefix=CHECK_NO_FILE +// RUN: %clang -### -working-directory %p/Inputs pchfile.cpp -c 2>&1 | FileCheck %s --check-prefix=CHECK_WORKS -//CHECK: no such file or directory: '/no/such/dir/input' +// CHECK: unable to set working directory: /no/such/dir/ + +// CHECK_NO_FILE: no such file or directory: 'no_such_file.cpp' + +// CHECK_WORKS: "-coverage-notes-file" "{{[^"]+}}test/Driver/Inputs/pchfile.gcno" +// CHECK_WORKS: "-working-directory" "{{[^"]+}}test/Driver/Inputs" +// CHECK_WORKS: "-fdebug-compilation-dir" "{{[^"]+}}test/Driver/Inputs" Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -616,11 +616,11 @@ } /// Add a CC1 option to specify the debug compilation directory. -static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs) { - SmallString<128> cwd; - if (!llvm::sys::fs::current_path(cwd)) { +static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs, + const llvm::vfs::FileSystem &VFS) { + if (llvm::ErrorOr<std::string> CWD = VFS.getCurrentWorkingDirectory()) { CmdArgs.push_back("-fdebug-compilation-dir"); - CmdArgs.push_back(Args.MakeArgString(cwd)); + CmdArgs.push_back(Args.MakeArgString(*CWD)); } } @@ -885,13 +885,8 @@ else OutputFilename = llvm::sys::path::filename(Output.getBaseInput()); SmallString<128> CoverageFilename = OutputFilename; - if (llvm::sys::path::is_relative(CoverageFilename)) { - SmallString<128> Pwd; - if (!llvm::sys::fs::current_path(Pwd)) { - llvm::sys::path::append(Pwd, CoverageFilename); - CoverageFilename.swap(Pwd); - } - } + if (llvm::sys::path::is_relative(CoverageFilename)) + (void)D.getVFS().makeAbsolute(CoverageFilename); llvm::sys::path::replace_extension(CoverageFilename, "gcno"); CmdArgs.push_back(Args.MakeArgString(CoverageFilename)); @@ -4354,7 +4349,7 @@ CmdArgs.push_back("-fno-autolink"); // Add in -fdebug-compilation-dir if necessary. - addDebugCompDirArg(Args, CmdArgs); + addDebugCompDirArg(Args, CmdArgs, D.getVFS()); addDebugPrefixMapArg(D, Args, CmdArgs); @@ -6063,7 +6058,7 @@ DebugInfoKind = (WantDebug ? codegenoptions::LimitedDebugInfo : codegenoptions::NoDebugInfo); // Add the -fdebug-compilation-dir flag if needed. - addDebugCompDirArg(Args, CmdArgs); + addDebugCompDirArg(Args, CmdArgs, C.getDriver().getVFS()); addDebugPrefixMapArg(getToolChain().getDriver(), Args, CmdArgs); Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp +++ lib/Driver/Driver.cpp @@ -133,7 +133,7 @@ // Provide a sane fallback if no VFS is specified. if (!this->VFS) - this->VFS = llvm::vfs::getRealFileSystem(); + this->VFS = llvm::vfs::createPhysicalFileSystem().release(); Name = llvm::sys::path::filename(ClangExecutable); Dir = llvm::sys::path::parent_path(ClangExecutable); @@ -1005,6 +1005,11 @@ } } + // Check for working directory option before accessing any files + if (Arg *WD = Args.getLastArg(options::OPT_working_directory)) + if (std::error_code EC = VFS->setCurrentWorkingDirectory(WD->getValue())) + Diag(diag::err_drv_unable_to_set_working_directory) << WD->getValue(); + // FIXME: This stuff needs to go into the Compilation, not the driver. bool CCCPrintPhases; @@ -1986,20 +1991,11 @@ if (Value == "-") return true; - SmallString<64> Path(Value); - if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory)) { - if (!llvm::sys::path::is_absolute(Path)) { - SmallString<64> Directory(WorkDir->getValue()); - llvm::sys::path::append(Directory, Value); - Path.assign(Directory); - } - } - - if (D.getVFS().exists(Path)) + if (D.getVFS().exists(Value)) return true; if (D.IsCLMode()) { - if (!llvm::sys::path::is_absolute(Twine(Path)) && + if (!llvm::sys::path::is_absolute(Twine(Value)) && llvm::sys::Process::FindInEnvPath("LIB", Value)) return true; @@ -2011,7 +2007,7 @@ } } - D.Diag(clang::diag::err_drv_no_such_file) << Path; + D.Diag(clang::diag::err_drv_no_such_file) << Value; return false; } Index: include/clang/Basic/DiagnosticDriverKinds.td =================================================================== --- include/clang/Basic/DiagnosticDriverKinds.td +++ include/clang/Basic/DiagnosticDriverKinds.td @@ -89,6 +89,8 @@ "there is no external assembler that can be used on this platform">; def err_drv_unable_to_remove_file : Error< "unable to remove file: %0">; +def err_drv_unable_to_set_working_directory : Error < + "unable to set working directory: %0">; def err_drv_command_failure : Error< "unable to execute command: %0">; def err_drv_invalid_darwin_version : Error<
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits