clang-tools 20.0.0git
modernize/UseRangesCheck.cpp
Go to the documentation of this file.
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#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 "copy",
31 "copy_if",
32 "copy_backward",
33 "move",
34 "move_backward",
35 "fill",
36 "transform",
37 "replace",
38 "replace_if",
39 "generate",
40 "remove",
41 "remove_if",
42 "remove_copy",
43 "remove_copy_if",
44 "unique",
45 "unique_copy",
46 "sample",
47 "partition_point",
48 "lower_bound",
49 "upper_bound",
50 "equal_range",
51 "binary_search",
52 "push_heap",
53 "pop_heap",
54 "make_heap",
55 "sort_heap",
56 "next_permutation",
57 "prev_permutation",
58 "reverse",
59 "reverse_copy",
60 "shift_left",
61 "shift_right",
62 "is_partitioned",
63 "partition",
64 "partition_copy",
65 "stable_partition",
66 "sort",
67 "stable_sort",
68 "is_sorted",
69 "is_sorted_until",
70 "is_heap",
71 "is_heap_until",
72 "max_element",
73 "min_element",
74 "minmax_element",
75 "uninitialized_copy",
76 "uninitialized_fill",
77 "uninitialized_move",
78 "uninitialized_default_construct",
79 "uninitialized_value_construct",
80 "destroy",
81};
82
83static constexpr const char *TwoRangeNames[] = {
84 "equal",
85 "mismatch",
86 "partial_sort_copy",
87 "includes",
88 "set_union",
89 "set_intersection",
90 "set_difference",
91 "set_symmetric_difference",
92 "merge",
93 "lexicographical_compare",
94 "find_end",
95 "search",
96 "is_permutation",
97};
98
99static constexpr const char *SinglePivotRangeNames[] = {"rotate", "rotate_copy",
100 "inplace_merge"};
101
102namespace {
103class StdReplacer : public utils::UseRangesCheck::Replacer {
104public:
105 explicit StdReplacer(SmallVector<UseRangesCheck::Signature> Signatures)
106 : Signatures(std::move(Signatures)) {}
107 std::optional<std::string>
108 getReplaceName(const NamedDecl &OriginalName) const override {
109 return ("std::ranges::" + OriginalName.getName()).str();
110 }
111 ArrayRef<UseRangesCheck::Signature>
112 getReplacementSignatures() const override {
113 return Signatures;
114 }
115
116private:
117 SmallVector<UseRangesCheck::Signature> Signatures;
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
138
140
141 // template<typename Iter> Func(Iter first, Iter last,...).
142 static const Signature SingleRangeArgs = {{0}};
143 // template<typename Iter1, typename Iter2>
144 // Func(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2,...).
145 static const Signature TwoRangeArgs = {{0}, {2}};
146
147 // template<typename Iter> Func(Iter first, Iter pivot, Iter last,...).
148 static const Signature SinglePivotRange = {{0, 2}};
149
150 static const Signature SingleRangeFunc[] = {SingleRangeArgs};
151
152 static const Signature TwoRangeFunc[] = {TwoRangeArgs};
153
154 static const Signature SinglePivotFunc[] = {SinglePivotRange};
155
156 static const std::pair<ArrayRef<Signature>, ArrayRef<const char *>>
157 AlgorithmNames[] = {{SingleRangeFunc, SingleRangeNames},
158 {TwoRangeFunc, TwoRangeNames},
159 {SinglePivotFunc, SinglePivotRangeNames}};
160 SmallString<64> Buff;
161 for (const auto &[Signatures, Values] : AlgorithmNames) {
162 auto Replacer = llvm::makeIntrusiveRefCnt<StdAlgorithmReplacer>(
163 SmallVector<UseRangesCheck::Signature>{Signatures});
164 for (const auto &Name : Values) {
165 Buff.assign({"::std::", Name});
166 Result.try_emplace(Buff, Replacer);
167 }
168 }
169 if (getLangOpts().CPlusPlus23)
170 Result.try_emplace(
171 "::std::iota",
172 llvm::makeIntrusiveRefCnt<StdNumericReplacer>(
173 SmallVector<UseRangesCheck::Signature>{std::begin(SingleRangeFunc),
174 std::end(SingleRangeFunc)}));
175 return Result;
176}
177
179 : utils::UseRangesCheck(Name, Context),
180 UseReversePipe(Options.get("UseReversePipe", false)) {}
181
184 Options.store(Opts, "UseReversePipe", UseReversePipe);
185}
186
188 const LangOptions &LangOpts) const {
189 return LangOpts.CPlusPlus20;
190}
191ArrayRef<std::pair<StringRef, StringRef>>
193 static const std::pair<StringRef, StringRef> Refs[] = {
194 {"::std::begin", "::std::end"}, {"::std::cbegin", "::std::cend"}};
195 return Refs;
196}
197std::optional<UseRangesCheck::ReverseIteratorDescriptor>
199 static const std::pair<StringRef, StringRef> Refs[] = {
200 {"::std::rbegin", "::std::rend"}, {"::std::crbegin", "::std::crend"}};
201 return ReverseIteratorDescriptor{UseReversePipe ? "std::views::reverse"
202 : "std::ranges::reverse_view",
203 "<ranges>", Refs, UseReversePipe};
204}
205} // namespace clang::tidy::modernize
llvm::SmallString< 256U > Name
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const
Stores an option with the check-local name LocalName with string value Value to Options.
const LangOptions & getLangOpts() const
Returns the language options from the context.
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
Detects calls to standard library iterator algorithms that could be replaced with a ranges version in...
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override
Override this to disable registering matchers and PP callbacks if an invalid language version is bein...
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 &Options) override
Should store all options supported by this check with their current values or default values for opti...
ReplacerMap getReplacerMap() const override
Gets a map of function to replace and methods to create the replacements.
std::optional< ReverseIteratorDescriptor > getReverseDescriptor() const override
void storeOptions(ClangTidyOptions::OptionMap &Options) override
Should store all options supported by this check with their current values or default values for opti...
llvm::StringMap< llvm::IntrusiveRefCntPtr< Replacer > > ReplacerMap
SmallVector< Indexes, 2 > Signature
static constexpr const char * TwoRangeNames[]
static constexpr const char * SinglePivotRangeNames[]
static constexpr const char * SingleRangeNames[]
llvm::StringMap< ClangTidyValue > OptionMap