371 lines · cpp
1// RUN: %check_clang_tidy -std=c++11-or-later %s google-readability-casting %t -- -- -fexceptions2 3bool g() { return false; }4 5enum Enum { Enum1 };6struct X {};7struct Y : public X {};8 9void 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 needed22 // CHECK-FIXES: static_cast<const char*>(t1);23 (Typedef1)cpc;24 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast (if needed25 // CHECK-FIXES: static_cast<Typedef1>(cpc);26 (Typedef1)t1;27 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant cast to the same type28 // 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 needed36 // CHECK-FIXES: Char *pChar = static_cast<Char*>(pc);37 38 (Char)*cpc;39 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast (if needed40 // CHECK-FIXES: static_cast<Char>(*cpc);41 42 (char)*pChar;43 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: {{.*}}; use static_cast (if needed44 // 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 {{.*}}106 // CHECK-FIXES: Y *pB = static_cast<Y*>(pX);107 Y &rB = (Y&)*pX;108 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}}; use static_cast {{.*}}109 // CHECK-FIXES: Y &rB = static_cast<Y&>(*pX);110 111 void *vp = (void *) pX;112 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: {{.*}}; use reinterpret_cast113 // CHECK-FIXES: void *vp = reinterpret_cast<void *>(pX);114 115 const char *pc3 = (const char*)cpv;116 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: {{.*}}; use static_cast [117 // CHECK-FIXES: const char *pc3 = static_cast<const char*>(cpv);118 119 char *pc4 = (char*)cpv;120 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [121 // CHECK-FIXES: char *pc4 = (char*)cpv;122 123 b1 = (int)Enum1;124 // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: {{.*}}; use static_cast [125 // CHECK-FIXES: b1 = static_cast<int>(Enum1);126 127 Enum e = (Enum)b1;128 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: {{.*}}; use static_cast [129 // CHECK-FIXES: Enum e = static_cast<Enum>(b1);130 131 e = (Enum)Enum1;132 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type133 // CHECK-FIXES: e = Enum1;134 135 e = (Enum)e;136 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type137 // CHECK-FIXES: e = e;138 139 e = (Enum) e;140 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type141 // CHECK-FIXES: e = e;142 143 e = (Enum) (e);144 // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: redundant cast to the same type145 // CHECK-FIXES: e = (e);146 147 static const int kZero = 0;148 (int)kZero;149 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: redundant cast to the same type150 // CHECK-FIXES: kZero;151 152 int b2 = static_cast<double>(b);153 int b3 = b;154 double aa = a;155 (void)aa;156 return (void)g();157}158 159template <typename T>160void template_function(T t, int n) {161 int i = (int)t;162 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast [163 // CHECK-FIXES: int i = (int)t;164 int j = (int)n;165 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: redundant cast to the same type166 // CHECK-FIXES: int j = n;167}168 169template <typename T>170struct TemplateStruct {171 void f(T t, int n) {172 int k = (int)t;173 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: {{.*}}; use static_cast/const_cast/reinterpret_cast174 // CHECK-FIXES: int k = (int)t;175 int l = (int)n;176 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: redundant cast to the same type177 // CHECK-FIXES: int l = n;178 }179};180 181void test_templates() {182 template_function(1, 42);183 template_function(1.0, 42);184 TemplateStruct<int>().f(1, 42);185 TemplateStruct<double>().f(1.0, 42);186}187 188extern "C" {189void extern_c_code(const char *cpc) {190 const char *cpc2 = (const char*)cpc;191 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: redundant cast to the same type192 // CHECK-FIXES: const char *cpc2 = cpc;193 char *pc = (char*)cpc;194}195}196 197#define CAST(type, value) (type)(value)198void macros(double d) {199 int i = CAST(int, d);200}201 202enum E { E1 = 1 };203template <E e>204struct A {205 // Usage of template argument e = E1 is represented as (E)1 in the AST for206 // some reason. We have a special treatment of this case to avoid warnings207 // here.208 static const E ee = e;209};210struct B : public A<E1> {};211 212 213void overloaded_function();214void overloaded_function(int);215 216template<typename Fn>217void g(Fn fn) {218 fn();219}220 221void function_casts() {222 typedef void (*FnPtrVoid)();223 typedef void (&FnRefVoid)();224 typedef void (&FnRefInt)(int);225 226 g((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 g((void (*)())&overloaded_function);230 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [231 // CHECK-FIXES: g(static_cast<void (*)()>(&overloaded_function));232 g((void (&)())overloaded_function);233 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [234 // CHECK-FIXES: g(static_cast<void (&)()>(overloaded_function));235 236 g((FnPtrVoid)overloaded_function);237 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [238 // CHECK-FIXES: g(static_cast<FnPtrVoid>(overloaded_function));239 g((FnPtrVoid)&overloaded_function);240 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [241 // CHECK-FIXES: g(static_cast<FnPtrVoid>(&overloaded_function));242 g((FnRefVoid)overloaded_function);243 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: C-style casts are discouraged; use static_cast [244 // CHECK-FIXES: g(static_cast<FnRefVoid>(overloaded_function));245 246 FnPtrVoid fn0 = (void (*)())&overloaded_function;247 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [248 // CHECK-FIXES: FnPtrVoid fn0 = static_cast<void (*)()>(&overloaded_function);249 FnPtrVoid fn1 = (void (*)())overloaded_function;250 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [251 // CHECK-FIXES: FnPtrVoid fn1 = static_cast<void (*)()>(overloaded_function);252 FnPtrVoid fn1a = (FnPtrVoid)overloaded_function;253 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: C-style casts are discouraged; use static_cast [254 // CHECK-FIXES: FnPtrVoid fn1a = static_cast<FnPtrVoid>(overloaded_function);255 FnRefInt fn2 = (void (&)(int))overloaded_function;256 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: C-style casts are discouraged; use static_cast [257 // CHECK-FIXES: FnRefInt fn2 = static_cast<void (&)(int)>(overloaded_function);258 auto fn3 = (void (*)())&overloaded_function;259 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [260 // CHECK-FIXES: auto fn3 = static_cast<void (*)()>(&overloaded_function);261 auto fn4 = (void (*)())overloaded_function;262 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [263 // CHECK-FIXES: auto fn4 = static_cast<void (*)()>(overloaded_function);264 auto fn5 = (void (&)(int))overloaded_function;265 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [266 // CHECK-FIXES: auto fn5 = static_cast<void (&)(int)>(overloaded_function);267 268 void (*fn6)() = (void (*)())&overloaded_function;269 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [270 // CHECK-FIXES: void (*fn6)() = static_cast<void (*)()>(&overloaded_function);271 void (*fn7)() = (void (*)())overloaded_function;272 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [273 // CHECK-FIXES: void (*fn7)() = static_cast<void (*)()>(overloaded_function);274 void (*fn8)() = (FnPtrVoid)overloaded_function;275 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: C-style casts are discouraged; use static_cast [276 // CHECK-FIXES: void (*fn8)() = static_cast<FnPtrVoid>(overloaded_function);277 void (&fn9)(int) = (void (&)(int))overloaded_function;278 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: C-style casts are discouraged; use static_cast [279 // CHECK-FIXES: void (&fn9)(int) = static_cast<void (&)(int)>(overloaded_function);280 281 void (*correct1)() = static_cast<void (*)()>(overloaded_function);282 FnPtrVoid correct2 = static_cast<void (*)()>(&overloaded_function);283 FnRefInt correct3 = static_cast<void (&)(int)>(overloaded_function);284}285 286struct S {287 S(const char *);288};289struct ConvertibleToS {290 operator S() const;291};292struct ConvertibleToSRef {293 operator const S&() const;294};295 296void conversions() {297 //auto s1 = (const S&)"";298 // C HECK-MESSAGES: :[[@LINE-1]]:10: warning: C-style casts are discouraged; use static_cast [299 // C HECK-FIXES: S s1 = static_cast<const S&>("");300 auto s2 = (S)"";301 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use constructor call syntax [302 // CHECK-FIXES: auto s2 = S("");303 auto s2a = (struct S)"";304 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [305 // CHECK-FIXES: auto s2a = static_cast<struct S>("");306 auto s2b = (const S)"";307 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: C-style casts are discouraged; use static_cast [308 // FIXME: This should be constructor call syntax: S("").309 // CHECK-FIXES: auto s2b = static_cast<const S>("");310 ConvertibleToS c;311 auto s3 = (const S&)c;312 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use static_cast/const_cast/reinterpret_cast [313 // CHECK-FIXES: auto s3 = (const S&)c;314 // FIXME: This should be a static_cast.315 // C HECK-FIXES: auto s3 = static_cast<const S&>(c);316 auto s4 = (S)c;317 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use constructor call syntax [318 // CHECK-FIXES: auto s4 = S(c);319 ConvertibleToSRef cr;320 auto s5 = (const S&)cr;321 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use static_cast/const_cast/reinterpret_cast [322 // CHECK-FIXES: auto s5 = (const S&)cr;323 // FIXME: This should be a static_cast.324 // C HECK-FIXES: auto s5 = static_cast<const S&>(cr);325 auto s6 = (S)cr;326 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: C-style casts are discouraged; use constructor call syntax [327 // CHECK-FIXES: auto s6 = S(cr);328}329 330template <class T>331T functional_cast_template(float i) {332 return T(i);333}334 335struct S2 {336 S2(float);337};338using T = S2;339using U = S2 &;340 341void functional_casts() {342 float x = 1.5F;343 auto y = int(x);344 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: C-style casts are discouraged; use static_cast345 // CHECK-FIXES: auto y = static_cast<int>(x);346 347#pragma clang diagnostic push348#pragma clang diagnostic ignored "-Wc++11-narrowing"349 // This if fine, compiler will warn about implicit conversions with brace initialization350 auto z = int{x};351#pragma clang diagnostic pop352 353 // Functional casts are allowed if S is of class type354 const char *str = "foo";355 auto s = S(str);356 357 // Functional casts in template functions358 functional_cast_template<S2>(x);359 functional_cast_template<int>(x);360 361 // New expressions are not functional casts362 auto w = new int(x);363 364 // Typedefs365 S2 t = T(x); // OK, constructor call366 S2 u = U(x); // NOK, it's a reinterpret_cast in disguise367 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: C-style casts are discouraged; use static_cast/const_cast/reinterpret_cast368 369 throw S2(5.0f);370}371