Skip to content

Conversation

@Dominicentek
Copy link

Adds an ability to change the current working directory for fallback commands.

@github-actions
Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot
Copy link
Member

llvmbot commented Aug 28, 2025

@llvm/pr-subscribers-clangd

@llvm/pr-subscribers-clang-tools-extra

Author: Dominicentek (Dominicentek)

Changes

Adds an ability to change the current working directory for fallback commands.


Full diff: https://github.com/llvm/llvm-project/pull/155905.diff

8 Files Affected:

  • (modified) clang-tools-extra/clangd/ClangdServer.cpp (+1)
  • (modified) clang-tools-extra/clangd/ClangdServer.h (+4)
  • (modified) clang-tools-extra/clangd/GlobalCompilationDatabase.cpp (+7-7)
  • (modified) clang-tools-extra/clangd/GlobalCompilationDatabase.h (+3-3)
  • (modified) clang-tools-extra/clangd/TUScheduler.cpp (+4-2)
  • (modified) clang-tools-extra/clangd/TUScheduler.h (+4)
  • (modified) clang-tools-extra/clangd/tool/Check.cpp (+2-2)
  • (modified) clang-tools-extra/clangd/tool/ClangdMain.cpp (+10)
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp
index ac1e9aa5f0ff1..51230b4506b1a 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -208,6 +208,7 @@ ClangdServer::Options::operator TUScheduler::Options() const {
   Opts.UpdateDebounce = UpdateDebounce;
   Opts.ContextProvider = ContextProvider;
   Opts.PreambleThrottler = PreambleThrottler;
+  Opts.FallbackProjectRoot = FallbackProjectRoot;
   return Opts;
 }
 
diff --git a/clang-tools-extra/clangd/ClangdServer.h b/clang-tools-extra/clangd/ClangdServer.h
index 4a1eae188f7eb..2c56d6f7e6d6c 100644
--- a/clang-tools-extra/clangd/ClangdServer.h
+++ b/clang-tools-extra/clangd/ClangdServer.h
@@ -152,6 +152,10 @@ class ClangdServer {
     /// FIXME: If not set, should use the current working directory.
     std::optional<std::string> WorkspaceRoot;
 
+    /// If set, fallback command uses this path as its current working directory
+    /// instead of the file's parent path.
+    std::optional<std::string> FallbackProjectRoot;
+
     /// The resource directory is used to find internal headers, overriding
     /// defaults and -resource-dir compiler flag).
     /// If std::nullopt, ClangdServer calls
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index c6afd0bc07cbd..b73697d4ee7e5 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -55,7 +55,7 @@ void actOnAllParentDirectories(PathRef FileName,
 } // namespace
 
 tooling::CompileCommand
-GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
+GlobalCompilationDatabase::getFallbackCommand(PathRef File, std::optional<std::string> ProjectRoot) const {
   std::vector<std::string> Argv = {"clang"};
   // Clang treats .h files as C by default and files without extension as linker
   // input, resulting in unhelpful diagnostics.
@@ -64,7 +64,7 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
   if (FileExtension.empty() || FileExtension == ".h")
     Argv.push_back("-xobjective-c++-header");
   Argv.push_back(std::string(File));
-  tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
+  tooling::CompileCommand Cmd(ProjectRoot ? *ProjectRoot : llvm::sys::path::parent_path(File),
                               llvm::sys::path::filename(File), std::move(Argv),
                               /*Output=*/"");
   Cmd.Heuristic = "clangd fallback";
@@ -797,8 +797,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
   return Cmd;
 }
 
-tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
-  auto Cmd = DelegatingCDB::getFallbackCommand(File);
+tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File, std::optional<std::string> ProjectRoot) const {
+  auto Cmd = DelegatingCDB::getFallbackCommand(File, ProjectRoot);
   std::lock_guard<std::mutex> Lock(Mutex);
   Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
                          FallbackFlags.end());
@@ -877,10 +877,10 @@ DelegatingCDB::getProjectModules(PathRef File) const {
   return Base->getProjectModules(File);
 }
 
-tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
+tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File, std::optional<std::string> ProjectRoot) const {
   if (!Base)
-    return GlobalCompilationDatabase::getFallbackCommand(File);
-  return Base->getFallbackCommand(File);
+    return GlobalCompilationDatabase::getFallbackCommand(File, ProjectRoot);
+  return Base->getFallbackCommand(File, ProjectRoot);
 }
 
 bool DelegatingCDB::blockUntilIdle(Deadline D) const {
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
index 1d636d73664be..5d1b5cb632154 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h
@@ -55,7 +55,7 @@ class GlobalCompilationDatabase {
   /// Makes a guess at how to build a file.
   /// The default implementation just runs clang on the file.
   /// Clangd should treat the results as unreliable.
-  virtual tooling::CompileCommand getFallbackCommand(PathRef File) const;
+  virtual tooling::CompileCommand getFallbackCommand(PathRef File, std::optional<std::string> ProjectRoot = std::nullopt) const;
 
   /// If the CDB does any asynchronous work, wait for it to complete.
   /// For use in tests.
@@ -86,7 +86,7 @@ class DelegatingCDB : public GlobalCompilationDatabase {
   std::unique_ptr<ProjectModules>
   getProjectModules(PathRef File) const override;
 
-  tooling::CompileCommand getFallbackCommand(PathRef File) const override;
+  tooling::CompileCommand getFallbackCommand(PathRef File, std::optional<std::string> ProjectRoot = std::nullopt) const override;
 
   bool blockUntilIdle(Deadline D) const override;
 
@@ -200,7 +200,7 @@ class OverlayCDB : public DelegatingCDB {
 
   std::optional<tooling::CompileCommand>
   getCompileCommand(PathRef File) const override;
-  tooling::CompileCommand getFallbackCommand(PathRef File) const override;
+  tooling::CompileCommand getFallbackCommand(PathRef File, std::optional<std::string> ProjectRoot = std::nullopt) const override;
 
   /// Sets or clears the compilation command for a particular file.
   /// Returns true if the command was changed (including insertion and removal),
diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp
index 035e5e63d8fbb..3dc53767e0ea4 100644
--- a/clang-tools-extra/clangd/TUScheduler.cpp
+++ b/clang-tools-extra/clangd/TUScheduler.cpp
@@ -723,6 +723,7 @@ class ASTWorker {
   const GlobalCompilationDatabase &CDB;
   /// Callback invoked when preamble or main file AST is built.
   ParsingCallbacks &Callbacks;
+  std::optional<std::string> FallbackProjectRoot;
 
   Semaphore &Barrier;
   /// Whether the 'onMainAST' callback ran for the current FileInputs.
@@ -840,13 +841,14 @@ ASTWorker::ASTWorker(PathRef FileName, const GlobalCompilationDatabase &CDB,
     : IdleASTs(LRUCache), HeaderIncluders(HeaderIncluders), RunSync(RunSync),
       UpdateDebounce(Opts.UpdateDebounce), FileName(FileName),
       ContextProvider(Opts.ContextProvider), CDB(CDB), Callbacks(Callbacks),
+      FallbackProjectRoot(Opts.FallbackProjectRoot),
       Barrier(Barrier), Done(false), Status(FileName, Callbacks),
       PreamblePeer(FileName, Callbacks, Opts.StorePreamblesInMemory, RunSync,
                    Opts.PreambleThrottler, Status, HeaderIncluders, *this) {
   // Set a fallback command because compile command can be accessed before
   // `Inputs` is initialized. Other fields are only used after initialization
   // from client inputs.
-  FileInputs.CompileCommand = CDB.getFallbackCommand(FileName);
+  FileInputs.CompileCommand = CDB.getFallbackCommand(FileName, FallbackProjectRoot);
 }
 
 ASTWorker::~ASTWorker() {
@@ -888,7 +890,7 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags,
     if (Cmd)
       Inputs.CompileCommand = std::move(*Cmd);
     else
-      Inputs.CompileCommand = CDB.getFallbackCommand(FileName);
+      Inputs.CompileCommand = CDB.getFallbackCommand(FileName, FallbackProjectRoot);
 
     bool InputsAreTheSame =
         std::tie(FileInputs.CompileCommand, FileInputs.Contents) ==
diff --git a/clang-tools-extra/clangd/TUScheduler.h b/clang-tools-extra/clangd/TUScheduler.h
index d0da20310a8b2..581a639646527 100644
--- a/clang-tools-extra/clangd/TUScheduler.h
+++ b/clang-tools-extra/clangd/TUScheduler.h
@@ -236,6 +236,10 @@ class TUScheduler {
     /// Typically to inject per-file configuration.
     /// If the path is empty, context sholud be "generic".
     std::function<Context(PathRef)> ContextProvider;
+
+    /// If set, fallback command uses this path as its current working directory
+    /// instead of the file's parent path.
+    std::optional<std::string> FallbackProjectRoot;
   };
 
   TUScheduler(const GlobalCompilationDatabase &CDB, const Options &Opts,
diff --git a/clang-tools-extra/clangd/tool/Check.cpp b/clang-tools-extra/clangd/tool/Check.cpp
index df8d075e80596..8d49b82d2ca53 100644
--- a/clang-tools-extra/clangd/tool/Check.cpp
+++ b/clang-tools-extra/clangd/tool/Check.cpp
@@ -187,7 +187,7 @@ class Checker {
           Cmd.Heuristic.empty() ? "from CDB" : Cmd.Heuristic, Cmd.Directory,
           printArgv(Cmd.CommandLine));
     } else {
-      Cmd = CDB->getFallbackCommand(File);
+      Cmd = CDB->getFallbackCommand(File, Opts.FallbackProjectRoot);
       log("Generic fallback command is: [{0}] {1}", Cmd.Directory,
           printArgv(Cmd.CommandLine));
     }
@@ -502,7 +502,7 @@ bool check(llvm::StringRef File, const ThreadsafeFS &TFS,
                  config::DiagnosticCallback Diag) const override {
       config::Fragment F;
       // If we're timing clang-tidy checks, implicitly disabling the slow ones
-      // is counterproductive! 
+      // is counterproductive!
       if (CheckTidyTime.getNumOccurrences())
         F.Diagnostics.ClangTidy.FastCheckFilter.emplace("None");
       return {std::move(F).compile(Diag)};
diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp
index f287439f10cab..75d71c5a78f45 100644
--- a/clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -499,6 +499,14 @@ opt<bool> EnableConfig{
     init(true),
 };
 
+opt<Path> ProjectRoot{
+    "project-root",
+    cat(Misc),
+    desc("Path to use as the current working directory for fallback commands."),
+    init(""),
+    ValueOptional,
+};
+
 opt<bool> UseDirtyHeaders{"use-dirty-headers", cat(Misc),
                           desc("Use files open in the editor when parsing "
                                "headers instead of reading from the disk"),
@@ -906,6 +914,8 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var
   }
   if (!ResourceDir.empty())
     Opts.ResourceDir = ResourceDir;
+  if (!ProjectRoot.empty())
+    Opts.FallbackProjectRoot = ProjectRoot;
   Opts.BuildDynamicSymbolIndex = true;
 #if CLANGD_ENABLE_REMOTE
   if (RemoteIndexAddress.empty() != ProjectRoot.empty()) {

@HighCommander4
Copy link
Collaborator

HighCommander4 commented Nov 18, 2025

Hi @Dominicentek! Thanks for submitting this PR.

The topic of this PR actually touches on a set of improvements I've been wanting to make to clangd for a long time, called "strong workspace mode". Some background on this proposed mode can be found in clangd/clangd#907 (with credit to @sam-mccall for the name and initial description).

Basically, "strong workspace mode" would be a mode of operation of clangd where an instance of clangd is more strongly coupled to a particular workspace/project, and clangd's default behaviours are adjusted to reflect this. The specific behaviours that I have in mind are:

  1. A compile_commands.json file in the workspace's root directory (or in build/) is used for all files opened by the clangd instance, as if --compile-commands-dir=<workspace_dir> were used.
  2. Settings in a .clangd file in the workspace's root directory are applied to all files opened by the clangd instance, including files outside the directory tree of the workspace.
  3. (This patch) the workspace's root directory is used as the working directory for fallback commands.

In addition, there is some discussion in clangd/clangd#1341 that suggests to me that it might make sense for "strong workspace mode" to be something the user opts into at the client level (for example, in vscode, using a setting provided by the vscode-clangd extension), which then allows it to enable additional client behaviours as well (for example, launching clangd as soon as the workspace is opened, so that operations like "Go to Symbol" are available even before a C/C++ file is opened).

I'd be curious to hear your opinion on the following:

  • Does the above outline of "strong workspace mode" make sense to you as a cohesive concept? Would it make sense to have these behaviours controlled by a single setting, rather than e.g. having a separate setting that controls just the working directory for fallback commands?
    • (Note that this doesn't have to mean implementing all these behaviours at once. We could implement them piece by piece, starting with the fallback commands. But it does mean adding any new setting with the understanding that in the future it will affect other behaviours as well.)
  • What do you think about opting into "strong workspace mode" at the client level (e.g. with a vscode-clangd setting) rather than at the server level (e.g. with a clangd command line argument)? Are you looking to use this with a client that has a clear notion of a "workspace", such as vscode?

@Dominicentek
Copy link
Author

Hi, thanks for reaching out.

I made this pull request as my editor's (Zed) built-in clangd client doesn't set the project root directory as the working directory for fallback commands. VSCode does actually have this behavior. Since I was relying on fallback commands rather than compile_commands.json and couldn't really find a way to make clangd behave like this with Zed, I made it so you can change the working directory for fallback commands via the --project-root flag with this patch.

As for the "strong workspace mode", I am quite fond of this idea. Though I'd like to see this being done at the server level (with a CLI flag), since both VSCode and Zed let you customize CLI arguments for clangd, but Zed doesn't really have any clangd-specific settings, as opposed to VSCode.

@HighCommander4
Copy link
Collaborator

my editor's (Zed) built-in clangd client doesn't set the project root directory as the working directory for fallback commands. VSCode does actually have this behavior.

Do you know how VSCode does this?

@Dominicentek
Copy link
Author

No, I'm not entirely sure.

@HighCommander4
Copy link
Collaborator

my editor's (Zed) built-in clangd client doesn't set the project root directory as the working directory for fallback commands. VSCode does actually have this behavior.

Do you know how VSCode does this?

I tried to reproduce the described behaviour in VSCode, and I haven't been able to.

Here's what I tried specifically:

  • Created /tmp/workspace with the directory structure:
    .
    ├── include
    │   └── foo.hpp
    └── src
        └── test.cpp
    ```
    
  • Gave src/test.cpp the contents #include "include/foo.hpp"
  • Added the vscode setting "clangd.fallbackFlags": ["-Iinclude"]
  • Opened src/test.cpp

The clangd logs are showing:

I[02:12:28.500] ASTWorker building file /tmp/workspace/src/test.cpp version 1 with command clangd fallback
[/tmp/workspace/src]
/usr/bin/clang -Iinclude -resource-dir=/usr/lib/llvm-21/lib/clang/21 -- /tmp/workspace/src/test.cpp

indicating that it's using the source file's containing directory (/tmp/workspace/src), and not the project root directory (/tmp/workspace) as the working directory for the command (and indeed, the include in the opened file is not resolved).

Could you elaborate on what VSCode behaviour you were observing?

@Dominicentek
Copy link
Author

Ah I apologize, I was misremembering.

I used -I${workspaceFolder}/include in my VSCode configuration, not -Iinclude.

@HighCommander4
Copy link
Collaborator

Thanks for the clarification.

I have a couple of follow-up questions about using clangd with Zed, with a view to understanding what sort of constraints we have on how to configure this behaviour:

  1. Does Zed send a suitable workspace path in InitializeParams, in any of the rootPath, rootUri, or workspaceFolders fields? (If unsure, feel free to post clangd logs taken with --log=verbose, which will include the entire contents of the client's initialize request.) I'm trying to understand whether we have the potential option of using this directory, rather than specifying an additional (possibly conflicting) directory as the value of a command-line argument such as --project-root.
  2. Does Zed provide some way of customizing the initialize request, such as injecting additional fields into it? (E.g. neovim allows this, with a short piece of Lua script.) If it does, and the way to activate this feature would be to inject e.g. strongWorkspaceMode: true or some such, would you consider that a sufficiently usable alternative to a command line option?

@Dominicentek
Copy link
Author

  1. I've attached my clangd log below.
  2. Zed only lets you configure CLI options, environment variables and path to the binary. I'm using ~/.config/clangd/config.yaml to configure the fallback flags.

clangd.log

@HighCommander4
Copy link
Collaborator

  1. I've attached my clangd log below.

I'm seeing the client include "rootUri":"file:///home/dominicentek/Desktop/project" in the initialize request.

I take it this is the same directory you were envisioning passing to --project-root?

  1. Zed only lets you configure CLI options, environment variables and path to the binary. I'm using ~/.config/clangd/config.yaml to configure the fallback flags.

Ok, thanks for checking.

So given all that, what do you think about the following approach:

  • Introduce a command-line flag --strong-workspace-mode which is boolean-valued rather than taking a string argument.
    • If set to true, this flag would currently have the effect of using the rootUri sent by the client as the working directory for fallback commands.
    • In the future, the effect of this flag would be extended to have the other effects described in this comment.

@Dominicentek
Copy link
Author

Yep, sounds great!

@HighCommander4
Copy link
Collaborator

Yep, sounds great!

Ok, cool.

Would you like to update this PR to implement this revised approach? I'd be happy to review and (if no one else objects) approve it.

@Dominicentek
Copy link
Author

Alright, I've made the changes.

@github-actions
Copy link

github-actions bot commented Nov 25, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@github-actions
Copy link

github-actions bot commented Nov 25, 2025

🐧 Linux x64 Test Results

The build failed before running any tests. Click on a failure below to see the details.

tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/TestFS.cpp.o
FAILED: tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/TestFS.cpp.o
sccache /opt/llvm/bin/clang++ -DGTEST_HAS_RTTI=0 -DLLVM_BUILD_STATIC -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GLIBCXX_USE_CXX11_ABI=1 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/clangd/unittests -I/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/unittests -I/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/../include-cleaner/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/clangd/../clang-tidy -I/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/clangd -I/home/gha/actions-runner/_work/llvm-project/llvm-project/third-party/unittest/googletest/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/third-party/unittest/googlemock/include -gmlt -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wno-pass-failed -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -fno-common -Woverloaded-virtual -Wno-nested-anon-types -O3 -DNDEBUG -std=c++17  -Wno-variadic-macros -Wno-gnu-zero-variadic-macro-arguments -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -Wno-suggest-override -MD -MT tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/TestFS.cpp.o -MF tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/TestFS.cpp.o.d -o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/TestFS.cpp.o -c /home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/unittests/TestFS.cpp
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/unittests/TestFS.cpp:47:26: error: constructor for 'clang::clangd::MockCompilationDatabase' must explicitly initialize the base class 'GlobalCompilationDatabase' which does not have a default constructor
47 | MockCompilationDatabase::MockCompilationDatabase(llvm::StringRef Directory,
|                          ^
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/GlobalCompilationDatabase.h:36:7: note: 'clang::clangd::GlobalCompilationDatabase' declared here
36 | class GlobalCompilationDatabase {
|       ^
1 error generated.
tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/GlobalCompilationDatabaseTests.cpp.o
FAILED: tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/GlobalCompilationDatabaseTests.cpp.o
sccache /opt/llvm/bin/clang++ -DGTEST_HAS_RTTI=0 -DLLVM_BUILD_STATIC -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GLIBCXX_USE_CXX11_ABI=1 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/clangd/unittests -I/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/unittests -I/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/../include-cleaner/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/clangd/../clang-tidy -I/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/clangd -I/home/gha/actions-runner/_work/llvm-project/llvm-project/third-party/unittest/googletest/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/third-party/unittest/googlemock/include -gmlt -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wno-pass-failed -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -fno-common -Woverloaded-virtual -Wno-nested-anon-types -O3 -DNDEBUG -std=c++17  -Wno-variadic-macros -Wno-gnu-zero-variadic-macro-arguments -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -Wno-suggest-override -MD -MT tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/GlobalCompilationDatabaseTests.cpp.o -MF tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/GlobalCompilationDatabaseTests.cpp.o.d -o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/GlobalCompilationDatabaseTests.cpp.o -c /home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp
In file included from /home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp:9:
In file included from /home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/GlobalCompilationDatabase.h:12:
In file included from /home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/ProjectModules.h:12:
In file included from /home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/support/Function.h:16:
In file included from /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/include/llvm/ADT/FunctionExtras.h:36:
In file included from /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/include/llvm/ADT/PointerUnion.h:20:
In file included from /home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/include/llvm/ADT/STLExtras.h:37:
In file included from /usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/memory:78:
/usr/lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/bits/unique_ptr.h:1070:34: error: call to implicitly-deleted default constructor of 'clang::clangd::(anonymous namespace)::OverlayCDBTest::BaseCDB'
1070 |     { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
|                                  ^
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp:98:32: note: in instantiation of function template specialization 'std::make_unique<clang::clangd::(anonymous namespace)::OverlayCDBTest::BaseCDB>' requested here
98 |   OverlayCDBTest() : Base(std::make_unique<BaseCDB>()) {}
|                                ^
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp:78:19: note: default constructor of 'BaseCDB' is implicitly deleted because base class 'GlobalCompilationDatabase' has no default constructor
78 |   class BaseCDB : public GlobalCompilationDatabase {
|                   ^
1 error generated.
tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/ClangdTests.cpp.o
FAILED: tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/ClangdTests.cpp.o
sccache /opt/llvm/bin/clang++ -DGTEST_HAS_RTTI=0 -DLLVM_BUILD_STATIC -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GLIBCXX_USE_CXX11_ABI=1 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/clangd/unittests -I/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/unittests -I/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/../include-cleaner/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/clangd/../clang-tidy -I/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/clangd -I/home/gha/actions-runner/_work/llvm-project/llvm-project/third-party/unittest/googletest/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/third-party/unittest/googlemock/include -gmlt -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wno-pass-failed -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -fno-common -Woverloaded-virtual -Wno-nested-anon-types -O3 -DNDEBUG -std=c++17  -Wno-variadic-macros -Wno-gnu-zero-variadic-macro-arguments -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -Wno-suggest-override -MD -MT tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/ClangdTests.cpp.o -MF tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/ClangdTests.cpp.o.d -o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/ClangdTests.cpp.o -c /home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/unittests/ClangdTests.cpp
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/unittests/ClangdTests.cpp:1112:5: error: constructor for 'DelayedCompilationDatabase' must explicitly initialize the base class 'GlobalCompilationDatabase' which does not have a default constructor
1112 |     DelayedCompilationDatabase(Notification &CanReturnCommand)
|     ^
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/GlobalCompilationDatabase.h:36:7: note: 'clang::clangd::GlobalCompilationDatabase' declared here
36 | class GlobalCompilationDatabase {
|       ^
1 error generated.
tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/TUSchedulerTests.cpp.o
FAILED: tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/TUSchedulerTests.cpp.o
sccache /opt/llvm/bin/clang++ -DGTEST_HAS_RTTI=0 -DLLVM_BUILD_STATIC -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GLIBCXX_USE_CXX11_ABI=1 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/clangd/unittests -I/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/unittests -I/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/../include-cleaner/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/clangd/../clang-tidy -I/home/gha/actions-runner/_work/llvm-project/llvm-project/clang/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/llvm/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd -I/home/gha/actions-runner/_work/llvm-project/llvm-project/build/tools/clang/tools/extra/clangd -I/home/gha/actions-runner/_work/llvm-project/llvm-project/third-party/unittest/googletest/include -I/home/gha/actions-runner/_work/llvm-project/llvm-project/third-party/unittest/googlemock/include -gmlt -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wno-pass-failed -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -fno-common -Woverloaded-virtual -Wno-nested-anon-types -O3 -DNDEBUG -std=c++17  -Wno-variadic-macros -Wno-gnu-zero-variadic-macro-arguments -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -Wno-suggest-override -MD -MT tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/TUSchedulerTests.cpp.o -MF tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/TUSchedulerTests.cpp.o.d -o tools/clang/tools/extra/clangd/unittests/CMakeFiles/ClangdTests.dir/TUSchedulerTests.cpp.o -c /home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp:1351:5: error: call to implicitly-deleted default constructor of 'struct NoHeadersCDB'
1351 |   } CDB;
|     ^
/home/gha/actions-runner/_work/llvm-project/llvm-project/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp:1331:25: note: default constructor of 'NoHeadersCDB' is implicitly deleted because base class 'GlobalCompilationDatabase' has no default constructor
1331 |   struct NoHeadersCDB : public GlobalCompilationDatabase {
|                         ^
1 error generated.

If these failures are unrelated to your changes (for example tests are broken or flaky at HEAD), please open an issue at https://github.com/llvm/llvm-project/issues and add the infrastructure label.

Copy link
Collaborator

@HighCommander4 HighCommander4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't had a chance to take a very detailed look, but some high-level feedback:

  • We shouldn't assume the current working directory (current_path) will be the workspace root, even if that happens to be the case today. Instead, let's propagate the rootUri (or rootPath) that the client sent in the initialize request to the place where we need it. We already propagate it into Opts.WorkspaceRoot, we can plumb it further from there into GlobalCompilationDatabase.
  • Rather than changing the GlobalCompilationDatabase::getFallbackCommand signature, let's provide the flag to the GlobalCompilationDatabase via its constructor (and derived classes' constructors).
    • In fact, since we need to tell it both the bool and the path, maybe we can group them into an optional<string>, which would contain the path in strong workspace mode, and be empty in the default mode.
  • We should add some sort of test coverage. We can add a unit test similar to GlobalCompilationDatabaseTest.FallbackCommand which makes assertions about Cmd.Directory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants