1 | // RUN: %check_clang_tidy %s performance-noexcept-destructor %t -- -- -fexceptions |
2 | |
3 | struct Empty |
4 | {}; |
5 | |
6 | struct IntWrapper { |
7 | int value; |
8 | }; |
9 | |
10 | template <typename T> |
11 | struct FalseT { |
12 | static constexpr bool value = false; |
13 | }; |
14 | |
15 | template <typename T> |
16 | struct TrueT { |
17 | static constexpr bool value = true; |
18 | }; |
19 | |
20 | struct ThrowOnAnything { |
21 | ThrowOnAnything() noexcept(false); |
22 | ThrowOnAnything(ThrowOnAnything&&) noexcept(false); |
23 | ThrowOnAnything& operator=(ThrowOnAnything &&) noexcept(false); |
24 | ~ThrowOnAnything() noexcept(false); |
25 | }; |
26 | |
27 | struct B { |
28 | static constexpr bool kFalse = false; |
29 | ~B() noexcept(kFalse); |
30 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: noexcept specifier on the destructor evaluates to 'false' [performance-noexcept-destructor] |
31 | }; |
32 | |
33 | struct D { |
34 | static constexpr bool kFalse = false; |
35 | ~D() noexcept(kFalse) = default; |
36 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: noexcept specifier on the destructor evaluates to 'false' [performance-noexcept-destructor] |
37 | }; |
38 | |
39 | template <typename> |
40 | struct E { |
41 | static constexpr bool kFalse = false; |
42 | ~E() noexcept(kFalse); |
43 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: noexcept specifier on the destructor evaluates to 'false' |
44 | }; |
45 | |
46 | template <typename> |
47 | struct F { |
48 | static constexpr bool kFalse = false; |
49 | ~F() noexcept(kFalse) = default; |
50 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: noexcept specifier on the destructor evaluates to 'false' [performance-noexcept-destructor] |
51 | }; |
52 | |
53 | struct G { |
54 | ~G() = default; |
55 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: destructors should be marked noexcept [performance-noexcept-destructor] |
56 | // CHECK-FIXES: ~G() noexcept = default; |
57 | |
58 | ThrowOnAnything field; |
59 | }; |
60 | |
61 | void throwing_function() noexcept(false) {} |
62 | |
63 | struct H { |
64 | ~H() noexcept(noexcept(throwing_function())); |
65 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: noexcept specifier on the destructor evaluates to 'false' [performance-noexcept-destructor] |
66 | }; |
67 | |
68 | template <typename> |
69 | struct I { |
70 | ~I() noexcept(noexcept(throwing_function())); |
71 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: noexcept specifier on the destructor evaluates to 'false' [performance-noexcept-destructor] |
72 | }; |
73 | |
74 | template <typename T> struct TemplatedType { |
75 | static void f() {} |
76 | }; |
77 | |
78 | template <> struct TemplatedType<int> { |
79 | static void f() noexcept {} |
80 | }; |
81 | |
82 | struct J { |
83 | ~J() noexcept(noexcept(TemplatedType<double>::f())); |
84 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: noexcept specifier on the destructor evaluates to 'false' [performance-noexcept-destructor] |
85 | }; |
86 | |
87 | struct K : public ThrowOnAnything { |
88 | ~K() = default; |
89 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: destructors should be marked noexcept [performance-noexcept-destructor] |
90 | // CHECK-FIXES: ~K() noexcept = default; |
91 | }; |
92 | |
93 | struct InheritFromThrowOnAnything : public ThrowOnAnything |
94 | {}; |
95 | |
96 | struct L { |
97 | ~L() = default; |
98 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: destructors should be marked noexcept [performance-noexcept-destructor] |
99 | // CHECK-FIXES: ~L() noexcept = default; |
100 | |
101 | InheritFromThrowOnAnything IFF; |
102 | }; |
103 | |
104 | struct M : public InheritFromThrowOnAnything { |
105 | ~M() = default; |
106 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: destructors should be marked noexcept [performance-noexcept-destructor] |
107 | // CHECK-FIXES: ~M() noexcept = default; |
108 | }; |
109 | |
110 | struct N : public IntWrapper, ThrowOnAnything { |
111 | ~N() = default; |
112 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: destructors should be marked noexcept [performance-noexcept-destructor] |
113 | // CHECK-FIXES: ~N() noexcept = default; |
114 | }; |
115 | |
116 | struct O : virtual IntWrapper, ThrowOnAnything { |
117 | ~O() = default; |
118 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: destructors should be marked noexcept [performance-noexcept-destructor] |
119 | // CHECK-FIXES: ~O() noexcept = default; |
120 | }; |
121 | |
122 | class OK {}; |
123 | |
124 | struct OK1 { |
125 | ~OK1() noexcept; |
126 | }; |
127 | |
128 | struct OK2 { |
129 | static constexpr bool kTrue = true; |
130 | |
131 | ~OK2() noexcept(true) {} |
132 | }; |
133 | |
134 | struct OK4 { |
135 | ~OK4() noexcept(false) {} |
136 | }; |
137 | |
138 | struct OK3 { |
139 | ~OK3() = default; |
140 | }; |
141 | |
142 | struct OK5 { |
143 | ~OK5() noexcept(true) = default; |
144 | }; |
145 | |
146 | struct OK6 { |
147 | ~OK6() = default; |
148 | }; |
149 | |
150 | template <typename> |
151 | struct OK7 { |
152 | ~OK7() = default; |
153 | }; |
154 | |
155 | template <typename> |
156 | struct OK8 { |
157 | ~OK8() noexcept = default; |
158 | }; |
159 | |
160 | template <typename> |
161 | struct OK9 { |
162 | ~OK9() noexcept(true) = default; |
163 | }; |
164 | |
165 | template <typename> |
166 | struct OK10 { |
167 | ~OK10() noexcept(false) = default; |
168 | }; |
169 | |
170 | template <typename> |
171 | struct OK11 { |
172 | ~OK11() = delete; |
173 | }; |
174 | |
175 | void noexcept_function() noexcept {} |
176 | |
177 | struct OK12 { |
178 | ~OK12() noexcept(noexcept(noexcept_function())); |
179 | }; |
180 | |
181 | struct OK13 { |
182 | ~OK13() noexcept(noexcept(noexcept_function())) = default; |
183 | }; |
184 | |
185 | template <typename> |
186 | struct OK14 { |
187 | ~OK14() noexcept(noexcept(TemplatedType<int>::f())); |
188 | }; |
189 | |
190 | struct OK15 { |
191 | ~OK15() = default; |
192 | |
193 | int member; |
194 | }; |
195 | |
196 | template <typename> |
197 | struct OK16 { |
198 | ~OK16() = default; |
199 | |
200 | int member; |
201 | }; |
202 | |
203 | struct OK17 { |
204 | ~OK17() = default; |
205 | |
206 | OK empty_field; |
207 | }; |
208 | |
209 | template <typename> |
210 | struct OK18 { |
211 | ~OK18() = default; |
212 | |
213 | OK empty_field; |
214 | }; |
215 | |
216 | struct OK19 : public OK { |
217 | ~OK19() = default; |
218 | }; |
219 | |
220 | struct OK20 : virtual OK { |
221 | ~OK20() = default; |
222 | }; |
223 | |
224 | template <typename T> |
225 | struct OK21 : public T { |
226 | ~OK21() = default; |
227 | }; |
228 | |
229 | template <typename T> |
230 | struct OK22 : virtual T { |
231 | ~OK22() = default; |
232 | }; |
233 | |
234 | template <typename T> |
235 | struct OK23 { |
236 | ~OK23() = default; |
237 | |
238 | T member; |
239 | }; |
240 | |
241 | void testTemplates() { |
242 | OK21<Empty> value(OK21<Empty>{}); |
243 | value = OK21<Empty>{}; |
244 | |
245 | OK22<Empty> value2{OK22<Empty>{}}; |
246 | value2 = OK22<Empty>{}; |
247 | |
248 | OK23<Empty> value3{OK23<Empty>{}}; |
249 | value3 =OK23<Empty>{}; |
250 | } |
251 | |
252 | struct OK24 : public Empty, OK1 { |
253 | ~OK24() = default; |
254 | }; |
255 | |
256 | struct OK25 : virtual Empty, OK1 { |
257 | ~OK25() = default; |
258 | }; |
259 | |
260 | struct OK26 : public Empty, IntWrapper { |
261 | ~OK26() = default; |
262 | }; |
263 | |
264 | template <typename T> |
265 | struct OK27 : public T { |
266 | ~OK27() = default; |
267 | }; |
268 | |
269 | template <typename T> |
270 | struct OK28 : virtual T { |
271 | ~OK28() = default; |
272 | }; |
273 | |
274 | template <typename T> |
275 | struct OK29 { |
276 | ~OK29() = default; |
277 | |
278 | T member; |
279 | }; |
280 | |
281 | struct OK30 { |
282 | ~OK30() noexcept(TrueT<OK30>::value) = default; |
283 | }; |
284 | |
285 | template <typename> |
286 | struct OK31 { |
287 | ~OK31() noexcept(TrueT<int>::value) = default; |
288 | }; |
289 | |
290 | struct OK32 { |
291 | ~OK32(); |
292 | }; |
293 | |
294 | template <typename> |
295 | struct OK33 { |
296 | ~OK33(); |
297 | }; |
298 | |
299 | struct OK34 { |
300 | ~OK34() {} |
301 | }; |
302 | |
303 | template <typename> |
304 | struct OK35 { |
305 | ~OK35() {} |
306 | }; |
307 | |