From 441f5b0e367ceee5b8b12d14c0d1ebb1c29fa414 Mon Sep 17 00:00:00 2001 From: Steven Wu Date: Thu, 31 Jul 2025 10:39:06 -0700 Subject: [PATCH] [clang] Infer compilation directory in driver When building with -fdebug-compilation-dir/-fcoverige-compilation-dir, infer the compilation directory in clang driver, rather than try to fallback to VFS current working directory lookup during CodeGen. This allows compilation directory to be used as it is passed via cc1 flag and the value can be empty to remove dependency on CWD if needed. Reviewers: adrian-prantl, dwblaikie Reviewed By: adrian-prantl, dwblaikie Pull Request: https://github.com/llvm/llvm-project/pull/150112 --- clang/lib/Driver/ToolChains/Clang.cpp | 38 ++++++++++++++------------- clang/test/Driver/compilation-dir.c | 5 ++++ 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index f4674a5b7154..4e1b1d9e3362 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -226,17 +226,19 @@ static bool ShouldEnableAutolink(const ArgList &Args, const ToolChain &TC, static const char *addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs, const llvm::vfs::FileSystem &VFS) { + std::string DebugCompDir; if (Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ, - options::OPT_fdebug_compilation_dir_EQ)) { - if (A->getOption().matches(options::OPT_ffile_compilation_dir_EQ)) - CmdArgs.push_back(Args.MakeArgString(Twine("-fdebug-compilation-dir=") + - A->getValue())); + options::OPT_fdebug_compilation_dir_EQ)) + DebugCompDir = A->getValue(); + + if (DebugCompDir.empty()) { + if (llvm::ErrorOr CWD = VFS.getCurrentWorkingDirectory()) + DebugCompDir = std::move(*CWD); else - A->render(Args, CmdArgs); - } else if (llvm::ErrorOr CWD = - VFS.getCurrentWorkingDirectory()) { - CmdArgs.push_back(Args.MakeArgString("-fdebug-compilation-dir=" + *CWD)); + return nullptr; } + CmdArgs.push_back( + Args.MakeArgString("-fdebug-compilation-dir=" + DebugCompDir)); StringRef Path(CmdArgs.back()); return Path.substr(Path.find('=') + 1).data(); } @@ -525,17 +527,17 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, CmdArgs.push_back("-fcoverage-mcdc"); } + StringRef CoverageCompDir; if (Arg *A = Args.getLastArg(options::OPT_ffile_compilation_dir_EQ, - options::OPT_fcoverage_compilation_dir_EQ)) { - if (A->getOption().matches(options::OPT_ffile_compilation_dir_EQ)) - CmdArgs.push_back(Args.MakeArgString( - Twine("-fcoverage-compilation-dir=") + A->getValue())); - else - A->render(Args, CmdArgs); - } else if (llvm::ErrorOr CWD = - D.getVFS().getCurrentWorkingDirectory()) { - CmdArgs.push_back(Args.MakeArgString("-fcoverage-compilation-dir=" + *CWD)); - } + options::OPT_fcoverage_compilation_dir_EQ)) + CoverageCompDir = A->getValue(); + if (CoverageCompDir.empty()) { + if (auto CWD = D.getVFS().getCurrentWorkingDirectory()) + CmdArgs.push_back( + Args.MakeArgString(Twine("-fcoverage-compilation-dir=") + *CWD)); + } else + CmdArgs.push_back(Args.MakeArgString(Twine("-fcoverage-compilation-dir=") + + CoverageCompDir)); if (Args.hasArg(options::OPT_fprofile_exclude_files_EQ)) { auto *Arg = Args.getLastArg(options::OPT_fprofile_exclude_files_EQ); diff --git a/clang/test/Driver/compilation-dir.c b/clang/test/Driver/compilation-dir.c index dbe801c9f5fc..70a117b064e6 100644 --- a/clang/test/Driver/compilation-dir.c +++ b/clang/test/Driver/compilation-dir.c @@ -8,3 +8,8 @@ // RUN: %clang -### -integrated-as -ffile-compilation-dir=. -x assembler %s 2>&1 | FileCheck -check-prefixes=CHECK-DEBUG-COMPILATION-DIR %s // CHECK-DEBUG-COMPILATION-DIR: "-fdebug-compilation-dir=." // CHECK-DEBUG-COMPILATION-DIR-NOT: "-ffile-compilation-dir=." + +// RUN: %clang -### -S %s -working-directory %S 2>&1 | FileCheck -check-prefix=CHECK-CWD %s +// RUN: cd %S +// RUN: %clang -### -S %s 2>&1 | FileCheck -check-prefix=CHECK-CWD %s +// CHECK-CWD: -fdebug-compilation-dir={{.*}}Driver