xref: /llvm-project/clang/test/SemaCXX/warn-unsafe-buffer-usage-pragma-fixit.cpp (revision fde4b80cb772897a8cf0b3d022f3041e10b6e816)
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 
basic(int * x)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: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int> "
11   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
12   // CHECK: 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 
withDiagnosticWarning()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: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int> "
25   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
26   // CHECK: 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 
withDiagnosticIgnore()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: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int> "
61   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
62   // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:24-[[@LINE-3]]:24}:", 10}"
63   int *p3 = new int[10];
64   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int> "
65   // CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:13-[[@LINE-2]]:13}:"{"
66   // CHECK: 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 
noteGoesWithVarDeclWarning()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.
suppressedVarInGroup()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.
suppressedVarInGroup_control()134 void suppressedVarInGroup_control() {
135   int * a;
136   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"
137   int * b;
138   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"
139   int * c;
140   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"
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`.
suppressedVarInGroup2()151 void suppressedVarInGroup2() {
152   int * a;
153   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"
154   int * b;
155   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"
156   int * c;
157   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"
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.
suppressedVarInGroup3()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-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
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 // FIXME: we do not fix `a = b` and `b = c` because the `.data()`  fix-it is not generally correct.
186 }
187 
188 // The implication edges are: `a` -> `b` -> `c` -> `a`.
189 // The unsafe operation on `b` is supressed, while the unsafe
190 // operation on `c` is not suppressed. Since the implication graph
191 // forms a cycle, all variables will be fixed.
suppressedVarInGroup4()192 void suppressedVarInGroup4() {
193   int * a;
194   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"
195   int * b;
196   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"
197   int * c;
198   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"
199 
200   c[5] = 5;
201 #pragma clang unsafe_buffer_usage begin
202   b[5] = 5;
203 #pragma clang unsafe_buffer_usage end
204   a = b;
205   b = c;
206   c = a;
207 }
208 
209 // There are two groups: `a` -> `b` -> `c` and `d` -> `e` -> `f`.
210 // Suppressing unsafe operations on variables in one group does not
211 // affect other groups.
suppressedVarInGroup5()212 void suppressedVarInGroup5() {
213   int * a;
214   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
215   int * b;
216   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
217   int * c;
218   // CHECK-NOT: fix-it:"{{.*}}":{[[@LINE-1]]:
219   int * d;
220   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"
221   int * e;
222   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"
223   int * f;
224   // CHECK: fix-it:"{{.*}}":{[[@LINE-1]]:3-[[@LINE-1]]:8}:"std::span<int>"
225 
226 #pragma clang unsafe_buffer_usage begin
227   a[5] = 5;
228 #pragma clang unsafe_buffer_usage end
229   a = b;
230   b = c;
231 
232   d[5] = 5;
233   d = e;
234   e = f;
235 }
236