xref: /llvm-project/clang/test/SemaCXX/warn-unsafe-buffer-usage-pragma-fixit.cpp (revision cfcf76c6ad72581917fc65b598e3b64ca28c5ce1)
1 // RUN: %clang_cc1 -std=c++20 -Wunsafe-buffer-usage \
2 // RUN:            -fsafe-buffer-usage-suggestions \
3 // RUN:            -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
4 
5 void basic(int * x) {
6   int tmp;
7   int *p1 = new int[10];  // no fix
8   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
9   int *p2 = new int[10];
10   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span<int> p2"
11   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
12   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"
13 #pragma clang unsafe_buffer_usage begin
14   tmp = p1[5];
15 #pragma clang unsafe_buffer_usage end
16   tmp = p2[5];
17 }
18 
19 void withDiagnosticWarning() {
20   int tmp;
21   int *p1 = new int[10]; // no fix
22   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
23   int *p2 = new int[10];
24   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span<int> p2"
25   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
26   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"
27 
28   // diagnostics in opt-out region
29 #pragma clang unsafe_buffer_usage begin
30   tmp = p1[5];  // not to warn
31   tmp = p2[5];  // not to warn
32 #pragma clang diagnostic push
33 #pragma clang diagnostic warning "-Wunsafe-buffer-usage"
34   tmp = p1[5];  // not to warn
35   tmp = p2[5];  // not to warn
36 #pragma clang diagnostic warning "-Weverything"
37   tmp = p1[5];  // not to warn
38   tmp = p2[5];  // not to warn
39 #pragma clang diagnostic pop
40 #pragma clang unsafe_buffer_usage end
41 
42   // opt-out region under diagnostic warning
43 #pragma clang diagnostic push
44 #pragma clang diagnostic warning "-Wunsafe-buffer-usage"
45 #pragma clang unsafe_buffer_usage begin
46   tmp = p1[5];  // not to warn
47   tmp = p2[5];  // not to warn
48 #pragma clang unsafe_buffer_usage end
49 #pragma clang diagnostic pop
50 
51   tmp = p2[5];
52 }
53 
54 
55 void withDiagnosticIgnore() {
56   int tmp;
57   int *p1 = new int[10];
58   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
59   int *p2 = new int[10];
60   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span<int> p2"
61   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
62   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"
63   int *p3 = new int[10];
64   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:12}:"std::span<int> p3"
65   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
66   // CHECK-DAG: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"
67 
68 #pragma clang unsafe_buffer_usage begin
69   tmp = p1[5];  // not to warn
70   tmp = p2[5];  // not to warn
71 #pragma clang diagnostic push
72 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
73   tmp = p1[5];  // not to warn
74   tmp = p2[5];  // not to warn
75 #pragma clang diagnostic ignored "-Weverything"
76   tmp = p1[5];  // not to warn
77   tmp = p2[5];  // not to warn
78 #pragma clang diagnostic pop
79 #pragma clang unsafe_buffer_usage end
80 
81 #pragma clang diagnostic push
82 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
83 #pragma clang unsafe_buffer_usage begin
84   tmp = p1[5];  // not to warn
85   tmp = p2[5];  // not to warn
86 #pragma clang unsafe_buffer_usage end
87 #pragma clang diagnostic pop
88 
89   tmp = p2[5];
90 
91 #pragma clang diagnostic push
92 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
93 #pragma clang unsafe_buffer_usage begin
94   tmp = p1[5];  // not to warn
95   tmp = p2[5];  // not to warn
96 #pragma clang unsafe_buffer_usage end
97   tmp = p3[5];  // expected-note{{used in buffer access here}}
98 #pragma clang diagnostic pop
99 }
100 
101 void noteGoesWithVarDeclWarning() {
102 #pragma clang diagnostic push
103 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
104   int *p = new int[10]; // not to warn
105   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
106 #pragma clang diagnostic pop
107 
108   p[5]; // not to note since the associated warning is suppressed
109 }
110 
111 
112 // Test suppressing interacts with variable grouping:
113 
114 // The implication edges are: `a` -> `b` -> `c`.
115 // If the unsafe operation on `a` is supressed, none of the variables
116 // will be fixed.
117 void suppressedVarInGroup() {
118   int * a;
119   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
120   int * b;
121   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
122   int * c;
123   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
124 
125 #pragma clang unsafe_buffer_usage begin
126   a[5] = 5;
127 #pragma clang unsafe_buffer_usage end
128   a = b;
129   b = c;
130 }
131 
132 // To show that if `a[5]` is not suppressed in the
133 // `suppressedVarInGroup` function above, all variables will be fixed.
134 void suppressedVarInGroup_control() {
135   int * a;
136   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> a"
137   int * b;
138   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> b"
139   int * c;
140   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> c"
141 
142   a[5] = 5;
143   a = b;
144   b = c;
145 }
146 
147 // The implication edges are: `a` -> `b` -> `c`.
148 // The unsafe operation on `b` is supressed, while the unsafe
149 // operation on `a` is not suppressed. Variable `b` will still be
150 // fixed when fixing `a`.
151 void suppressedVarInGroup2() {
152   int * a;
153   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> a"
154   int * b;
155   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> b"
156   int * c;
157   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> c"
158 
159   a[5] = 5;
160 #pragma clang unsafe_buffer_usage begin
161   b[5] = 5;
162 #pragma clang unsafe_buffer_usage end
163   a = b;
164   b = c;
165 }
166 
167 // The implication edges are: `a` -> `b` -> `c`.
168 // The unsafe operation on `b` is supressed, while the unsafe
169 // operation on `c` is not suppressed. Only variable `c` will be fixed
170 // then.
171 void suppressedVarInGroup3() {
172   int * a;
173   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
174   int * b;
175   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
176   int * c;
177   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> c"
178 
179   c[5] = 5;
180 #pragma clang unsafe_buffer_usage begin
181   b[5] = 5;
182 #pragma clang unsafe_buffer_usage end
183   a = b;
184   b = c;
185 }
186 
187 // The implication edges are: `a` -> `b` -> `c` -> `a`.
188 // The unsafe operation on `b` is supressed, while the unsafe
189 // operation on `c` is not suppressed. Since the implication graph
190 // forms a cycle, all variables will be fixed.
191 void suppressedVarInGroup4() {
192   int * a;
193   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> a"
194   int * b;
195   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> b"
196   int * c;
197   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> c"
198 
199   c[5] = 5;
200 #pragma clang unsafe_buffer_usage begin
201   b[5] = 5;
202 #pragma clang unsafe_buffer_usage end
203   a = b;
204   b = c;
205   c = a;
206 }
207 
208 // There are two groups: `a` -> `b` -> `c` and `d` -> `e` -> `f`.
209 // Suppressing unsafe operations on variables in one group does not
210 // affect other groups.
211 void suppressedVarInGroup5() {
212   int * a;
213   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
214   int * b;
215   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
216   int * c;
217   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
218   int * d;
219   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> d"
220   int * e;
221   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> e"
222   int * f;
223   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:10}:"std::span<int> f"
224 
225 #pragma clang unsafe_buffer_usage begin
226   a[5] = 5;
227 #pragma clang unsafe_buffer_usage end
228   a = b;
229   b = c;
230 
231   d[5] = 5;
232   d = e;
233   e = f;
234 }
235