Skip to content

Add checks to convert std library iterator algorithms into c++20 or boost ranges #97764

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 8, 2024

Conversation

njames93
Copy link
Member

@njames93 njames93 commented Jul 4, 2024

No description provided.

@llvmbot
Copy link
Member

llvmbot commented Jul 4, 2024

@llvm/pr-subscribers-clang-tidy

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

Author: Nathan James (njames93)

Changes

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

17 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/boost/BoostTidyModule.cpp (+2)
  • (modified) clang-tools-extra/clang-tidy/boost/CMakeLists.txt (+1)
  • (added) clang-tools-extra/clang-tidy/boost/UseRangesCheck.cpp (+208)
  • (added) clang-tools-extra/clang-tidy/boost/UseRangesCheck.h (+34)
  • (modified) clang-tools-extra/clang-tidy/modernize/CMakeLists.txt (+1)
  • (modified) clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp (+2)
  • (added) clang-tools-extra/clang-tidy/modernize/UseRangesCheck.cpp (+148)
  • (added) clang-tools-extra/clang-tidy/modernize/UseRangesCheck.h (+31)
  • (modified) clang-tools-extra/clang-tidy/utils/CMakeLists.txt (+1)
  • (added) clang-tools-extra/clang-tidy/utils/UseRangesCheck.cpp (+253)
  • (added) clang-tools-extra/clang-tidy/utils/UseRangesCheck.h (+58)
  • (modified) clang-tools-extra/docs/ReleaseNotes.rst (+12)
  • (added) clang-tools-extra/docs/clang-tidy/checks/boost/use-ranges.rst (+24)
  • (modified) clang-tools-extra/docs/clang-tidy/checks/list.rst (+2)
  • (added) clang-tools-extra/docs/clang-tidy/checks/modernize/use-ranges.rst (+24)
  • (added) clang-tools-extra/test/clang-tidy/checkers/boost/use-ranges.cpp (+132)
  • (added) clang-tools-extra/test/clang-tidy/checkers/modernize/use-ranges.cpp (+171)
diff --git a/clang-tools-extra/clang-tidy/boost/BoostTidyModule.cpp b/clang-tools-extra/clang-tidy/boost/BoostTidyModule.cpp
index 4c5808daa6ae7..79d0e380e402d 100644
--- a/clang-tools-extra/clang-tidy/boost/BoostTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/boost/BoostTidyModule.cpp
@@ -9,6 +9,7 @@
 #include "../ClangTidy.h"
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
+#include "UseRangesCheck.h"
 #include "UseToStringCheck.h"
 using namespace clang::ast_matchers;
 
@@ -18,6 +19,7 @@ namespace boost {
 class BoostModule : public ClangTidyModule {
 public:
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
+    CheckFactories.registerCheck<UseRangesCheck>("boost-use-ranges");
     CheckFactories.registerCheck<UseToStringCheck>("boost-use-to-string");
   }
 };
diff --git a/clang-tools-extra/clang-tidy/boost/CMakeLists.txt b/clang-tools-extra/clang-tidy/boost/CMakeLists.txt
index 167b6fab774b7..fed3c3ba01c16 100644
--- a/clang-tools-extra/clang-tidy/boost/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/boost/CMakeLists.txt
@@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS
 
 add_clang_library(clangTidyBoostModule
   BoostTidyModule.cpp
+  UseRangesCheck.cpp
   UseToStringCheck.cpp
 
   LINK_LIBS
diff --git a/clang-tools-extra/clang-tidy/boost/UseRangesCheck.cpp b/clang-tools-extra/clang-tidy/boost/UseRangesCheck.cpp
new file mode 100644
index 0000000000000..eb9e9a262d63a
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/boost/UseRangesCheck.cpp
@@ -0,0 +1,208 @@
+//===--- UseRangesCheck.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 "UseRangesCheck.h"
+#include "clang/AST/Decl.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/StringRef.h"
+#include <initializer_list>
+#include <string>
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::boost {
+
+namespace {
+/// Base replacer that handles the boost include path and namespace
+class BoostReplacer : public UseRangesCheck::Replacer {
+public:
+  BoostReplacer(ArrayRef<ArrayRef<Indexes>> Signature, bool IncludeSystem)
+      : Signature(Signature), IncludeSystem(IncludeSystem) {}
+
+  ArrayRef<ArrayRef<Indexes>> getReplacementSignatures() const final {
+    return Signature;
+  }
+
+  virtual std::pair<StringRef, StringRef>
+  getBoostName(const NamedDecl &OriginalName) const = 0;
+  virtual std::pair<StringRef, StringRef>
+  getBoostHeader(const NamedDecl &OriginalName) const = 0;
+
+  std::string getReplaceName(const NamedDecl &OriginalName) const final {
+    auto [Namespace, Function] = getBoostName(OriginalName);
+    return ("boost::" + Namespace + (Namespace.empty() ? "" : "::") + Function)
+        .str();
+  }
+
+  std::optional<std::string>
+  getHeaderInclusion(const NamedDecl &OriginalName) const final {
+    auto [Path, HeaderName] = getBoostHeader(OriginalName);
+    return ((IncludeSystem ? "<boost/" : "boost/") + Path +
+            (Path.empty() ? "" : "/") + HeaderName +
+            (IncludeSystem ? ".hpp>" : ".hpp"))
+        .str();
+  }
+
+private:
+  ArrayRef<ArrayRef<Indexes>> Signature;
+  bool IncludeSystem;
+};
+
+/// Creates replaces where the header file lives in
+/// `boost/algorithm/<FUNC_NAME>.hpp and the function is named
+/// `boost::range::<FUNC_NAME>`
+class BoostRangeAlgorithmReplacer : public BoostReplacer {
+public:
+  using BoostReplacer::BoostReplacer;
+  std::pair<StringRef, StringRef>
+  getBoostName(const NamedDecl &OriginalName) const override {
+    return {"range", OriginalName.getName()};
+  }
+
+  std::pair<StringRef, StringRef>
+  getBoostHeader(const NamedDecl &OriginalName) const override {
+    return {"range/algorithm", OriginalName.getName()};
+  }
+};
+
+/// Creates replaces where the header file lives in
+/// `boost/algorithm/<CUSTOM_HEADER>.hpp and the function is named
+/// `boost::range::<FUNC_NAME>`
+class CustomBoostAlgorithmHeaderReplacer : public BoostRangeAlgorithmReplacer {
+public:
+  CustomBoostAlgorithmHeaderReplacer(StringRef HeaderName,
+                                     ArrayRef<ArrayRef<Indexes>> Signature,
+                                     bool IncludeSystem)
+      : BoostRangeAlgorithmReplacer(Signature, IncludeSystem),
+        HeaderName(HeaderName) {}
+
+  std::pair<StringRef, StringRef>
+  getBoostHeader(const NamedDecl & /*OriginalName*/) const override {
+    return {"range/algorithm", HeaderName};
+  }
+
+private:
+  StringRef HeaderName;
+};
+
+/// Creates replaces where the header file lives in
+/// `boost/algorithm/<SUB_HEADER>.hpp and the function is named
+/// `boost::algorithm::<FUNC_NAME>`
+class BoostAlgorithmReplacer : public BoostReplacer {
+public:
+  BoostAlgorithmReplacer(StringRef SubHeader,
+                         ArrayRef<ArrayRef<Indexes>> Signature,
+                         bool IncludeSystem)
+      : BoostReplacer(Signature, IncludeSystem),
+        SubHeader(("algorithm/" + SubHeader).str()) {}
+  std::pair<StringRef, StringRef>
+  getBoostName(const NamedDecl &OriginalName) const override {
+    return {"algorithm", OriginalName.getName()};
+  }
+
+  std::pair<StringRef, StringRef>
+  getBoostHeader(const NamedDecl &OriginalName) const override {
+    return {SubHeader, OriginalName.getName()};
+  }
+
+  std::string SubHeader;
+};
+
+/// Creates replaces where the header file lives in
+/// `boost/algorithm/<SUB_HEADER>/<HEADER_NAME>.hpp and the function is named
+/// `boost::algorithm::<FUNC_NAME>`
+class CustomBoostAlgorithmReplacer : public BoostReplacer {
+public:
+  CustomBoostAlgorithmReplacer(StringRef SubHeader, StringRef HeaderName,
+                               ArrayRef<ArrayRef<Indexes>> Signature,
+                               bool IncludeSystem)
+      : BoostReplacer(Signature, IncludeSystem),
+        SubHeader(("algorithm/" + SubHeader).str()), HeaderName(HeaderName) {}
+  std::pair<StringRef, StringRef>
+  getBoostName(const NamedDecl &OriginalName) const override {
+    return {"algorithm", OriginalName.getName()};
+  }
+
+  std::pair<StringRef, StringRef>
+  getBoostHeader(const NamedDecl & /*OriginalName*/) const override {
+    return {SubHeader, HeaderName};
+  }
+
+  std::string SubHeader;
+  StringRef HeaderName;
+};
+
+} // namespace
+
+utils::UseRangesCheck::ReplacerMap UseRangesCheck::GetReplacerMap() const {
+
+  ReplacerMap Results;
+  static const Replacer::Indexes SingleSig[] = {{0}};
+  static const Replacer::Indexes TwoSig[] = {{0}, {2}};
+  static const ArrayRef<Replacer::Indexes> Single = {SingleSig};
+  static const ArrayRef<Replacer::Indexes> Two = {TwoSig};
+  static const auto Add =
+      [&Results](llvm::IntrusiveRefCntPtr<BoostReplacer> Replacer,
+                 std::initializer_list<StringRef> Names) {
+        for (const auto &Name : Names) {
+          Results.try_emplace(("::std::" + Name).str(), Replacer);
+        }
+      };
+
+  Add(llvm::makeIntrusiveRefCnt<CustomBoostAlgorithmHeaderReplacer>(
+          "set_algorithm", Two, IncludeBoostSystem),
+      {"includes", "set_union", "set_intersection", "set_difference",
+       "set_symmetric_difference"});
+  Add(llvm::makeIntrusiveRefCnt<BoostRangeAlgorithmReplacer>(
+          Single, IncludeBoostSystem),
+      {"unique",         "lower_bound",   "stable_sort",
+       "equal_range",    "remove_if",     "sort",
+       "random_shuffle", "remove_copy",   "stable_partition",
+       "remove_copy_if", "count",         "copy_backward",
+       "reverse_copy",   "adjacent_find", "remove",
+       "upper_bound",    "binary_search", "replace_copy_if",
+       "for_each",       "generate",      "count_if",
+       "min_element",    "reverse",       "replace_copy",
+       "fill",           "unique_copy",   "transform",
+       "copy",           "replace",       "find",
+       "replace_if",     "find_if",       "partition",
+       "max_element"});
+  Add(llvm::makeIntrusiveRefCnt<BoostRangeAlgorithmReplacer>(
+          Two, IncludeBoostSystem),
+      {"find_end", "merge", "partial_sort_copy", "find_first_of", "search",
+       "lexicographical_compare", "equal", "mismatch"});
+  Add(llvm::makeIntrusiveRefCnt<CustomBoostAlgorithmHeaderReplacer>(
+          "permutation", Single, IncludeBoostSystem),
+      {"next_permutation", "prev_permutation"});
+  Add(llvm::makeIntrusiveRefCnt<CustomBoostAlgorithmHeaderReplacer>(
+          "heap_algorithm", Single, IncludeBoostSystem),
+      {"push_heap", "pop_heap", "make_heap", "sort_heap"});
+  Add(llvm::makeIntrusiveRefCnt<BoostAlgorithmReplacer>("cxx11", Single,
+                                                        IncludeBoostSystem),
+      {"copy_if", "is_permutation", "is_partitioned", "find_if_not",
+       "partition_copy", "any_of", "iota", "all_of", "partition_point",
+       "is_sorted", "none_of"});
+  Add(llvm::makeIntrusiveRefCnt<CustomBoostAlgorithmReplacer>(
+          "cxx11", "is_sorted", Single, IncludeBoostSystem),
+      {"is_sorted_until"});
+  Add(llvm::makeIntrusiveRefCnt<BoostAlgorithmReplacer>("cxx17", Single,
+                                                        IncludeBoostSystem),
+      {"reduce"});
+
+  return Results;
+}
+
+UseRangesCheck::UseRangesCheck(StringRef Name, ClangTidyContext *Context)
+    : utils::UseRangesCheck(Name, Context),
+      IncludeBoostSystem(Options.get("IncludeBoostSystem", true)) {}
+
+void UseRangesCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
+  utils::UseRangesCheck::storeOptions(Opts);
+  Options.store(Opts, "IncludeBoostSystem", IncludeBoostSystem);
+}
+} // namespace clang::tidy::boost
diff --git a/clang-tools-extra/clang-tidy/boost/UseRangesCheck.h b/clang-tools-extra/clang-tidy/boost/UseRangesCheck.h
new file mode 100644
index 0000000000000..8ae21e2c5262b
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/boost/UseRangesCheck.h
@@ -0,0 +1,34 @@
+//===--- UseRangesCheck.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_BOOST_USERANGESCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BOOST_USERANGESCHECK_H
+
+#include "../utils/UseRangesCheck.h"
+
+namespace clang::tidy::boost {
+
+/// FIXME: Write a short description.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/boost/use-ranges.html
+class UseRangesCheck : public utils::UseRangesCheck {
+public:
+  UseRangesCheck(StringRef Name, ClangTidyContext *Context);
+
+  void storeOptions(ClangTidyOptions::OptionMap &Options) override;
+
+  ReplacerMap GetReplacerMap() const override;
+
+private:
+  bool IncludeBoostSystem;
+};
+
+} // namespace clang::tidy::boost
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BOOST_USERANGESCHECK_H
diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index 576805c4c7f18..4f68c487cac9d 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -40,6 +40,7 @@ add_clang_library(clangTidyModernizeModule
   UseNoexceptCheck.cpp
   UseNullptrCheck.cpp
   UseOverrideCheck.cpp
+  UseRangesCheck.cpp
   UseStartsEndsWithCheck.cpp
   UseStdFormatCheck.cpp
   UseStdNumbersCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
index b9c7a2dc383e8..1860759332063 100644
--- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
@@ -41,6 +41,7 @@
 #include "UseNoexceptCheck.h"
 #include "UseNullptrCheck.h"
 #include "UseOverrideCheck.h"
+#include "UseRangesCheck.h"
 #include "UseStartsEndsWithCheck.h"
 #include "UseStdFormatCheck.h"
 #include "UseStdNumbersCheck.h"
@@ -75,6 +76,7 @@ class ModernizeModule : public ClangTidyModule {
     CheckFactories.registerCheck<PassByValueCheck>("modernize-pass-by-value");
     CheckFactories.registerCheck<UseDesignatedInitializersCheck>(
         "modernize-use-designated-initializers");
+    CheckFactories.registerCheck<UseRangesCheck>("modernize-use-ranges");
     CheckFactories.registerCheck<UseStartsEndsWithCheck>(
         "modernize-use-starts-ends-with");
     CheckFactories.registerCheck<UseStdFormatCheck>("modernize-use-std-format");
diff --git a/clang-tools-extra/clang-tidy/modernize/UseRangesCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseRangesCheck.cpp
new file mode 100644
index 0000000000000..e40428a8217b7
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/UseRangesCheck.cpp
@@ -0,0 +1,148 @@
+//===--- UseRangesCheck.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 "UseRangesCheck.h"
+#include "clang/AST/Decl.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang::tidy::modernize {
+
+utils::UseRangesCheck::ReplacerMap UseRangesCheck::GetReplacerMap() const {
+  class StdReplacer : public utils::UseRangesCheck::Replacer {
+  public:
+    explicit StdReplacer(ArrayRef<ArrayRef<Indexes>> Indexes)
+        : Indexes(Indexes) {}
+    std::string getReplaceName(const NamedDecl &OriginalName) const override {
+      return ("std::ranges::" + OriginalName.getName()).str();
+    }
+    ArrayRef<ArrayRef<Indexes>> getReplacementSignatures() const override {
+      return Indexes;
+    }
+    std::optional<std::string>
+    getHeaderInclusion(const NamedDecl &OriginalName) const override {
+      return "<algorithm>";
+    }
+
+  private:
+    ArrayRef<ArrayRef<Indexes>> Indexes;
+  };
+  using Indexes = UseRangesCheck::Replacer::Indexes;
+  // using Signatures = Signature[];
+  utils::UseRangesCheck::ReplacerMap Result;
+  // template<typename Iter> Func(Iter first, Iter last,...).
+  static const Indexes SingleRangeArgs[] = {{0}};
+  // template<typename Policy, typename Iter>
+  // Func(Policy policy, Iter first, // Iter last,...).
+  static const Indexes SingleRangeExecPolicy[] = {{1}};
+  // template<typename Iter1, typename Iter2>
+  // Func(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2,...).
+  static const Indexes TwoRangeArgs[] = {{0}, {2}};
+  // template<typename Policy, typename Iter1, typename Iter2>
+  // Func(Policy policy, Iter1 first1, Iter1 last1, Iter2 first2, Iter2
+  // last2,...).
+  static const Indexes TwoRangeExecPolicy[] = {{1}, {3}};
+
+  static const ArrayRef<Indexes> SingleRangeFunc[] = {SingleRangeArgs};
+
+  static const ArrayRef<Indexes> SingleRangeExecFunc[] = {
+      SingleRangeArgs, SingleRangeExecPolicy};
+  static const ArrayRef<Indexes> TwoRangeExecFunc[] = {TwoRangeArgs,
+                                                       TwoRangeExecPolicy};
+  static const ArrayRef<Indexes> OneOrTwoFunc[] = {SingleRangeArgs,
+                                                   TwoRangeArgs};
+  static const ArrayRef<Indexes> OneOrTwoExecFunc[] = {
+      SingleRangeArgs, SingleRangeExecPolicy, TwoRangeArgs, TwoRangeExecPolicy};
+
+  static const std::pair<ArrayRef<ArrayRef<Indexes>>, ArrayRef<StringRef>>
+      Names[] = {
+          {SingleRangeFunc,
+           {"all_of",
+            "any_of",
+            "none_of",
+            "for_each",
+            "find",
+            "find_if",
+            "find_if_not",
+            "adjacent_find",
+            "copy",
+            "copy_if",
+            "copy_backward",
+            "move",
+            "move_backward",
+            "fill",
+            "transform",
+            "replace",
+            "replace_if",
+            "generate",
+            "remove",
+            "remove_if",
+            "remove_copy",
+            "remove_copy_if",
+            "unique",
+            "unique_copy",
+            "sample",
+            "partition_point",
+            "lower_bound",
+            "upper_bound",
+            "equal_range",
+            "binary_search",
+            "push_heap",
+            "pop_heap",
+            "make_heap",
+            "sort_heap",
+            "next_permutation",
+            "prev_permutation",
+            "iota"}},
+          {SingleRangeExecFunc,
+           {"reverse",
+            "reverse_copy",
+            "shift_left",
+            "shift_right",
+            "is_partitioned",
+            "partition",
+            "partition_copy",
+            "stable_partition",
+            "sort",
+            "stable_sort",
+            "is_sorted",
+            "is_sorted_until",
+            "is_heap",
+            "is_heap_until",
+            "max_element",
+            "min_element",
+            "minmax_element",
+            "uninitialized_copy",
+            "uninitialized_fill",
+            "uninitialized_move",
+            "uninitialized_default_construct",
+            "uninitialized_value_construct",
+            "destroy"}},
+          {TwoRangeExecFunc,
+           {"partial_sort_copy", "includes", "set_union", "set_intersection",
+            "set_difference", "set_symmetric_difference", "merge",
+            "lexicographical_compare", "find_end", "search"}},
+          {OneOrTwoFunc, {"is_permutation"}},
+          {OneOrTwoExecFunc, {"equal", "mismatch"}}};
+  SmallString<64> Buff;
+  for (const auto &[Signature, Values] : Names) {
+    auto Replacer = llvm::makeIntrusiveRefCnt<StdReplacer>(Signature);
+    for (const auto &Name : Values) {
+      Buff.clear();
+      Result.try_emplace(("::std::" + Name).toStringRef(Buff), Replacer);
+    }
+  }
+  return Result;
+}
+
+bool UseRangesCheck::isLanguageVersionSupported(
+    const LangOptions &LangOpts) const {
+  return LangOpts.CPlusPlus20;
+}
+} // namespace clang::tidy::modernize
diff --git a/clang-tools-extra/clang-tidy/modernize/UseRangesCheck.h b/clang-tools-extra/clang-tidy/modernize/UseRangesCheck.h
new file mode 100644
index 0000000000000..4cb82016d45cf
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/UseRangesCheck.h
@@ -0,0 +1,31 @@
+//===--- UseRangesCheck.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_MODERNIZE_USERANGESCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USERANGESCHECK_H
+
+#include "../utils/UseRangesCheck.h"
+
+namespace clang::tidy::modernize {
+
+/// Detects calls to standard library iterator algorithms that could be
+/// replaced with a ranges version instead
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/modernize/use-ranges.html
+class UseRangesCheck : public utils::UseRangesCheck {
+public:
+  using utils::UseRangesCheck::UseRangesCheck;
+
+  ReplacerMap GetReplacerMap() const override;
+  bool isLanguageVersionSupported(const LangOptions &LangOpts) const override;
+};
+
+} // namespace clang::tidy::modernize
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USERANGESCHECK_H
diff --git a/clang-tools-extra/clang-tidy/utils/CMakeLists.txt b/clang-tools-extra/clang-tidy/utils/CMakeLists.txt
index 9cff7d475425d..1841ea981359c 100644
--- a/clang-tools-extra/clang-tidy/utils/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/utils/CMakeLists.txt
@@ -26,6 +26,7 @@ add_clang_library(clangTidyUtils
   TransformerClangTidyCheck.cpp
   TypeTraits.cpp
   UsingInserter.cpp
+  UseRangesCheck.cpp
 
   LINK_LIBS
   clangTidy
diff --git a/clang-tools-extra/clang-tidy/utils/UseRangesCheck.cpp b...
[truncated]

Copy link
Member

@PiotrZSL PiotrZSL left a comment

Choose a reason for hiding this comment

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

Few nits. Mainly documentation require some love.

@PiotrZSL PiotrZSL requested a review from 5chmidti July 5, 2024 07:42
Copy link

github-actions bot commented Jul 5, 2024

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

@njames93 njames93 force-pushed the tidy-use-ranges branch 2 times, most recently from e23f13c to a8beb1e Compare July 5, 2024 10:16
@njames93 njames93 force-pushed the tidy-use-ranges branch 2 times, most recently from 9b4439c to 9f24645 Compare July 5, 2024 15:08
Copy link
Contributor

@5chmidti 5chmidti left a comment

Choose a reason for hiding this comment

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

This will be great to have.

It should be possible to add support for template function decls in a follow-up. Maybe this should be documented to avoid confusion?

@njames93 njames93 force-pushed the tidy-use-ranges branch 2 times, most recently from d1f1f72 to 071f243 Compare July 7, 2024 09:55

If `true` the boost headers are included as system headers with angle
brackets (`#include <boost.hpp>`), otherwise quotes are used
(`#include "boost.hpp"`).
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing default value.

@njames93
Copy link
Member Author

njames93 commented Jul 7, 2024

  • Added some more functions for boost/range/numeric
  • Added support for Reverse range iteration

njames93 added 2 commits July 7, 2024 15:07
Akin to the modernize-use-ranges check but good for users of older
toolchains who can't use c++20 ranges and rely on boost instead
Copy link
Member

@PiotrZSL PiotrZSL left a comment

Choose a reason for hiding this comment

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

Looks good enough for me.

Note: Prefer pushing changes in additional commits instead of merge + rebase, it's easier to track what changed between first review and fixes.

@njames93
Copy link
Member Author

njames93 commented Jul 8, 2024

I no longer have commit access, would you do the honours instead

@PiotrZSL
Copy link
Member

PiotrZSL commented Jul 8, 2024

@njames93 You should be able to merge, if not get, commit access renewed, after all you still an owner of this tool.

@PiotrZSL PiotrZSL merged commit 1038db6 into llvm:main Jul 8, 2024
8 checks passed
@njames93 njames93 deleted the tidy-use-ranges branch July 8, 2024 19:19
@HighCommander4
Copy link
Collaborator

FYI, the new boost-use-ranges check is pretty crashy in clangd (#109037, #109367, clangd/clangd#2173, clangd/clangd#2151).

@hia3
Copy link

hia3 commented Oct 5, 2024

It crashes most likely because a local variable is captured in the static lambda.

[&Results](llvm::IntrusiveRefCntPtr<UseRangesCheck::Replacer> Replacer,

@HighCommander4
Copy link
Collaborator

It crashes most likely because a local variable is captured in the static lambda.

[&Results](llvm::IntrusiveRefCntPtr<UseRangesCheck::Replacer> Replacer,

Nice find! That does seem to be the problem. I've put up a fix at #111282.

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.

7 participants