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 {
205 static const Signature SingleSig = {{0}};
206 static const Signature TwoSig = {{0}, {2}};
208 [&Results](llvm::IntrusiveRefCntPtr<UseRangesCheck::Replacer>
Replacer,
209 std::initializer_list<StringRef> Names, StringRef Prefix) {
210 llvm::SmallString<64> Buffer;
211 for (
const auto &Name : Names) {
212 Buffer.assign({
"::", Prefix, (Prefix.empty() ?
"" :
"::"), Name});
213 Results.try_emplace(Buffer,
Replacer);
217 const auto AddFromStd =
218 [&](llvm::IntrusiveRefCntPtr<UseRangesCheck::Replacer>
Replacer,
219 std::initializer_list<StringRef> Names) {
220 AddFrom(std::move(
Replacer), Names,
"std");
223 const auto AddFromBoost =
224 [&](
const llvm::IntrusiveRefCntPtr<UseRangesCheck::Replacer> &
Replacer,
225 std::initializer_list<
226 std::pair<StringRef, std::initializer_list<StringRef>>>
228 for (
auto [Namespace, Names] : NamespaceAndNames)
230 SmallString<64>{
"boost", (Namespace.empty() ?
"" :
"::"),
234 AddFromStd(llvm::makeIntrusiveRefCnt<CustomBoostAlgorithmHeaderReplacer>(
235 "set_algorithm", TwoSig, IncludeBoostSystem),
236 {
"includes",
"set_union",
"set_intersection",
"set_difference",
237 "set_symmetric_difference"});
239 AddFromStd(llvm::makeIntrusiveRefCnt<BoostRangeAlgorithmReplacer>(
240 SingleSig, IncludeBoostSystem),
241 {
"unique",
"lower_bound",
"stable_sort",
242 "equal_range",
"remove_if",
"sort",
243 "random_shuffle",
"remove_copy",
"stable_partition",
244 "remove_copy_if",
"count",
"copy_backward",
245 "reverse_copy",
"adjacent_find",
"remove",
246 "upper_bound",
"binary_search",
"replace_copy_if",
247 "for_each",
"generate",
"count_if",
248 "min_element",
"reverse",
"replace_copy",
249 "fill",
"unique_copy",
"transform",
250 "copy",
"replace",
"find",
251 "replace_if",
"find_if",
"partition",
254 AddFromStd(llvm::makeIntrusiveRefCnt<BoostRangeAlgorithmReplacer>(
255 TwoSig, IncludeBoostSystem),
256 {
"find_end",
"merge",
"partial_sort_copy",
"find_first_of",
257 "search",
"lexicographical_compare",
"equal",
"mismatch"});
259 AddFromStd(llvm::makeIntrusiveRefCnt<CustomBoostAlgorithmHeaderReplacer>(
260 "permutation", SingleSig, IncludeBoostSystem),
261 {
"next_permutation",
"prev_permutation"});
263 AddFromStd(llvm::makeIntrusiveRefCnt<CustomBoostAlgorithmHeaderReplacer>(
264 "heap_algorithm", SingleSig, IncludeBoostSystem),
265 {
"push_heap",
"pop_heap",
"make_heap",
"sort_heap"});
267 AddFromStd(llvm::makeIntrusiveRefCnt<BoostAlgorithmReplacer>(
268 "cxx11", SingleSig, IncludeBoostSystem),
269 {
"copy_if",
"is_permutation",
"is_partitioned",
"find_if_not",
270 "partition_copy",
"any_of",
"iota",
"all_of",
"partition_point",
271 "is_sorted",
"none_of"});
273 AddFromStd(llvm::makeIntrusiveRefCnt<CustomBoostAlgorithmReplacer>(
274 "cxx11",
"is_sorted", SingleSig, IncludeBoostSystem),
275 {
"is_sorted_until"});
277 AddFromStd(llvm::makeIntrusiveRefCnt<FixedBoostReplace>(
278 "range/numeric", SingleSig, IncludeBoostSystem),
279 {
"accumulate",
"partial_sum",
"adjacent_difference"});
281 if (getLangOpts().CPlusPlus17)
282 AddFromStd(llvm::makeIntrusiveRefCnt<BoostAlgorithmReplacer>(
283 "cxx17", SingleSig, IncludeBoostSystem),
286 AddFromBoost(llvm::makeIntrusiveRefCnt<MakeOverloadReplacer>(SingleSig),
292 "find_if_not_backward",
296 "is_partitioned_until",
319 "is_strictly_increasing",
320 "is_strictly_decreasing",
326 llvm::makeIntrusiveRefCnt<MakeOverloadReplacer>(TwoSig),
327 {{
"algorithm", {
"apply_permutation",
"apply_reverse_permutation"}}});
334 IncludeBoostSystem(Options.get(
"IncludeBoostSystem", true)),
335 UseReversePipe(Options.get(
"UseReversePipe", false)) {}
339 Options.store(Opts,
"IncludeBoostSystem", IncludeBoostSystem);
340 Options.store(Opts,
"UseReversePipe", UseReversePipe);
344 const DiagnosticBuilder D =
345 diag(Call.getBeginLoc(),
"use a %0 version of this algorithm");
346 D << (Call.getDirectCallee()->isInStdNamespace() ?
"boost" :
"ranged");
349ArrayRef<std::pair<StringRef, StringRef>>
351 static const std::pair<StringRef, StringRef> Refs[] = {
352 {
"::std::begin",
"::std::end"},
353 {
"::std::cbegin",
"::std::cend"},
354 {
"::boost::range_adl_barrier::begin",
"::boost::range_adl_barrier::end"},
355 {
"::boost::range_adl_barrier::const_begin",
356 "::boost::range_adl_barrier::const_end"},
360std::optional<UseRangesCheck::ReverseIteratorDescriptor>
362 static const std::pair<StringRef, StringRef> Refs[] = {
363 {
"::std::rbegin",
"::std::rend"},
364 {
"::std::crbegin",
"::std::crend"},
365 {
"::boost::rbegin",
"::boost::rend"},
366 {
"::boost::const_rbegin",
"::boost::const_rend"},
369 UseReversePipe ?
"boost::adaptors::reversed" :
"boost::adaptors::reverse",
370 IncludeBoostSystem ?
"<boost/range/adaptor/reversed.hpp>"
371 :
"boost/range/adaptor/reversed.hpp",
372 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