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>
28class BoostReplacer :
public UseRangesCheck::Replacer {
30 BoostReplacer(ArrayRef<UseRangesCheck::Signature> Signatures,
32 : Signatures(Signatures), IncludeSystem(IncludeSystem) {}
34 ArrayRef<UseRangesCheck::Signature> getReplacementSignatures() const final {
38 virtual std::pair<StringRef, StringRef>
39 getBoostName(
const NamedDecl &OriginalName)
const = 0;
41 virtual std::pair<StringRef, StringRef>
42 getBoostHeader(
const NamedDecl &OriginalName)
const = 0;
44 std::optional<std::string>
45 getReplaceName(
const NamedDecl &OriginalName)
const final {
47 return (
"boost::" + Namespace + (
Namespace.empty() ?
"" :
"::") + Function)
51 std::optional<std::string>
52 getHeaderInclusion(
const NamedDecl &OriginalName)
const final {
53 auto [
Path, HeaderName] = getBoostHeader(OriginalName);
54 return ((IncludeSystem ?
"<boost/" :
"boost/") +
Path +
55 (
Path.empty() ?
"" :
"/") + HeaderName +
56 (IncludeSystem ?
".hpp>" :
".hpp"))
61 SmallVector<UseRangesCheck::Signature> Signatures;
68class BoostRangeAlgorithmReplacer :
public BoostReplacer {
70 using BoostReplacer::BoostReplacer;
72 std::pair<StringRef, StringRef>
73 getBoostName(
const NamedDecl &OriginalName)
const override {
74 return {
"range", OriginalName.getName()};
77 std::pair<StringRef, StringRef>
78 getBoostHeader(
const NamedDecl &OriginalName)
const override {
79 return {
"range/algorithm", OriginalName.getName()};
86class CustomBoostAlgorithmHeaderReplacer :
public BoostRangeAlgorithmReplacer {
88 CustomBoostAlgorithmHeaderReplacer(
89 StringRef HeaderName, ArrayRef<UseRangesCheck::Signature> Signatures,
91 : BoostRangeAlgorithmReplacer(Signatures, IncludeSystem),
92 HeaderName(HeaderName) {}
94 std::pair<StringRef, StringRef>
95 getBoostHeader(
const NamedDecl & )
const override {
96 return {
"range/algorithm", HeaderName};
100 StringRef HeaderName;
106class BoostAlgorithmReplacer :
public BoostReplacer {
108 BoostAlgorithmReplacer(StringRef SubHeader,
109 ArrayRef<UseRangesCheck::Signature> Signatures,
111 : BoostReplacer(Signatures, IncludeSystem),
112 SubHeader((
"algorithm/" + SubHeader).str()) {}
113 std::pair<StringRef, StringRef>
114 getBoostName(
const NamedDecl &OriginalName)
const override {
115 return {
"algorithm", OriginalName.getName()};
118 std::pair<StringRef, StringRef>
119 getBoostHeader(
const NamedDecl &OriginalName)
const override {
120 return {SubHeader, OriginalName.getName()};
124 std::string SubHeader;
130class CustomBoostAlgorithmReplacer :
public BoostReplacer {
132 CustomBoostAlgorithmReplacer(StringRef SubHeader, StringRef HeaderName,
133 ArrayRef<UseRangesCheck::Signature> Signatures,
135 : BoostReplacer(Signatures, IncludeSystem),
136 SubHeader((
"algorithm/" + SubHeader).str()), HeaderName(HeaderName) {}
137 std::pair<StringRef, StringRef>
138 getBoostName(
const NamedDecl &OriginalName)
const override {
139 return {
"algorithm", OriginalName.getName()};
142 std::pair<StringRef, StringRef>
143 getBoostHeader(
const NamedDecl & )
const override {
144 return {SubHeader, HeaderName};
148 std::string SubHeader;
149 StringRef HeaderName;
153class MakeOverloadReplacer :
public UseRangesCheck::Replacer {
155 explicit MakeOverloadReplacer(ArrayRef<UseRangesCheck::Signature> Signatures)
156 : Signatures(Signatures) {}
158 ArrayRef<UseRangesCheck::Signature>
159 getReplacementSignatures()
const override {
163 std::optional<std::string>
164 getReplaceName(
const NamedDecl & )
const override {
168 std::optional<std::string>
169 getHeaderInclusion(
const NamedDecl & )
const override {
174 SmallVector<UseRangesCheck::Signature> Signatures;
179class FixedBoostReplace :
public BoostReplacer {
181 FixedBoostReplace(StringRef Header,
182 ArrayRef<UseRangesCheck::Signature> Signatures,
183 bool IncludeBoostSystem)
184 : BoostReplacer(Signatures, IncludeBoostSystem), Header(Header) {}
186 std::pair<StringRef, StringRef>
187 getBoostName(
const NamedDecl &OriginalName)
const override {
188 return {{}, OriginalName.getName()};
191 std::pair<StringRef, StringRef>
192 getBoostHeader(
const NamedDecl & )
const override {
205 static const Signature SingleSig = {{0}};
206 static const Signature TwoSig = {{0}, {2}};
207 static const auto AddFrom =
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});
217 static const auto AddFromStd =
218 [](llvm::IntrusiveRefCntPtr<UseRangesCheck::Replacer>
Replacer,
219 std::initializer_list<StringRef> Names) {
223 static const auto AddFromBoost =
224 [](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"});
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);
344 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};
llvm::SmallString< 256U > Name
std::vector< CodeCompletionResult > Results
std::vector< HeaderHandle > Path
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.
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
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 boost ranges vers...
ArrayRef< std::pair< StringRef, StringRef > > getFreeBeginEndMethods() const override
Gets the fully qualified names of begin and end functions.
UseRangesCheck(StringRef Name, ClangTidyContext *Context)
DiagnosticBuilder createDiag(const CallExpr &Call) override
Create a diagnostic for the CallExpr Override this to support custom diagnostic messages.
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
llvm::StringMap< ClangTidyValue > OptionMap