https://github.com/HighCommander4 updated 
https://github.com/llvm/llvm-project/pull/214951

>From 92c6aef642d9cedbee379f0d71e4102c28a35af8 Mon Sep 17 00:00:00 2001
From: Fil-Den <[email protected]>
Date: Sat, 11 Jul 2026 18:46:03 +0300
Subject: [PATCH 1/4] Clangd-indexer respects .clangd files

---
 clang-tools-extra/clangd/ConfigProvider.cpp   | 27 ++++++++++++++
 clang-tools-extra/clangd/ConfigProvider.h     | 10 +++++
 .../clangd/indexer/IndexerMain.cpp            | 37 ++++++++++++++++++-
 .../clangd/test/indexer-clangd-config.test    | 25 +++++++++++++
 clang-tools-extra/clangd/tool/ClangdMain.cpp  | 24 ++----------
 5 files changed, 100 insertions(+), 23 deletions(-)
 create mode 100644 clang-tools-extra/clangd/test/indexer-clangd-config.test

diff --git a/clang-tools-extra/clangd/ConfigProvider.cpp 
b/clang-tools-extra/clangd/ConfigProvider.cpp
index ac437ee8b6eb1..e26509d8b1c8b 100644
--- a/clang-tools-extra/clangd/ConfigProvider.cpp
+++ b/clang-tools-extra/clangd/ConfigProvider.cpp
@@ -10,10 +10,12 @@
 #include "Config.h"
 #include "ConfigFragment.h"
 #include "support/FileCache.h"
+#include "support/Logger.h"
 #include "support/Path.h"
 #include "support/ThreadsafeFS.h"
 #include "support/Trace.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Path.h"
@@ -166,6 +168,31 @@ Provider::combine(std::vector<const Provider *> Providers) 
{
   return std::make_unique<CombinedProvider>(std::move(Providers));
 }
 
+std::vector<std::unique_ptr<Provider>>
+Provider::createDefaultProviders(const ThreadsafeFS &TFS) {
+  std::vector<std::unique_ptr<Provider>> Providers;
+  Providers.push_back(fromAncestorRelativeYAMLFiles(".clangd", TFS));
+  llvm::SmallString<256> UserConfig;
+  if (llvm::sys::path::user_config_directory(UserConfig)) {
+    llvm::sys::path::append(UserConfig, "clangd", "config.yaml");
+    vlog("User config file is {0}", UserConfig);
+    Providers.push_back(
+        fromYAMLFile(UserConfig, /*Directory=*/"", TFS, /*Trusted=*/true));
+  } else {
+    elog("Couldn't determine user config file, not loading");
+  }
+  return Providers;
+}
+
+const char *const Provider::EnableConfigFlagDesc =
+    "Read user and project configuration from YAML files.\n"
+    "Project config is from a .clangd file in the project directory.\n"
+    "User config is from clangd/config.yaml in the following directories:\n"
+    "\tWindows: %USERPROFILE%\\AppData\\Local\n"
+    "\tMac OS: ~/Library/Preferences/\n"
+    "\tOthers: $XDG_CONFIG_HOME, usually ~/.config\n"
+    "Configuration is documented at https://clangd.llvm.org/config.html";;
+
 Config Provider::getConfig(const Params &P, DiagnosticCallback DC) const {
   trace::Span Tracer("getConfig");
   if (!P.Path.empty())
diff --git a/clang-tools-extra/clangd/ConfigProvider.h 
b/clang-tools-extra/clangd/ConfigProvider.h
index f268edb1df2a5..e1a52604e7de8 100644
--- a/clang-tools-extra/clangd/ConfigProvider.h
+++ b/clang-tools-extra/clangd/ConfigProvider.h
@@ -84,9 +84,19 @@ class Provider {
   /// Order is preserved; later providers take precedence over earlier ones.
   static std::unique_ptr<Provider> combine(std::vector<const Provider *>);
 
+  /// Returns providers for the configuration files that clangd tools read by
+  /// default: project config (ancestor `.clangd` files) and the user's
+  /// global config file.
+  static std::vector<std::unique_ptr<Provider>>
+  createDefaultProviders(const ThreadsafeFS &);
+
   /// Build a config based on this provider.
   Config getConfig(const Params &, DiagnosticCallback) const;
 
+  /// Help text for the --enable-config flag, shared by clangd tools that
+  /// expose createDefaultProviders() on the command line.
+  static const char *const EnableConfigFlagDesc;
+
 private:
   /// Provide fragments that may be relevant to the file.
   /// The configuration provider is not responsible for testing conditions.
diff --git a/clang-tools-extra/clangd/indexer/IndexerMain.cpp 
b/clang-tools-extra/clangd/indexer/IndexerMain.cpp
index 94db860f0b9b5..c330be298a87a 100644
--- a/clang-tools-extra/clangd/indexer/IndexerMain.cpp
+++ b/clang-tools-extra/clangd/indexer/IndexerMain.cpp
@@ -10,21 +10,29 @@
 //
 
//===----------------------------------------------------------------------===//
 
+#include "ClangdServer.h"
 #include "CompileCommands.h"
 #include "Compiler.h"
+#include "ConfigProvider.h"
 #include "index/IndexAction.h"
 #include "index/Merge.h"
 #include "index/Ref.h"
 #include "index/Serialization.h"
 #include "index/Symbol.h"
 #include "index/SymbolCollector.h"
+#include "support/Context.h"
 #include "support/Logger.h"
+#include "support/ThreadsafeFS.h"
 #include "clang/Tooling/ArgumentsAdjusters.h"
 #include "clang/Tooling/Execution.h"
 #include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Signals.h"
+#include <memory>
 #include <utility>
+#include <vector>
 
 namespace clang {
 namespace clangd {
@@ -48,6 +56,12 @@ static llvm::cl::list<std::string> QueryDriverGlobs{
     llvm::cl::CommaSeparated,
 };
 
+static llvm::cl::opt<bool> EnableConfig{
+    "enable-config",
+    llvm::cl::desc(config::Provider::EnableConfigFlagDesc),
+    llvm::cl::init(true),
+};
+
 class IndexActionFactory : public tooling::FrontendActionFactory {
 public:
   IndexActionFactory(IndexFileIn &Result) : Result(Result) {}
@@ -152,6 +166,20 @@ int main(int argc, const char **argv) {
     return 1;
   }
 
+  clang::clangd::RealThreadsafeFS TFS;
+  std::vector<std::unique_ptr<clang::clangd::config::Provider>> ProviderStack;
+  if (clang::clangd::EnableConfig)
+    ProviderStack =
+        clang::clangd::config::Provider::createDefaultProviders(TFS);
+  std::vector<const clang::clangd::config::Provider *> ProviderPointers;
+  for (const auto &P : ProviderStack)
+    ProviderPointers.push_back(P.get());
+  auto ConfigProvider =
+      clang::clangd::config::Provider::combine(std::move(ProviderPointers));
+  auto ContextProvider =
+      clang::clangd::ClangdServer::createConfiguredContextProvider(
+          ConfigProvider.get(), /*Callbacks=*/nullptr);
+
   // Collect symbols found in each translation unit, merging as we go.
   clang::clangd::IndexFileIn Data;
   auto Mangler = std::make_shared<clang::clangd::CommandMangler>(
@@ -162,8 +190,13 @@ int main(int argc, const char **argv) {
   auto Err = Executor->get()->execute(
       std::make_unique<clang::clangd::IndexActionFactory>(Data),
       clang::tooling::ArgumentsAdjuster(
-          [Mangler = std::move(Mangler)](const std::vector<std::string> &Args,
-                                         llvm::StringRef File) {
+          [Mangler = std::move(Mangler),
+           ContextProvider = std::move(ContextProvider)](
+              const std::vector<std::string> &Args, llvm::StringRef File) {
+            llvm::SmallString<256> AbsFile(File);
+            llvm::sys::fs::make_absolute(AbsFile);
+            clang::clangd::WithContext WithCfg(ContextProvider(AbsFile));
+
             clang::tooling::CompileCommand Cmd;
             Cmd.CommandLine = Args;
             Mangler->operator()(Cmd, File);
diff --git a/clang-tools-extra/clangd/test/indexer-clangd-config.test 
b/clang-tools-extra/clangd/test/indexer-clangd-config.test
new file mode 100644
index 0000000000000..f99f2db410ee3
--- /dev/null
+++ b/clang-tools-extra/clangd/test/indexer-clangd-config.test
@@ -0,0 +1,25 @@
+# Test that clangd-indexer respects CompileFlags
+
+# RUN: rm -rf %t.dir && mkdir -p %t.dir
+# RUN: split-file %s %t.dir
+
+# By default config is enabled, so the .clangd file's CompileFlags.Add should
+# define FROM_CLANGD_FILE, and the #error below must not fire.
+# RUN: clangd-indexer %t.dir/test.cpp 2>&1 | FileCheck --check-prefix=ENABLED 
%s
+# ENABLED-NOT: error: "FROM_CLANGD_FILE not defined
+
+# With config disabled, the macro isn't defined by the .clangd file, so the
+# #error must fire.
+# RUN: clangd-indexer --enable-config=0 %t.dir/test.cpp 2>&1 \
+# RUN:     | FileCheck --check-prefix=DISABLED %s
+# DISABLED: error: "FROM_CLANGD_FILE not defined - .clangd file was not 
applied"
+
+#--- .clangd
+CompileFlags:
+  Add: [-DFROM_CLANGD_FILE=1]
+
+#--- test.cpp
+#ifndef FROM_CLANGD_FILE
+#error "FROM_CLANGD_FILE not defined - .clangd file was not applied"
+#endif
+int foo() { return 0; }
diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp 
b/clang-tools-extra/clangd/tool/ClangdMain.cpp
index 13fe4d3911731..f95e2dbf5eb38 100644
--- a/clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -489,14 +489,7 @@ opt<bool> PrettyPrint{
 opt<bool> EnableConfig{
     "enable-config",
     cat(Misc),
-    desc(
-        "Read user and project configuration from YAML files.\n"
-        "Project config is from a .clangd file in the project directory.\n"
-        "User config is from clangd/config.yaml in the following 
directories:\n"
-        "\tWindows: %USERPROFILE%\\AppData\\Local\n"
-        "\tMac OS: ~/Library/Preferences/\n"
-        "\tOthers: $XDG_CONFIG_HOME, usually ~/.config\n"
-        "Configuration is documented at https://clangd.llvm.org/config.html";),
+    desc(config::Provider::EnableConfigFlagDesc),
     init(true),
 };
 
@@ -998,19 +991,8 @@ clangd accepts flags on the commandline, and in the 
CLANGD_FLAGS environment var
   RealThreadsafeFS TFS;
   std::vector<std::unique_ptr<config::Provider>> ProviderStack;
   std::unique_ptr<config::Provider> Config;
-  if (EnableConfig) {
-    ProviderStack.push_back(
-        config::Provider::fromAncestorRelativeYAMLFiles(".clangd", TFS));
-    llvm::SmallString<256> UserConfig;
-    if (llvm::sys::path::user_config_directory(UserConfig)) {
-      llvm::sys::path::append(UserConfig, "clangd", "config.yaml");
-      vlog("User config file is {0}", UserConfig);
-      ProviderStack.push_back(config::Provider::fromYAMLFile(
-          UserConfig, /*Directory=*/"", TFS, /*Trusted=*/true));
-    } else {
-      elog("Couldn't determine user config file, not loading");
-    }
-  }
+  if (EnableConfig)
+    ProviderStack = config::Provider::createDefaultProviders(TFS);
   ProviderStack.push_back(std::make_unique<FlagsConfigProvider>());
   std::vector<const config::Provider *> ProviderPointers;
   for (const auto &P : ProviderStack)

>From d19475d436d308f26bc71d9fe2f0caffb14674c4 Mon Sep 17 00:00:00 2001
From: Fil-Den <[email protected]>
Date: Tue, 11 Aug 2026 20:58:31 +0300
Subject: [PATCH 2/4] Disable config by default

---
 .../clangd/indexer/IndexerMain.cpp             |  2 +-
 .../clangd/test/indexer-clangd-config.test     | 18 +++++++++---------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/clang-tools-extra/clangd/indexer/IndexerMain.cpp 
b/clang-tools-extra/clangd/indexer/IndexerMain.cpp
index c330be298a87a..154374606e38d 100644
--- a/clang-tools-extra/clangd/indexer/IndexerMain.cpp
+++ b/clang-tools-extra/clangd/indexer/IndexerMain.cpp
@@ -59,7 +59,7 @@ static llvm::cl::list<std::string> QueryDriverGlobs{
 static llvm::cl::opt<bool> EnableConfig{
     "enable-config",
     llvm::cl::desc(config::Provider::EnableConfigFlagDesc),
-    llvm::cl::init(true),
+    llvm::cl::init(false),
 };
 
 class IndexActionFactory : public tooling::FrontendActionFactory {
diff --git a/clang-tools-extra/clangd/test/indexer-clangd-config.test 
b/clang-tools-extra/clangd/test/indexer-clangd-config.test
index f99f2db410ee3..c87e6fb1f1e28 100644
--- a/clang-tools-extra/clangd/test/indexer-clangd-config.test
+++ b/clang-tools-extra/clangd/test/indexer-clangd-config.test
@@ -3,17 +3,17 @@
 # RUN: rm -rf %t.dir && mkdir -p %t.dir
 # RUN: split-file %s %t.dir
 
-# By default config is enabled, so the .clangd file's CompileFlags.Add should
-# define FROM_CLANGD_FILE, and the #error below must not fire.
-# RUN: clangd-indexer %t.dir/test.cpp 2>&1 | FileCheck --check-prefix=ENABLED 
%s
-# ENABLED-NOT: error: "FROM_CLANGD_FILE not defined
-
-# With config disabled, the macro isn't defined by the .clangd file, so the
-# #error must fire.
-# RUN: clangd-indexer --enable-config=0 %t.dir/test.cpp 2>&1 \
-# RUN:     | FileCheck --check-prefix=DISABLED %s
+# By default config is disabled, so the .clangd file's CompileFlags.Add is not
+# applied and the #error below must fire.
+# RUN: clangd-indexer %t.dir/test.cpp 2>&1 | FileCheck --check-prefix=DISABLED 
%s
 # DISABLED: error: "FROM_CLANGD_FILE not defined - .clangd file was not 
applied"
 
+# With config enabled, the .clangd file's CompileFlags.Add should define
+# FROM_CLANGD_FILE, so the #error below must not fire.
+# RUN: clangd-indexer --enable-config %t.dir/test.cpp 2>&1 \
+# RUN:     | FileCheck --check-prefix=ENABLED %s
+# ENABLED-NOT: error: "FROM_CLANGD_FILE not defined
+
 #--- .clangd
 CompileFlags:
   Add: [-DFROM_CLANGD_FILE=1]

>From 4b135375aaa35082fa0769a4fda6ea46fd3f400e Mon Sep 17 00:00:00 2001
From: Fil-Den <[email protected]>
Date: Tue, 11 Aug 2026 23:22:05 +0300
Subject: [PATCH 3/4] move some logic into combineOwned

---
 clang-tools-extra/clangd/ConfigProvider.cpp      |  9 +++++++++
 clang-tools-extra/clangd/ConfigProvider.h        | 15 +++++++++++++++
 clang-tools-extra/clangd/indexer/IndexerMain.cpp |  7 ++-----
 clang-tools-extra/clangd/tool/ClangdMain.cpp     |  8 ++------
 4 files changed, 28 insertions(+), 11 deletions(-)

diff --git a/clang-tools-extra/clangd/ConfigProvider.cpp 
b/clang-tools-extra/clangd/ConfigProvider.cpp
index e26509d8b1c8b..a5bfee9ec303f 100644
--- a/clang-tools-extra/clangd/ConfigProvider.cpp
+++ b/clang-tools-extra/clangd/ConfigProvider.cpp
@@ -168,6 +168,15 @@ Provider::combine(std::vector<const Provider *> Providers) 
{
   return std::make_unique<CombinedProvider>(std::move(Providers));
 }
 
+Provider::OwningProvider
+Provider::combineOwned(std::vector<std::unique_ptr<Provider>> Sources) {
+  std::vector<const Provider *> Pointers;
+  Pointers.reserve(Sources.size());
+  for (const auto &P : Sources)
+    Pointers.push_back(P.get());
+  return {combine(std::move(Pointers)), std::move(Sources)};
+}
+
 std::vector<std::unique_ptr<Provider>>
 Provider::createDefaultProviders(const ThreadsafeFS &TFS) {
   std::vector<std::unique_ptr<Provider>> Providers;
diff --git a/clang-tools-extra/clangd/ConfigProvider.h 
b/clang-tools-extra/clangd/ConfigProvider.h
index e1a52604e7de8..9f5eeee2c8456 100644
--- a/clang-tools-extra/clangd/ConfigProvider.h
+++ b/clang-tools-extra/clangd/ConfigProvider.h
@@ -90,6 +90,21 @@ class Provider {
   static std::vector<std::unique_ptr<Provider>>
   createDefaultProviders(const ThreadsafeFS &);
 
+  /// The result of combining several providers, bundled together with the
+  /// providers themselves. combine() only stores raw pointers to the
+  /// providers it combines, so those providers must outlive it; keeping
+  /// them together in one movable object (rather than as separate
+  /// same-scope variables at the call site) makes it hard to accidentally
+  /// let them go out of scope before Combined does.
+  struct OwningProvider {
+    std::unique_ptr<Provider> Combined;
+    std::vector<std::unique_ptr<Provider>> Sources;
+  };
+
+  /// Like combine(), but takes ownership of the providers being combined.
+  static OwningProvider
+  combineOwned(std::vector<std::unique_ptr<Provider>> Sources);
+
   /// Build a config based on this provider.
   Config getConfig(const Params &, DiagnosticCallback) const;
 
diff --git a/clang-tools-extra/clangd/indexer/IndexerMain.cpp 
b/clang-tools-extra/clangd/indexer/IndexerMain.cpp
index 154374606e38d..9479106e829ea 100644
--- a/clang-tools-extra/clangd/indexer/IndexerMain.cpp
+++ b/clang-tools-extra/clangd/indexer/IndexerMain.cpp
@@ -171,14 +171,11 @@ int main(int argc, const char **argv) {
   if (clang::clangd::EnableConfig)
     ProviderStack =
         clang::clangd::config::Provider::createDefaultProviders(TFS);
-  std::vector<const clang::clangd::config::Provider *> ProviderPointers;
-  for (const auto &P : ProviderStack)
-    ProviderPointers.push_back(P.get());
   auto ConfigProvider =
-      clang::clangd::config::Provider::combine(std::move(ProviderPointers));
+      clang::clangd::config::Provider::combineOwned(std::move(ProviderStack));
   auto ContextProvider =
       clang::clangd::ClangdServer::createConfiguredContextProvider(
-          ConfigProvider.get(), /*Callbacks=*/nullptr);
+          ConfigProvider.Combined.get(), /*Callbacks=*/nullptr);
 
   // Collect symbols found in each translation unit, merging as we go.
   clang::clangd::IndexFileIn Data;
diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp 
b/clang-tools-extra/clangd/tool/ClangdMain.cpp
index f95e2dbf5eb38..c0bf11a6c8a44 100644
--- a/clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -990,15 +990,11 @@ clangd accepts flags on the commandline, and in the 
CLANGD_FLAGS environment var
 
   RealThreadsafeFS TFS;
   std::vector<std::unique_ptr<config::Provider>> ProviderStack;
-  std::unique_ptr<config::Provider> Config;
   if (EnableConfig)
     ProviderStack = config::Provider::createDefaultProviders(TFS);
   ProviderStack.push_back(std::make_unique<FlagsConfigProvider>());
-  std::vector<const config::Provider *> ProviderPointers;
-  for (const auto &P : ProviderStack)
-    ProviderPointers.push_back(P.get());
-  Config = config::Provider::combine(std::move(ProviderPointers));
-  Opts.ConfigProvider = Config.get();
+  auto Config = config::Provider::combineOwned(std::move(ProviderStack));
+  Opts.ConfigProvider = Config.Combined.get();
 
   // Create an empty clang-tidy option.
   TidyProvider ClangTidyOptProvider;

>From 4da0a7b2f22f70d343bee374323270fd0100f560 Mon Sep 17 00:00:00 2001
From: Nathan Ridge <[email protected]>
Date: Mon, 31 Aug 2026 03:38:24 -0400
Subject: [PATCH 4/4] Test demonstrating a bug in the patch

---
 .../indexer-clangd-config-relative-path.test  | 47 +++++++++++++++++++
 1 file changed, 47 insertions(+)
 create mode 100644 
clang-tools-extra/clangd/test/indexer-clangd-config-relative-path.test

diff --git 
a/clang-tools-extra/clangd/test/indexer-clangd-config-relative-path.test 
b/clang-tools-extra/clangd/test/indexer-clangd-config-relative-path.test
new file mode 100644
index 0000000000000..261bcd2a3fd38
--- /dev/null
+++ b/clang-tools-extra/clangd/test/indexer-clangd-config-relative-path.test
@@ -0,0 +1,47 @@
+# Test that clangd-indexer finds the .clangd file when the compilation database
+# names its source files relative to the compile command's "directory".
+#
+# We specify a custom path in XDG_CONFIG_HOME, which only works on some
+# systems, so that the developer's own user config can't affect the result.
+# UNSUPPORTED: system-windows
+# UNSUPPORTED: system-darwin
+
+# RUN: rm -rf %t.dir && mkdir -p %t.dir
+# RUN: split-file %s %t.dir
+# RUN: mkdir -p %t.dir/elsewhere %t.dir/xdg
+
+# Two databases for the same project: one naming test.cpp relative to
+# "directory", one naming it absolutely. They should behave the same.
+# RUN: mkdir -p %t.dir/rel %t.dir/abs
+# RUN: echo '[{"directory":"%/t.dir/proj","command":"clang++ -c 
test.cpp","file":"test.cpp"}]' > %t.dir/rel/compile_commands.json
+# RUN: echo '[{"directory":"%/t.dir/proj","command":"clang++ -c 
test.cpp","file":"%/t.dir/proj/test.cpp"}]' > %t.dir/abs/compile_commands.json
+
+# Run from a directory that is neither the project nor the build directory, so
+# that a process-CWD-relative lookup is guaranteed to look in the wrong place.
+
+# Relative "file" entry: the .clangd file's CompileFlags.Add should still be
+# applied, so the #error must not fire.
+# RUN: cd %t.dir/elsewhere && env XDG_CONFIG_HOME=%t.dir/xdg \
+# RUN:     clangd-indexer --enable-config --executor=all-TUs \
+# RUN:     %t.dir/rel/compile_commands.json > %t.dir/rel.idx 2> %t.dir/rel.log
+# RUN: FileCheck --check-prefix=REL --input-file=%t.dir/rel.log %s
+# REL: Processing file {{.*}}test.cpp
+# REL-NOT: error: "FROM_CLANGD_FILE not defined
+
+# Absolute "file" entry: same project, same config, and this one works today.
+# RUN: cd %t.dir/elsewhere && env XDG_CONFIG_HOME=%t.dir/xdg \
+# RUN:     clangd-indexer --enable-config --executor=all-TUs \
+# RUN:     %t.dir/abs/compile_commands.json > %t.dir/abs.idx 2> %t.dir/abs.log
+# RUN: FileCheck --check-prefix=ABS --input-file=%t.dir/abs.log %s
+# ABS: Processing file {{.*}}test.cpp
+# ABS-NOT: error: "FROM_CLANGD_FILE not defined
+
+#--- proj/.clangd
+CompileFlags:
+  Add: [-DFROM_CLANGD_FILE=1]
+
+#--- proj/test.cpp
+#ifndef FROM_CLANGD_FILE
+#error "FROM_CLANGD_FILE not defined - .clangd file was not applied"
+#endif
+int foo() { return 0; }

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to