1 // RUN: %clang_cc1 -std=c++20 -Wno-all -Wunsafe-buffer-usage \
2 // RUN: -fsafe-buffer-usage-suggestions \
3 // RUN: -fblocks -include %s -verify %s
5 // RUN: %clang -x c++ -fsyntax-only -fblocks -include %s %s 2>&1 | FileCheck --allow-empty %s
6 // RUN: %clang_cc1 -std=c++11 -fblocks -include %s %s 2>&1 | FileCheck --allow-empty %s
7 // RUN: %clang_cc1 -std=c++20 -fblocks -include %s %s 2>&1 | FileCheck --allow-empty %s
8 // CHECK-NOT: [-Wunsafe-buffer-usage]
12 #pragma clang system_header
14 // no spanification warnings for system headers
15 void foo(...); // let arguments of `foo` to hold testing expressions
16 void testAsSystemHeader(char *p
) {
29 void testIncrement(char *p
) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}
30 ++p
; // expected-note{{used in pointer arithmetic here}}
31 p
++; // expected-note{{used in pointer arithmetic here}}
32 --p
; // expected-note{{used in pointer arithmetic here}}
33 p
--; // expected-note{{used in pointer arithmetic here}}
36 void * voidPtrCall(void);
37 char * charPtrCall(void);
39 void testArraySubscripts(int idx
, int *p
, int **pp
) {
40 // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
41 // expected-warning@-2{{'pp' is an unsafe pointer used for buffer access}}
42 foo(p
[1], // expected-note{{used in buffer access here}}
43 pp
[1][1], // expected-note{{used in buffer access here}}
44 // expected-warning@-1{{unsafe buffer access}}
45 1[1[pp
]], // expected-note{{used in buffer access here}}
46 // expected-warning@-1{{unsafe buffer access}}
47 1[pp
][1] // expected-note{{used in buffer access here}}
48 // expected-warning@-1{{unsafe buffer access}}
51 if (p
[3]) { // expected-note{{used in buffer access here}}
54 foo(((int*)q
)[10]); // expected-warning{{unsafe buffer access}}
57 foo(((int*)voidPtrCall())[3], // expected-warning{{unsafe buffer access}}
58 3[(int*)voidPtrCall()], // expected-warning{{unsafe buffer access}}
59 charPtrCall()[3], // expected-warning{{unsafe buffer access}}
60 3[charPtrCall()] // expected-warning{{unsafe buffer access}}
63 int a
[10]; // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}}
64 // expected-note@-1{{change type of 'a' to 'std::array' to label it for hardening}}
65 int b
[10][10]; // expected-warning{{'b' is an unsafe buffer that does not perform bounds checks}}
67 foo(a
[idx
], idx
[a
], // expected-note2{{used in buffer access here}}
68 b
[idx
][idx
+ 1], // expected-warning{{unsafe buffer access}}
69 // expected-note@-1{{used in buffer access here}}
70 (idx
+ 1)[b
][idx
],// expected-warning{{unsafe buffer access}}
71 // expected-note@-1{{used in buffer access here}}
73 // expected-warning@-1{{unsafe buffer access}}
74 // expected-note@-2{{used in buffer access here}}
76 // Not to warn when index is zero
77 foo(p
[0], pp
[0][0], 0[0[pp
]], 0[pp
][0],
78 ((int*)voidPtrCall())[0],
79 0[(int*)voidPtrCall()],
85 void testArraySubscriptsWithAuto() {
87 // We do not fix a declaration if the type is `auto`. Because the actual type may change later.
88 auto ap1
= a
; // expected-warning{{'ap1' is an unsafe pointer used for buffer access}}
89 foo(ap1
[1]); // expected-note{{used in buffer access here}}
91 // In case the type is `auto *`, we know it must be a pointer. We can fix it.
92 auto * ap2
= a
; // expected-warning{{'ap2' is an unsafe pointer used for buffer access}} \
93 expected
-note
{{change type of
'ap2' to
'std::span' to preserve bounds information
}}
94 foo(ap2
[1]); // expected-note{{used in buffer access here}}
97 void testUnevaluatedContext(int * p
) {// no-warning
98 foo(sizeof(p
[1]), // no-warning
99 sizeof(decltype(p
[1]))); // no-warning
102 void testQualifiedParameters(const int * p
, const int * const q
, const int a
[10], const int b
[10][10]) {
103 // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
104 // expected-warning@-2{{'q' is an unsafe pointer used for buffer access}}
105 // expected-warning@-3{{'a' is an unsafe pointer used for buffer access}}
106 // expected-warning@-4{{'b' is an unsafe pointer used for buffer access}}
108 foo(p
[1], 1[p
], p
[-1], // expected-note3{{used in buffer access here}}
109 q
[1], 1[q
], q
[-1], // expected-note3{{used in buffer access here}}
110 a
[1], // expected-note{{used in buffer access here}} `a` is of pointer type
111 b
[1][2] // expected-note{{used in buffer access here}} `b[1]` is of array type
112 // expected-warning@-1{{unsafe buffer access}}
125 typedef struct T T_t
;
130 void testStructMembers(struct T
* sp
, struct T s
, T_t
* sp2
, T_t s2
) {
131 foo(sp
->a
[1], // expected-warning{{unsafe buffer access}}
132 sp
->b
[1], // expected-warning{{unsafe buffer access}}
133 sp
->c
.a
[1], // expected-warning{{unsafe buffer access}}
134 sp
->c
.b
[1], // expected-warning{{unsafe buffer access}}
135 s
.a
[1], // expected-warning{{unsafe buffer access}}
136 s
.b
[1], // expected-warning{{unsafe buffer access}}
137 s
.c
.a
[1], // expected-warning{{unsafe buffer access}}
138 s
.c
.b
[1], // expected-warning{{unsafe buffer access}}
139 sp2
->a
[1], // expected-warning{{unsafe buffer access}}
140 sp2
->b
[1], // expected-warning{{unsafe buffer access}}
141 sp2
->c
.a
[1], // expected-warning{{unsafe buffer access}}
142 sp2
->c
.b
[1], // expected-warning{{unsafe buffer access}}
143 s2
.a
[1], // expected-warning{{unsafe buffer access}}
144 s2
.b
[1], // expected-warning{{unsafe buffer access}}
145 s2
.c
.a
[1], // expected-warning{{unsafe buffer access}}
146 s2
.c
.b
[1], // expected-warning{{unsafe buffer access}}
147 funRetT().a
[1], // expected-warning{{unsafe buffer access}}
148 funRetT().b
[1], // expected-warning{{unsafe buffer access}}
149 funRetTStar()->a
[1], // expected-warning{{unsafe buffer access}}
150 funRetTStar()->b
[1] // expected-warning{{unsafe buffer access}}
154 int garray
[10]; // expected-warning{{'garray' is an unsafe buffer that does not perform bounds checks}}
155 int * gp
= garray
; // expected-warning{{'gp' is an unsafe pointer used for buffer access}}
156 int gvar
= gp
[1]; // FIXME: file scope unsafe buffer access is not warned
158 void testLambdaCaptureAndGlobal(int * p
) {
159 // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
160 int a
[10]; // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}}
162 auto Lam
= [p
, a
](int idx
) {
163 return p
[1] // expected-note{{used in buffer access here}}
164 + a
[idx
] + garray
[idx
]// expected-note2{{used in buffer access here}}
165 + gp
[1]; // expected-note{{used in buffer access here}}
170 auto file_scope_lambda
= [](int *ptr
) {
171 // expected-warning@-1{{'ptr' is an unsafe pointer used for buffer access}}
173 ptr
[5] = 10; // expected-note{{used in buffer access here}}
176 void testLambdaCapture() {
177 int a
[10]; // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}}
178 int b
[10]; // expected-warning{{'b' is an unsafe buffer that does not perform bounds checks}}
179 // expected-note@-1{{change type of 'b' to 'std::array' to label it for hardening}}
182 auto Lam1
= [a
](unsigned idx
) {
183 return a
[idx
]; // expected-note{{used in buffer access here}}
186 auto Lam2
= [x
= b
[c
[5]]]() { // expected-note{{used in buffer access here}}
190 auto Lam
= [x
= c
](unsigned idx
) { // expected-warning{{'x' is an unsafe pointer used for buffer access}}
191 return x
[idx
]; // expected-note{{used in buffer access here}}
195 void testLambdaImplicitCapture(long idx
) {
196 int a
[10]; // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}}
197 // expected-note@-1{{change type of 'a' to 'std::array' to label it for hardening}}
198 int b
[10]; // expected-warning{{'b' is an unsafe buffer that does not perform bounds checks}}
199 // expected-note@-1{{change type of 'b' to 'std::array' to label it for hardening}}
202 return a
[idx
]; // expected-note{{used in buffer access here}}
206 return b
[idx
]; // expected-note{{used in buffer access here}}
210 typedef T_t
* T_ptr_t
;
212 void testTypedefs(T_ptr_t p
) {
213 // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
214 foo(p
[1], // expected-note{{used in buffer access here}}
215 p
[1].a
[1], // expected-note{{used in buffer access here}}
216 // expected-warning@-1{{unsafe buffer access}}
217 p
[1].b
[1] // expected-note{{used in buffer access here}}
218 // expected-warning@-1{{unsafe buffer access}}
222 template<typename T
, int N
> T
f(T t
, T
* pt
, T a
[N
], T (&b
)[N
]) {
223 // expected-warning@-1{{'t' is an unsafe pointer used for buffer access}}
224 // expected-warning@-2{{'pt' is an unsafe pointer used for buffer access}}
225 // expected-warning@-3{{'a' is an unsafe pointer used for buffer access}}
226 // expected-warning@-4{{'b' is an unsafe buffer that does not perform bounds checks}}
227 foo(pt
[1], // expected-note{{used in buffer access here}}
228 a
[1], // expected-note{{used in buffer access here}}
229 b
[1]); // expected-note{{used in buffer access here}}
230 return &t
[1]; // expected-note{{used in buffer access here}}
233 // Testing pointer arithmetic for pointer-to-int, qualified multi-level
234 // pointer, pointer to a template type, and auto type
238 void testPointerArithmetic(int * p
, const int **q
, T
* x
) {
239 // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
240 // expected-warning@-2{{'x' is an unsafe pointer used for buffer access}}
242 auto y
= &a
[0]; // expected-warning{{'y' is an unsafe pointer used for buffer access}}
244 foo(p
+ 1, 1 + p
, p
- 1, // expected-note3{{used in pointer arithmetic here}}
245 *q
+ 1, 1 + *q
, *q
- 1, // expected-warning3{{unsafe pointer arithmetic}}
246 x
+ 1, 1 + x
, x
- 1, // expected-note3{{used in pointer arithmetic here}}
247 y
+ 1, 1 + y
, y
- 1, // expected-note3{{used in pointer arithmetic here}}
248 getPtr() + 1, 1 + getPtr(), getPtr() - 1 // expected-warning3{{unsafe pointer arithmetic}}
251 p
+= 1; p
-= 1; // expected-note2{{used in pointer arithmetic here}}
252 *q
+= 1; *q
-= 1; // expected-warning2{{unsafe pointer arithmetic}}
253 y
+= 1; y
-= 1; // expected-note2{{used in pointer arithmetic here}}
254 x
+= 1; x
-= 1; // expected-note2{{used in pointer arithmetic here}}
257 void testTemplate(int * p
) {
259 foo(f(p
, &p
, a
, a
)[1]); // expected-warning{{unsafe buffer access}}
260 // FIXME: expected note@-1{{in instantiation of function template specialization 'f<int *, 10>' requested here}}
262 const int **q
= const_cast<const int **>(&p
);
264 testPointerArithmetic(p
, q
, p
); //FIXME: expected note{{in instantiation of}}
267 void testPointerToMember() {
273 int S_t::* p
= &S_t::x
;
274 int * S_t::* q
= &S_t::y
;
277 (S
.*q
)[1]); // expected-warning{{unsafe buffer access}}
280 // test that nested callable definitions are scanned only once
281 void testNestedCallableDefinition(int * p
) {
283 void inner(int * p
) {
284 // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
285 p
++; // expected-note{{used in pointer arithmetic here}}
288 static void innerStatic(int * p
) {
289 // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
290 p
++; // expected-note{{used in pointer arithmetic here}}
293 void innerInner(int * p
) {
295 int * q
= p
; // expected-warning{{'q' is an unsafe pointer used for buffer access}}
296 q
++; // expected-note{{used in pointer arithmetic here}}
303 int * q
= p
; // expected-warning{{'q' is an unsafe pointer used for buffer access}}
304 q
++; // expected-note{{used in pointer arithmetic here}}
308 auto LamLam
= [p
]() {
310 int * q
= p
; // expected-warning{{'q' is an unsafe pointer used for buffer access}}
311 q
++; // expected-note{{used in pointer arithmetic here}}
316 void (^Blk
)(int*) = ^(int *p
) {
317 // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
318 p
++; // expected-note{{used in pointer arithmetic here}}
321 void (^BlkBlk
)(int*) = ^(int *p
) {
322 void (^Blk
)(int*) = ^(int *p
) {
323 // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
324 p
++; // expected-note{{used in pointer arithmetic here}}
329 // lambda and block as call arguments...
330 foo( [p
]() { int * q
= p
; // expected-warning{{'q' is an unsafe pointer used for buffer access}}
331 q
++; // expected-note{{used in pointer arithmetic here}}
334 ^(int *p
) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}
335 p
++; // expected-note{{used in pointer arithmetic here}}
340 int testVariableDecls(int * p
) {
341 // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
342 int * q
= p
++; // expected-note{{used in pointer arithmetic here}}
343 int a
[p
[1]]; // expected-note{{used in buffer access here}}
344 int b
= p
[1]; // expected-note{{used in buffer access here}}
345 return p
[1]; // expected-note{{used in buffer access here}}
348 template<typename T
> void fArr(T t
[], long long idx
) {
349 // expected-warning@-1{{'t' is an unsafe pointer used for buffer access}}
350 foo(t
[1]); // expected-note{{used in buffer access here}}
351 T ar
[8]; // expected-warning{{'ar' is an unsafe buffer that does not perform bounds checks}}
352 // expected-note@-1{{change type of 'ar' to 'std::array' to label it for hardening}}
353 foo(ar
[idx
]); // expected-note{{used in buffer access here}}
356 template void fArr
<int>(int t
[], long long); // FIXME: expected note {{in instantiation of}}
358 int testReturn(int t
[]) {// expected-note{{change type of 't' to 'std::span' to preserve bounds information}}
359 // expected-warning@-1{{'t' is an unsafe pointer used for buffer access}}
360 return t
[1]; // expected-note{{used in buffer access here}}
363 int testArrayAccesses(int n
, int idx
) {
364 // auto deduced array type
365 int cArr
[2][3] = {{1, 2, 3}, {4, 5, 6}};
366 // expected-warning@-1{{'cArr' is an unsafe buffer that does not perform bounds checks}}
369 foo(cArr
[idx
][idx
+ 1]); // expected-note{{used in buffer access here}}
370 // expected-warning@-1{{unsafe buffer access}}
371 auto cPtr
= cArr
[idx
][idx
* 2]; // expected-note{{used in buffer access here}}
372 // expected-warning@-1{{unsafe buffer access}}
377 const A tArr
= {4, 5, 6};
378 foo(tArr
[0], tArr
[1]);
379 return cArr
[0][1]; // expected-warning{{unsafe buffer access}}
382 void testArrayPtrArithmetic(int x
[]) { // expected-warning{{'x' is an unsafe pointer used for buffer access}}
383 foo (x
+ 3); // expected-note{{used in pointer arithmetic here}}
385 int y
[3] = {0, 1, 2}; // expected-warning{{'y' is an unsafe buffer that does not perform bounds checks}}
386 foo(y
+ 4); // expected-note{{used in pointer arithmetic here}}
389 void testMultiLineDeclStmt(int * p
) {
394 ap1
= p
; // expected-warning{{'ap1' is an unsafe pointer used for buffer access}} \
395 expected
-note
{{change type of
'ap1' to
'std::span' to preserve bounds information
}}
397 foo(ap1
[1]); // expected-note{{used in buffer access here}}