1 // RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \
2 // RUN:            -fsafe-buffer-usage-suggestions \
3 // RUN:            -triple=arm-apple \
4 // RUN:            -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
5 
6 int f(unsigned long, void *);
7 
8 [[clang::unsafe_buffer_usage]]
9 int unsafe_f(unsigned long, void *);
10 
address_to_integer(int x)11 void address_to_integer(int x) {
12   int * p = new int[10];
13   unsigned long n = (unsigned long) &p[5];
14   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:37-[[@LINE-1]]:42}:"&p.data()[5]"
15   unsigned long m = (unsigned long) &p[x];
16   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:37-[[@LINE-1]]:42}:"&p.data()[x]"
17 }
18 
address_to_bool(int x)19 void address_to_bool(int x) {
20   int * p = new int[10];
21   bool a = (bool) &p[5];
22   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:19-[[@LINE-1]]:24}:"&p.data()[5]"
23   bool b = (bool) &p[x];
24   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:19-[[@LINE-1]]:24}:"&p.data()[x]"
25 
26   bool a1 = &p[5];
27   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:18}:"&p.data()[5]"
28   bool b1 = &p[x];
29   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:13-[[@LINE-1]]:18}:"&p.data()[x]"
30 
31   if (&p[5]) {
32     // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:12}:"&p.data()[5]"
33     return;
34   }
35 }
36 
call_argument(int x)37 void call_argument(int x) {
38   int * p = new int[10];
39 
40   f((unsigned long) &p[5], &p[x]);
41   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:21-[[@LINE-1]]:26}:"&p.data()[5]"
42   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:28-[[@LINE-2]]:33}:"&p.data()[x]"
43 }
44 
ignore_unsafe_calls(int x)45 void ignore_unsafe_calls(int x) {
46   // Cannot fix `&p[x]` for now as it is an argument of an unsafe
47   // call. So no fix for variable `p`.
48   int * p = new int[10];
49   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
50   unsafe_f((unsigned long) &p[5],
51 	   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
52 	   &p[x]);
53 
54   int * q = new int[10];
55   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"
56   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
57   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"
58   unsafe_f((unsigned long) &q[5],
59 	   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:28-[[@LINE-1]]:33}:"&q.data()[5]"
60 	   (void*)0);
61 }
62 
odd_subscript_form()63 void odd_subscript_form() {
64   int * p = new int[10];
65   unsigned long n = (unsigned long) &5[p];
66   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:37-[[@LINE-1]]:42}:"&p.data()[5]"
67 }
68 
index_is_zero()69 void index_is_zero() {
70   int * p = new int[10];
71   int n = p[5];
72 
73   f((unsigned long)&p[0],
74     // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:20-[[@LINE-1]]:25}:"p.data()"
75     &p[0]);
76   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:5-[[@LINE-1]]:10}:"p.data()"
77 }
78 
pointer_subtraction(int x)79 void pointer_subtraction(int x) {
80   int * p = new int[10];
81   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"
82   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
83   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"
84 
85   int n = &p[9] - &p[4];
86   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:11-[[@LINE-1]]:16}:"&p.data()[9]"
87   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:19-[[@LINE-2]]:24}:"&p.data()[4]"
88   if (&p[9] - &p[x]) {
89     // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:7-[[@LINE-1]]:12}:"&p.data()[9]"
90     // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:15-[[@LINE-2]]:20}:"&p.data()[x]"
91     return;
92   }
93 }
94 
95 // To test multiple function declarations, each of which carries
96 // different incomplete informations.
97 // no fix-it in the rest of this test:
98 
99 [[clang::unsafe_buffer_usage]]
100 void unsafe_g(void*);
101 
102 void unsafe_g(void*);
103 
multiple_unsafe_fundecls()104 void multiple_unsafe_fundecls() {
105   int * p = new int[10];
106   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
107   unsafe_g(&p[5]);
108   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
109 }
110 
111 void unsafe_h(void*);
112 
113 [[clang::unsafe_buffer_usage]]
114 void unsafe_h(void*);
115 
unsafe_h(void * p)116 void unsafe_h(void* p) { ((char*)p)[10]; }
117 
multiple_unsafe_fundecls2()118 void multiple_unsafe_fundecls2() {
119   int * p = new int[10];
120   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
121   unsafe_h(&p[5]);
122   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]
123 }
124