1 | // RUN: %check_clang_tidy -std=c++11-or-later %s google-readability-casting %t -- -- -fexceptions |
2 | |
3 | bool g() { return false; } |
4 | |
5 | enum Enum { Enum1 }; |
6 | struct X {}; |
7 | struct Y : public X {}; |
8 | |
9 | void f(int a, double b, const char *cpc, const void *cpv, X *pX) { |
10 | const char *cpc2 = (const char*)cpc; |
11 | // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: redundant cast to the same type [google-readability-casting] |
12 | // CHECK-FIXES: const char *cpc2 = cpc; |
13 | |
14 | typedef const char *Typedef1; |
15 | typedef const char *Typedef2; |
16 | Typedef1 t1; |
17 | (Typedef2)t1; |
18 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: C-style casts are discouraged; use static_cast (if needed, the cast may be redundant) [google-readability-casting] |
19 | // CHECK-FIXES: {{^}} static_cast<Typedef2>(t1); |
20 | (const char*)t1; |
21 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast (if needed |
22 | // CHECK-FIXES: {{^}} static_cast<const char*>(t1); |
23 | (Typedef1)cpc; |
24 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast (if needed |
25 | // CHECK-FIXES: {{^}} static_cast<Typedef1>(cpc); |
26 | (Typedef1)t1; |
27 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant cast to the same type |
28 | // CHECK-FIXES: {{^}} t1; |
29 | |
30 | char *pc = (char*)cpc; |
31 | // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use const_cast [google-readability-casting] |
32 | // CHECK-FIXES: char *pc = const_cast<char*>(cpc); |
33 | typedef char Char; |
34 | Char *pChar = (Char*)pc; |
35 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: {{.*}}; use static_cast (if needed |
36 | // CHECK-FIXES: {{^}} Char *pChar = static_cast<Char*>(pc); |
37 | |
38 | (Char)*cpc; |
39 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast (if needed |
40 | // CHECK-FIXES: {{^}} static_cast<Char>(*cpc); |
41 | |
42 | (char)*pChar; |
43 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast (if needed |
44 | // CHECK-FIXES: {{^}} static_cast<char>(*pChar); |
45 | |
46 | (const char*)cpv; |
47 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast [ |
48 | // CHECK-FIXES: static_cast<const char*>(cpv); |
49 | |
50 | char *pc2 = (char*)(cpc + 33); |
51 | // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}}; use const_cast [ |
52 | // CHECK-FIXES: char *pc2 = const_cast<char*>(cpc + 33); |
53 | |
54 | const char &crc = *cpc; |
55 | char &rc = (char&)crc; |
56 | // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}}; use const_cast [ |
57 | // CHECK-FIXES: char &rc = const_cast<char&>(crc); |
58 | |
59 | char &rc2 = (char&)*cpc; |
60 | // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}}; use const_cast [ |
61 | // CHECK-FIXES: char &rc2 = const_cast<char&>(*cpc); |
62 | |
63 | char ** const* const* ppcpcpc; |
64 | char ****ppppc = (char****)ppcpcpc; |
65 | // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: {{.*}}; use const_cast [ |
66 | // CHECK-FIXES: char ****ppppc = const_cast<char****>(ppcpcpc); |
67 | |
68 | char ***pppc = (char***)*(ppcpcpc); |
69 | // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: {{.*}}; use const_cast [ |
70 | // CHECK-FIXES: char ***pppc = const_cast<char***>(*(ppcpcpc)); |
71 | |
72 | char ***pppc2 = (char***)(*ppcpcpc); |
73 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: {{.*}}; use const_cast [ |
74 | // CHECK-FIXES: char ***pppc2 = const_cast<char***>(*ppcpcpc); |
75 | |
76 | char *pc5 = (char*)(const char*)(cpv); |
77 | // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}}; use const_cast [ |
78 | // CHECK-MESSAGES: :[[@LINE-2]]:22: warning: {{.*}}; use static_cast [ |
79 | // CHECK-FIXES: char *pc5 = const_cast<char*>(static_cast<const char*>(cpv)); |
80 | |
81 | int b1 = (int)b; |
82 | // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: {{.*}}; use static_cast [ |
83 | // CHECK-FIXES: int b1 = static_cast<int>(b); |
84 | b1 = (const int&)b; |
85 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [ |
86 | // CHECK-FIXES: b1 = (const int&)b; |
87 | |
88 | b1 = (int) b; |
89 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast {{.*}} |
90 | // CHECK-FIXES: b1 = static_cast<int>(b); |
91 | |
92 | b1 = (int) b; |
93 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast {{.*}} |
94 | // CHECK-FIXES: b1 = static_cast<int>(b); |
95 | |
96 | b1 = (int) (b); |
97 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast {{.*}} |
98 | // CHECK-FIXES: b1 = static_cast<int>(b); |
99 | |
100 | b1 = (int) (b); |
101 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast {{.*}} |
102 | // CHECK-FIXES: b1 = static_cast<int>(b); |
103 | |
104 | Y *pB = (Y*)pX; |
105 | // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [ |
106 | Y &rB = (Y&)*pX; |
107 | // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [ |
108 | |
109 | const char *pc3 = (const char*)cpv; |
110 | // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: {{.*}}; use static_cast [ |
111 | // CHECK-FIXES: const char *pc3 = static_cast<const char*>(cpv); |
112 | |
113 | char *pc4 = (char*)cpv; |
114 | // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [ |
115 | // CHECK-FIXES: char *pc4 = (char*)cpv; |
116 | |
117 | b1 = (int)Enum1; |
118 | // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast [ |
119 | // CHECK-FIXES: b1 = static_cast<int>(Enum1); |
120 | |
121 | Enum e = (Enum)b1; |
122 | // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: {{.*}}; use static_cast [ |
123 | // CHECK-FIXES: Enum e = static_cast<Enum>(b1); |
124 | |
125 | e = (Enum)Enum1; |
126 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type |
127 | // CHECK-FIXES: {{^}} e = Enum1; |
128 | |
129 | e = (Enum)e; |
130 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type |
131 | // CHECK-FIXES: {{^}} e = e; |
132 | |
133 | e = (Enum) e; |
134 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type |
135 | // CHECK-FIXES: {{^}} e = e; |
136 | |
137 | e = (Enum) (e); |
138 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type |
139 | // CHECK-FIXES: {{^}} e = (e); |
140 | |
141 | static const int kZero = 0; |
142 | (int)kZero; |
143 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant cast to the same type |
144 | // CHECK-FIXES: {{^}} kZero; |
145 | |
146 | int b2 = static_cast<double>(b); |
147 | int b3 = b; |
148 | double aa = a; |
149 | (void)aa; |
150 | return (void)g(); |
151 | } |
152 | |
153 | template <typename T> |
154 | void template_function(T t, int n) { |
155 | int i = (int)t; |
156 | // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [ |
157 | // CHECK-FIXES: int i = (int)t; |
158 | int j = (int)n; |
159 | // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant cast to the same type |
160 | // CHECK-FIXES: int j = n; |
161 | } |
162 | |
163 | template <typename T> |
164 | struct TemplateStruct { |
165 | void f(T t, int n) { |
166 | int k = (int)t; |
167 | // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast |
168 | // CHECK-FIXES: int k = (int)t; |
169 | int l = (int)n; |
170 | // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant cast to the same type |
171 | // CHECK-FIXES: int l = n; |
172 | } |
173 | }; |
174 | |
175 | void test_templates() { |
176 | template_function(t: 1, n: 42); |
177 | template_function(t: 1.0, n: 42); |
178 | TemplateStruct<int>().f(t: 1, n: 42); |
179 | TemplateStruct<double>().f(t: 1.0, n: 42); |
180 | } |
181 | |
182 | extern "C" { |
183 | void extern_c_code(const char *cpc) { |
184 | const char *cpc2 = (const char*)cpc; |
185 | // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: redundant cast to the same type |
186 | // CHECK-FIXES: const char *cpc2 = cpc; |
187 | char *pc = (char*)cpc; |
188 | } |
189 | } |
190 | |
191 | #define CAST(type, value) (type)(value) |
192 | void macros(double d) { |
193 | int i = CAST(int, d); |
194 | } |
195 | |
196 | enum E { E1 = 1 }; |
197 | template <E e> |
198 | struct A { |
199 | // Usage of template argument e = E1 is represented as (E)1 in the AST for |
200 | // some reason. We have a special treatment of this case to avoid warnings |
201 | // here. |
202 | static const E ee = e; |
203 | }; |
204 | struct B : public A<E1> {}; |
205 | |
206 | |
207 | void overloaded_function(); |
208 | void overloaded_function(int); |
209 | |
210 | template<typename Fn> |
211 | void g(Fn fn) { |
212 | fn(); |
213 | } |
214 | |
215 | void function_casts() { |
216 | typedef void (*FnPtrVoid)(); |
217 | typedef void (&FnRefVoid)(); |
218 | typedef void (&FnRefInt)(int); |
219 | |
220 | g(fn: (void (*)())overloaded_function); |
221 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [ |
222 | // CHECK-FIXES: g(static_cast<void (*)()>(overloaded_function)); |
223 | g(fn: (void (*)())&overloaded_function); |
224 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [ |
225 | // CHECK-FIXES: g(static_cast<void (*)()>(&overloaded_function)); |
226 | g(fn: (void (&)())overloaded_function); |
227 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [ |
228 | // CHECK-FIXES: g(static_cast<void (&)()>(overloaded_function)); |
229 | |
230 | g(fn: (FnPtrVoid)overloaded_function); |
231 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [ |
232 | // CHECK-FIXES: g(static_cast<FnPtrVoid>(overloaded_function)); |
233 | g(fn: (FnPtrVoid)&overloaded_function); |
234 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [ |
235 | // CHECK-FIXES: g(static_cast<FnPtrVoid>(&overloaded_function)); |
236 | g(fn: (FnRefVoid)overloaded_function); |
237 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [ |
238 | // CHECK-FIXES: g(static_cast<FnRefVoid>(overloaded_function)); |
239 | |
240 | FnPtrVoid fn0 = (void (*)())&overloaded_function; |
241 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [ |
242 | // CHECK-FIXES: FnPtrVoid fn0 = static_cast<void (*)()>(&overloaded_function); |
243 | FnPtrVoid fn1 = (void (*)())overloaded_function; |
244 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [ |
245 | // CHECK-FIXES: FnPtrVoid fn1 = static_cast<void (*)()>(overloaded_function); |
246 | FnPtrVoid fn1a = (FnPtrVoid)overloaded_function; |
247 | // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: C-style casts are discouraged; use static_cast [ |
248 | // CHECK-FIXES: FnPtrVoid fn1a = static_cast<FnPtrVoid>(overloaded_function); |
249 | FnRefInt fn2 = (void (&)(int))overloaded_function; |
250 | // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: C-style casts are discouraged; use static_cast [ |
251 | // CHECK-FIXES: FnRefInt fn2 = static_cast<void (&)(int)>(overloaded_function); |
252 | auto fn3 = (void (*)())&overloaded_function; |
253 | // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [ |
254 | // CHECK-FIXES: auto fn3 = static_cast<void (*)()>(&overloaded_function); |
255 | auto fn4 = (void (*)())overloaded_function; |
256 | // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [ |
257 | // CHECK-FIXES: auto fn4 = static_cast<void (*)()>(overloaded_function); |
258 | auto fn5 = (void (&)(int))overloaded_function; |
259 | // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [ |
260 | // CHECK-FIXES: auto fn5 = static_cast<void (&)(int)>(overloaded_function); |
261 | |
262 | void (*fn6)() = (void (*)())&overloaded_function; |
263 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [ |
264 | // CHECK-FIXES: void (*fn6)() = static_cast<void (*)()>(&overloaded_function); |
265 | void (*fn7)() = (void (*)())overloaded_function; |
266 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [ |
267 | // CHECK-FIXES: void (*fn7)() = static_cast<void (*)()>(overloaded_function); |
268 | void (*fn8)() = (FnPtrVoid)overloaded_function; |
269 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [ |
270 | // CHECK-FIXES: void (*fn8)() = static_cast<FnPtrVoid>(overloaded_function); |
271 | void (&fn9)(int) = (void (&)(int))overloaded_function; |
272 | // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: C-style casts are discouraged; use static_cast [ |
273 | // CHECK-FIXES: void (&fn9)(int) = static_cast<void (&)(int)>(overloaded_function); |
274 | |
275 | void (*correct1)() = static_cast<void (*)()>(overloaded_function); |
276 | FnPtrVoid correct2 = static_cast<void (*)()>(&overloaded_function); |
277 | FnRefInt correct3 = static_cast<void (&)(int)>(overloaded_function); |
278 | } |
279 | |
280 | struct S { |
281 | S(const char *); |
282 | }; |
283 | struct ConvertibleToS { |
284 | operator S() const; |
285 | }; |
286 | struct ConvertibleToSRef { |
287 | operator const S&() const; |
288 | }; |
289 | |
290 | void conversions() { |
291 | //auto s1 = (const S&)""; |
292 | // C HECK-MESSAGES: :[[@LINE-1]]:10: warning: C-style casts are discouraged; use static_cast [ |
293 | // C HECK-FIXES: S s1 = static_cast<const S&>(""); |
294 | auto s2 = (S)"" ; |
295 | // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use constructor call syntax [ |
296 | // CHECK-FIXES: auto s2 = S(""); |
297 | auto s2a = (struct S)"" ; |
298 | // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [ |
299 | // CHECK-FIXES: auto s2a = static_cast<struct S>(""); |
300 | auto s2b = (const S)"" ; |
301 | // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [ |
302 | // FIXME: This should be constructor call syntax: S(""). |
303 | // CHECK-FIXES: auto s2b = static_cast<const S>(""); |
304 | ConvertibleToS c; |
305 | auto s3 = (const S&)c; |
306 | // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use static_cast/const_cast/reinterpret_cast [ |
307 | // CHECK-FIXES: auto s3 = (const S&)c; |
308 | // FIXME: This should be a static_cast. |
309 | // C HECK-FIXES: auto s3 = static_cast<const S&>(c); |
310 | auto s4 = (S)c; |
311 | // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use constructor call syntax [ |
312 | // CHECK-FIXES: auto s4 = S(c); |
313 | ConvertibleToSRef cr; |
314 | auto s5 = (const S&)cr; |
315 | // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use static_cast/const_cast/reinterpret_cast [ |
316 | // CHECK-FIXES: auto s5 = (const S&)cr; |
317 | // FIXME: This should be a static_cast. |
318 | // C HECK-FIXES: auto s5 = static_cast<const S&>(cr); |
319 | auto s6 = (S)cr; |
320 | // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use constructor call syntax [ |
321 | // CHECK-FIXES: auto s6 = S(cr); |
322 | } |
323 | |
324 | template <class T> |
325 | T functional_cast_template(float i) { |
326 | return T(i); |
327 | } |
328 | |
329 | struct S2 { |
330 | S2(float); |
331 | }; |
332 | using T = S2; |
333 | using U = S2 &; |
334 | |
335 | void functional_casts() { |
336 | float x = 1.5F; |
337 | auto y = int(x); |
338 | // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: C-style casts are discouraged; use static_cast |
339 | // CHECK-FIXES: auto y = static_cast<int>(x); |
340 | |
341 | #pragma clang diagnostic push |
342 | #pragma clang diagnostic ignored "-Wc++11-narrowing" |
343 | // This if fine, compiler will warn about implicit conversions with brace initialization |
344 | auto z = int{x}; |
345 | #pragma clang diagnostic pop |
346 | |
347 | // Functional casts are allowed if S is of class type |
348 | const char *str = "foo" ; |
349 | auto s = S(str); |
350 | |
351 | // Functional casts in template functions |
352 | functional_cast_template<S2>(i: x); |
353 | functional_cast_template<int>(i: x); |
354 | |
355 | // New expressions are not functional casts |
356 | auto w = new int(x); |
357 | |
358 | // Typedefs |
359 | S2 t = T(x); // OK, constructor call |
360 | S2 u = U(x); // NOK, it's a reinterpret_cast in disguise |
361 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: C-style casts are discouraged; use static_cast/const_cast/reinterpret_cast |
362 | |
363 | throw S2(5.0f); |
364 | } |
365 | |