mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-19 02:56:49 +00:00
[clang-tidy] Allow specifying pipe syntax for use-ranges checks (#98696)
Add `UseReversePipe` option to (boost|modernize)-use-ranges checks. This controls whether to create a reverse view using function syntax (`reverse(Range)`) or pipe syntax (`Range | reverse`)
This commit is contained in:
parent
31d4c97506
commit
87ca6386f9
@ -331,12 +331,15 @@ utils::UseRangesCheck::ReplacerMap UseRangesCheck::getReplacerMap() const {
|
||||
|
||||
UseRangesCheck::UseRangesCheck(StringRef Name, ClangTidyContext *Context)
|
||||
: utils::UseRangesCheck(Name, Context),
|
||||
IncludeBoostSystem(Options.get("IncludeBoostSystem", true)) {}
|
||||
IncludeBoostSystem(Options.get("IncludeBoostSystem", true)),
|
||||
UseReversePipe(Options.get("UseReversePipe", false)) {}
|
||||
|
||||
void UseRangesCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
|
||||
utils::UseRangesCheck::storeOptions(Opts);
|
||||
Options.store(Opts, "IncludeBoostSystem", IncludeBoostSystem);
|
||||
Options.store(Opts, "UseReversePipe", UseReversePipe);
|
||||
}
|
||||
|
||||
DiagnosticBuilder UseRangesCheck::createDiag(const CallExpr &Call) {
|
||||
DiagnosticBuilder D =
|
||||
diag(Call.getBeginLoc(), "use a %0 version of this algorithm");
|
||||
@ -362,10 +365,10 @@ UseRangesCheck::getReverseDescriptor() const {
|
||||
{"::boost::rbegin", "::boost::rend"},
|
||||
{"::boost::const_rbegin", "::boost::const_rend"},
|
||||
};
|
||||
return ReverseIteratorDescriptor{"boost::adaptors::reverse",
|
||||
IncludeBoostSystem
|
||||
? "<boost/range/adaptor/reversed.hpp>"
|
||||
: "boost/range/adaptor/reversed.hpp",
|
||||
Refs};
|
||||
return ReverseIteratorDescriptor{
|
||||
UseReversePipe ? "boost::adaptors::reversed" : "boost::adaptors::reverse",
|
||||
IncludeBoostSystem ? "<boost/range/adaptor/reversed.hpp>"
|
||||
: "boost/range/adaptor/reversed.hpp",
|
||||
Refs, UseReversePipe};
|
||||
}
|
||||
} // namespace clang::tidy::boost
|
||||
|
@ -36,6 +36,7 @@ public:
|
||||
|
||||
private:
|
||||
bool IncludeBoostSystem;
|
||||
bool UseReversePipe;
|
||||
};
|
||||
|
||||
} // namespace clang::tidy::boost
|
||||
|
@ -166,6 +166,15 @@ utils::UseRangesCheck::ReplacerMap UseRangesCheck::getReplacerMap() const {
|
||||
return Result;
|
||||
}
|
||||
|
||||
UseRangesCheck::UseRangesCheck(StringRef Name, ClangTidyContext *Context)
|
||||
: utils::UseRangesCheck(Name, Context),
|
||||
UseReversePipe(Options.get("UseReversePipe", false)) {}
|
||||
|
||||
void UseRangesCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
|
||||
utils::UseRangesCheck::storeOptions(Opts);
|
||||
Options.store(Opts, "UseReversePipe", UseReversePipe);
|
||||
}
|
||||
|
||||
bool UseRangesCheck::isLanguageVersionSupported(
|
||||
const LangOptions &LangOpts) const {
|
||||
return LangOpts.CPlusPlus20;
|
||||
@ -180,6 +189,8 @@ std::optional<UseRangesCheck::ReverseIteratorDescriptor>
|
||||
UseRangesCheck::getReverseDescriptor() const {
|
||||
static const std::pair<StringRef, StringRef> Refs[] = {
|
||||
{"::std::rbegin", "::std::rend"}, {"::std::crbegin", "::std::crend"}};
|
||||
return ReverseIteratorDescriptor{"std::views::reverse", "<ranges>", Refs};
|
||||
return ReverseIteratorDescriptor{UseReversePipe ? "std::views::reverse"
|
||||
: "std::ranges::reverse_view",
|
||||
"<ranges>", Refs, UseReversePipe};
|
||||
}
|
||||
} // namespace clang::tidy::modernize
|
||||
|
@ -20,7 +20,9 @@ namespace clang::tidy::modernize {
|
||||
/// http://clang.llvm.org/extra/clang-tidy/checks/modernize/use-ranges.html
|
||||
class UseRangesCheck : public utils::UseRangesCheck {
|
||||
public:
|
||||
using utils::UseRangesCheck::UseRangesCheck;
|
||||
UseRangesCheck(StringRef CheckName, ClangTidyContext *Context);
|
||||
|
||||
void storeOptions(ClangTidyOptions::OptionMap &Options) override;
|
||||
|
||||
ReplacerMap getReplacerMap() const override;
|
||||
|
||||
@ -31,6 +33,9 @@ public:
|
||||
getReverseDescriptor() const override;
|
||||
|
||||
bool isLanguageVersionSupported(const LangOptions &LangOpts) const override;
|
||||
|
||||
private:
|
||||
bool UseReversePipe;
|
||||
};
|
||||
|
||||
} // namespace clang::tidy::modernize
|
||||
|
@ -242,16 +242,20 @@ void UseRangesCheck::check(const MatchFinder::MatchResult &Result) {
|
||||
Diag << Inserter.createIncludeInsertion(
|
||||
Result.SourceManager->getFileID(Call->getBeginLoc()),
|
||||
*ReverseDescriptor->ReverseHeader);
|
||||
StringRef ArgText = Lexer::getSourceText(
|
||||
CharSourceRange::getTokenRange(ArgExpr->getSourceRange()),
|
||||
Result.Context->getSourceManager(), Result.Context->getLangOpts());
|
||||
SmallString<128> ReplaceText;
|
||||
if (ReverseDescriptor->IsPipeSyntax)
|
||||
ReplaceText.assign(
|
||||
{ArgText, " | ", ReverseDescriptor->ReverseAdaptorName});
|
||||
else
|
||||
ReplaceText.assign(
|
||||
{ReverseDescriptor->ReverseAdaptorName, "(", ArgText, ")"});
|
||||
Diag << FixItHint::CreateReplacement(
|
||||
Call->getArg(Replace == Indexes::Second ? Second : First)
|
||||
->getSourceRange(),
|
||||
SmallString<128>{
|
||||
ReverseDescriptor->ReverseAdaptorName, "(",
|
||||
Lexer::getSourceText(
|
||||
CharSourceRange::getTokenRange(ArgExpr->getSourceRange()),
|
||||
Result.Context->getSourceManager(),
|
||||
Result.Context->getLangOpts()),
|
||||
")"});
|
||||
ReplaceText);
|
||||
}
|
||||
ToRemove.push_back(Replace == Indexes::Second ? First : Second);
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ public:
|
||||
StringRef ReverseAdaptorName;
|
||||
std::optional<StringRef> ReverseHeader;
|
||||
ArrayRef<std::pair<StringRef, StringRef>> FreeReverseNames;
|
||||
bool IsPipeSyntax = false;
|
||||
};
|
||||
|
||||
class Replacer : public llvm::RefCountedBase<Replacer> {
|
||||
|
@ -154,8 +154,8 @@ Transforms to:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
auto AreSame = std::equal(boost::adaptors::reverse(Items1),
|
||||
boost::adaptors::reverse(Items2));
|
||||
auto AreSame = boost::range::equal(boost::adaptors::reverse(Items1),
|
||||
boost::adaptors::reverse(Items2));
|
||||
|
||||
Options
|
||||
-------
|
||||
@ -170,3 +170,18 @@ Options
|
||||
If `true` (default value) the boost headers are included as system headers
|
||||
with angle brackets (`#include <boost.hpp>`), otherwise quotes are used
|
||||
(`#include "boost.hpp"`).
|
||||
|
||||
.. option:: UseReversePipe
|
||||
|
||||
When `true` (default `false`), fixes which involve reverse ranges will use the
|
||||
pipe adaptor syntax instead of the function syntax.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
std::find(Items.rbegin(), Items.rend(), 0);
|
||||
|
||||
Transforms to:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
boost::range::find(Items | boost::adaptors::reversed, 0);
|
||||
|
@ -116,8 +116,8 @@ Transforms to:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
auto AreSame = std::equal(std::views::reverse(Items1),
|
||||
std::views::reverse(Items2));
|
||||
auto AreSame = std::ranges::equal(std::ranges::reverse_view(Items1),
|
||||
std::ranges::reverse_view(Items2));
|
||||
|
||||
Options
|
||||
-------
|
||||
@ -127,3 +127,17 @@ Options
|
||||
A string specifying which include-style is used, `llvm` or `google`. Default
|
||||
is `llvm`.
|
||||
|
||||
.. option:: UseReversePipe
|
||||
|
||||
When `true` (default `false`), fixes which involve reverse ranges will use the
|
||||
pipe adaptor syntax instead of the function syntax.
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
std::find(Items.rbegin(), Items.rend(), 0);
|
||||
|
||||
Transforms to:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
std::ranges::find(Items | std::views::reverse, 0);
|
||||
|
@ -0,0 +1,29 @@
|
||||
#ifndef USE_RANGES_FAKE_BOOST_H
|
||||
#define USE_RANGES_FAKE_BOOST_H
|
||||
|
||||
namespace boost {
|
||||
namespace range_adl_barrier {
|
||||
|
||||
template <typename T> void *begin(T &);
|
||||
template <typename T> void *end(T &);
|
||||
template <typename T> void *const_begin(const T &);
|
||||
template <typename T> void *const_end(const T &);
|
||||
} // namespace range_adl_barrier
|
||||
|
||||
using namespace range_adl_barrier;
|
||||
|
||||
template <typename T> void *rbegin(T &);
|
||||
template <typename T> void *rend(T &);
|
||||
|
||||
template <typename T> void *const_rbegin(T &);
|
||||
template <typename T> void *const_rend(T &);
|
||||
namespace algorithm {
|
||||
|
||||
template <class InputIterator, class T, class BinaryOperation>
|
||||
T reduce(InputIterator first, InputIterator last, T init, BinaryOperation bOp) {
|
||||
return init;
|
||||
}
|
||||
} // namespace algorithm
|
||||
} // namespace boost
|
||||
|
||||
#endif // USE_RANGES_FAKE_BOOST_H
|
@ -0,0 +1,99 @@
|
||||
#ifndef USE_RANGES_FAKE_STD_H
|
||||
#define USE_RANGES_FAKE_STD_H
|
||||
namespace std {
|
||||
|
||||
template <typename T> class vector {
|
||||
public:
|
||||
using iterator = T *;
|
||||
using const_iterator = const T *;
|
||||
using reverse_iterator = T*;
|
||||
using reverse_const_iterator = const T*;
|
||||
|
||||
constexpr const_iterator begin() const;
|
||||
constexpr const_iterator end() const;
|
||||
constexpr const_iterator cbegin() const;
|
||||
constexpr const_iterator cend() const;
|
||||
constexpr iterator begin();
|
||||
constexpr iterator end();
|
||||
constexpr reverse_const_iterator rbegin() const;
|
||||
constexpr reverse_const_iterator rend() const;
|
||||
constexpr reverse_const_iterator crbegin() const;
|
||||
constexpr reverse_const_iterator crend() const;
|
||||
constexpr reverse_iterator rbegin();
|
||||
constexpr reverse_iterator rend();
|
||||
};
|
||||
|
||||
template <typename Container> constexpr auto begin(const Container &Cont) {
|
||||
return Cont.begin();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto begin(Container &Cont) {
|
||||
return Cont.begin();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto end(const Container &Cont) {
|
||||
return Cont.end();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto end(Container &Cont) {
|
||||
return Cont.end();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto cbegin(const Container &Cont) {
|
||||
return Cont.cbegin();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto cend(const Container &Cont) {
|
||||
return Cont.cend();
|
||||
}
|
||||
// Find
|
||||
template< class InputIt, class T >
|
||||
InputIt find(InputIt first, InputIt last, const T& value);
|
||||
|
||||
template <typename Iter> void reverse(Iter begin, Iter end);
|
||||
|
||||
template <class InputIt1, class InputIt2>
|
||||
bool includes(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2);
|
||||
|
||||
template <class ForwardIt1, class ForwardIt2>
|
||||
bool is_permutation(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2,
|
||||
ForwardIt2 last2);
|
||||
|
||||
template <class BidirIt>
|
||||
bool next_permutation(BidirIt first, BidirIt last);
|
||||
|
||||
inline namespace inline_test{
|
||||
|
||||
template <class ForwardIt1, class ForwardIt2>
|
||||
bool equal(ForwardIt1 first1, ForwardIt1 last1,
|
||||
ForwardIt2 first2, ForwardIt2 last2);
|
||||
|
||||
template <class RandomIt>
|
||||
void push_heap(RandomIt first, RandomIt last);
|
||||
|
||||
template <class InputIt, class OutputIt, class UnaryPred>
|
||||
OutputIt copy_if(InputIt first, InputIt last, OutputIt d_first, UnaryPred pred);
|
||||
|
||||
template <class ForwardIt>
|
||||
ForwardIt is_sorted_until(ForwardIt first, ForwardIt last);
|
||||
|
||||
template <class InputIt>
|
||||
void reduce(InputIt first, InputIt last);
|
||||
|
||||
template <class InputIt, class T>
|
||||
T reduce(InputIt first, InputIt last, T init);
|
||||
|
||||
template <class InputIt, class T, class BinaryOp>
|
||||
T reduce(InputIt first, InputIt last, T init, BinaryOp op) {
|
||||
// Need a definition to suppress undefined_internal_type when invoked with lambda
|
||||
return init;
|
||||
}
|
||||
|
||||
template <class InputIt, class T>
|
||||
T accumulate(InputIt first, InputIt last, T init);
|
||||
|
||||
} // namespace inline_test
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // USE_RANGES_FAKE_STD_H
|
@ -0,0 +1,18 @@
|
||||
// RUN: %check_clang_tidy -std=c++14 %s boost-use-ranges %t -check-suffixes=,PIPE \
|
||||
// RUN: -config="{CheckOptions: { \
|
||||
// RUN: boost-use-ranges.UseReversePipe: true }}" -- -I %S/Inputs/use-ranges/
|
||||
// RUN: %check_clang_tidy -std=c++14 %s boost-use-ranges %t -check-suffixes=,NOPIPE -- -I %S/Inputs/use-ranges/
|
||||
|
||||
// CHECK-FIXES: #include <boost/algorithm/cxx11/is_sorted.hpp>
|
||||
// CHECK-FIXES: #include <boost/range/adaptor/reversed.hpp>
|
||||
|
||||
#include "fake_std.h"
|
||||
|
||||
void stdLib() {
|
||||
std::vector<int> I;
|
||||
std::is_sorted_until(I.rbegin(), I.rend());
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a boost version of this algorithm
|
||||
// CHECK-FIXES-NOPIPE: boost::algorithm::is_sorted_until(boost::adaptors::reverse(I));
|
||||
// CHECK-FIXES-PIPE: boost::algorithm::is_sorted_until(I | boost::adaptors::reversed);
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
// RUN: %check_clang_tidy -std=c++14 %s boost-use-ranges %t
|
||||
// RUN: %check_clang_tidy -std=c++17 %s boost-use-ranges %t -check-suffixes=,CPP17
|
||||
// RUN: %check_clang_tidy -std=c++14 %s boost-use-ranges %t -- -- -I %S/Inputs/use-ranges/
|
||||
// RUN: %check_clang_tidy -std=c++17 %s boost-use-ranges %t -check-suffixes=,CPP17 -- -I %S/Inputs/use-ranges/
|
||||
|
||||
// CHECK-FIXES: #include <boost/range/algorithm/find.hpp>
|
||||
// CHECK-FIXES: #include <boost/range/algorithm/reverse.hpp>
|
||||
@ -13,111 +13,8 @@
|
||||
// CHECK-FIXES: #include <boost/range/adaptor/reversed.hpp>
|
||||
// CHECK-FIXES: #include <boost/range/numeric.hpp>
|
||||
|
||||
namespace std {
|
||||
|
||||
template <typename T> class vector {
|
||||
public:
|
||||
using iterator = T *;
|
||||
using const_iterator = const T *;
|
||||
constexpr const_iterator begin() const;
|
||||
constexpr const_iterator end() const;
|
||||
constexpr const_iterator cbegin() const;
|
||||
constexpr const_iterator cend() const;
|
||||
constexpr iterator begin();
|
||||
constexpr iterator end();
|
||||
};
|
||||
|
||||
template <typename Container> constexpr auto begin(const Container &Cont) {
|
||||
return Cont.begin();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto begin(Container &Cont) {
|
||||
return Cont.begin();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto end(const Container &Cont) {
|
||||
return Cont.end();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto end(Container &Cont) {
|
||||
return Cont.end();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto cbegin(const Container &Cont) {
|
||||
return Cont.cbegin();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto cend(const Container &Cont) {
|
||||
return Cont.cend();
|
||||
}
|
||||
// Find
|
||||
template< class InputIt, class T >
|
||||
InputIt find(InputIt first, InputIt last, const T& value);
|
||||
|
||||
template <typename Iter> void reverse(Iter begin, Iter end);
|
||||
|
||||
template <class InputIt1, class InputIt2>
|
||||
bool includes(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2);
|
||||
|
||||
template <class ForwardIt1, class ForwardIt2>
|
||||
bool is_permutation(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2,
|
||||
ForwardIt2 last2);
|
||||
|
||||
template <class BidirIt>
|
||||
bool next_permutation(BidirIt first, BidirIt last);
|
||||
|
||||
template <class ForwardIt1, class ForwardIt2>
|
||||
bool equal(ForwardIt1 first1, ForwardIt1 last1,
|
||||
ForwardIt2 first2, ForwardIt2 last2);
|
||||
|
||||
template <class RandomIt>
|
||||
void push_heap(RandomIt first, RandomIt last);
|
||||
|
||||
template <class InputIt, class OutputIt, class UnaryPred>
|
||||
OutputIt copy_if(InputIt first, InputIt last, OutputIt d_first, UnaryPred pred);
|
||||
|
||||
template <class ForwardIt>
|
||||
ForwardIt is_sorted_until(ForwardIt first, ForwardIt last);
|
||||
|
||||
template <class InputIt>
|
||||
void reduce(InputIt first, InputIt last);
|
||||
|
||||
template <class InputIt, class T>
|
||||
T reduce(InputIt first, InputIt last, T init);
|
||||
|
||||
template <class InputIt, class T, class BinaryOp>
|
||||
T reduce(InputIt first, InputIt last, T init, BinaryOp op) {
|
||||
// Need a definition to suppress undefined_internal_type when invoked with lambda
|
||||
return init;
|
||||
}
|
||||
|
||||
template <class InputIt, class T>
|
||||
T accumulate(InputIt first, InputIt last, T init);
|
||||
|
||||
} // namespace std
|
||||
|
||||
namespace boost {
|
||||
namespace range_adl_barrier {
|
||||
template <typename T> void *begin(T &);
|
||||
template <typename T> void *end(T &);
|
||||
template <typename T> void *const_begin(const T &);
|
||||
template <typename T> void *const_end(const T &);
|
||||
} // namespace range_adl_barrier
|
||||
using namespace range_adl_barrier;
|
||||
|
||||
template <typename T> void *rbegin(T &);
|
||||
template <typename T> void *rend(T &);
|
||||
|
||||
template <typename T> void *const_rbegin(T &);
|
||||
template <typename T> void *const_rend(T &);
|
||||
namespace algorithm {
|
||||
|
||||
template <class InputIterator, class T, class BinaryOperation>
|
||||
T reduce(InputIterator first, InputIterator last, T init, BinaryOperation bOp) {
|
||||
return init;
|
||||
}
|
||||
} // namespace algorithm
|
||||
} // namespace boost
|
||||
#include "fake_boost.h"
|
||||
#include "fake_std.h"
|
||||
|
||||
bool returnTrue(int val) {
|
||||
return true;
|
||||
|
@ -0,0 +1,111 @@
|
||||
#ifndef USE_RANGES_FAKE_STD_H
|
||||
#define USE_RANGES_FAKE_STD_H
|
||||
|
||||
namespace std {
|
||||
|
||||
template <typename T> class vector {
|
||||
public:
|
||||
using iterator = T *;
|
||||
using const_iterator = const T *;
|
||||
using reverse_iterator = T*;
|
||||
using reverse_const_iterator = const T*;
|
||||
|
||||
constexpr const_iterator begin() const;
|
||||
constexpr const_iterator end() const;
|
||||
constexpr const_iterator cbegin() const;
|
||||
constexpr const_iterator cend() const;
|
||||
constexpr iterator begin();
|
||||
constexpr iterator end();
|
||||
constexpr reverse_const_iterator rbegin() const;
|
||||
constexpr reverse_const_iterator rend() const;
|
||||
constexpr reverse_const_iterator crbegin() const;
|
||||
constexpr reverse_const_iterator crend() const;
|
||||
constexpr reverse_iterator rbegin();
|
||||
constexpr reverse_iterator rend();
|
||||
};
|
||||
|
||||
template <typename Container> constexpr auto begin(const Container &Cont) {
|
||||
return Cont.begin();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto begin(Container &Cont) {
|
||||
return Cont.begin();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto end(const Container &Cont) {
|
||||
return Cont.end();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto end(Container &Cont) {
|
||||
return Cont.end();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto cbegin(const Container &Cont) {
|
||||
return Cont.cbegin();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto cend(const Container &Cont) {
|
||||
return Cont.cend();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto rbegin(const Container &Cont) {
|
||||
return Cont.rbegin();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto rbegin(Container &Cont) {
|
||||
return Cont.rbegin();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto rend(const Container &Cont) {
|
||||
return Cont.rend();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto rend(Container &Cont) {
|
||||
return Cont.rend();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto crbegin(const Container &Cont) {
|
||||
return Cont.crbegin();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto crend(const Container &Cont) {
|
||||
return Cont.crend();
|
||||
}
|
||||
// Find
|
||||
template< class InputIt, class T >
|
||||
InputIt find( InputIt first, InputIt last, const T& value );
|
||||
|
||||
// Reverse
|
||||
template <typename Iter> void reverse(Iter begin, Iter end);
|
||||
|
||||
// Includes
|
||||
template <class InputIt1, class InputIt2>
|
||||
bool includes(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2);
|
||||
|
||||
// IsPermutation
|
||||
template <class ForwardIt1, class ForwardIt2>
|
||||
bool is_permutation(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2);
|
||||
template <class ForwardIt1, class ForwardIt2>
|
||||
bool is_permutation(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2,
|
||||
ForwardIt2 last2);
|
||||
|
||||
// Equal
|
||||
template <class InputIt1, class InputIt2>
|
||||
bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2);
|
||||
|
||||
template <class InputIt1, class InputIt2>
|
||||
bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2);
|
||||
|
||||
template <class InputIt1, class InputIt2, class BinaryPred>
|
||||
bool equal(InputIt1 first1, InputIt1 last1,
|
||||
InputIt2 first2, InputIt2 last2, BinaryPred p) {
|
||||
// Need a definition to suppress undefined_internal_type when invoked with lambda
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class ForwardIt, class T>
|
||||
void iota(ForwardIt first, ForwardIt last, T value);
|
||||
|
||||
} // namespace std
|
||||
|
||||
#endif // USE_RANGES_FAKE_STD_H
|
@ -0,0 +1,18 @@
|
||||
// RUN: %check_clang_tidy -std=c++20 %s modernize-use-ranges %t -check-suffixes=,PIPE \
|
||||
// RUN: -config="{CheckOptions: { \
|
||||
// RUN: modernize-use-ranges.UseReversePipe: true }}" -- -I %S/Inputs/use-ranges/
|
||||
// RUN: %check_clang_tidy -std=c++20 %s modernize-use-ranges %t -check-suffixes=,NOPIPE -- -I %S/Inputs/use-ranges/
|
||||
|
||||
// CHECK-FIXES: #include <algorithm>
|
||||
// CHECK-FIXES: #include <ranges>
|
||||
|
||||
#include "fake_std.h"
|
||||
|
||||
void stdLib() {
|
||||
std::vector<int> I;
|
||||
std::find(I.rbegin(), I.rend(), 0);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm
|
||||
// CHECK-FIXES-NOPIPE: std::ranges::find(std::ranges::reverse_view(I), 0);
|
||||
// CHECK-FIXES-PIPE: std::ranges::find(I | std::views::reverse, 0);
|
||||
|
||||
}
|
@ -1,116 +1,11 @@
|
||||
// RUN: %check_clang_tidy -std=c++20 %s modernize-use-ranges %t
|
||||
// RUN: %check_clang_tidy -std=c++23 %s modernize-use-ranges %t -check-suffixes=,CPP23
|
||||
// RUN: %check_clang_tidy -std=c++20 %s modernize-use-ranges %t -- -- -I %S/Inputs/use-ranges/
|
||||
// RUN: %check_clang_tidy -std=c++23 %s modernize-use-ranges %t -check-suffixes=,CPP23 -- -I %S/Inputs/use-ranges/
|
||||
|
||||
// CHECK-FIXES: #include <algorithm>
|
||||
// CHECK-FIXES-CPP23: #include <numeric>
|
||||
// CHECK-FIXES: #include <ranges>
|
||||
|
||||
namespace std {
|
||||
|
||||
template <typename T> class vector {
|
||||
public:
|
||||
using iterator = T *;
|
||||
using const_iterator = const T *;
|
||||
using reverse_iterator = T*;
|
||||
using reverse_const_iterator = const T*;
|
||||
|
||||
constexpr const_iterator begin() const;
|
||||
constexpr const_iterator end() const;
|
||||
constexpr const_iterator cbegin() const;
|
||||
constexpr const_iterator cend() const;
|
||||
constexpr iterator begin();
|
||||
constexpr iterator end();
|
||||
constexpr reverse_const_iterator rbegin() const;
|
||||
constexpr reverse_const_iterator rend() const;
|
||||
constexpr reverse_const_iterator crbegin() const;
|
||||
constexpr reverse_const_iterator crend() const;
|
||||
constexpr reverse_iterator rbegin();
|
||||
constexpr reverse_iterator rend();
|
||||
};
|
||||
|
||||
template <typename Container> constexpr auto begin(const Container &Cont) {
|
||||
return Cont.begin();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto begin(Container &Cont) {
|
||||
return Cont.begin();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto end(const Container &Cont) {
|
||||
return Cont.end();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto end(Container &Cont) {
|
||||
return Cont.end();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto cbegin(const Container &Cont) {
|
||||
return Cont.cbegin();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto cend(const Container &Cont) {
|
||||
return Cont.cend();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto rbegin(const Container &Cont) {
|
||||
return Cont.rbegin();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto rbegin(Container &Cont) {
|
||||
return Cont.rbegin();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto rend(const Container &Cont) {
|
||||
return Cont.rend();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto rend(Container &Cont) {
|
||||
return Cont.rend();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto crbegin(const Container &Cont) {
|
||||
return Cont.crbegin();
|
||||
}
|
||||
|
||||
template <typename Container> constexpr auto crend(const Container &Cont) {
|
||||
return Cont.crend();
|
||||
}
|
||||
// Find
|
||||
template< class InputIt, class T >
|
||||
InputIt find( InputIt first, InputIt last, const T& value );
|
||||
|
||||
// Reverse
|
||||
template <typename Iter> void reverse(Iter begin, Iter end);
|
||||
|
||||
// Includes
|
||||
template <class InputIt1, class InputIt2>
|
||||
bool includes(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2);
|
||||
|
||||
// IsPermutation
|
||||
template <class ForwardIt1, class ForwardIt2>
|
||||
bool is_permutation(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2);
|
||||
template <class ForwardIt1, class ForwardIt2>
|
||||
bool is_permutation(ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2,
|
||||
ForwardIt2 last2);
|
||||
|
||||
// Equal
|
||||
template <class InputIt1, class InputIt2>
|
||||
bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2);
|
||||
|
||||
template <class InputIt1, class InputIt2>
|
||||
bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2);
|
||||
|
||||
template <class InputIt1, class InputIt2, class BinaryPred>
|
||||
bool equal(InputIt1 first1, InputIt1 last1,
|
||||
InputIt2 first2, InputIt2 last2, BinaryPred p) {
|
||||
// Need a definition to suppress undefined_internal_type when invoked with lambda
|
||||
return true;
|
||||
}
|
||||
|
||||
template <class ForwardIt, class T>
|
||||
void iota(ForwardIt first, ForwardIt last, T value);
|
||||
|
||||
} // namespace std
|
||||
#include "fake_std.h"
|
||||
|
||||
void Positives() {
|
||||
std::vector<int> I, J;
|
||||
@ -179,15 +74,15 @@ void Reverse(){
|
||||
std::vector<int> I, J;
|
||||
std::find(I.rbegin(), I.rend(), 0);
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm
|
||||
// CHECK-FIXES: std::ranges::find(std::views::reverse(I), 0);
|
||||
// CHECK-FIXES: std::ranges::find(std::ranges::reverse_view(I), 0);
|
||||
|
||||
std::equal(std::rbegin(I), std::rend(I), J.begin(), J.end());
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm
|
||||
// CHECK-FIXES: std::ranges::equal(std::views::reverse(I), J);
|
||||
// CHECK-FIXES: std::ranges::equal(std::ranges::reverse_view(I), J);
|
||||
|
||||
std::equal(I.begin(), I.end(), std::crbegin(J), std::crend(J));
|
||||
// CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm
|
||||
// CHECK-FIXES: std::ranges::equal(I, std::views::reverse(J));
|
||||
// CHECK-FIXES: std::ranges::equal(I, std::ranges::reverse_view(J));
|
||||
}
|
||||
|
||||
void Negatives() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user