| //===--- UseRangesCheck.cpp - clang-tidy ----------------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "UseRangesCheck.h" |
| #include "clang/AST/Decl.h" |
| #include "llvm/ADT/ArrayRef.h" |
| #include "llvm/ADT/IntrusiveRefCntPtr.h" |
| #include "llvm/ADT/SmallVector.h" |
| #include "llvm/ADT/StringRef.h" |
| #include <initializer_list> |
| |
| // FixItHint - Let the docs script know that this class does provide fixits |
| |
| namespace clang::tidy::modernize { |
| |
| static constexpr const char *SingleRangeNames[] = { |
| "all_of", |
| "any_of", |
| "none_of", |
| "for_each", |
| "find", |
| "find_if", |
| "find_if_not", |
| "adjacent_find", |
| "copy", |
| "copy_if", |
| "copy_backward", |
| "move", |
| "move_backward", |
| "fill", |
| "transform", |
| "replace", |
| "replace_if", |
| "generate", |
| "remove", |
| "remove_if", |
| "remove_copy", |
| "remove_copy_if", |
| "unique", |
| "unique_copy", |
| "sample", |
| "partition_point", |
| "lower_bound", |
| "upper_bound", |
| "equal_range", |
| "binary_search", |
| "push_heap", |
| "pop_heap", |
| "make_heap", |
| "sort_heap", |
| "next_permutation", |
| "prev_permutation", |
| "reverse", |
| "reverse_copy", |
| "shift_left", |
| "shift_right", |
| "is_partitioned", |
| "partition", |
| "partition_copy", |
| "stable_partition", |
| "sort", |
| "stable_sort", |
| "is_sorted", |
| "is_sorted_until", |
| "is_heap", |
| "is_heap_until", |
| "max_element", |
| "min_element", |
| "minmax_element", |
| "uninitialized_copy", |
| "uninitialized_fill", |
| "uninitialized_move", |
| "uninitialized_default_construct", |
| "uninitialized_value_construct", |
| "destroy", |
| }; |
| |
| static constexpr const char *TwoRangeNames[] = { |
| "equal", |
| "mismatch", |
| "partial_sort_copy", |
| "includes", |
| "set_union", |
| "set_intersection", |
| "set_difference", |
| "set_symmetric_difference", |
| "merge", |
| "lexicographical_compare", |
| "find_end", |
| "search", |
| "is_permutation", |
| }; |
| |
| static constexpr const char *SinglePivotRangeNames[] = {"rotate", "rotate_copy", |
| "inplace_merge"}; |
| |
| namespace { |
| class StdReplacer : public utils::UseRangesCheck::Replacer { |
| public: |
| explicit StdReplacer(SmallVector<UseRangesCheck::Signature> Signatures) |
| : Signatures(std::move(Signatures)) {} |
| std::optional<std::string> |
| getReplaceName(const NamedDecl &OriginalName) const override { |
| return ("std::ranges::" + OriginalName.getName()).str(); |
| } |
| ArrayRef<UseRangesCheck::Signature> |
| getReplacementSignatures() const override { |
| return Signatures; |
| } |
| |
| private: |
| SmallVector<UseRangesCheck::Signature> Signatures; |
| }; |
| |
| class StdAlgorithmReplacer : public StdReplacer { |
| using StdReplacer::StdReplacer; |
| std::optional<std::string> |
| getHeaderInclusion(const NamedDecl & /*OriginalName*/) const override { |
| return "<algorithm>"; |
| } |
| }; |
| |
| class StdNumericReplacer : public StdReplacer { |
| using StdReplacer::StdReplacer; |
| std::optional<std::string> |
| getHeaderInclusion(const NamedDecl & /*OriginalName*/) const override { |
| return "<numeric>"; |
| } |
| }; |
| } // namespace |
| |
| utils::UseRangesCheck::ReplacerMap UseRangesCheck::getReplacerMap() const { |
| |
| utils::UseRangesCheck::ReplacerMap Result; |
| |
| // template<typename Iter> Func(Iter first, Iter last,...). |
| static const Signature SingleRangeArgs = {{0}}; |
| // template<typename Iter1, typename Iter2> |
| // Func(Iter1 first1, Iter1 last1, Iter2 first2, Iter2 last2,...). |
| static const Signature TwoRangeArgs = {{0}, {2}}; |
| |
| // template<typename Iter> Func(Iter first, Iter pivot, Iter last,...). |
| static const Signature SinglePivotRange = {{0, 2}}; |
| |
| static const Signature SingleRangeFunc[] = {SingleRangeArgs}; |
| |
| static const Signature TwoRangeFunc[] = {TwoRangeArgs}; |
| |
| static const Signature SinglePivotFunc[] = {SinglePivotRange}; |
| |
| static const std::pair<ArrayRef<Signature>, ArrayRef<const char *>> |
| AlgorithmNames[] = {{SingleRangeFunc, SingleRangeNames}, |
| {TwoRangeFunc, TwoRangeNames}, |
| {SinglePivotFunc, SinglePivotRangeNames}}; |
| SmallString<64> Buff; |
| for (const auto &[Signatures, Values] : AlgorithmNames) { |
| auto Replacer = llvm::makeIntrusiveRefCnt<StdAlgorithmReplacer>( |
| SmallVector<UseRangesCheck::Signature>{Signatures}); |
| for (const auto &Name : Values) { |
| Buff.assign({"::std::", Name}); |
| Result.try_emplace(Buff, Replacer); |
| } |
| } |
| if (getLangOpts().CPlusPlus23) |
| Result.try_emplace( |
| "::std::iota", |
| llvm::makeIntrusiveRefCnt<StdNumericReplacer>( |
| SmallVector<UseRangesCheck::Signature>{std::begin(SingleRangeFunc), |
| std::end(SingleRangeFunc)})); |
| 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; |
| } |
| ArrayRef<std::pair<StringRef, StringRef>> |
| UseRangesCheck::getFreeBeginEndMethods() const { |
| static const std::pair<StringRef, StringRef> Refs[] = { |
| {"::std::begin", "::std::end"}, {"::std::cbegin", "::std::cend"}}; |
| return Refs; |
| } |
| std::optional<UseRangesCheck::ReverseIteratorDescriptor> |
| UseRangesCheck::getReverseDescriptor() const { |
| static const std::pair<StringRef, StringRef> Refs[] = { |
| {"::std::rbegin", "::std::rend"}, {"::std::crbegin", "::std::crend"}}; |
| return ReverseIteratorDescriptor{UseReversePipe ? "std::views::reverse" |
| : "std::ranges::reverse_view", |
| "<ranges>", Refs, UseReversePipe}; |
| } |
| } // namespace clang::tidy::modernize |