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 | |