1 // RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits -fblocks -fsafe-buffer-usage-suggestions -verify %s
2 // RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits -fblocks -fsafe-buffer-usage-suggestions \
3 // RUN: %s 2>&1 | FileCheck %s
5 // FIXME: what about possible diagnostic message non-determinism?
7 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]:
8 void parmsNoFix(int *p
, int *q
) {
10 int * b
= new int[10]; //expected-warning{{'b' is an unsafe pointer used for buffer access}} \
11 expected
-note
{{change type of
'b' to
'std::span' to preserve bounds information
}}
15 b
[5] = 5; // expected-note{{used in buffer access here}}
18 // CHECK: fix-it:{{.*}}:{[[@LINE+2]]:21-[[@LINE+2]]:27}:"std::span<int> p"
19 // CHECK: fix-it:{{.*}}:{[[@LINE+14]]:2-[[@LINE+14]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void parmsSingleton(int *p) {return parmsSingleton(std::span<int>(p, <# size #>));}\n"
20 void parmsSingleton(int *p
) { //expected-warning{{'p' is an unsafe pointer used for buffer access}} \
21 expected
-note
{{change type of
'p' to
'std::span' to preserve bounds information
}}
22 // CHECK: fix-it:{{.*}}:{[[@LINE+3]]:3-[[@LINE+3]]:8}:"std::span<int>"
23 // CHECK: fix-it:{{.*}}:{[[@LINE+2]]:13-[[@LINE+2]]:13}:"{"
24 // CHECK: fix-it:{{.*}}:{[[@LINE+1]]:24-[[@LINE+1]]:24}:", 10}"
25 int * a
= new int[10];
26 // CHECK: fix-it:{{.*}}:{[[@LINE+1]]:3-[[@LINE+1]]:8}:"std::span<int>"
27 int * b
; //expected-warning{{'b' is an unsafe pointer used for buffer access}} \
28 expected
-note
{{change type of
'b' to
'std::span' to preserve bounds information
, and change
'a' to
'std::span' to propagate bounds information between them
}}
31 b
[5] = 5; // expected-note{{used in buffer access here}}
32 p
[5] = 5; // expected-note{{used in buffer access here}}
36 // Parameters other than `r` all will be fixed
37 // CHECK: fix-it:{{.*}}:{[[@LINE+15]]:24-[[@LINE+15]]:30}:"std::span<int> p"
38 // CHECK fix-it:{{.*}}:{[[@LINE+14]]:32-[[@LINE+14]]:39}:"std::span<int *> q"
39 // CHECK: fix-it:{{.*}}:{[[@LINE+13]]:41-[[@LINE+13]]:48}:"std::span<int> a"
40 // CHECK: fix-it:{{.*}}:{[[@LINE+23]]:2-[[@LINE+23]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void * multiParmAllFix(int *p, int **q, int a[], int * r) {return multiParmAllFix(std::span<int>(p, <# size #>), std::span<int *>(q, <# size #>), std::span<int>(a, <# size #>), r);}\n"
42 // repeat 2 more times as each of the 3 fixing parameters generates the set of fix-its above.
44 // CHECK: fix-it:{{.*}}:{[[@LINE+8]]:24-[[@LINE+8]]:30}:"std::span<int> p"
45 // CHECK fix-it:{{.*}}:{[[@LINE+7]]:32-[[@LINE+7]]:39}:"std::span<int *> q"
46 // CHECK: fix-it:{{.*}}:{[[@LINE+6]]:41-[[@LINE+6]]:48}:"std::span<int> a"
47 // CHECK: fix-it:{{.*}}:{[[@LINE+16]]:2-[[@LINE+16]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void * multiParmAllFix(int *p, int **q, int a[], int * r) {return multiParmAllFix(std::span<int>(p, <# size #>), std::span<int *>(q, <# size #>), std::span<int>(a, <# size #>), r);}\n"
48 // CHECK: fix-it:{{.*}}:{[[@LINE+4]]:24-[[@LINE+4]]:30}:"std::span<int> p"
49 // CHECK fix-it:{{.*}}:{[[@LINE+3]]:32-[[@LINE+3]]:39}:"std::span<int *> q"
50 // CHECK: fix-it:{{.*}}:{[[@LINE+2]]:41-[[@LINE+2]]:48}:"std::span<int> a"
51 // CHECK: fix-it:{{.*}}:{[[@LINE+12]]:2-[[@LINE+12]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void * multiParmAllFix(int *p, int **q, int a[], int * r) {return multiParmAllFix(std::span<int>(p, <# size #>), std::span<int *>(q, <# size #>), std::span<int>(a, <# size #>), r);}\n"
52 void * multiParmAllFix(int *p
, int **q
, int a
[], int * r
) { // expected-warning{{'p' is an unsafe pointer used for buffer access}} expected-warning{{'q' is an unsafe pointer used for buffer access}} \
53 expected
-warning
{{'a' is an unsafe pointer used
for buffer access
}} \
54 expected
-note
{{change type of
'p' to
'std::span' to preserve bounds information
, and change
'q' and 'a' to safe types to make function
'multiParmAllFix' bounds
-safe
}} \
55 expected
-note
{{change type of
'q' to
'std::span' to preserve bounds information
, and change
'p' and 'a' to safe types to make function
'multiParmAllFix' bounds
-safe
}} \
56 expected
-note
{{change type of
'a' to
'std::span' to preserve bounds information
, and change
'p' and 'q' to safe types to make function
'multiParmAllFix' bounds
-safe
}}
59 tmp
= p
[5]; // expected-note{{used in buffer access here}}
60 tmp
= a
[5]; // expected-note{{used in buffer access here}}
61 if (++q
) {} // expected-note{{used in pointer arithmetic here}}
65 void * multiParmAllFix(int *p
, int **q
, int a
[], int * r
);
66 // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:1-[[@LINE-1]]:1}:"{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} "
67 // CHECK: fix-it:{{.*}}:{[[@LINE-2]]:58-[[@LINE-2]]:58}:";\nvoid * multiParmAllFix(std::span<int> p, std::span<int *> q, std::span<int> a, int * r)"
69 // Fixing local variables implicates fixing parameters
70 void multiParmLocalAllFix(int *p
, int * r
) {
71 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
72 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]:
73 int * x
; // expected-warning{{'x' is an unsafe pointer used for buffer access}}
74 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]:
75 int * z
; // expected-warning{{'z' is an unsafe pointer used for buffer access}}
79 y
= x
; // FIXME: we do not fix `y = x` here as the `.data()` fix-it is not generally correct
80 // `x` needs to be fixed so does the pointer assigned to `x`, i.e.,`p`
81 x
[5] = 5; // expected-note{{used in buffer access here}}
83 // `z` needs to be fixed so does the pointer assigned to `z`, i.e.,`r`
84 z
[5] = 5; // expected-note{{used in buffer access here}}
85 // Since `p` and `r` are parameters need to be fixed together,
86 // fixing `x` involves fixing all `p`, `r` and `z`. Similar for
89 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
92 // Fixing parameters implicates fixing local variables
93 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]:
94 void multiParmLocalAllFix2(int *p
, int * r
) { // expected-warning{{'p' is an unsafe pointer used for buffer access}} \
95 expected
-warning
{{'r' is an unsafe pointer used
for buffer access
}}
96 int * x
= new int[10];
97 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
98 int * z
= new int[10];
99 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
103 y
= x
; // FIXME: we do not fix `y = x` here as the `.data()` fix-it is not generally correct
104 p
[5] = 5; // expected-note{{used in buffer access here}}
106 r
[5] = 5; // expected-note{{used in buffer access here}}
108 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]:
111 // No fix emitted for any of the parameter since parameter `r` cannot be fixed
112 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]
113 void noneParmFix(int * p
, int * q
, int * r
) { // expected-warning{{'p' is an unsafe pointer used for buffer access}} \
114 expected
-warning
{{'q' is an unsafe pointer used
for buffer access
}} \
115 expected
-warning
{{'r' is an unsafe pointer used
for buffer access
}}
116 int tmp
= p
[5]; // expected-note{{used in buffer access here}}
117 tmp
= q
[5]; // expected-note{{used in buffer access here}}
118 r
++; // expected-note{{used in pointer arithmetic here}}
119 tmp
= r
[5]; // expected-note{{used in buffer access here}}
121 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]
123 // To show what if the `r` in `noneParmFix` can be fixed:
124 void noneParmFix_control(int * p
, int * q
, int * r
) { // expected-warning{{'p' is an unsafe pointer used for buffer access}} \
125 expected
-note
{{change type of
'p' to
'std::span' to preserve bounds information
, and change
'q' and 'r' to safe types to make function
'noneParmFix_control' bounds
-safe
}} \
126 expected
-warning
{{'q' is an unsafe pointer used
for buffer access
}} \
127 expected
-note
{{change type of
'q' to
'std::span' to preserve bounds information
, and change
'p' and 'r' to safe types to make function
'noneParmFix_control' bounds
-safe
}} \
128 expected
-warning
{{'r' is an unsafe pointer used
for buffer access
}} \
129 expected
-note
{{change type of
'r' to
'std::span' to preserve bounds information
, and change
'p' and 'q' to safe types to make function
'noneParmFix_control' bounds
-safe
}}
130 int tmp
= p
[5]; // expected-note{{used in buffer access here}}
131 tmp
= q
[5]; // expected-note{{used in buffer access here}}
132 if (++r
) {} // expected-note{{used in pointer arithmetic here}}
133 tmp
= r
[5]; // expected-note{{used in buffer access here}}
137 // No fix emitted for any of the parameter since local variable `l` cannot be fixed.
138 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]
139 void noneParmOrLocalFix(int * p
, int * q
, int * r
) { // expected-warning{{'p' is an unsafe pointer used for buffer access}} \
140 expected
-warning
{{'q' is an unsafe pointer used
for buffer access
}} \
141 expected
-warning
{{'r' is an unsafe pointer used
for buffer access
}}
142 int tmp
= p
[5]; // expected-note{{used in buffer access here}}
143 tmp
= q
[5]; // expected-note{{used in buffer access here}}
144 tmp
= r
[5]; // expected-note{{used in buffer access here}}
145 // `l` and `r` must be fixed together while all parameters must be fixed together as well:
146 int * l
; l
= r
; // expected-warning{{'l' is an unsafe pointer used for buffer access}}
148 l
++; // expected-note{{used in pointer arithmetic here}}
150 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]
152 // To show what if the `l` can be fixed in `noneParmOrLocalFix`:
153 void noneParmOrLocalFix_control(int * p
, int * q
, int * r
) {// \
154 expected
-warning
{{'p' is an unsafe pointer used
for buffer access
}} \
155 expected
-note
{{change type of
'p' to
'std::span' to preserve bounds information
, and change
'q', 'r', and 'l' to safe types to make function
'noneParmOrLocalFix_control' bounds
-safe
}} \
156 expected
-warning
{{'q' is an unsafe pointer used
for buffer access
}} \
157 expected
-note
{{change type of
'q' to
'std::span' to preserve bounds information
, and change
'p', 'r', and 'l' to safe types to make function
'noneParmOrLocalFix_control' bounds
-safe
}} \
158 expected
-warning
{{'r' is an unsafe pointer used
for buffer access
}} \
159 expected
-note
{{change type of
'r' to
'std::span' to preserve bounds information
, and change
'p', 'q', and 'l' to safe types to make function
'noneParmOrLocalFix_control' bounds
-safe
}}
160 int tmp
= p
[5]; // expected-note{{used in buffer access here}}
161 tmp
= q
[5]; // expected-note{{used in buffer access here}}
162 tmp
= r
[5]; // expected-note{{used in buffer access here}}
163 int * l
; // expected-warning{{'l' is an unsafe pointer used for buffer access}} \
164 expected
-note
{{change type of
'l' to
'std::span' to preserve bounds information
, and change
'p', 'q', and 'r' to safe types to make function
'noneParmOrLocalFix_control' bounds
-safe
}}
166 if (++l
){}; // expected-note{{used in pointer arithmetic here}}
170 // No fix emitted for any of the parameter since local variable `l` cannot be fixed.
171 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]
172 void noneParmOrLocalFix2(int * p
, int * q
, int * r
) { // expected-warning{{'p' is an unsafe pointer used for buffer access}} \
173 expected
-warning
{{'q' is an unsafe pointer used
for buffer access
}} \
174 expected
-warning
{{'r' is an unsafe pointer used
for buffer access
}}
175 int tmp
= p
[5]; // expected-note{{used in buffer access here}}
176 tmp
= q
[5]; // expected-note{{used in buffer access here}}
177 tmp
= r
[5]; // expected-note{{used in buffer access here}}
181 int * l
; l
= b
; // expected-warning{{'l' is an unsafe pointer used for buffer access}}
183 // `a, b, l` and parameters must be fixed together but `l` can't be fixed:
184 l
++; // expected-note{{used in pointer arithmetic here}}
186 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]
188 // To show what if the `l` can be fixed in `noneParmOrLocalFix2`:
189 void noneParmOrLocalFix2_control(int * p
, int * q
, int * r
) { // \
190 expected
-warning
{{'p' is an unsafe pointer used
for buffer access
}} \
191 expected
-note
{{change type of
'p' to
'std::span' to preserve bounds information
, and change
'q', 'r', 'l', 'b', and 'a' to safe types to make function
'noneParmOrLocalFix2_control' bounds
-safe
}} \
192 expected
-warning
{{'q' is an unsafe pointer used
for buffer access
}} \
193 expected
-note
{{change type of
'q' to
'std::span' to preserve bounds information
, and change
'p', 'r', 'l', 'b', and 'a' to safe types to make function
'noneParmOrLocalFix2_control' bounds
-safe
}} \
194 expected
-warning
{{'r' is an unsafe pointer used
for buffer access
}} \
195 expected
-note
{{change type of
'r' to
'std::span' to preserve bounds information
, and change
'p', 'q', 'l', 'b', and 'a' to safe types to make function
'noneParmOrLocalFix2_control' bounds
-safe
}}
196 int tmp
= p
[5]; // expected-note{{used in buffer access here}}
197 tmp
= q
[5]; // expected-note{{used in buffer access here}}
198 tmp
= r
[5]; // expected-note{{used in buffer access here}}
202 int * l
; // expected-warning{{'l' is an unsafe pointer used for buffer access}} \
203 expected
-note
{{change type of
'l' to
'std::span' to preserve bounds information
, and change
'p', 'q', 'r', 'b', and 'a' to safe types to make function
'noneParmOrLocalFix2_control' bounds
-safe
}}
206 if(++l
){} // expected-note{{used in pointer arithmetic here}}
209 // No fix emitted for any of the parameter since local variable `l` cannot be fixed
210 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]
211 void noneParmOrLocalFix3(int * p
, int * q
, int * r
) { // expected-warning{{'p' is an unsafe pointer used for buffer access}} \
212 expected
-warning
{{'q' is an unsafe pointer used
for buffer access
}} \
213 expected
-warning
{{'r' is an unsafe pointer used
for buffer access
}}
214 int tmp
= p
[5]; // expected-note{{used in buffer access here}}
215 tmp
= q
[5]; // expected-note{{used in buffer access here}}
216 tmp
= r
[5]; // expected-note{{used in buffer access here}}
220 int * l
; l
= b
; // expected-warning{{'l' is an unsafe pointer used for buffer access}}
222 l
++; // expected-note{{used in pointer arithmetic here}}
224 int * x
; x
= p
; // expected-warning{{'x' is an unsafe pointer used for buffer access}}
225 tmp
= x
[5]; // expected-note{{used in buffer access here}}
227 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]
229 void noneParmOrLocalFix3_control(int * p
, int * q
, int * r
) { // \
230 expected
-warning
{{'p' is an unsafe pointer used
for buffer access
}} \
231 expected
-note
{{change type of
'p' to
'std::span' to preserve bounds information
, and change
'x', 'q', 'r', 'l', 'b', and 'a' to safe types to make function
'noneParmOrLocalFix3_control' bounds
-safe
}} \
232 expected
-warning
{{'q' is an unsafe pointer used
for buffer access
}} \
233 expected
-note
{{change type of
'q' to
'std::span' to preserve bounds information
, and change
'p', 'x', 'r', 'l', 'b', and 'a' to safe types to make function
'noneParmOrLocalFix3_control' bounds
-safe
}} \
234 expected
-warning
{{'r' is an unsafe pointer used
for buffer access
}} \
235 expected
-note
{{change type of
'r' to
'std::span' to preserve bounds information
, and change
'p', 'x', 'q', 'l', 'b', and 'a' to safe types to make function
'noneParmOrLocalFix3_control' bounds
-safe
}}
236 int tmp
= p
[5]; // expected-note{{used in buffer access here}}
237 tmp
= q
[5]; // expected-note{{used in buffer access here}}
238 tmp
= r
[5]; // expected-note{{used in buffer access here}}
242 int * l
; // expected-warning{{'l' is an unsafe pointer used for buffer access}} \
243 expected
-note
{{change type of
'l' to
'std::span' to preserve bounds information
, and change
'p', 'x', 'q', 'r', 'b', and 'a' to safe types to make function
'noneParmOrLocalFix3_control' bounds
-safe
}}
246 if (++l
){}; // expected-note{{used in pointer arithmetic here}}
248 int * x
; // expected-warning{{'x' is an unsafe pointer used for buffer access}} \
249 expected
-note
{{change type of
'x' to
'std::span' to preserve bounds information
, and change
'p', 'q', 'r', 'l', 'b', and 'a' to safe types to make function
'noneParmOrLocalFix3_control' bounds
-safe
}}
251 tmp
= x
[5]; // expected-note{{used in buffer access here}}
255 // No fix emitted for any of the parameter but some local variables will get fixed
256 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE+1]]
257 void noneParmSomeLocalFix(int * p
, int * q
, int * r
) { // expected-warning{{'p' is an unsafe pointer used for buffer access}} \
258 expected
-warning
{{'q' is an unsafe pointer used
for buffer access
}} \
259 expected
-warning
{{'r' is an unsafe pointer used
for buffer access
}}
260 int tmp
= p
[5]; // expected-note{{used in buffer access here}}
261 tmp
= q
[5]; // expected-note{{used in buffer access here}}
262 tmp
= r
[5]; // expected-note{{used in buffer access here}}
266 int * l
; l
= b
; // expected-warning{{'l' is an unsafe pointer used for buffer access}}
268 l
++; // expected-note{{used in pointer arithmetic here}}
270 //`x` and `y` can be fixed
271 int * x
= new int[10];
272 // CHECK: fix-it:{{.*}}:{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"
273 // CHECK: fix-it:{{.*}}:{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
274 // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"
275 // CHECK: fix-it:{{.*}}:{[[@LINE+1]]:3-[[@LINE+1]]:8}:"std::span<int>"
276 int * y
; // expected-warning{{'y' is an unsafe pointer used for buffer access}} \
277 expected
-note
{{change type of
'y' to
'std::span' to preserve bounds information
, and change
'x' to
'std::span' to propagate bounds information between them
}}
279 tmp
= y
[5]; // expected-note{{used in buffer access here}}
281 // CHECK-NOT: fix-it:{{.*}}:{[[@LINE-1]]
283 // Test that other parameters of (lambdas and blocks) do not interfere
284 // the grouping of variables of the function.
285 // CHECK: fix-it:{{.*}}:{[[@LINE+3]]:30-[[@LINE+3]]:37}:"std::span<int> p"
286 // CHECK: fix-it:{{.*}}:{[[@LINE+2]]:39-[[@LINE+2]]:46}:"std::span<int> q"
287 // CHECK: fix-it:{{.*}}:{[[@LINE+20]]:2-[[@LINE+20]]:2}:"\n{{\[}}{{\[}}clang::unsafe_buffer_usage{{\]}}{{\]}} void parmsFromLambdaAndBlock(int * p, int * q) {return parmsFromLambdaAndBlock(std::span<int>(p, <# size #>), std::span<int>(q, <# size #>));}\n"
288 void parmsFromLambdaAndBlock(int * p
, int * q
) {
289 // CHECK: fix-it:{{.*}}:{[[@LINE+1]]:3-[[@LINE+1]]:8}:"std::span<int>"
290 int * a
; // expected-warning{{'a' is an unsafe pointer used for buffer access}} \
291 expected
-note
{{change type of
'a' to
'std::span' to preserve bounds information
, and change
'p', 'b', and 'q' to safe types to make function
'parmsFromLambdaAndBlock' bounds
-safe
}}
292 // CHECK: fix-it:{{.*}}:{[[@LINE+1]]:3-[[@LINE+1]]:8}:"std::span<int>"
293 int * b
; // expected-warning{{'b' is an unsafe pointer used for buffer access}} \
294 expected
-note
{{change type of
'b' to
'std::span' to preserve bounds information
, and change
'a', 'p', and 'q' to safe types to make function
'parmsFromLambdaAndBlock' bounds
-safe
}}
295 auto Lamb
= [](int * x
) -> void { // expected-warning{{'x' is an unsafe pointer used for buffer access}}
296 x
[5] = 5; // expected-note{{used in buffer access here}}
299 void (^Blk
)(int*) = ^(int * y
) { // expected-warning{{'y' is an unsafe pointer used for buffer access}}
300 y
[5] = 5; // expected-note{{used in buffer access here}}
305 a
[5] = 5; // expected-note{{used in buffer access here}}
306 b
[5] = 5; // expected-note{{used in buffer access here}}