10#include "clang/AST/Decl.h"
11#include "clang/Basic/Diagnostic.h"
12#include "clang/Basic/LLVM.h"
13#include "llvm/ADT/ArrayRef.h"
14#include "llvm/ADT/IntrusiveRefCntPtr.h"
15#include "llvm/ADT/SmallString.h"
16#include "llvm/ADT/SmallVector.h"
17#include "llvm/ADT/StringRef.h"
18#include <initializer_list>
31 BoostReplacer(ArrayRef<UseRangesCheck::Signature> Signatures,
33 : Signatures(Signatures), IncludeSystem(IncludeSystem) {}
35 ArrayRef<UseRangesCheck::Signature> getReplacementSignatures() const final {
39 virtual std::pair<StringRef, StringRef>
40 getBoostName(
const NamedDecl &OriginalName)
const = 0;
42 virtual std::pair<StringRef, StringRef>
43 getBoostHeader(
const NamedDecl &OriginalName)
const = 0;
45 std::optional<std::string>
46 getReplaceName(
const NamedDecl &OriginalName)
const final {
48 return (
"boost::" + Namespace + (
Namespace.empty() ?
"" :
"::") + Function)
52 std::optional<std::string>
53 getHeaderInclusion(
const NamedDecl &OriginalName)
const final {
54 auto [
Path, HeaderName] = getBoostHeader(OriginalName);
55 return ((IncludeSystem ?
"<boost/" :
"boost/") + Path +
56 (
Path.empty() ?
"" :
"/") + HeaderName +
57 (IncludeSystem ?
".hpp>" :
".hpp"))
62 SmallVector<UseRangesCheck::Signature> Signatures;
69class BoostRangeAlgorithmReplacer :
public BoostReplacer {
71 using BoostReplacer::BoostReplacer;
73 std::pair<StringRef, StringRef>
74 getBoostName(
const NamedDecl &OriginalName)
const override {
75 return {
"range", OriginalName.getName()};
78 std::pair<StringRef, StringRef>
79 getBoostHeader(
const NamedDecl &OriginalName)
const override {
80 return {
"range/algorithm", OriginalName.getName()};
87class CustomBoostAlgorithmHeaderReplacer :
public BoostRangeAlgorithmReplacer {
89 CustomBoostAlgorithmHeaderReplacer(
90 StringRef HeaderName, ArrayRef<UseRangesCheck::Signature> Signatures,
92 : BoostRangeAlgorithmReplacer(Signatures, IncludeSystem),
93 HeaderName(HeaderName) {}
95 std::pair<StringRef, StringRef>
96 getBoostHeader(
const NamedDecl & )
const override {
97 return {
"range/algorithm", HeaderName};
101 StringRef HeaderName;
107class BoostAlgorithmReplacer :
public BoostReplacer {
109 BoostAlgorithmReplacer(StringRef SubHeader,
110 ArrayRef<UseRangesCheck::Signature> Signatures,
112 : BoostReplacer(Signatures, IncludeSystem),
113 SubHeader((
"algorithm/" + SubHeader).str()) {}
114 std::pair<StringRef, StringRef>
115 getBoostName(
const NamedDecl &OriginalName)
const override {
116 return {
"algorithm", OriginalName.getName()};
119 std::pair<StringRef, StringRef>
120 getBoostHeader(
const NamedDecl &OriginalName)
const override {
121 return {SubHeader, OriginalName.getName()};
125 std::string SubHeader;
131class CustomBoostAlgorithmReplacer :
public BoostReplacer {
133 CustomBoostAlgorithmReplacer(StringRef SubHeader, StringRef HeaderName,
134 ArrayRef<UseRangesCheck::Signature> Signatures,
136 : BoostReplacer(Signatures, IncludeSystem),
137 SubHeader((
"algorithm/" + SubHeader).str()), HeaderName(HeaderName) {}
138 std::pair<StringRef, StringRef>
139 getBoostName(
const NamedDecl &OriginalName)
const override {
140 return {
"algorithm", OriginalName.getName()};
143 std::pair<StringRef, StringRef>
144 getBoostHeader(
const NamedDecl & )
const override {
145 return {SubHeader, HeaderName};
149 std::string SubHeader;
150 StringRef HeaderName;
156 explicit MakeOverloadReplacer(ArrayRef<UseRangesCheck::Signature> Signatures)
157 : Signatures(Signatures) {}
159 ArrayRef<UseRangesCheck::Signature>
160 getReplacementSignatures()
const override {
164 std::optional<std::string>
165 getReplaceName(
const NamedDecl & )
const override {
169 std::optional<std::string>
170 getHeaderInclusion(
const NamedDecl & )
const override {
175 SmallVector<UseRangesCheck::Signature> Signatures;
180class FixedBoostReplace :
public BoostReplacer {
182 FixedBoostReplace(StringRef Header,
183 ArrayRef<UseRangesCheck::Signature> Signatures,
184 bool IncludeBoostSystem)
185 : BoostReplacer(Signatures, IncludeBoostSystem), Header(Header) {}
187 std::pair<StringRef, StringRef>
188 getBoostName(
const NamedDecl &OriginalName)
const override {
189 return {{}, OriginalName.getName()};
192 std::pair<StringRef, StringRef>
193 getBoostHeader(
const NamedDecl & )
const override {
206 static const Signature SingleSig = {{0}};
207 static const Signature TwoSig = {{0}, {2}};
209 [&Results](llvm::IntrusiveRefCntPtr<UseRangesCheck::Replacer>
Replacer,
210 std::initializer_list<StringRef> Names, StringRef Prefix) {
211 llvm::SmallString<64> Buffer;
212 for (
const auto &Name : Names) {
213 Buffer.assign({
"::", Prefix, (Prefix.empty() ?
"" :
"::"), Name});
214 Results.try_emplace(Buffer,
Replacer);
218 const auto AddFromStd =
219 [&](llvm::IntrusiveRefCntPtr<UseRangesCheck::Replacer>
Replacer,
220 std::initializer_list<StringRef> Names) {
221 AddFrom(std::move(
Replacer), Names,
"std");
224 const auto AddFromBoost =
225 [&](
const llvm::IntrusiveRefCntPtr<UseRangesCheck::Replacer> &
Replacer,
226 std::initializer_list<
227 std::pair<StringRef, std::initializer_list<StringRef>>>
229 for (
auto [Namespace, Names] : NamespaceAndNames)
231 SmallString<64>{
"boost", (Namespace.empty() ?
"" :
"::"),
235 AddFromStd(llvm::makeIntrusiveRefCnt<CustomBoostAlgorithmHeaderReplacer>(
236 "set_algorithm", TwoSig, IncludeBoostSystem),
237 {
"includes",
"set_union",
"set_intersection",
"set_difference",
238 "set_symmetric_difference"});
240 AddFromStd(llvm::makeIntrusiveRefCnt<BoostRangeAlgorithmReplacer>(
241 SingleSig, IncludeBoostSystem),
242 {
"unique",
"lower_bound",
"stable_sort",
243 "equal_range",
"remove_if",
"sort",
244 "random_shuffle",
"remove_copy",
"stable_partition",
245 "remove_copy_if",
"count",
"copy_backward",
246 "reverse_copy",
"adjacent_find",
"remove",
247 "upper_bound",
"binary_search",
"replace_copy_if",
248 "for_each",
"generate",
"count_if",
249 "min_element",
"reverse",
"replace_copy",
250 "fill",
"unique_copy",
"transform",
251 "copy",
"replace",
"find",
252 "replace_if",
"find_if",
"partition",
255 AddFromStd(llvm::makeIntrusiveRefCnt<BoostRangeAlgorithmReplacer>(
256 TwoSig, IncludeBoostSystem),
257 {
"find_end",
"merge",
"partial_sort_copy",
"find_first_of",
258 "search",
"lexicographical_compare",
"equal",
"mismatch"});
260 AddFromStd(llvm::makeIntrusiveRefCnt<CustomBoostAlgorithmHeaderReplacer>(
261 "permutation", SingleSig, IncludeBoostSystem),
262 {
"next_permutation",
"prev_permutation"});
264 AddFromStd(llvm::makeIntrusiveRefCnt<CustomBoostAlgorithmHeaderReplacer>(
265 "heap_algorithm", SingleSig, IncludeBoostSystem),
266 {
"push_heap",
"pop_heap",
"make_heap",
"sort_heap"});
268 AddFromStd(llvm::makeIntrusiveRefCnt<BoostAlgorithmReplacer>(
269 "cxx11", SingleSig, IncludeBoostSystem),
270 {
"copy_if",
"is_permutation",
"is_partitioned",
"find_if_not",
271 "partition_copy",
"any_of",
"iota",
"all_of",
"partition_point",
272 "is_sorted",
"none_of"});
274 AddFromStd(llvm::makeIntrusiveRefCnt<CustomBoostAlgorithmReplacer>(
275 "cxx11",
"is_sorted", SingleSig, IncludeBoostSystem),
276 {
"is_sorted_until"});
278 AddFromStd(llvm::makeIntrusiveRefCnt<FixedBoostReplace>(
279 "range/numeric", SingleSig, IncludeBoostSystem),
280 {
"accumulate",
"partial_sum",
"adjacent_difference"});
282 if (getLangOpts().CPlusPlus17)
283 AddFromStd(llvm::makeIntrusiveRefCnt<BoostAlgorithmReplacer>(
284 "cxx17", SingleSig, IncludeBoostSystem),
287 AddFromBoost(llvm::makeIntrusiveRefCnt<MakeOverloadReplacer>(SingleSig),
293 "find_if_not_backward",
297 "is_partitioned_until",
320 "is_strictly_increasing",
321 "is_strictly_decreasing",
327 llvm::makeIntrusiveRefCnt<MakeOverloadReplacer>(TwoSig),
328 {{
"algorithm", {
"apply_permutation",
"apply_reverse_permutation"}}});
335 IncludeBoostSystem(Options.get(
"IncludeBoostSystem", true)),
336 UseReversePipe(Options.get(
"UseReversePipe", false)) {}
340 Options.store(Opts,
"IncludeBoostSystem", IncludeBoostSystem);
341 Options.store(Opts,
"UseReversePipe", UseReversePipe);
345 const DiagnosticBuilder D =
346 diag(Call.getBeginLoc(),
"use a %0 version of this algorithm");
347 D << (Call.getDirectCallee()->isInStdNamespace() ?
"boost" :
"ranged");
350ArrayRef<std::pair<StringRef, StringRef>>
352 static const std::pair<StringRef, StringRef> Refs[] = {
353 {
"::std::begin",
"::std::end"},
354 {
"::std::cbegin",
"::std::cend"},
355 {
"::boost::range_adl_barrier::begin",
"::boost::range_adl_barrier::end"},
356 {
"::boost::range_adl_barrier::const_begin",
357 "::boost::range_adl_barrier::const_end"},
361std::optional<UseRangesCheck::ReverseIteratorDescriptor>
363 static const std::pair<StringRef, StringRef> Refs[] = {
364 {
"::std::rbegin",
"::std::rend"},
365 {
"::std::crbegin",
"::std::crend"},
366 {
"::boost::rbegin",
"::boost::rend"},
367 {
"::boost::const_rbegin",
"::boost::const_rend"},
370 UseReversePipe ?
"boost::adaptors::reversed" :
"boost::adaptors::reverse",
371 IncludeBoostSystem ?
"<boost/range/adaptor/reversed.hpp>"
372 :
"boost/range/adaptor/reversed.hpp",
373 Refs, UseReversePipe};
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
ArrayRef< std::pair< StringRef, StringRef > > getFreeBeginEndMethods() const override
Gets the fully qualified names of begin and end functions.
UseRangesCheck(StringRef Name, ClangTidyContext *Context)
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
DiagnosticBuilder createDiag(const CallExpr &Call) override
Create a diagnostic for the CallExpr Override this to support custom diagnostic messages.
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
SmallVector< Indexes, 2 > Signature
std::string Path
A typedef to represent a file path.
llvm::StringMap< ClangTidyValue > OptionMap