Skip to content

Conversation

HerrCai0907
Copy link
Contributor

@HerrCai0907 HerrCai0907 commented Mar 18, 2025

summary

  • remove ERROR diag level, it can be done by warning as error
  • add cmake option to design enable / disable this feature
  • configuration format: I prefer that we should still use structured options

Design for Compatibility

For new field design

  1. we must make sure the required fields do not change in quiet long time.
  2. we should tolerant the unknown optional field (do not exist now) in the future.

For large project integration (3rd party)

  1. For config itself, since we can tolerant the unknown optional fields and required fields should not change, the user can decide whether to use custom check from third-party.
    2.For clang-query, if there are some break change, since the query will be parsed at check time, the user can disable the check and it will not damage the whole clang-tidy

Inherit from #123734
RFC: https://discourse.llvm.org/t/support-query-based-clang-tidy-external-check/85331

this patch introduce query based custom check by CustomChecks options.

The major improvement compared with #123734:

  1. don't need to define config yaml file in command line
  2. all behavior including InheritFromParantConfig is same as other config.
  3. change configuration schema from KV structured to List structured to make extend new function easier.
  4. Split bind string and diag message to two field to give more freedom to design query.

example:

Checks: -*,custom-call-main-function
CustomChecks:
  - Name: call-main-function
    Query: |
        match callExpr(
          callee(
            functionDecl(isMain()).bind("fn")
          )
        ).bind("callee")
    Diagnostic:
      - BindName: fn
        Message: main function.
        Level: Note
      - BindName: callee
        Message: call to main function.
        Level: Warning
int main(); // note: main function.

void bar() {
  main(); // warning: call to main function. [custom-call-main-function]
}

To make this PR don't do too much things that hard to review, here are some possible features not included in this PR

  • support language
  • support traverse
  • easier used template string in diagnostics message

Copy link
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@HerrCai0907 HerrCai0907 marked this pull request as ready for review March 18, 2025 13:56
@HerrCai0907 HerrCai0907 changed the title origin pr [clang-tidy] support query based custom check Mar 18, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 18, 2025

@llvm/pr-subscribers-clang-tidy

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

Author: Congcong Cai (HerrCai0907)

Changes

Patch is 31.84 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/131804.diff

25 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/CMakeLists.txt (+2)
  • (modified) clang-tools-extra/clang-tidy/ClangTidy.cpp (+8-1)
  • (modified) clang-tools-extra/clang-tidy/ClangTidyForceLinker.h (+5)
  • (modified) clang-tools-extra/clang-tidy/ClangTidyModule.h (+2)
  • (modified) clang-tools-extra/clang-tidy/ClangTidyOptions.cpp (+53-3)
  • (modified) clang-tools-extra/clang-tidy/ClangTidyOptions.h (+15)
  • (added) clang-tools-extra/clang-tidy/custom/CMakeLists.txt (+20)
  • (added) clang-tools-extra/clang-tidy/custom/CustomTidyModule.cpp (+50)
  • (added) clang-tools-extra/clang-tidy/custom/QueryCheck.cpp (+102)
  • (added) clang-tools-extra/clang-tidy/custom/QueryCheck.h (+42)
  • (modified) clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp (+2)
  • (modified) clang-tools-extra/docs/ReleaseNotes.rst (+3)
  • (added) clang-tools-extra/docs/clang-tidy/QueryBasedCustomChecks.rst (+57)
  • (modified) clang-tools-extra/docs/clang-tidy/index.rst (+3)
  • (added) clang-tools-extra/test/clang-tidy/checkers/custom/Inputs/clang-tidy.yml (+22)
  • (added) clang-tools-extra/test/clang-tidy/checkers/custom/Inputs/incorrect-clang-tidy.yml (+10)
  • (added) clang-tools-extra/test/clang-tidy/checkers/custom/query-incorrect-query.cpp (+3)
  • (added) clang-tools-extra/test/clang-tidy/checkers/custom/query-partially-active-check.cpp (+5)
  • (added) clang-tools-extra/test/clang-tidy/checkers/custom/query.cpp (+7)
  • (added) clang-tools-extra/test/clang-tidy/infrastructure/Inputs/custom-query-check/append-clang-tidy.yml (+8)
  • (added) clang-tools-extra/test/clang-tidy/infrastructure/Inputs/custom-query-check/empty-clang-tidy.yml (+1)
  • (added) clang-tools-extra/test/clang-tidy/infrastructure/Inputs/custom-query-check/override-clang-tidy.yml (+11)
  • (added) clang-tools-extra/test/clang-tidy/infrastructure/Inputs/custom-query-check/root-clang-tidy.yml (+11)
  • (added) clang-tools-extra/test/clang-tidy/infrastructure/Inputs/custom-query-check/vfsoverlay.yaml (+44)
  • (added) clang-tools-extra/test/clang-tidy/infrastructure/custom-query-check.cpp (+45)
diff --git a/clang-tools-extra/clang-tidy/CMakeLists.txt b/clang-tools-extra/clang-tidy/CMakeLists.txt
index 93117cf1d6373..90efd2ef1f451 100644
--- a/clang-tools-extra/clang-tidy/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/CMakeLists.txt
@@ -58,6 +58,7 @@ add_subdirectory(bugprone)
 add_subdirectory(cert)
 add_subdirectory(concurrency)
 add_subdirectory(cppcoreguidelines)
+add_subdirectory(custom)
 add_subdirectory(darwin)
 add_subdirectory(fuchsia)
 add_subdirectory(google)
@@ -85,6 +86,7 @@ set(ALL_CLANG_TIDY_CHECKS
   clangTidyCERTModule
   clangTidyConcurrencyModule
   clangTidyCppCoreGuidelinesModule
+  clangTidyCustomModule
   clangTidyDarwinModule
   clangTidyFuchsiaModule
   clangTidyGoogleModule
diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp
index d99847a82d168..f2a69e01a32c5 100644
--- a/clang-tools-extra/clang-tidy/ClangTidy.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp
@@ -57,6 +57,11 @@ LLVM_INSTANTIATE_REGISTRY(clang::tidy::ClangTidyModuleRegistry)
 
 namespace clang::tidy {
 
+namespace custom {
+extern void registerCustomChecks(ClangTidyOptions const &O,
+                                 ClangTidyCheckFactories &Factories);
+} // namespace custom
+
 namespace {
 #if CLANG_TIDY_ENABLE_STATIC_ANALYZER
 static const char *AnalyzerCheckNamePrefix = "clang-analyzer-";
@@ -346,6 +351,7 @@ ClangTidyASTConsumerFactory::ClangTidyASTConsumerFactory(
     IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem> OverlayFS)
     : Context(Context), OverlayFS(std::move(OverlayFS)),
       CheckFactories(new ClangTidyCheckFactories) {
+  custom::registerCustomChecks(Context.getOptions(), *CheckFactories);
   for (ClangTidyModuleRegistry::entry E : ClangTidyModuleRegistry::entries()) {
     std::unique_ptr<ClangTidyModule> Module = E.instantiate();
     Module->addCheckFactories(*CheckFactories);
@@ -416,7 +422,7 @@ ClangTidyASTConsumerFactory::createASTConsumer(
                         .getCurrentWorkingDirectory();
   if (WorkingDir)
     Context.setCurrentBuildDirectory(WorkingDir.get());
-
+  custom::registerCustomChecks(Context.getOptions(), *CheckFactories);
   std::vector<std::unique_ptr<ClangTidyCheck>> Checks =
       CheckFactories->createChecksForLanguage(&Context);
 
@@ -659,6 +665,7 @@ getAllChecksAndOptions(bool AllowEnablingAnalyzerAlphaCheckers) {
       std::make_unique<DefaultOptionsProvider>(ClangTidyGlobalOptions(), Opts),
       AllowEnablingAnalyzerAlphaCheckers);
   ClangTidyCheckFactories Factories;
+  custom::registerCustomChecks(Context.getOptions(), Factories);
   for (const ClangTidyModuleRegistry::entry &Module :
        ClangTidyModuleRegistry::entries()) {
     Module.instantiate()->addCheckFactories(Factories);
diff --git a/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h b/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
index adde9136ff1dd..50ac6e138df18 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyForceLinker.h
@@ -54,6 +54,11 @@ extern volatile int CppCoreGuidelinesModuleAnchorSource;
 static int LLVM_ATTRIBUTE_UNUSED CppCoreGuidelinesModuleAnchorDestination =
     CppCoreGuidelinesModuleAnchorSource;
 
+// This anchor is used to force the linker to link the CustomModule.
+extern volatile int CustomModuleAnchorSource;
+static int LLVM_ATTRIBUTE_UNUSED CustomModuleAnchorDestination =
+    CustomModuleAnchorSource;
+
 // This anchor is used to force the linker to link the DarwinModule.
 extern volatile int DarwinModuleAnchorSource;
 static int LLVM_ATTRIBUTE_UNUSED DarwinModuleAnchorDestination =
diff --git a/clang-tools-extra/clang-tidy/ClangTidyModule.h b/clang-tools-extra/clang-tidy/ClangTidyModule.h
index 28f54331755a7..6f0b2bf32a291 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyModule.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyModule.h
@@ -62,6 +62,8 @@ class ClangTidyCheckFactories {
                          });
   }
 
+  void erase(llvm::StringRef CheckName) { Factories.erase(CheckName); }
+
   /// Create instances of checks that are enabled.
   std::vector<std::unique_ptr<ClangTidyCheck>>
   createChecks(ClangTidyContext *Context) const;
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
index 8bac6f161fa05..acedbd8d41faa 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
+++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.cpp
@@ -8,12 +8,12 @@
 
 #include "ClangTidyOptions.h"
 #include "ClangTidyModuleRegistry.h"
+#include "clang/Basic/DiagnosticIDs.h"
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Debug.h"
-#include "llvm/Support/Errc.h"
 #include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/MemoryBufferRef.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/YAMLTraits.h"
@@ -72,7 +72,8 @@ struct NOptionMap {
   NOptionMap(IO &, const ClangTidyOptions::OptionMap &OptionMap) {
     Options.reserve(OptionMap.size());
     for (const auto &KeyValue : OptionMap)
-      Options.emplace_back(std::string(KeyValue.getKey()), KeyValue.getValue().Value);
+      Options.emplace_back(std::string(KeyValue.getKey()),
+                           KeyValue.getValue().Value);
   }
   ClangTidyOptions::OptionMap denormalize(IO &) {
     ClangTidyOptions::OptionMap Map;
@@ -126,6 +127,52 @@ void yamlize(IO &IO, ClangTidyOptions::OptionMap &Val, bool,
   }
 }
 
+namespace {
+struct MultiLineString {
+  std::string &S;
+};
+} // namespace
+
+template <> struct BlockScalarTraits<MultiLineString> {
+  static void output(const MultiLineString &S, void *Ctxt, raw_ostream &OS) {
+    OS << S.S;
+  }
+  static StringRef input(StringRef Str, void *Ctxt, MultiLineString &S) {
+    S.S = Str;
+    return "";
+  }
+};
+
+template <> struct ScalarEnumerationTraits<clang::DiagnosticIDs::Level> {
+  static void enumeration(IO &IO, clang::DiagnosticIDs::Level &Level) {
+    IO.enumCase(Level, "Error", clang::DiagnosticIDs::Level::Error);
+    IO.enumCase(Level, "Warning", clang::DiagnosticIDs::Level::Warning);
+    IO.enumCase(Level, "Note", clang::DiagnosticIDs::Level::Note);
+  }
+};
+template <> struct SequenceElementTraits<ClangTidyOptions::CustomCheckDiag> {
+  static const bool flow = false;
+};
+template <> struct MappingTraits<ClangTidyOptions::CustomCheckDiag> {
+  static void mapping(IO &IO, ClangTidyOptions::CustomCheckDiag &D) {
+    IO.mapRequired("BindName", D.BindName);
+    MultiLineString MLS{D.Message};
+    IO.mapRequired("Message", MLS);
+    IO.mapOptional("Level", D.Level);
+  }
+};
+template <> struct SequenceElementTraits<ClangTidyOptions::CustomCheckValue> {
+  static const bool flow = false;
+};
+template <> struct MappingTraits<ClangTidyOptions::CustomCheckValue> {
+  static void mapping(IO &IO, ClangTidyOptions::CustomCheckValue &V) {
+    IO.mapRequired("Name", V.Name);
+    MultiLineString MLS{V.Query};
+    IO.mapRequired("Query", MLS);
+    IO.mapRequired("Diagnostic", V.Diags);
+  }
+};
+
 struct ChecksVariant {
   std::optional<std::string> AsString;
   std::optional<std::vector<std::string>> AsVector;
@@ -181,6 +228,7 @@ template <> struct MappingTraits<ClangTidyOptions> {
     IO.mapOptional("InheritParentConfig", Options.InheritParentConfig);
     IO.mapOptional("UseColor", Options.UseColor);
     IO.mapOptional("SystemHeaders", Options.SystemHeaders);
+    IO.mapOptional("CustomChecks", Options.CustomChecks);
   }
 };
 
@@ -249,6 +297,8 @@ ClangTidyOptions &ClangTidyOptions::mergeWith(const ClangTidyOptions &Other,
         ClangTidyValue(KeyValue.getValue().Value,
                        KeyValue.getValue().Priority + Order));
   }
+  mergeVectors(CustomChecks, Other.CustomChecks);
+
   return *this;
 }
 
diff --git a/clang-tools-extra/clang-tidy/ClangTidyOptions.h b/clang-tools-extra/clang-tidy/ClangTidyOptions.h
index dd78c570d25d9..2a64ee8fdf7ea 100644
--- a/clang-tools-extra/clang-tidy/ClangTidyOptions.h
+++ b/clang-tools-extra/clang-tidy/ClangTidyOptions.h
@@ -9,6 +9,7 @@
 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYOPTIONS_H
 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYOPTIONS_H
 
+#include "clang/Basic/DiagnosticIDs.h"
 #include "llvm/ADT/IntrusiveRefCntPtr.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringMap.h"
@@ -17,6 +18,7 @@
 #include "llvm/Support/MemoryBufferRef.h"
 #include "llvm/Support/VirtualFileSystem.h"
 #include <functional>
+#include <map>
 #include <optional>
 #include <string>
 #include <system_error>
@@ -129,6 +131,19 @@ struct ClangTidyOptions {
   /// Key-value mapping used to store check-specific options.
   OptionMap CheckOptions;
 
+  struct CustomCheckDiag {
+    std::string BindName;
+    std::string Message;
+    std::optional<DiagnosticIDs::Level> Level;
+  };
+  struct CustomCheckValue {
+    std::string Name;
+    std::string Query;
+    llvm::SmallVector<CustomCheckDiag> Diags;
+  };
+  using CustomCheckValueList = llvm::SmallVector<CustomCheckValue>;
+  std::optional<CustomCheckValueList> CustomChecks;
+
   using ArgList = std::vector<std::string>;
 
   /// Add extra compilation arguments to the end of the list.
diff --git a/clang-tools-extra/clang-tidy/custom/CMakeLists.txt b/clang-tools-extra/clang-tidy/custom/CMakeLists.txt
new file mode 100644
index 0000000000000..40387b73b5253
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/custom/CMakeLists.txt
@@ -0,0 +1,20 @@
+set(LLVM_LINK_COMPONENTS
+  support
+  )
+
+add_clang_library(clangTidyCustomModule STATIC
+  CustomTidyModule.cpp
+  QueryCheck.cpp
+
+  LINK_LIBS
+  clangTidy
+  clangTidyUtils
+
+  DEPENDS
+  ClangDriverOptions
+  )
+
+clang_target_link_libraries(clangTidyCustomModule
+  PRIVATE
+  clangQuery
+  )
diff --git a/clang-tools-extra/clang-tidy/custom/CustomTidyModule.cpp b/clang-tools-extra/clang-tidy/custom/CustomTidyModule.cpp
new file mode 100644
index 0000000000000..e11a39f1a4ccf
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/custom/CustomTidyModule.cpp
@@ -0,0 +1,50 @@
+#include "../ClangTidy.h"
+#include "../ClangTidyModule.h"
+#include "../ClangTidyModuleRegistry.h"
+#include "../ClangTidyOptions.h"
+#include "QueryCheck.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include <memory>
+
+namespace clang::tidy {
+namespace custom {
+
+class CustomModule : public ClangTidyModule {
+public:
+  void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {}
+};
+
+// FIXME: could be clearer to add parameter of addCheckFactories to pass
+// Options?
+extern void registerCustomChecks(ClangTidyOptions const &Options,
+                                 ClangTidyCheckFactories &Factories) {
+  static llvm::SmallSet<llvm::SmallString<32>, 8> CustomCheckNames{};
+  if (!Options.CustomChecks.has_value() || Options.CustomChecks->empty())
+    return;
+  for (llvm::SmallString<32> const &Name : CustomCheckNames)
+    Factories.erase(Name);
+  for (const ClangTidyOptions::CustomCheckValue &V :
+       Options.CustomChecks.value()) {
+    llvm::SmallString<32> Name = llvm::StringRef{"custom-" + V.Name};
+    Factories.registerCheckFactory(
+        // add custom- prefix to avoid conflicts with builtin checks
+        Name, [&V](llvm::StringRef Name, ClangTidyContext *Context) {
+          return std::make_unique<custom::QueryCheck>(Name, V, Context);
+        });
+    CustomCheckNames.insert(std::move(Name));
+  }
+}
+
+} // namespace custom
+
+// Register the AlteraTidyModule using this statically initialized variable.
+static ClangTidyModuleRegistry::Add<custom::CustomModule>
+    X("custom-module", "Adds custom query lint checks.");
+
+// This anchor is used to force the linker to link in the generated object file
+// and thus register the AlteraModule.
+volatile int CustomModuleAnchorSource = 0;
+
+} // namespace clang::tidy
diff --git a/clang-tools-extra/clang-tidy/custom/QueryCheck.cpp b/clang-tools-extra/clang-tidy/custom/QueryCheck.cpp
new file mode 100644
index 0000000000000..c69e76918f7ed
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/custom/QueryCheck.cpp
@@ -0,0 +1,102 @@
+//===--- QueryCheck.cpp - clang-tidy --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "QueryCheck.h"
+#include "../../clang-query/Query.h"
+#include "../../clang-query/QueryParser.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include <string>
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::custom {
+
+QueryCheck::QueryCheck(llvm::StringRef Name,
+                       const ClangTidyOptions::CustomCheckValue &V,
+                       ClangTidyContext *Context)
+    : ClangTidyCheck(Name, Context) {
+  for (const ClangTidyOptions::CustomCheckDiag &D : V.Diags) {
+    auto DiagnosticIdIt =
+        Diags
+            .try_emplace(D.Level.value_or(DiagnosticIDs::Warning),
+                         llvm::StringMap<llvm::SmallVector<std::string>>{})
+            .first;
+    auto DiagMessageIt =
+        DiagnosticIdIt->getSecond()
+            .try_emplace(D.BindName, llvm::SmallVector<std::string>{})
+            .first;
+    DiagMessageIt->second.emplace_back(D.Message);
+  }
+
+  clang::query::QuerySession QS({});
+  llvm::StringRef QueryStringRef{V.Query};
+  while (!QueryStringRef.empty()) {
+    query::QueryRef Q = query::QueryParser::parse(QueryStringRef, QS);
+    switch (Q->Kind) {
+    case query::QK_Match: {
+      const auto &MatchQuerry = llvm::cast<query::MatchQuery>(*Q);
+      Matchers.push_back(MatchQuerry.Matcher);
+      break;
+    }
+    case query::QK_Let: {
+      const auto &LetQuerry = llvm::cast<query::LetQuery>(*Q);
+      LetQuerry.run(llvm::errs(), QS);
+      break;
+    }
+    case query::QK_Invalid: {
+      const auto &InvalidQuerry = llvm::cast<query::InvalidQuery>(*Q);
+      Context->configurationDiag(InvalidQuerry.ErrStr);
+      break;
+    }
+    // FIXME: TODO
+    case query::QK_File:
+    case query::QK_DisableOutputKind:
+    case query::QK_EnableOutputKind:
+    case query::QK_SetOutputKind:
+    case query::QK_SetTraversalKind:
+    case query::QK_Help:
+    case query::QK_NoOp:
+    case query::QK_Quit:
+    case query::QK_SetBool: {
+      Context->configurationDiag("unsupported querry kind");
+    }
+    }
+    QueryStringRef = Q->RemainingContent;
+  }
+}
+
+void QueryCheck::registerMatchers(MatchFinder *Finder) {
+  for (const ast_matchers::dynamic::DynTypedMatcher &M : Matchers)
+    Finder->addDynamicMatcher(M, this);
+}
+
+void QueryCheck::check(const MatchFinder::MatchResult &Result) {
+  auto Emit = [this](DiagMaps const &DiagMaps, std::string const &BindName,
+                     DynTypedNode const &Node, DiagnosticIDs::Level Level) {
+    if (!DiagMaps.contains(Level))
+      return;
+    auto &DiagMap = DiagMaps.at(Level);
+    if (!DiagMap.contains(BindName))
+      return;
+    for (const std::string &Message : DiagMap.at(BindName)) {
+      diag(Node.getSourceRange().getBegin(), Message, Level);
+    }
+  };
+  for (auto &[Name, Node] : Result.Nodes.getMap())
+    Emit(Diags, Name, Node, DiagnosticIDs::Error);
+  for (auto &[Name, Node] : Result.Nodes.getMap())
+    Emit(Diags, Name, Node, DiagnosticIDs::Warning);
+  // place Note last, otherwise it will not be emitted
+  for (auto &[Name, Node] : Result.Nodes.getMap())
+    Emit(Diags, Name, Node, DiagnosticIDs::Note);
+}
+} // namespace clang::tidy::custom
diff --git a/clang-tools-extra/clang-tidy/custom/QueryCheck.h b/clang-tools-extra/clang-tidy/custom/QueryCheck.h
new file mode 100644
index 0000000000000..ded4cad4e3459
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/custom/QueryCheck.h
@@ -0,0 +1,42 @@
+//===--- QueryCheck.h - clang-tidy ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CUSTOM_QUERYCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CUSTOM_QUERYCHECK_H
+
+#include "../ClangTidyCheck.h"
+#include "clang/ASTMatchers/Dynamic/VariantValue.h"
+#include "clang/Basic/DiagnosticIDs.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+
+namespace clang::tidy::custom {
+
+/// FIXME: Write a short description.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/custom/query.html
+class QueryCheck : public ClangTidyCheck {
+public:
+  QueryCheck(llvm::StringRef Name, const ClangTidyOptions::CustomCheckValue &V,
+             ClangTidyContext *Context);
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  llvm::SmallVector<ast_matchers::dynamic::DynTypedMatcher> Matchers{};
+  using DiagMaps =
+      llvm::DenseMap<DiagnosticIDs::Level,
+                     llvm::StringMap<llvm::SmallVector<std::string>>>;
+  DiagMaps Diags;
+};
+
+} // namespace clang::tidy::custom
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CUSTOM_QUERYCHECK_H
diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
index fa8887e4639b4..5784b05d2281d 100644
--- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
+++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
@@ -60,6 +60,8 @@ Configuration files:
   Checks                       - Same as '--checks'. Additionally, the list of
                                  globs can be specified as a list instead of a
                                  string.
+  CustomChecks                 - Array of user defined checks based on
+                                 clang-query syntax.
   ExcludeHeaderFilterRegex     - Same as '--exclude-header-filter'.
   ExtraArgs                    - Same as '--extra-arg'.
   ExtraArgsBefore              - Same as '--extra-arg-before'.
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 2252efb498c2c..6d22f83f2248b 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -96,6 +96,9 @@ Improvements to clang-tidy
   `SystemHeaders` option is enabled.
   Note: this may lead to false negatives; downstream users may need to adjust
   their checks to preserve existing behavior.
+- :program:`clang-tidy` now supports query based custom checks by `CustomChecks`
+  configuration option.
+  :doc:`Query Based Custom Check Document <clang-tidy/QueryBasedCustomChecks>`
 
 New checks
 ^^^^^^^^^^
diff --git a/clang-tools-extra/docs/clang-tidy/QueryBasedCustomChecks.rst b/clang-tools-extra/docs/clang-tidy/QueryBasedCustomChecks.rst
new file mode 100644
index 0000000000000..6efd8fe6797df
--- /dev/null
+++ b/clang-tools-extra/docs/clang-tidy/QueryBasedCustomChecks.rst
@@ -0,0 +1,57 @@
+====================================
+Query Based Custom Clang-Tidy Checks
+====================================
+
+Introduction
+============
+
+This page provides examples of how to add query based custom checks for
+:program:`clang-tidy`.
+
+Custom checks are based on clang-query syntax. Every custom checks will be
+registered in `custom` module to avoid name conflict. They can be enabled or
+disabled by the checks option like the builtin checks.
+
+Custom checks support inheritance from parent configurations like other
+configuration items.
+
+Configuration
+=============
+
+`CustomChecks` is a list of custom checks. Each check must contain
+  - Name: check name can been used in `-checks` option.
+  - Query: query string
+  - Diagnostic: list of diagnostics to be reported.
+     - BindName: name of the node to be bound in `Query`.
+     - Message: message to be reported.
+     - Level: severity of the diagnostic, the possible val...
[truncated]

@HerrCai0907 HerrCai0907 force-pushed the users/ccc/clang-tidy/query-check branch from c6e485e to 64c45dc Compare March 18, 2025 14:05
@HerrCai0907
Copy link
Contributor Author

--dump-config will create incorrect YAML due to #131694.

@carlosgalvezp
Copy link
Contributor

Sorry for being late for the review. This is a major new feature of clang-tidy, so I believe it would be good to have an RFC before looking at the detailed implementation. What problem does it solve, why should clang-tidy solve it, what the API towards the user should be, etc. Should we do that?

@olologin
Copy link

olologin commented Mar 19, 2025

@carlosgalvezp Hi, I tried to explain everything here: #107680
@HerrCai0907 maybe you can reference that issue in the first post in this PR.

@HerrCai0907
Copy link
Contributor Author

I see builds failing in the link, per the report from @llvm-ci above: https://lab.llvm.org/buildbot/#/builders/145/builds/9815

FAILED: lib/libclangTidy.so.22.0git 
: && /home/buildbots/llvm-external-buildbots/clang.19.1.7/bin/clang++ --gcc-toolchain=/gcc-toolchain/usr -fPIC -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 -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -fno-common -Woverloaded-virtual -Wno-nested-anon-types -O3 -DNDEBUG  -Wl,-z,defs -Wl,-z,nodelete -Wl,--color-diagnostics   -Wl,--gc-sections  -Xlinker --dependency-file=tools/clang/tools/extra/clang-tidy/CMakeFiles/clangTidy.dir/link.d -shared -Wl,-soname,libclangTidy.so.22.0git -o lib/libclangTidy.so.22.0git tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidy.cpp.o tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidyCheck.cpp.o tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidyModule.cpp.o tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidyDiagnosticConsumer.cpp.o tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidyOptions.cpp.o tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidyProfiling.cpp.o tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ExpandModularHeadersPPCallbacks.cpp.o tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/GlobList.cpp.o tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/NoLintDirectiveHandler.cpp.o  -Wl,-rpath,"\$ORIGIN/../lib:/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/build/lib:"  lib/libclangTooling.so.22.0git  lib/libclangStaticAnalyzerFrontend.so.22.0git  lib/libclangStaticAnalyzerCore.so.22.0git  lib/libclangFormat.so.22.0git  lib/libclangFrontend.so.22.0git  lib/libclangSerialization.so.22.0git  lib/libclangToolingCore.so.22.0git  lib/libclangRewrite.so.22.0git  lib/libclangAnalysis.so.22.0git  lib/libclangASTMatchers.so.22.0git  lib/libclangAST.so.22.0git  lib/libclangLex.so.22.0git  lib/libclangBasic.so.22.0git  lib/libLLVMFrontendOpenMP.so.22.0git  lib/libLLVMSupport.so.22.0git  -Wl,-rpath-link,/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/build/lib && :
ld.lld: error: undefined symbol: clang::tidy::custom::registerCustomChecks(clang::tidy::ClangTidyOptions const&, clang::tidy::ClangTidyCheckFactories&)
>>> referenced by ClangTidy.cpp
>>>               tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidy.cpp.o:(clang::tidy::ClangTidyASTConsumerFactory::ClangTidyASTConsumerFactory(clang::tidy::ClangTidyContext&, llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>))
>>> referenced by ClangTidy.cpp
>>>               tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidy.cpp.o:(clang::tidy::ClangTidyASTConsumerFactory::createASTConsumer(clang::CompilerInstance&, llvm::StringRef))
>>> referenced by ClangTidy.cpp
>>>               tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidy.cpp.o:(clang::tidy::getAllChecksAndOptions(bool, bool))
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

I don't find any cmake build issue. According to error message, it looks like clangTidyCustomModule does not be linked. Are there anyone can reproduce this build issue?

@ingomueller-net
Copy link
Contributor

I can reproduce locally. This only happens with the CMake build, so it is unrelated to #159289, which fixed the bazel build. I'll take a look into the CMake targets now.

ingomueller-net added a commit that referenced this pull request Sep 17, 2025
ingomueller-net added a commit that referenced this pull request Sep 17, 2025
ingomueller-net added a commit that referenced this pull request Sep 17, 2025
Reverts #131804.

This breaks a build bot; see discussion in the original PR. I could
reproduce this problem locally. The problem is that the original PR
makes use of `registerCustomChecks` in `ClangTidy.cpp` but does not add
the new custom module to the dependencies of the target that builds that
file. Adding the dependency would create a cyclic dependency, so the fix
doesn't seem obvious. See details in the PR description.
ingomueller-net added a commit that referenced this pull request Sep 17, 2025
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request Sep 17, 2025
…59380)

Reverts llvm/llvm-project#131804.

This breaks a build bot; see discussion in the original PR. I could
reproduce this problem locally. The problem is that the original PR
makes use of `registerCustomChecks` in `ClangTidy.cpp` but does not add
the new custom module to the dependencies of the target that builds that
file. Adding the dependency would create a cyclic dependency, so the fix
doesn't seem obvious. See details in the PR description.
@HerrCai0907 HerrCai0907 restored the users/ccc/clang-tidy/query-check branch September 18, 2025 09:04
HerrCai0907 added a commit that referenced this pull request Sep 18, 2025
@llvm-ci
Copy link
Collaborator

llvm-ci commented Sep 19, 2025

LLVM Buildbot has detected a new failure on builder clang-ppc64le-linux-multistage running on ppc64le-clang-multistage-test while building clang-tools-extra at step 4 "build stage 1".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/76/builds/12911

Here is the relevant piece of the build log for the reference
Step 4 (build stage 1) failure: 'ninja' (failure)
...
[5929/6523] Building CXX object tools/clang/tools/extra/clang-tidy/modernize/CMakeFiles/obj.clangTidyModernizeModule.dir/MakeSmartPtrCheck.cpp.o
[5930/6523] Building CXX object tools/clang/tools/extra/clang-tidy/misc/CMakeFiles/obj.clangTidyMiscModule.dir/StaticAssertCheck.cpp.o
[5931/6523] Building CXX object tools/clang/tools/extra/clang-tidy/modernize/CMakeFiles/obj.clangTidyModernizeModule.dir/UseEmplaceCheck.cpp.o
[5932/6523] Building CXX object tools/clang/tools/extra/clang-tidy/modernize/CMakeFiles/obj.clangTidyModernizeModule.dir/UseEqualsDefaultCheck.cpp.o
[5933/6523] Building CXX object tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidy.cpp.o
[5934/6523] Linking CXX executable bin/llvm-exegesis
[5935/6523] Building CXX object tools/clang/tools/extra/clang-tidy/bugprone/CMakeFiles/obj.clangTidyBugproneModule.dir/UnhandledSelfAssignmentCheck.cpp.o
[5936/6523] Building CXX object tools/clang/tools/extra/clangd/CMakeFiles/obj.clangDaemon.dir/TidyProvider.cpp.o
[5937/6523] Building CXX object tools/clang/tools/extra/clang-tidy/bugprone/CMakeFiles/obj.clangTidyBugproneModule.dir/StringviewNullptrCheck.cpp.o
[5938/6523] Linking CXX shared library lib/libclangTidy.so.22.0git
FAILED: lib/libclangTidy.so.22.0git 
: && /usr/lib64/ccache/c++ -fPIC -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wno-missing-field-initializers -pedantic -Wno-long-long -Wimplicit-fallthrough -Wno-uninitialized -Wno-nonnull -Wno-class-memaccess -Wno-array-bounds -Wno-noexcept-type -Wdelete-non-virtual-dtor -Wno-comment -Wno-misleading-indentation -fdiagnostics-color -ffunction-sections -fdata-sections -fno-common -Woverloaded-virtual -O3 -DNDEBUG  -Wl,-z,defs -Wl,-z,nodelete   -Wl,-rpath-link,/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/stage1/./lib  -Wl,--gc-sections -shared -Wl,-soname,libclangTidy.so.22.0git -o lib/libclangTidy.so.22.0git tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidy.cpp.o tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidyCheck.cpp.o tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidyModule.cpp.o tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidyDiagnosticConsumer.cpp.o tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidyOptions.cpp.o tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidyProfiling.cpp.o tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ExpandModularHeadersPPCallbacks.cpp.o tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/GlobList.cpp.o tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/NoLintDirectiveHandler.cpp.o  -Wl,-rpath,"\$ORIGIN/../lib:/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/stage1/lib:"  lib/libclangTooling.so.22.0git  lib/libclangStaticAnalyzerFrontend.so.22.0git  lib/libclangStaticAnalyzerCore.so.22.0git  lib/libclangFormat.so.22.0git  lib/libclangFrontend.so.22.0git  lib/libclangSerialization.so.22.0git  lib/libclangToolingCore.so.22.0git  lib/libclangRewrite.so.22.0git  lib/libclangAnalysis.so.22.0git  lib/libclangASTMatchers.so.22.0git  lib/libclangAST.so.22.0git  lib/libclangLex.so.22.0git  lib/libclangBasic.so.22.0git  lib/libLLVMFrontendOpenMP.so.22.0git  lib/libLLVMSupport.so.22.0git  -Wl,-rpath-link,/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-multistage-test/clang-ppc64le-multistage/stage1/lib && :
tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidy.cpp.o: In function `clang::tidy::ClangTidyASTConsumerFactory::ClangTidyASTConsumerFactory(clang::tidy::ClangTidyContext&, llvm::IntrusiveRefCntPtr<llvm::vfs::OverlayFileSystem>) [clone .localalias.3]':
ClangTidy.cpp:(.text._ZN5clang4tidy27ClangTidyASTConsumerFactoryC2ERNS0_16ClangTidyContextEN4llvm18IntrusiveRefCntPtrINS4_3vfs17OverlayFileSystemEEE+0x168): undefined reference to `clang::tidy::custom::registerCustomChecks(clang::tidy::ClangTidyOptions const&, clang::tidy::ClangTidyCheckFactories&)'
tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidy.cpp.o: In function `clang::tidy::ClangTidyASTConsumerFactory::createASTConsumer(clang::CompilerInstance&, llvm::StringRef) [clone .localalias.2]':
ClangTidy.cpp:(.text._ZN5clang4tidy27ClangTidyASTConsumerFactory17createASTConsumerERNS_16CompilerInstanceEN4llvm9StringRefE+0x8d0): undefined reference to `clang::tidy::custom::registerCustomChecks(clang::tidy::ClangTidyOptions const&, clang::tidy::ClangTidyCheckFactories&)'
tools/clang/tools/extra/clang-tidy/CMakeFiles/obj.clangTidy.dir/ClangTidy.cpp.o: In function `clang::tidy::getAllChecksAndOptions(bool, bool)':
ClangTidy.cpp:(.text._ZN5clang4tidy22getAllChecksAndOptionsEbb+0x920): undefined reference to `clang::tidy::custom::registerCustomChecks(clang::tidy::ClangTidyOptions const&, clang::tidy::ClangTidyCheckFactories&)'
collect2: error: ld returned 1 exit status
[5939/6523] Building CXX object tools/clang/tools/extra/clang-tidy/modernize/CMakeFiles/obj.clangTidyModernizeModule.dir/ModernizeTidyModule.cpp.o
[5940/6523] Building CXX object tools/clang/tools/extra/clang-tidy/bugprone/CMakeFiles/obj.clangTidyBugproneModule.dir/UseAfterMoveCheck.cpp.o
[5941/6523] Building CXX object tools/clang/tools/extra/clang-tidy/bugprone/CMakeFiles/obj.clangTidyBugproneModule.dir/BugproneTidyModule.cpp.o
[5942/6523] Linking CXX shared library lib/libclangCodeGen.so.22.0git
[5943/6523] Building CXX object tools/clang/tools/extra/clang-tidy/bugprone/CMakeFiles/obj.clangTidyBugproneModule.dir/NotNullTerminatedResultCheck.cpp.o
[5944/6523] Building CXX object tools/clang/tools/extra/clangd/CMakeFiles/obj.clangDaemon.dir/ConfigCompile.cpp.o
[5945/6523] Building AMDGPUGenAsmMatcher.inc...
[5946/6523] Building CXX object tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/RemoveUsingNamespace.cpp.o
[5947/6523] Building CXX object tools/clang/tools/extra/clangd/refactor/tweaks/CMakeFiles/obj.clangDaemonTweaks.dir/AddUsing.cpp.o
[5948/6523] Building CXX object tools/clang/tools/extra/clangd/CMakeFiles/obj.clangDaemon.dir/Compiler.cpp.o
[5949/6523] Building CXX object tools/clang/tools/extra/clang-tidy/bugprone/CMakeFiles/obj.clangTidyBugproneModule.dir/BranchCloneCheck.cpp.o
[5950/6523] Building CXX object tools/clang/tools/extra/clangd/CMakeFiles/obj.clangDaemon.dir/refactor/Rename.cpp.o
[5951/6523] Building CXX object tools/clang/tools/extra/clang-tidy/readability/CMakeFiles/obj.clangTidyReadabilityModule.dir/FunctionSizeCheck.cpp.o
[5952/6523] Building CXX object tools/clang/tools/extra/clang-tidy/readability/CMakeFiles/obj.clangTidyReadabilityModule.dir/ConvertMemberFunctionsToStatic.cpp.o
[5953/6523] Building CXX object tools/clang/tools/extra/clang-tidy/readability/CMakeFiles/obj.clangTidyReadabilityModule.dir/SimplifyBooleanExprCheck.cpp.o
[5954/6523] Building CXX object tools/clang/tools/extra/clang-tidy/readability/CMakeFiles/obj.clangTidyReadabilityModule.dir/MakeMemberFunctionConstCheck.cpp.o
[5955/6523] Building CXX object tools/clang/tools/extra/clangd/CMakeFiles/obj.clangDaemon.dir/HeaderSourceSwitch.cpp.o
[5956/6523] Building CXX object tools/clang/tools/extra/clang-tidy/modernize/CMakeFiles/obj.clangTidyModernizeModule.dir/UseTrailingReturnTypeCheck.cpp.o
[5957/6523] Building CXX object tools/clang/tools/extra/clang-tidy/utils/CMakeFiles/obj.clangTidyUtils.dir/RenamerClangTidyCheck.cpp.o
[5958/6523] Building CXX object tools/clang/tools/extra/clangd/CMakeFiles/obj.clangDaemon.dir/ASTSignals.cpp.o
[5959/6523] Building CXX object tools/clang/tools/extra/clangd/CMakeFiles/obj.clangDaemon.dir/Quality.cpp.o
[5960/6523] Building CXX object tools/clang/tools/extra/clangd/CMakeFiles/obj.clangDaemon.dir/SemanticSelection.cpp.o
[5961/6523] Building CXX object tools/clang/tools/extra/clangd/CMakeFiles/obj.clangDaemon.dir/index/StdLib.cpp.o
[5962/6523] Building CXX object tools/clang/tools/extra/clangd/CMakeFiles/obj.clangDaemon.dir/Headers.cpp.o
[5963/6523] Building CXX object tools/clang/tools/extra/clang-tidy/misc/CMakeFiles/obj.clangTidyMiscModule.dir/UnusedParametersCheck.cpp.o
[5964/6523] Building CXX object tools/clang/tools/extra/clangd/CMakeFiles/obj.clangDaemon.dir/IncludeCleaner.cpp.o
[5965/6523] Building CXX object tools/clang/tools/extra/clangd/CMakeFiles/obj.clangDaemon.dir/SourceCode.cpp.o
[5966/6523] Building AMDGPUGenRegisterInfo.inc...
[5967/6523] Building CXX object tools/clang/tools/extra/clangd/CMakeFiles/obj.clangDaemon.dir/index/FileIndex.cpp.o
[5968/6523] Building CXX object tools/clang/tools/extra/clangd/CMakeFiles/obj.clangDaemon.dir/refactor/Tweak.cpp.o

HerrCai0907 added a commit that referenced this pull request Sep 19, 2025
reapply #131804 and #159289
Fixed cmake link issue.

---------

Co-authored-by: DeNiCoN <[email protected]>
Co-authored-by: Baranov Victor <[email protected]>
@nico
Copy link
Contributor

nico commented Sep 19, 2025

Edit: This is now at #159547 (comment)

@olologin
Copy link

olologin commented Oct 1, 2025

Thanks to everyone involved! I am happy to see this merged!

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.