From 070a713efb6e860fd7d5b0af2d2b8e4fe35ff196 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Tue, 5 Aug 2025 01:15:02 +0300 Subject: [PATCH 1/2] [clang-tidy] Add new check 'llvm-use-ranges' --- .../clang-tidy/llvm/CMakeLists.txt | 1 + .../clang-tidy/llvm/LLVMTidyModule.cpp | 2 + .../clang-tidy/llvm/UseRangesCheck.cpp | 90 ++++++++++++ .../clang-tidy/llvm/UseRangesCheck.h | 33 +++++ clang-tools-extra/docs/ReleaseNotes.rst | 6 + .../docs/clang-tidy/checks/list.rst | 3 +- .../clang-tidy/checks/llvm/use-ranges.rst | 58 ++++++++ .../clang-tidy/checkers/llvm/use-ranges.cpp | 128 ++++++++++++++++++ 8 files changed, 320 insertions(+), 1 deletion(-) create mode 100644 clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp create mode 100644 clang-tools-extra/clang-tidy/llvm/UseRangesCheck.h create mode 100644 clang-tools-extra/docs/clang-tidy/checks/llvm/use-ranges.rst create mode 100644 clang-tools-extra/test/clang-tidy/checkers/llvm/use-ranges.cpp diff --git a/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt b/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt index 41386cdb55b1f..78ef0444305ff 100644 --- a/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/llvm/CMakeLists.txt @@ -12,6 +12,7 @@ add_clang_library(clangTidyLLVMModule STATIC PreferStaticOverAnonymousNamespaceCheck.cpp TwineLocalCheck.cpp UseNewMLIROpBuilderCheck.cpp + UseRangesCheck.cpp LINK_LIBS clangTidy diff --git a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp index c7c61fd1649cc..c1f78caf44d16 100644 --- a/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/llvm/LLVMTidyModule.cpp @@ -19,6 +19,7 @@ #include "PreferStaticOverAnonymousNamespaceCheck.h" #include "TwineLocalCheck.h" #include "UseNewMLIROpBuilderCheck.h" +#include "UseRangesCheck.h" namespace clang::tidy { namespace llvm_check { @@ -43,6 +44,7 @@ class LLVMModule : public ClangTidyModule { CheckFactories.registerCheck("llvm-twine-local"); CheckFactories.registerCheck( "llvm-use-new-mlir-op-builder"); + CheckFactories.registerCheck("llvm-use-ranges"); } ClangTidyOptions getModuleOptions() override { diff --git a/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp b/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp new file mode 100644 index 0000000000000..0e11a017c60d5 --- /dev/null +++ b/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp @@ -0,0 +1,90 @@ +//===--- 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" + +namespace clang::tidy::llvm_check { + +namespace { + +class StdToLLVMReplacer : public utils::UseRangesCheck::Replacer { +public: + explicit StdToLLVMReplacer( + ArrayRef Signatures) + : Signatures(Signatures) {} + + ArrayRef + getReplacementSignatures() const override { + return Signatures; + } + + std::optional + getReplaceName(const NamedDecl &OriginalName) const override { + return ("llvm::" + OriginalName.getName()).str(); + } + + std::optional + getHeaderInclusion(const NamedDecl &) const override { + return "llvm/ADT/STLExtras.h"; + } + +private: + SmallVector Signatures; +}; + +} // namespace + +utils::UseRangesCheck::ReplacerMap UseRangesCheck::getReplacerMap() const { + ReplacerMap Results; + + static const Signature SingleSig = {{0}}; + static const Signature TwoSig = {{0}, {2}}; + + const auto AddStdToLLVM = + [&Results](llvm::IntrusiveRefCntPtr Replacer, + std::initializer_list Names) { + for (const auto &Name : Names) { + Results.try_emplace(("::std::" + Name).str(), Replacer); + } + }; + + // Single range algorithms + AddStdToLLVM(llvm::makeIntrusiveRefCnt(SingleSig), + {"all_of", "any_of", "none_of", "for_each", + "find", "find_if", "find_if_not", "count", + "count_if", "transform", "replace", "remove_if", + "sort", "partition", "is_sorted", "min_element", + "max_element", "binary_search", "lower_bound", "upper_bound", + "unique", "copy", "copy_if", "fill"}); + + // Two range algorithms + AddStdToLLVM(llvm::makeIntrusiveRefCnt(TwoSig), + {"equal", "mismatch"}); + + return Results; +} + +UseRangesCheck::UseRangesCheck(StringRef Name, ClangTidyContext *Context) + : utils::UseRangesCheck(Name, Context) {} + +DiagnosticBuilder UseRangesCheck::createDiag(const CallExpr &Call) { + return diag(Call.getBeginLoc(), "use a llvm range-based algorithm"); +} + +ArrayRef> +UseRangesCheck::getFreeBeginEndMethods() const { + static const std::pair Refs[] = { + {"::std::begin", "::std::end"}, + {"::std::cbegin", "::std::cend"}, + {"::std::rbegin", "::std::rend"}, + {"::std::crbegin", "::std::crend"}, + }; + return Refs; +} + +} // namespace clang::tidy::llvm_check diff --git a/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.h b/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.h new file mode 100644 index 0000000000000..e9904e11ced36 --- /dev/null +++ b/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.h @@ -0,0 +1,33 @@ +//===--- UseRangesCheck.h - clang-tidy --------------------------*- C++ -*-===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_USERANGESCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_USERANGESCHECK_H + +#include "../utils/UseRangesCheck.h" + +namespace clang::tidy::llvm_check { + +/// Finds calls to STL iterator algorithms that can be replaced with LLVM +/// range-based algorithms from `llvm/ADT/STLExtras.h`. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/llvm/use-ranges.html +class UseRangesCheck : public utils::UseRangesCheck { +public: + UseRangesCheck(StringRef Name, ClangTidyContext *Context); + + ReplacerMap getReplacerMap() const override; + DiagnosticBuilder createDiag(const CallExpr &Call) override; + ArrayRef> + getFreeBeginEndMethods() const override; +}; + +} // namespace clang::tidy::llvm_check + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LLVM_USERANGESCHECK_H diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 85b31bc0b42a6..823ce382c61c6 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -124,6 +124,12 @@ New checks Checks for uses of MLIR's old/to be deprecated ``OpBuilder::create`` form and suggests using ``T::create`` instead. +- New :doc:`llvm-use-ranges + ` check. + + Detects calls to standard library iterator algorithms that could be replaced + with LLVM range-based algorithms from ``llvm/ADT/STLExtras.h``. + New check aliases ^^^^^^^^^^^^^^^^^ diff --git a/clang-tools-extra/docs/clang-tidy/checks/list.rst b/clang-tools-extra/docs/clang-tidy/checks/list.rst index b6444eb3c9aec..87c24cc1dfdfe 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/list.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/list.rst @@ -248,12 +248,13 @@ Clang-Tidy Checks :doc:`linuxkernel-must-check-errs `, :doc:`llvm-header-guard `, :doc:`llvm-include-order `, "Yes" - :doc:`llvm-use-new-mlir-op-builder `, "Yes" :doc:`llvm-namespace-comment `, :doc:`llvm-prefer-isa-or-dyn-cast-in-conditionals `, "Yes" :doc:`llvm-prefer-register-over-unsigned `, "Yes" :doc:`llvm-prefer-static-over-anonymous-namespace `, :doc:`llvm-twine-local `, "Yes" + :doc:`llvm-use-new-mlir-op-builder `, "Yes" + :doc:`llvm-use-ranges `, "Yes" :doc:`llvmlibc-callee-namespace `, :doc:`llvmlibc-implementation-in-namespace `, :doc:`llvmlibc-inline-function-decl `, "Yes" diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvm/use-ranges.rst b/clang-tools-extra/docs/clang-tidy/checks/llvm/use-ranges.rst new file mode 100644 index 0000000000000..a5fc83ad5d2c2 --- /dev/null +++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/use-ranges.rst @@ -0,0 +1,58 @@ +.. title:: clang-tidy - llvm-use-ranges + +llvm-use-ranges +=============== + +Detects calls to standard library iterator algorithms that could be replaced +with LLVM range-based algorithms from ``llvm/ADT/STLExtras.h``. + +Example +------- + +.. code-block:: c++ + + auto it = std::find(vec.begin(), vec.end(), value); + bool all = std::all_of(vec.begin(), vec.end(), + [](int x) { return x > 0; }); + +Transforms to: + +.. code-block:: c++ + + auto it = llvm::find(vec, value); + bool all = llvm::all_of(vec, [](int x) { return x > 0; }); + +Supported algorithms +-------------------- + +Calls to the following ``std`` library algorithms are checked: + +``std::all_of``, +``std::any_of``, +``std::binary_search``, +``std::copy``, +``std::copy_if``, +``std::count``, +``std::count_if``, +``std::equal``, +``std::fill``, +``std::find``, +``std::find_if``, +``std::find_if_not``, +``std::for_each``, +``std::is_sorted``, +``std::lower_bound``, +``std::max_element``, +``std::min_element``, +``std::mismatch``, +``std::none_of``, +``std::partition``, +``std::remove_if``, +``std::replace``, +``std::sort``, +``std::transform``, +``std::unique``, +``std::upper_bound``. + +The check will add the necessary ``#include "llvm/ADT/STLExtras.h"`` directive +when applying fixes. diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/use-ranges.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-ranges.cpp new file mode 100644 index 0000000000000..3c42caa8cc1d1 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-ranges.cpp @@ -0,0 +1,128 @@ +// RUN: %check_clang_tidy %s llvm-use-ranges %t + +// Test that the header is included +// CHECK-FIXES: #include "llvm/ADT/STLExtras.h" + +namespace std { + +template class vector { +public: + using iterator = T *; + using const_iterator = const T *; + + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + const_iterator cbegin() const; + const_iterator cend() const; +}; + +template T* begin(T (&arr)[5]); +template T* end(T (&arr)[5]); + +template +InputIt find(InputIt first, InputIt last, const T &value); + +template +void sort(RandomIt first, RandomIt last); + +template +bool all_of(InputIt first, InputIt last, UnaryPredicate p); + +template +UnaryFunction for_each(InputIt first, InputIt last, UnaryFunction f); + +template +ForwardIt remove(ForwardIt first, ForwardIt last, const T& value); + +template +ForwardIt min_element(ForwardIt first, ForwardIt last); + +template +bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2); + +template +bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2); + +template +OutputIt copy(InputIt first, InputIt last, OutputIt d_first); + +template +void fill(ForwardIt first, ForwardIt last, const T& value); + +template +void reverse(BidirIt first, BidirIt last); + +template +ForwardIt unique(ForwardIt first, ForwardIt last); + +template +bool is_sorted(ForwardIt first, ForwardIt last); + +} // namespace std + +bool is_even(int x); +void double_ref(int& x); + +void test_positive() { + std::vector vec; + int arr[5] = {1, 2, 3, 4, 5}; + + auto it1 = std::find(vec.begin(), vec.end(), 3); + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use a llvm range-based algorithm + // CHECK-FIXES: auto it1 = llvm::find(vec, 3); + + auto it2 = std::find(std::begin(arr), std::end(arr), 3); + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use a llvm range-based algorithm + // CHECK-FIXES: auto it2 = llvm::find(arr, 3); + + std::sort(vec.begin(), vec.end()); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a llvm range-based algorithm + // CHECK-FIXES: llvm::sort(vec); + + bool all = std::all_of(vec.begin(), vec.end(), is_even); + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use a llvm range-based algorithm + // CHECK-FIXES: bool all = llvm::all_of(vec, is_even); + + std::for_each(vec.begin(), vec.end(), double_ref); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a llvm range-based algorithm + // CHECK-FIXES: llvm::for_each(vec, double_ref); + + auto min_it = std::min_element(vec.begin(), vec.end()); + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use a llvm range-based algorithm + // CHECK-FIXES: auto min_it = llvm::min_element(vec); + + std::vector vec2; + bool eq = std::equal(vec.begin(), vec.end(), vec2.begin(), vec2.end()); + // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use a llvm range-based algorithm + // CHECK-FIXES: bool eq = llvm::equal(vec, vec2); + + std::copy(vec.begin(), vec.end(), vec2.begin()); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a llvm range-based algorithm + // CHECK-FIXES: llvm::copy(vec, vec2.begin()); + + std::fill(vec.begin(), vec.end(), 0); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a llvm range-based algorithm + // CHECK-FIXES: llvm::fill(vec, 0); + + auto last = std::unique(vec.begin(), vec.end()); + // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use a llvm range-based algorithm + // CHECK-FIXES: auto last = llvm::unique(vec); + + bool sorted = std::is_sorted(vec.begin(), vec.end()); + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use a llvm range-based algorithm + // CHECK-FIXES: bool sorted = llvm::is_sorted(vec); +} + +void test_negative() { + std::vector v; + + //non-begin/end iterators + auto it1 = std::find(v.begin() + 1, v.end(), 2); + auto it2 = std::find(v.begin(), v.end() - 1, 2); + + // Using different containers (3-arg equal) + std::vector v2; + bool eq = std::equal(v.begin(), v.end(), v2.begin()); +} From 1b555b2c47be50f3fe4a59dd3a90f9da456261c1 Mon Sep 17 00:00:00 2001 From: Victor Baranov Date: Tue, 5 Aug 2025 10:38:30 +0300 Subject: [PATCH 2/2] adjust supported algorithms and convert `llvm` -> `LLVM` --- .../clang-tidy/llvm/UseRangesCheck.cpp | 19 +++++---- .../clang-tidy/checks/llvm/use-ranges.rst | 4 +- .../clang-tidy/checkers/llvm/use-ranges.cpp | 39 ++++++++++++------- 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp b/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp index 0e11a017c60d5..4c9eb923c4dd1 100644 --- a/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp +++ b/clang-tools-extra/clang-tidy/llvm/UseRangesCheck.cpp @@ -55,16 +55,19 @@ utils::UseRangesCheck::ReplacerMap UseRangesCheck::getReplacerMap() const { // Single range algorithms AddStdToLLVM(llvm::makeIntrusiveRefCnt(SingleSig), - {"all_of", "any_of", "none_of", "for_each", - "find", "find_if", "find_if_not", "count", - "count_if", "transform", "replace", "remove_if", - "sort", "partition", "is_sorted", "min_element", - "max_element", "binary_search", "lower_bound", "upper_bound", - "unique", "copy", "copy_if", "fill"}); + {"all_of", "any_of", "none_of", + "for_each", "find", "find_if", + "find_if_not", "count", "count_if", + "transform", "replace", "remove_if", + "stable_sort", "partition", "partition_point", + "is_sorted", "min_element", "max_element", + "binary_search", "lower_bound", "upper_bound", + "unique", "copy", "copy_if", + "fill"}); // Two range algorithms AddStdToLLVM(llvm::makeIntrusiveRefCnt(TwoSig), - {"equal", "mismatch"}); + {"equal", "mismatch", "includes"}); return Results; } @@ -73,7 +76,7 @@ UseRangesCheck::UseRangesCheck(StringRef Name, ClangTidyContext *Context) : utils::UseRangesCheck(Name, Context) {} DiagnosticBuilder UseRangesCheck::createDiag(const CallExpr &Call) { - return diag(Call.getBeginLoc(), "use a llvm range-based algorithm"); + return diag(Call.getBeginLoc(), "use a LLVM range-based algorithm"); } ArrayRef> diff --git a/clang-tools-extra/docs/clang-tidy/checks/llvm/use-ranges.rst b/clang-tools-extra/docs/clang-tidy/checks/llvm/use-ranges.rst index a5fc83ad5d2c2..34352ffcb9481 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/llvm/use-ranges.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/llvm/use-ranges.rst @@ -40,6 +40,7 @@ Calls to the following ``std`` library algorithms are checked: ``std::find_if``, ``std::find_if_not``, ``std::for_each``, +``std::includes``, ``std::is_sorted``, ``std::lower_bound``, ``std::max_element``, @@ -47,9 +48,10 @@ Calls to the following ``std`` library algorithms are checked: ``std::mismatch``, ``std::none_of``, ``std::partition``, +``std::partition_point``, ``std::remove_if``, ``std::replace``, -``std::sort``, +``std::stable_sort``, ``std::transform``, ``std::unique``, ``std::upper_bound``. diff --git a/clang-tools-extra/test/clang-tidy/checkers/llvm/use-ranges.cpp b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-ranges.cpp index 3c42caa8cc1d1..70bdf1fed8417 100644 --- a/clang-tools-extra/test/clang-tidy/checkers/llvm/use-ranges.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/llvm/use-ranges.cpp @@ -27,6 +27,9 @@ InputIt find(InputIt first, InputIt last, const T &value); template void sort(RandomIt first, RandomIt last); +template +void stable_sort(RandomIt first, RandomIt last); + template bool all_of(InputIt first, InputIt last, UnaryPredicate p); @@ -60,6 +63,9 @@ ForwardIt unique(ForwardIt first, ForwardIt last); template bool is_sorted(ForwardIt first, ForwardIt last); +template +bool includes(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2); + } // namespace std bool is_even(int x); @@ -70,54 +76,61 @@ void test_positive() { int arr[5] = {1, 2, 3, 4, 5}; auto it1 = std::find(vec.begin(), vec.end(), 3); - // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use a llvm range-based algorithm + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use a LLVM range-based algorithm // CHECK-FIXES: auto it1 = llvm::find(vec, 3); auto it2 = std::find(std::begin(arr), std::end(arr), 3); - // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use a llvm range-based algorithm + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use a LLVM range-based algorithm // CHECK-FIXES: auto it2 = llvm::find(arr, 3); - std::sort(vec.begin(), vec.end()); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a llvm range-based algorithm - // CHECK-FIXES: llvm::sort(vec); + std::stable_sort(vec.begin(), vec.end()); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a LLVM range-based algorithm + // CHECK-FIXES: llvm::stable_sort(vec); bool all = std::all_of(vec.begin(), vec.end(), is_even); - // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use a llvm range-based algorithm + // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use a LLVM range-based algorithm // CHECK-FIXES: bool all = llvm::all_of(vec, is_even); std::for_each(vec.begin(), vec.end(), double_ref); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a llvm range-based algorithm + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a LLVM range-based algorithm // CHECK-FIXES: llvm::for_each(vec, double_ref); auto min_it = std::min_element(vec.begin(), vec.end()); - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use a llvm range-based algorithm + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use a LLVM range-based algorithm // CHECK-FIXES: auto min_it = llvm::min_element(vec); std::vector vec2; bool eq = std::equal(vec.begin(), vec.end(), vec2.begin(), vec2.end()); - // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use a llvm range-based algorithm + // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use a LLVM range-based algorithm // CHECK-FIXES: bool eq = llvm::equal(vec, vec2); std::copy(vec.begin(), vec.end(), vec2.begin()); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a llvm range-based algorithm + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a LLVM range-based algorithm // CHECK-FIXES: llvm::copy(vec, vec2.begin()); std::fill(vec.begin(), vec.end(), 0); - // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a llvm range-based algorithm + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a LLVM range-based algorithm // CHECK-FIXES: llvm::fill(vec, 0); auto last = std::unique(vec.begin(), vec.end()); - // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use a llvm range-based algorithm + // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use a LLVM range-based algorithm // CHECK-FIXES: auto last = llvm::unique(vec); bool sorted = std::is_sorted(vec.begin(), vec.end()); - // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use a llvm range-based algorithm + // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use a LLVM range-based algorithm // CHECK-FIXES: bool sorted = llvm::is_sorted(vec); + + std::includes(vec.begin(), vec.end(), std::begin(arr), std::end(arr)); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a LLVM range-based algorithm + // CHECK-FIXES: llvm::includes(vec, arr); } void test_negative() { std::vector v; + // can not use `llvm::sort` because of potential different ordering from `std::sort`. + std::sort(v.begin(), v.end()); + //non-begin/end iterators auto it1 = std::find(v.begin() + 1, v.end(), 2); auto it2 = std::find(v.begin(), v.end() - 1, 2);