1 // RUN: %check_clang_tidy %s cppcoreguidelines-pro-type-static-cast-downcast %t
2 
3 class Base {
4 };
5 
6 class Derived : public Base {
7 };
8 
9 class Base2 {
10 };
11 
12 class MultiDerived : public Base, public Base2 {
13 };
14 
15 class PolymorphicBase {
16 public:
17   virtual ~PolymorphicBase();
18 };
19 
20 class PolymorphicDerived : public PolymorphicBase {
21 };
22 
23 class PolymorphicMultiDerived : public Base, public PolymorphicBase {
24 };
25 
pointers()26 void pointers() {
27 
28   auto P0 = static_cast<Derived*>(new Base());
29   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use static_cast to downcast from a base to a derived class [cppcoreguidelines-pro-type-static-cast-downcast]
30 
31   const Base* B0;
32   auto PC0 = static_cast<const Derived*>(B0);
33   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use static_cast to downcast from a base to a derived class [cppcoreguidelines-pro-type-static-cast-downcast]
34 
35   auto P1 = static_cast<Base*>(new Derived()); // OK, upcast to a public base
36   auto P2 = static_cast<Base*>(new MultiDerived()); // OK, upcast to a public base
37   auto P3 = static_cast<Base2*>(new MultiDerived()); // OK, upcast to a public base
38 }
39 
pointers_polymorphic()40 void pointers_polymorphic() {
41 
42   auto PP0 = static_cast<PolymorphicDerived*>(new PolymorphicBase());
43   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead [cppcoreguidelines-pro-type-static-cast-downcast]
44   // CHECK-FIXES: auto PP0 = dynamic_cast<PolymorphicDerived*>(new PolymorphicBase());
45 
46   const PolymorphicBase* B0;
47   auto PPC0 = static_cast<const PolymorphicDerived*>(B0);
48   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead [cppcoreguidelines-pro-type-static-cast-downcast]
49   // CHECK-FIXES: auto PPC0 = dynamic_cast<const PolymorphicDerived*>(B0);
50 
51 
52   auto B1 = static_cast<PolymorphicBase*>(new PolymorphicDerived()); // OK, upcast to a public base
53   auto B2 = static_cast<PolymorphicBase*>(new PolymorphicMultiDerived()); // OK, upcast to a public base
54   auto B3 = static_cast<Base*>(new PolymorphicMultiDerived()); // OK, upcast to a public base
55 }
56 
arrays()57 void arrays() {
58   Base ArrayOfBase[10];
59   auto A0 = static_cast<Derived*>(ArrayOfBase);
60   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use static_cast to downcast from a base to a derived class [cppcoreguidelines-pro-type-static-cast-downcast]
61 }
62 
arrays_polymorphic()63 void arrays_polymorphic() {
64   PolymorphicBase ArrayOfPolymorphicBase[10];
65   auto AP0 = static_cast<PolymorphicDerived*>(ArrayOfPolymorphicBase);
66   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead
67   // CHECK-FIXES: auto AP0 = dynamic_cast<PolymorphicDerived*>(ArrayOfPolymorphicBase);
68 }
69 
references()70 void references() {
71   Base B0;
72   auto R0 = static_cast<Derived&>(B0);
73   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use static_cast to downcast from a base to a derived class [cppcoreguidelines-pro-type-static-cast-downcast]
74   Base& RefToBase = B0;
75   auto R1 = static_cast<Derived&>(RefToBase);
76   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: do not use static_cast to downcast from a base to a derived class [cppcoreguidelines-pro-type-static-cast-downcast]
77 
78   const Base& ConstRefToBase = B0;
79   auto RC1 = static_cast<const Derived&>(ConstRefToBase);
80   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use static_cast to downcast from a base to a derived class [cppcoreguidelines-pro-type-static-cast-downcast]
81 
82 
83   Derived RD1;
84   auto R2 = static_cast<Base&>(RD1); // OK, upcast to a public base
85 }
86 
references_polymorphic()87 void references_polymorphic() {
88   PolymorphicBase B0;
89   auto RP0 = static_cast<PolymorphicDerived&>(B0);
90   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead
91   // CHECK-FIXES: auto RP0 = dynamic_cast<PolymorphicDerived&>(B0);
92 
93   PolymorphicBase& RefToPolymorphicBase = B0;
94   auto RP1 = static_cast<PolymorphicDerived&>(RefToPolymorphicBase);
95   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead [cppcoreguidelines-pro-type-static-cast-downcast]
96   // CHECK-FIXES: auto RP1 = dynamic_cast<PolymorphicDerived&>(RefToPolymorphicBase);
97 
98   const PolymorphicBase& ConstRefToPolymorphicBase = B0;
99   auto RPC2 = static_cast<const PolymorphicDerived&>(ConstRefToPolymorphicBase);
100   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: do not use static_cast to downcast from a base to a derived class; use dynamic_cast instead [cppcoreguidelines-pro-type-static-cast-downcast]
101   // CHECK-FIXES: auto RPC2 = dynamic_cast<const PolymorphicDerived&>(ConstRefToPolymorphicBase);
102 
103   PolymorphicDerived d1;
104   auto RP2 = static_cast<PolymorphicBase&>(d1); // OK, upcast to a public base
105 }
106 
107 template<class B, class D>
templ()108 void templ() {
109   auto B0 = static_cast<B*>(new D());
110 }
111 
templ_bad_call()112 void templ_bad_call() {
113   templ<Derived, Base>(); //FIXME: this should trigger a warning
114 }
115 
templ_good_call()116 void templ_good_call() {
117   templ<Base, Derived>(); // OK, upcast to a public base
118 }
119