[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / SemaCXX / warn-unsafe-buffer-usage.cpp
blob642db0e9d3c632f2257ac3b184b5193240206546
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 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}}
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 // 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}}
72 (idx + 1)[idx[b]]);
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()],
80 charPtrCall()[0],
81 0[charPtrCall()]
85 void testArraySubscriptsWithAuto() {
86 int a[10];
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}}
116 struct T {
117 int a[10];
118 int * b;
119 struct {
120 int a[10];
121 int * b;
122 } c;
125 typedef struct T T_t;
127 T_t funRetT();
128 T_t * funRetTStar();
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}}
180 int c[10];
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}}
187 return x;
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}}
201 auto Lam1 = [=]() {
202 return a[idx]; // expected-note{{used in buffer access here}}
205 auto Lam2 = [&]() {
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
235 T_ptr_t getPtr();
237 template<typename T>
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}}
241 int a[10];
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) {
258 int *a[10];
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() {
268 struct S_t {
269 int x;
270 int * y;
271 } S;
273 int S_t::* p = &S_t::x;
274 int * S_t::* q = &S_t::y;
276 foo(S.*p,
277 (S.*q)[1]); // expected-warning{{unsafe buffer access}}
280 // test that nested callable definitions are scanned only once
281 void testNestedCallableDefinition(int * p) {
282 class A {
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) {
294 auto Lam = [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}}
297 return *q;
302 auto Lam = [p]() {
303 int * q = p; // expected-warning{{'q' is an unsafe pointer used for buffer access}}
304 q++; // expected-note{{used in pointer arithmetic here}}
305 return *q;
308 auto LamLam = [p]() {
309 auto Lam = [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}}
312 return *q;
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}}
326 Blk(p);
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}}
332 return *q;
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}}
367 int d = cArr[0][0];
368 foo(cArr[0][0]);
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}}
373 foo(cPtr);
375 // Typdefs
376 typedef int A[3];
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}}
400 #endif