Skip to content

Commit ad55d54

Browse files
committed
Add a modernize-use-ranges check
1 parent f190343 commit ad55d54

File tree

11 files changed

+724
-0
lines changed

11 files changed

+724
-0
lines changed

clang-tools-extra/clang-tidy/modernize/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ add_clang_library(clangTidyModernizeModule
4040
UseNoexceptCheck.cpp
4141
UseNullptrCheck.cpp
4242
UseOverrideCheck.cpp
43+
UseRangesCheck.cpp
4344
UseStartsEndsWithCheck.cpp
4445
UseStdFormatCheck.cpp
4546
UseStdNumbersCheck.cpp

clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "UseNoexceptCheck.h"
4242
#include "UseNullptrCheck.h"
4343
#include "UseOverrideCheck.h"
44+
#include "UseRangesCheck.h"
4445
#include "UseStartsEndsWithCheck.h"
4546
#include "UseStdFormatCheck.h"
4647
#include "UseStdNumbersCheck.h"
@@ -75,6 +76,7 @@ class ModernizeModule : public ClangTidyModule {
7576
CheckFactories.registerCheck<PassByValueCheck>("modernize-pass-by-value");
7677
CheckFactories.registerCheck<UseDesignatedInitializersCheck>(
7778
"modernize-use-designated-initializers");
79+
CheckFactories.registerCheck<UseRangesCheck>("modernize-use-ranges");
7880
CheckFactories.registerCheck<UseStartsEndsWithCheck>(
7981
"modernize-use-starts-ends-with");
8082
CheckFactories.registerCheck<UseStdFormatCheck>("modernize-use-std-format");
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
//===--- UseRangesCheck.cpp - clang-tidy ----------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "UseRangesCheck.h"
10+
#include "clang/AST/Decl.h"
11+
#include "llvm/ADT/ArrayRef.h"
12+
#include "llvm/ADT/IntrusiveRefCntPtr.h"
13+
#include "llvm/ADT/SmallVector.h"
14+
#include "llvm/ADT/StringRef.h"
15+
16+
namespace clang::tidy::modernize {
17+
18+
utils::UseRangesCheck::ReplacerMap UseRangesCheck::getReplacerMap() const {
19+
class StdReplacer : public utils::UseRangesCheck::Replacer {
20+
public:
21+
explicit StdReplacer(SmallVector<UseRangesCheck::Signature> Indexes)
22+
: Indexes(std::move(Indexes)) {}
23+
std::string getReplaceName(const NamedDecl &OriginalName) const override {
24+
return ("std::ranges::" + OriginalName.getName()).str();
25+
}
26+
ArrayRef<UseRangesCheck::Signature>
27+
getReplacementSignatures() const override {
28+
return Indexes;
29+
}
30+
std::optional<std::string>
31+
getHeaderInclusion(const NamedDecl & /*OriginalName*/) const override {
32+
return "<algorithm>";
33+
}
34+
35+
private:
36+
SmallVector<UseRangesCheck::Signature> Indexes;
37+
};
38+
39+
utils::UseRangesCheck::ReplacerMap Result;
40+
41+
// template<typename Iter> Func(Iter first, Iter last,...).
42+
static const Signature SingleRangeArgs = {{0}};
43+
// template<typename Policy, typename Iter>
44+
// Func(Policy policy, Iter first, // Iter last,...).
45+
static const Signature SingleRangeExecPolicy = {{1}};
46+
// template<typename Iter1, typename Iter2>
47+
// Func(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2,...).
48+
static const Signature TwoRangeArgs = {{0}, {2}};
49+
// template<typename Policy, typename Iter1, typename Iter2>
50+
// Func(Policy policy, Iter1 first1, Iter1 last1, Iter2 first2, Iter2
51+
// last2,...).
52+
static const Signature TwoRangeExecPolicy = {{1}, {3}};
53+
54+
static const Signature SingleRangeFunc[] = {SingleRangeArgs};
55+
56+
static const Signature SingleRangeExecFunc[] = {SingleRangeArgs,
57+
SingleRangeExecPolicy};
58+
static const Signature TwoRangeExecFunc[] = {TwoRangeArgs,
59+
TwoRangeExecPolicy};
60+
static const Signature OneOrTwoFunc[] = {SingleRangeArgs, TwoRangeArgs};
61+
static const Signature OneOrTwoExecFunc[] = {
62+
SingleRangeArgs, SingleRangeExecPolicy, TwoRangeArgs, TwoRangeExecPolicy};
63+
64+
static const std::pair<ArrayRef<Signature>, ArrayRef<StringRef>> Names[] = {
65+
{SingleRangeFunc,
66+
{"all_of",
67+
"any_of",
68+
"none_of",
69+
"for_each",
70+
"find",
71+
"find_if",
72+
"find_if_not",
73+
"adjacent_find",
74+
"copy",
75+
"copy_if",
76+
"copy_backward",
77+
"move",
78+
"move_backward",
79+
"fill",
80+
"transform",
81+
"replace",
82+
"replace_if",
83+
"generate",
84+
"remove",
85+
"remove_if",
86+
"remove_copy",
87+
"remove_copy_if",
88+
"unique",
89+
"unique_copy",
90+
"sample",
91+
"partition_point",
92+
"lower_bound",
93+
"upper_bound",
94+
"equal_range",
95+
"binary_search",
96+
"push_heap",
97+
"pop_heap",
98+
"make_heap",
99+
"sort_heap",
100+
"next_permutation",
101+
"prev_permutation",
102+
"iota"}},
103+
{SingleRangeExecFunc,
104+
{"reverse",
105+
"reverse_copy",
106+
"shift_left",
107+
"shift_right",
108+
"is_partitioned",
109+
"partition",
110+
"partition_copy",
111+
"stable_partition",
112+
"sort",
113+
"stable_sort",
114+
"is_sorted",
115+
"is_sorted_until",
116+
"is_heap",
117+
"is_heap_until",
118+
"max_element",
119+
"min_element",
120+
"minmax_element",
121+
"uninitialized_copy",
122+
"uninitialized_fill",
123+
"uninitialized_move",
124+
"uninitialized_default_construct",
125+
"uninitialized_value_construct",
126+
"destroy"}},
127+
{TwoRangeExecFunc,
128+
{"partial_sort_copy", "includes", "set_union", "set_intersection",
129+
"set_difference", "set_symmetric_difference", "merge",
130+
"lexicographical_compare", "find_end", "search"}},
131+
{OneOrTwoFunc, {"is_permutation"}},
132+
{OneOrTwoExecFunc, {"equal", "mismatch"}}};
133+
SmallString<64> Buff;
134+
for (const auto &[Signature, Values] : Names) {
135+
auto Replacer = llvm::makeIntrusiveRefCnt<StdReplacer>(
136+
SmallVector<UseRangesCheck::Signature>{Signature.begin(),
137+
Signature.end()});
138+
for (const auto &Name : Values) {
139+
Buff.clear();
140+
Result.try_emplace(("::std::" + Name).toStringRef(Buff), Replacer);
141+
}
142+
}
143+
return Result;
144+
}
145+
146+
bool UseRangesCheck::isLanguageVersionSupported(
147+
const LangOptions &LangOpts) const {
148+
return LangOpts.CPlusPlus20;
149+
}
150+
} // namespace clang::tidy::modernize
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
//===--- UseRangesCheck.h - clang-tidy --------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USERANGESCHECK_H
10+
#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USERANGESCHECK_H
11+
12+
#include "../utils/UseRangesCheck.h"
13+
14+
namespace clang::tidy::modernize {
15+
16+
/// Detects calls to standard library iterator algorithms that could be
17+
/// replaced with a ranges version instead
18+
///
19+
/// For the user-facing documentation see:
20+
/// http://clang.llvm.org/extra/clang-tidy/checks/modernize/use-ranges.html
21+
class UseRangesCheck : public utils::UseRangesCheck {
22+
public:
23+
using utils::UseRangesCheck::UseRangesCheck;
24+
25+
ReplacerMap getReplacerMap() const override;
26+
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override;
27+
};
28+
29+
} // namespace clang::tidy::modernize
30+
31+
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USERANGESCHECK_H

clang-tools-extra/clang-tidy/utils/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ add_clang_library(clangTidyUtils
2626
TransformerClangTidyCheck.cpp
2727
TypeTraits.cpp
2828
UsingInserter.cpp
29+
UseRangesCheck.cpp
2930

3031
LINK_LIBS
3132
clangTidy

0 commit comments

Comments
 (0)