1 //===--- UseRangesCheck.cpp - clang-tidy ----------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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>
17 // FixItHint - Let the docs script know that this class does provide fixits
19 namespace clang::tidy::modernize
{
21 static constexpr const char *SingleRangeNames
[] = {
78 "uninitialized_default_construct",
79 "uninitialized_value_construct",
83 static constexpr const char *TwoRangeNames
[] = {
91 "set_symmetric_difference",
93 "lexicographical_compare",
99 static constexpr const char *SinglePivotRangeNames
[] = {"rotate", "rotate_copy",
103 class StdReplacer
: public utils::UseRangesCheck::Replacer
{
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();
111 ArrayRef
<UseRangesCheck::Signature
>
112 getReplacementSignatures() const override
{
117 SmallVector
<UseRangesCheck::Signature
> Signatures
;
120 class StdAlgorithmReplacer
: public StdReplacer
{
121 using StdReplacer::StdReplacer
;
122 std::optional
<std::string
>
123 getHeaderInclusion(const NamedDecl
& /*OriginalName*/) const override
{
124 return "<algorithm>";
128 class StdNumericReplacer
: public StdReplacer
{
129 using StdReplacer::StdReplacer
;
130 std::optional
<std::string
>
131 getHeaderInclusion(const NamedDecl
& /*OriginalName*/) const override
{
137 utils::UseRangesCheck::ReplacerMap
UseRangesCheck::getReplacerMap() const {
139 utils::UseRangesCheck::ReplacerMap Result
;
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}};
147 // template<typename Iter> Func(Iter first, Iter pivot, Iter last,...).
148 static const Signature SinglePivotRange
= {{0, 2}};
150 static const Signature SingleRangeFunc
[] = {SingleRangeArgs
};
152 static const Signature TwoRangeFunc
[] = {TwoRangeArgs
};
154 static const Signature SinglePivotFunc
[] = {SinglePivotRange
};
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
);
169 if (getLangOpts().CPlusPlus23
)
172 llvm::makeIntrusiveRefCnt
<StdNumericReplacer
>(
173 SmallVector
<UseRangesCheck::Signature
>{std::begin(SingleRangeFunc
),
174 std::end(SingleRangeFunc
)}));
178 UseRangesCheck::UseRangesCheck(StringRef Name
, ClangTidyContext
*Context
)
179 : utils::UseRangesCheck(Name
, Context
),
180 UseReversePipe(Options
.get("UseReversePipe", false)) {}
182 void UseRangesCheck::storeOptions(ClangTidyOptions::OptionMap
&Opts
) {
183 utils::UseRangesCheck::storeOptions(Opts
);
184 Options
.store(Opts
, "UseReversePipe", UseReversePipe
);
187 bool UseRangesCheck::isLanguageVersionSupported(
188 const LangOptions
&LangOpts
) const {
189 return LangOpts
.CPlusPlus20
;
191 ArrayRef
<std::pair
<StringRef
, StringRef
>>
192 UseRangesCheck::getFreeBeginEndMethods() const {
193 static const std::pair
<StringRef
, StringRef
> Refs
[] = {
194 {"::std::begin", "::std::end"}, {"::std::cbegin", "::std::cend"}};
197 std::optional
<UseRangesCheck::ReverseIteratorDescriptor
>
198 UseRangesCheck::getReverseDescriptor() const {
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
};
205 } // namespace clang::tidy::modernize