Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / SemaCXX / warn-unsafe-buffer-usage.cpp
blobc5f0a9ef929371bc15d1f7e4f4762f3ac9ff082a
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]
10 #ifndef INCLUDED
11 #define INCLUDED
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) {
17 ++p;
19 auto ap1 = p;
20 auto ap2 = &p;
22 foo(p[1],
23 ap1[1],
24 ap2[2][3]);
27 #else
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}}
52 void * q = p;
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()],
78 charPtrCall()[0],
79 0[charPtrCall()]
83 void testArraySubscriptsWithAuto() {
84 int a[10];
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}}
114 struct T {
115 int a[10];
116 int * b;
117 struct {
118 int a[10];
119 int * b;
120 } c;
123 typedef struct T T_t;
125 T_t funRetT();
126 T_t * funRetTStar();
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}}
177 int c[10];
179 auto Lam1 = [a]() {
180 return a[1]; // expected-note{{used in buffer access here}}
183 auto Lam2 = [x = b[3]]() { // expected-note{{used in buffer access here}}
184 return x;
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}}
196 auto Lam1 = [=]() {
197 return a[1]; // expected-note{{used in buffer access here}}
200 auto Lam2 = [&]() {
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
230 T_ptr_t getPtr();
232 template<typename T>
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}}
236 int a[10];
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) {
253 int *a[10];
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() {
263 struct S_t {
264 int x;
265 int * y;
266 } S;
268 int S_t::* p = &S_t::x;
269 int * S_t::* q = &S_t::y;
271 foo(S.*p,
272 (S.*q)[1]); // expected-warning{{unsafe buffer access}}
275 // test that nested callable definitions are scanned only once
276 void testNestedCallableDefinition(int * p) {
277 class A {
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) {
289 auto Lam = [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}}
292 return *q;
297 auto Lam = [p]() {
298 int * q = p; // expected-warning{{'q' is an unsafe pointer used for buffer access}}
299 q++; // expected-note{{used in pointer arithmetic here}}
300 return *q;
303 auto LamLam = [p]() {
304 auto Lam = [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}}
307 return *q;
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}}
321 Blk(p);
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}}
327 return *q;
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}}
361 int d = cArr[0][0];
362 foo(cArr[0][0]);
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}}
367 foo(cPtr);
369 // Typdefs
370 typedef int A[3];
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}}
395 #endif