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 *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 int b
[10][10]; // expected-warning{{'b' is an unsafe buffer that does not perform bounds checks}}
66 foo(a
[1], 1[a
], // expected-note2{{used in buffer access here}}
67 b
[3][4], // expected-warning{{unsafe buffer access}}
68 // expected-note@-1{{used in buffer access here}}
69 4[b
][3], // expected-warning{{unsafe buffer access}}
70 // expected-note@-1{{used in buffer access here}}
71 4[3[b
]]); // expected-warning{{unsafe buffer access}}
72 // expected-note@-1{{used in buffer access here}}
74 // Not to warn when index is zero
75 foo(p
[0], pp
[0][0], 0[0[pp
]], 0[pp
][0],
76 ((int*)voidPtrCall())[0],
77 0[(int*)voidPtrCall()],
83 void testArraySubscriptsWithAuto() {
85 // We do not fix a declaration if the type is `auto`. Because the actual type may change later.
86 auto ap1
= a
; // expected-warning{{'ap1' is an unsafe pointer used for buffer access}}
87 foo(ap1
[1]); // expected-note{{used in buffer access here}}
89 // In case the type is `auto *`, we know it must be a pointer. We can fix it.
90 auto * ap2
= a
; // expected-warning{{'ap2' is an unsafe pointer used for buffer access}} \
91 expected
-note
{{change type of
'ap2' to
'std::span' to preserve bounds information
}}
92 foo(ap2
[1]); // expected-note{{used in buffer access here}}
95 void testUnevaluatedContext(int * p
) {// no-warning
96 foo(sizeof(p
[1]), // no-warning
97 sizeof(decltype(p
[1]))); // no-warning
100 void testQualifiedParameters(const int * p
, const int * const q
, const int a
[10], const int b
[10][10]) {
101 // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
102 // expected-warning@-2{{'q' is an unsafe pointer used for buffer access}}
103 // expected-warning@-3{{'a' is an unsafe pointer used for buffer access}}
104 // expected-warning@-4{{'b' is an unsafe pointer used for buffer access}}
106 foo(p
[1], 1[p
], p
[-1], // expected-note3{{used in buffer access here}}
107 q
[1], 1[q
], q
[-1], // expected-note3{{used in buffer access here}}
108 a
[1], // expected-note{{used in buffer access here}} `a` is of pointer type
109 b
[1][2] // expected-note{{used in buffer access here}} `b[1]` is of array type
110 // expected-warning@-1{{unsafe buffer access}}
123 typedef struct T T_t
;
128 void testStructMembers(struct T
* sp
, struct T s
, T_t
* sp2
, T_t s2
) {
129 foo(sp
->a
[1], // expected-warning{{unsafe buffer access}}
130 sp
->b
[1], // expected-warning{{unsafe buffer access}}
131 sp
->c
.a
[1], // expected-warning{{unsafe buffer access}}
132 sp
->c
.b
[1], // expected-warning{{unsafe buffer access}}
133 s
.a
[1], // expected-warning{{unsafe buffer access}}
134 s
.b
[1], // expected-warning{{unsafe buffer access}}
135 s
.c
.a
[1], // expected-warning{{unsafe buffer access}}
136 s
.c
.b
[1], // expected-warning{{unsafe buffer access}}
137 sp2
->a
[1], // expected-warning{{unsafe buffer access}}
138 sp2
->b
[1], // expected-warning{{unsafe buffer access}}
139 sp2
->c
.a
[1], // expected-warning{{unsafe buffer access}}
140 sp2
->c
.b
[1], // expected-warning{{unsafe buffer access}}
141 s2
.a
[1], // expected-warning{{unsafe buffer access}}
142 s2
.b
[1], // expected-warning{{unsafe buffer access}}
143 s2
.c
.a
[1], // expected-warning{{unsafe buffer access}}
144 s2
.c
.b
[1], // expected-warning{{unsafe buffer access}}
145 funRetT().a
[1], // expected-warning{{unsafe buffer access}}
146 funRetT().b
[1], // expected-warning{{unsafe buffer access}}
147 funRetTStar()->a
[1], // expected-warning{{unsafe buffer access}}
148 funRetTStar()->b
[1] // expected-warning{{unsafe buffer access}}
152 int garray
[10]; // expected-warning{{'garray' is an unsafe buffer that does not perform bounds checks}}
153 int * gp
= garray
; // expected-warning{{'gp' is an unsafe pointer used for buffer access}}
154 int gvar
= gp
[1]; // FIXME: file scope unsafe buffer access is not warned
156 void testLambdaCaptureAndGlobal(int * p
) {
157 // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
158 int a
[10]; // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}}
160 auto Lam
= [p
, a
]() {
161 return p
[1] // expected-note{{used in buffer access here}}
162 + a
[1] + garray
[1] // expected-note2{{used in buffer access here}}
163 + gp
[1]; // expected-note{{used in buffer access here}}
168 auto file_scope_lambda
= [](int *ptr
) {
169 // expected-warning@-1{{'ptr' is an unsafe pointer used for buffer access}}
171 ptr
[5] = 10; // expected-note{{used in buffer access here}}
174 void testLambdaCapture() {
175 int a
[10]; // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}}
176 int b
[10]; // expected-warning{{'b' is an unsafe buffer that does not perform bounds checks}}
180 return a
[1]; // expected-note{{used in buffer access here}}
183 auto Lam2
= [x
= b
[3]]() { // expected-note{{used in buffer access here}}
187 auto Lam
= [x
= c
]() { // expected-warning{{'x' is an unsafe pointer used for buffer access}}
188 return x
[3]; // expected-note{{used in buffer access here}}
192 void testLambdaImplicitCapture() {
193 int a
[10]; // expected-warning{{'a' is an unsafe buffer that does not perform bounds checks}}
194 int b
[10]; // expected-warning{{'b' is an unsafe buffer that does not perform bounds checks}}
197 return a
[1]; // expected-note{{used in buffer access here}}
201 return b
[1]; // expected-note{{used in buffer access here}}
205 typedef T_t
* T_ptr_t
;
207 void testTypedefs(T_ptr_t p
) {
208 // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
209 foo(p
[1], // expected-note{{used in buffer access here}}
210 p
[1].a
[1], // expected-note{{used in buffer access here}}
211 // expected-warning@-1{{unsafe buffer access}}
212 p
[1].b
[1] // expected-note{{used in buffer access here}}
213 // expected-warning@-1{{unsafe buffer access}}
217 template<typename T
, int N
> T
f(T t
, T
* pt
, T a
[N
], T (&b
)[N
]) {
218 // expected-warning@-1{{'t' is an unsafe pointer used for buffer access}}
219 // expected-warning@-2{{'pt' is an unsafe pointer used for buffer access}}
220 // expected-warning@-3{{'a' is an unsafe pointer used for buffer access}}
221 // expected-warning@-4{{'b' is an unsafe buffer that does not perform bounds checks}}
222 foo(pt
[1], // expected-note{{used in buffer access here}}
223 a
[1], // expected-note{{used in buffer access here}}
224 b
[1]); // expected-note{{used in buffer access here}}
225 return &t
[1]; // expected-note{{used in buffer access here}}
228 // Testing pointer arithmetic for pointer-to-int, qualified multi-level
229 // pointer, pointer to a template type, and auto type
233 void testPointerArithmetic(int * p
, const int **q
, T
* x
) {
234 // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
235 // expected-warning@-2{{'x' is an unsafe pointer used for buffer access}}
237 auto y
= &a
[0]; // expected-warning{{'y' is an unsafe pointer used for buffer access}}
239 foo(p
+ 1, 1 + p
, p
- 1, // expected-note3{{used in pointer arithmetic here}}
240 *q
+ 1, 1 + *q
, *q
- 1, // expected-warning3{{unsafe pointer arithmetic}}
241 x
+ 1, 1 + x
, x
- 1, // expected-note3{{used in pointer arithmetic here}}
242 y
+ 1, 1 + y
, y
- 1, // expected-note3{{used in pointer arithmetic here}}
243 getPtr() + 1, 1 + getPtr(), getPtr() - 1 // expected-warning3{{unsafe pointer arithmetic}}
246 p
+= 1; p
-= 1; // expected-note2{{used in pointer arithmetic here}}
247 *q
+= 1; *q
-= 1; // expected-warning2{{unsafe pointer arithmetic}}
248 y
+= 1; y
-= 1; // expected-note2{{used in pointer arithmetic here}}
249 x
+= 1; x
-= 1; // expected-note2{{used in pointer arithmetic here}}
252 void testTemplate(int * p
) {
254 foo(f(p
, &p
, a
, a
)[1]); // expected-warning{{unsafe buffer access}}
255 // FIXME: expected note@-1{{in instantiation of function template specialization 'f<int *, 10>' requested here}}
257 const int **q
= const_cast<const int **>(&p
);
259 testPointerArithmetic(p
, q
, p
); //FIXME: expected note{{in instantiation of}}
262 void testPointerToMember() {
268 int S_t::* p
= &S_t::x
;
269 int * S_t::* q
= &S_t::y
;
272 (S
.*q
)[1]); // expected-warning{{unsafe buffer access}}
275 // test that nested callable definitions are scanned only once
276 void testNestedCallableDefinition(int * p
) {
278 void inner(int * p
) {
279 // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
280 p
++; // expected-note{{used in pointer arithmetic here}}
283 static void innerStatic(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 void innerInner(int * p
) {
290 int * q
= p
; // expected-warning{{'q' is an unsafe pointer used for buffer access}}
291 q
++; // expected-note{{used in pointer arithmetic here}}
298 int * q
= p
; // expected-warning{{'q' is an unsafe pointer used for buffer access}}
299 q
++; // expected-note{{used in pointer arithmetic here}}
303 auto LamLam
= [p
]() {
305 int * q
= p
; // expected-warning{{'q' is an unsafe pointer used for buffer access}}
306 q
++; // expected-note{{used in pointer arithmetic here}}
311 void (^Blk
)(int*) = ^(int *p
) {
312 // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
313 p
++; // expected-note{{used in pointer arithmetic here}}
316 void (^BlkBlk
)(int*) = ^(int *p
) {
317 void (^Blk
)(int*) = ^(int *p
) {
318 // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
319 p
++; // expected-note{{used in pointer arithmetic here}}
324 // lambda and block as call arguments...
325 foo( [p
]() { int * q
= p
; // expected-warning{{'q' is an unsafe pointer used for buffer access}}
326 q
++; // expected-note{{used in pointer arithmetic here}}
329 ^(int *p
) { // expected-warning{{'p' is an unsafe pointer used for buffer access}}
330 p
++; // expected-note{{used in pointer arithmetic here}}
335 int testVariableDecls(int * p
) {
336 // expected-warning@-1{{'p' is an unsafe pointer used for buffer access}}
337 int * q
= p
++; // expected-note{{used in pointer arithmetic here}}
338 int a
[p
[1]]; // expected-note{{used in buffer access here}}
339 int b
= p
[1]; // expected-note{{used in buffer access here}}
340 return p
[1]; // expected-note{{used in buffer access here}}
343 template<typename T
> void fArr(T t
[]) {
344 // expected-warning@-1{{'t' is an unsafe pointer used for buffer access}}
345 foo(t
[1]); // expected-note{{used in buffer access here}}
346 T ar
[8]; // expected-warning{{'ar' is an unsafe buffer that does not perform bounds checks}}
347 foo(ar
[5]); // expected-note{{used in buffer access here}}
350 template void fArr
<int>(int t
[]); // FIXME: expected note {{in instantiation of}}
352 int testReturn(int t
[]) {// expected-note{{change type of 't' to 'std::span' to preserve bounds information}}
353 // expected-warning@-1{{'t' is an unsafe pointer used for buffer access}}
354 return t
[1]; // expected-note{{used in buffer access here}}
357 int testArrayAccesses(int n
) {
358 // auto deduced array type
359 int cArr
[2][3] = {{1, 2, 3}, {4, 5, 6}};
360 // expected-warning@-1{{'cArr' is an unsafe buffer that does not perform bounds checks}}
363 foo(cArr
[1][2]); // expected-note{{used in buffer access here}}
364 // expected-warning@-1{{unsafe buffer access}}
365 auto cPtr
= cArr
[1][2]; // expected-note{{used in buffer access here}}
366 // expected-warning@-1{{unsafe buffer access}}
371 const A tArr
= {4, 5, 6};
372 // expected-warning@-1{{'tArr' is an unsafe buffer that does not perform bounds checks}}
373 foo(tArr
[0], tArr
[1]); // expected-note{{used in buffer access here}}
374 return cArr
[0][1]; // expected-warning{{unsafe buffer access}}
377 void testArrayPtrArithmetic(int x
[]) { // expected-warning{{'x' is an unsafe pointer used for buffer access}}
378 foo (x
+ 3); // expected-note{{used in pointer arithmetic here}}
380 int y
[3] = {0, 1, 2}; // expected-warning{{'y' is an unsafe buffer that does not perform bounds checks}}
381 foo(y
+ 4); // expected-note{{used in pointer arithmetic here}}
384 void testMultiLineDeclStmt(int * p
) {
389 ap1
= p
; // expected-warning{{'ap1' is an unsafe pointer used for buffer access}} \
390 expected
-note
{{change type of
'ap1' to
'std::span' to preserve bounds information
}}
392 foo(ap1
[1]); // expected-note{{used in buffer access here}}