clang-tools 24.0.0git
modernize/UseRangesCheck.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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#include <initializer_list>
16
17// FixItHint - Let the docs script know that this class does provide fixits
18
19namespace clang::tidy::modernize {
20
21static constexpr const char *SingleRangeNames[] = {
22 "all_of",
23 "any_of",
24 "none_of",
25 "for_each",
26 "find",
27 "find_if",
28 "find_if_not",
29 "adjacent_find",
30 "fill",
31 "replace",
32 "replace_if",
33 "generate",
34 "sample",
35 "partition_point",
36 "lower_bound",
37 "upper_bound",
38 "equal_range",
39 "binary_search",
40 "push_heap",
41 "pop_heap",
42 "make_heap",
43 "sort_heap",
44 "next_permutation",
45 "prev_permutation",
46 "reverse",
47 "shift_left",
48 "shift_right",
49 "is_partitioned",
50 "partition_copy",
51 "sort",
52 "stable_sort",
53 "is_sorted",
54 "is_sorted_until",
55 "is_heap",
56 "is_heap_until",
57 "max_element",
58 "min_element",
59 "minmax_element",
60 "uninitialized_fill",
61 "uninitialized_default_construct",
62 "uninitialized_value_construct",
63 "destroy",
64};
65
66static constexpr const char *SingleRangeBeginResultNames[] = {
67 "remove", "remove_if", "stable_partition", "partition", "unique"};
68
69static constexpr const char *SingleRangeOutResultNames[] = {
70 "copy", "copy_if", "copy_backward", "move",
71 "move_backward", "remove_copy", "remove_copy_if", "reverse_copy",
72 "transform", "unique_copy", "uninitialized_copy", "uninitialized_move",
73};
74
75static constexpr const char *TwoRangeNames[] = {
76 "equal", "mismatch", "includes", "lexicographical_compare",
77 "find_end", "search", "is_permutation",
78};
79
80static constexpr const char *TwoRangeOutResultNames[] = {
81 "merge",
82 "partial_sort_copy",
83 "set_difference",
84 "set_intersection",
85 "set_symmetric_difference",
86 "set_union",
87};
88
89static constexpr const char *SinglePivotRangeNames[] = {"inplace_merge"};
90
91static constexpr const char *SinglePivotRangeBeginResultNames[] = {"rotate"};
92
93static constexpr const char *SinglePivotRangeOutResultNames[] = {"rotate_copy"};
94
95namespace {
96class StdReplacer : public utils::UseRangesCheck::Replacer {
97public:
99
100 explicit StdReplacer(SmallVector<UseRangesCheck::Signature> Signatures,
101 ResultUsePolicy ResultPolicy = {})
102 : Signatures(std::move(Signatures)), ResultPolicy(ResultPolicy) {}
103 std::optional<std::string>
104 getReplaceName(const NamedDecl &OriginalName) const override {
105 return ("std::ranges::" + OriginalName.getName()).str();
106 }
107 ArrayRef<UseRangesCheck::Signature>
108 getReplacementSignatures() const override {
109 return Signatures;
110 }
111 ResultUsePolicy getResultUsePolicy(const NamedDecl &, bool) const override {
112 return ResultPolicy;
113 }
114
115private:
116 SmallVector<UseRangesCheck::Signature> Signatures;
117 ResultUsePolicy ResultPolicy;
118};
119
120class StdAlgorithmReplacer : public StdReplacer {
121 using StdReplacer::StdReplacer;
122 std::optional<std::string>
123 getHeaderInclusion(const NamedDecl & /*OriginalName*/) const override {
124 return "<algorithm>";
125 }
126};
127
128class StdNumericReplacer : public StdReplacer {
129 using StdReplacer::StdReplacer;
130 std::optional<std::string>
131 getHeaderInclusion(const NamedDecl & /*OriginalName*/) const override {
132 return "<numeric>";
133 }
134};
135} // namespace
136
139
140 // template<typename Iter> Func(Iter first, Iter last,...).
141 static const Signature SingleRangeArgs = {{0}};
142 // template<typename Iter1, typename Iter2>
143 // Func(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2,...).
144 static const Signature TwoRangeArgs = {{0}, {2}};
145
146 // template<typename Iter> Func(Iter first, Iter pivot, Iter last,...).
147 static const Signature SinglePivotRange = {{0, 2}};
148
149 static const Signature SingleRangeFunc[] = {SingleRangeArgs};
150
151 static const Signature TwoRangeFunc[] = {TwoRangeArgs};
152
153 static const Signature SinglePivotFunc[] = {SinglePivotRange};
154
155 using ResultPolicy = StdReplacer::ResultUsePolicy;
156 using PolicyKind = ResultPolicy::Kind;
157 const ResultPolicy DefaultPolicy;
158 const ResultPolicy BeginResultPolicy = {
159 PolicyKind::AppendAccessorForUsedResult, ".begin()"};
160 const ResultPolicy OutResultPolicy = {PolicyKind::AppendAccessorForUsedResult,
161 ".out"};
162
163 struct AlgorithmGroup {
164 ArrayRef<Signature> Signatures;
165 ArrayRef<const char *> Names;
166 ResultPolicy Policy;
167 };
168 const AlgorithmGroup AlgorithmNames[] = {
169 {SingleRangeFunc, SingleRangeNames, DefaultPolicy},
170 {SingleRangeFunc, SingleRangeBeginResultNames, BeginResultPolicy},
171 {SingleRangeFunc, SingleRangeOutResultNames, OutResultPolicy},
172 {TwoRangeFunc, TwoRangeNames, DefaultPolicy},
173 {TwoRangeFunc, TwoRangeOutResultNames, OutResultPolicy},
174 {SinglePivotFunc, SinglePivotRangeNames, DefaultPolicy},
175 {SinglePivotFunc, SinglePivotRangeBeginResultNames, BeginResultPolicy},
176 {SinglePivotFunc, SinglePivotRangeOutResultNames, OutResultPolicy},
177 };
178 SmallString<64> Buff;
179 for (const auto &[Signatures, Values, Policy] : AlgorithmNames) {
180 auto Replacer = llvm::makeIntrusiveRefCnt<StdAlgorithmReplacer>(
181 SmallVector<UseRangesCheck::Signature>{Signatures}, Policy);
182 for (const auto &Name : Values) {
183 Buff.assign({"::std::", Name});
184 Result.try_emplace(Buff, Replacer);
185 }
186 }
187 if (getLangOpts().CPlusPlus23)
188 Result.try_emplace(
189 "::std::iota",
190 llvm::makeIntrusiveRefCnt<StdNumericReplacer>(
191 SmallVector<UseRangesCheck::Signature>{std::begin(SingleRangeFunc),
192 std::end(SingleRangeFunc)}));
193 return Result;
194}
195
197 : utils::UseRangesCheck(Name, Context),
198 UseReversePipe(Options.get("UseReversePipe", false)) {}
199
202 Options.store(Opts, "UseReversePipe", UseReversePipe);
203}
204
206 const LangOptions &LangOpts) const {
207 return LangOpts.CPlusPlus20;
208}
209ArrayRef<std::pair<StringRef, StringRef>>
211 static constexpr std::pair<StringRef, StringRef> Refs[] = {
212 {"::std::begin", "::std::end"}, {"::std::cbegin", "::std::cend"}};
213 return Refs;
214}
215std::optional<UseRangesCheck::ReverseIteratorDescriptor>
217 static constexpr std::pair<StringRef, StringRef> Refs[] = {
218 {"::std::rbegin", "::std::rend"}, {"::std::crbegin", "::std::crend"}};
219 return ReverseIteratorDescriptor{"std::views::reverse", "<ranges>", Refs,
220 UseReversePipe};
221}
222} // namespace clang::tidy::modernize
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override
ArrayRef< std::pair< StringRef, StringRef > > getFreeBeginEndMethods() const override
Gets the fully qualified names of begin and end functions.
UseRangesCheck(StringRef CheckName, ClangTidyContext *Context)
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
ReplacerMap getReplacerMap() const override
Gets a map of function to replace and methods to create the replacements.
std::optional< ReverseIteratorDescriptor > getReverseDescriptor() const override
llvm::StringMap< llvm::IntrusiveRefCntPtr< Replacer > > ReplacerMap
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
static constexpr const char * SingleRangeBeginResultNames[]
static constexpr const char * TwoRangeOutResultNames[]
static constexpr const char * TwoRangeNames[]
static constexpr const char * SinglePivotRangeNames[]
static constexpr const char * SinglePivotRangeBeginResultNames[]
static constexpr const char * SinglePivotRangeOutResultNames[]
static constexpr const char * SingleRangeNames[]
static constexpr const char * SingleRangeOutResultNames[]
llvm::StringMap< ClangTidyValue > OptionMap