| 1 | // RUN: %check_clang_tidy -std=c++20 %s modernize-use-ranges %t -- -- -I %S/Inputs/ |
| 2 | // RUN: %check_clang_tidy -std=c++23 %s modernize-use-ranges %t -check-suffixes=,CPP23 -- -I %S/Inputs/ |
| 3 | // Example: ./check_clang_tidy.py -std=c++20 checkers/modernize/use-ranges.cpp modernize-use-ranges temp.txt -- -- -I ~/llvm-project/clang-tools-extra/test/clang-tidy/checkers/modernize/Inputs/ |
| 4 | |
| 5 | // CHECK-FIXES: #include <algorithm> |
| 6 | // CHECK-FIXES-CPP23: #include <numeric> |
| 7 | // CHECK-FIXES: #include <ranges> |
| 8 | |
| 9 | #include "use-ranges/fake_std.h" |
| 10 | #include "smart-ptr/unique_ptr.h" |
| 11 | |
| 12 | void Positives() { |
| 13 | std::vector<int> I, J; |
| 14 | std::vector<std::unique_ptr<int>> K; |
| 15 | |
| 16 | // Expect to have no check messages |
| 17 | std::find(K.begin(), K.end(), nullptr); |
| 18 | |
| 19 | std::find(K.begin(), K.end(), std::unique_ptr<int>()); |
| 20 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 21 | // CHECK-FIXES: std::ranges::find(K, std::unique_ptr<int>()); |
| 22 | |
| 23 | std::find(I.begin(), I.end(), 0); |
| 24 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 25 | // CHECK-FIXES: std::ranges::find(I, 0); |
| 26 | |
| 27 | std::find(I.cbegin(), I.cend(), 1); |
| 28 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 29 | // CHECK-FIXES: std::ranges::find(I, 1); |
| 30 | |
| 31 | std::find(std::begin(I), std::end(I), 2); |
| 32 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 33 | // CHECK-FIXES: std::ranges::find(I, 2); |
| 34 | |
| 35 | std::find(std::cbegin(I), std::cend(I), 3); |
| 36 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 37 | // CHECK-FIXES: std::ranges::find(I, 3); |
| 38 | |
| 39 | std::find(std::cbegin(I), I.cend(), 4); |
| 40 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 41 | // CHECK-FIXES: std::ranges::find(I, 4); |
| 42 | |
| 43 | std::reverse(I.begin(), I.end()); |
| 44 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 45 | // CHECK-FIXES: std::ranges::reverse(I); |
| 46 | |
| 47 | std::includes(I.begin(), I.end(), I.begin(), I.end()); |
| 48 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 49 | // CHECK-FIXES: std::ranges::includes(I, I); |
| 50 | |
| 51 | std::includes(I.begin(), I.end(), J.begin(), J.end()); |
| 52 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 53 | // CHECK-FIXES: std::ranges::includes(I, J); |
| 54 | |
| 55 | std::is_permutation(I.begin(), I.end(), J.begin(), J.end()); |
| 56 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 57 | // CHECK-FIXES: std::ranges::is_permutation(I, J); |
| 58 | |
| 59 | std::equal(I.begin(), I.end(), J.begin(), J.end()); |
| 60 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 61 | // CHECK-FIXES: std::ranges::equal(I, J); |
| 62 | |
| 63 | std::equal(I.begin(), I.end(), J.begin(), J.end(), [](int a, int b){ return a == b; }); |
| 64 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 65 | // CHECK-FIXES: std::ranges::equal(I, J, [](int a, int b){ return a == b; }); |
| 66 | |
| 67 | std::iota(I.begin(), I.end(), 0); |
| 68 | // CHECK-MESSAGES-CPP23: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 69 | // CHECK-FIXES-CPP23: std::ranges::iota(I, 0); |
| 70 | |
| 71 | std::rotate(I.begin(), I.begin() + 2, I.end()); |
| 72 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 73 | // CHECK-FIXES: std::ranges::rotate(I, I.begin() + 2); |
| 74 | |
| 75 | using std::find; |
| 76 | namespace my_std = std; |
| 77 | |
| 78 | // Potentially these could be updated to better qualify the replaced function name |
| 79 | find(I.begin(), I.end(), 5); |
| 80 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 81 | // CHECK-FIXES: std::ranges::find(I, 5); |
| 82 | |
| 83 | my_std::find(I.begin(), I.end(), 6); |
| 84 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 85 | // CHECK-FIXES: std::ranges::find(I, 6); |
| 86 | } |
| 87 | |
| 88 | void Reverse(){ |
| 89 | std::vector<int> I, J; |
| 90 | std::vector<std::unique_ptr<int>> K; |
| 91 | |
| 92 | // Expect to have no check messages |
| 93 | std::find(K.rbegin(), K.rend(), nullptr); |
| 94 | |
| 95 | std::find(K.rbegin(), K.rend(), std::unique_ptr<int>()); |
| 96 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 97 | // CHECK-FIXES: std::ranges::find(std::ranges::reverse_view(K), std::unique_ptr<int>()); |
| 98 | |
| 99 | std::find(I.rbegin(), I.rend(), 0); |
| 100 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 101 | // CHECK-FIXES: std::ranges::find(std::ranges::reverse_view(I), 0); |
| 102 | |
| 103 | std::equal(std::rbegin(I), std::rend(I), J.begin(), J.end()); |
| 104 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 105 | // CHECK-FIXES: std::ranges::equal(std::ranges::reverse_view(I), J); |
| 106 | |
| 107 | std::equal(I.begin(), I.end(), std::crbegin(J), std::crend(J)); |
| 108 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use a ranges version of this algorithm |
| 109 | // CHECK-FIXES: std::ranges::equal(I, std::ranges::reverse_view(J)); |
| 110 | } |
| 111 | |
| 112 | void Negatives() { |
| 113 | std::vector<int> I, J; |
| 114 | std::find(I.begin(), J.end(), 0); |
| 115 | std::find(I.begin(), I.begin(), 0); |
| 116 | std::find(I.end(), I.begin(), 0); |
| 117 | |
| 118 | |
| 119 | // Need both ranges for this one |
| 120 | std::is_permutation(I.begin(), I.end(), J.begin()); |
| 121 | |
| 122 | // We only have one valid match here and the ranges::equal function needs 2 complete ranges |
| 123 | std::equal(I.begin(), I.end(), J.begin()); |
| 124 | std::equal(I.begin(), I.end(), J.end(), J.end()); |
| 125 | std::equal(std::rbegin(I), std::rend(I), std::rend(J), std::rbegin(J)); |
| 126 | std::equal(I.begin(), J.end(), I.begin(), I.end()); |
| 127 | |
| 128 | // std::rotate expects the full range in the 1st and 3rd argument. |
| 129 | // Anyone writing this code has probably written a bug, but this isn't the |
| 130 | // purpose of this check. |
| 131 | std::rotate(I.begin(), I.end(), I.begin() + 2); |
| 132 | // Pathological, but probably shouldn't diagnose this |
| 133 | std::rotate(I.begin(), I.end(), I.end() + 0); |
| 134 | } |
| 135 | |