1 // RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.MemoryUnsafeCastChecker -verify %s
4 class Derived
: public Base
{ };
6 template<typename Target
, typename Source
>
7 Target
& downcast_ref(Source
& source
){
9 return static_cast<Target
&>(source
);
12 template<typename Target
, typename Source
>
13 Target
* downcast_ptr(Source
* source
){
15 return static_cast<Target
*>(source
);
18 void test_pointers(Base
*base
) {
19 Derived
*derived_static
= static_cast<Derived
*>(base
);
20 // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}}
21 Derived
*derived_reinterpret
= reinterpret_cast<Derived
*>(base
);
22 // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}}
23 Derived
*derived_c
= (Derived
*)base
;
24 // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}}
25 Derived
*derived_d
= downcast_ptr
<Derived
, Base
>(base
); // no warning
28 void test_non_pointers(Derived derived
) {
29 Base base_static
= static_cast<Base
>(derived
); // no warning
32 void test_refs(Base
&base
) {
33 Derived
&derived_static
= static_cast<Derived
&>(base
);
34 // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}}
35 Derived
&derived_reinterpret
= reinterpret_cast<Derived
&>(base
);
36 // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}}
37 Derived
&derived_c
= (Derived
&)base
;
38 // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}}
39 Derived
&derived_d
= downcast_ref
<Derived
, Base
>(base
); // no warning
43 virtual void virtual_base_function();
46 class DerivedVirtual
: public BaseVirtual
{
47 void virtual_base_function() override
{ }
50 void test_dynamic_casts(BaseVirtual
*base_ptr
, BaseVirtual
&base_ref
) {
51 DerivedVirtual
*derived_dynamic_ptr
= dynamic_cast<DerivedVirtual
*>(base_ptr
);
52 // expected-warning@-1{{Unsafe cast from base type 'BaseVirtual' to derived type 'DerivedVirtual'}}
53 DerivedVirtual
&derived_dynamic_ref
= dynamic_cast<DerivedVirtual
&>(base_ref
);
54 // expected-warning@-1{{Unsafe cast from base type 'BaseVirtual' to derived type 'DerivedVirtual'}}
57 struct BaseStruct
{ };
58 struct DerivedStruct
: BaseStruct
{ };
60 void test_struct_pointers(struct BaseStruct
*base_struct
) {
61 struct DerivedStruct
*derived_static
= static_cast<struct DerivedStruct
*>(base_struct
);
62 // expected-warning@-1{{Unsafe cast from base type 'BaseStruct' to derived type 'DerivedStruct'}}
63 struct DerivedStruct
*derived_reinterpret
= reinterpret_cast<struct DerivedStruct
*>(base_struct
);
64 // expected-warning@-1{{Unsafe cast from base type 'BaseStruct' to derived type 'DerivedStruct'}}
65 struct DerivedStruct
*derived_c
= (struct DerivedStruct
*)base_struct
;
66 // expected-warning@-1{{Unsafe cast from base type 'BaseStruct' to derived type 'DerivedStruct'}}
69 typedef struct BaseStruct BStruct
;
70 typedef struct DerivedStruct DStruct
;
72 void test_struct_refs(BStruct
&base_struct
) {
73 DStruct
&derived_static
= static_cast<DStruct
&>(base_struct
);
74 // expected-warning@-1{{Unsafe cast from base type 'BaseStruct' to derived type 'DerivedStruct'}}
75 DStruct
&derived_reinterpret
= reinterpret_cast<DStruct
&>(base_struct
);
76 // expected-warning@-1{{Unsafe cast from base type 'BaseStruct' to derived type 'DerivedStruct'}}
77 DStruct
&derived_c
= (DStruct
&)base_struct
;
78 // expected-warning@-1{{Unsafe cast from base type 'BaseStruct' to derived type 'DerivedStruct'}}
82 void test_recursive(BStruct
&base_struct
) {
86 DStruct
&derived_static
= static_cast<DStruct
&>(base_struct
);
87 // expected-warning@-1{{Unsafe cast from base type 'BaseStruct' to derived type 'DerivedStruct'}}
91 class BaseTemplate
{ };
94 class DerivedTemplate
: public BaseTemplate
<T
> { };
96 void test_templates(BaseTemplate
<int> *base
, BaseTemplate
<int> &base_ref
) {
97 DerivedTemplate
<int> *derived_static
= static_cast<DerivedTemplate
<int>*>(base
);
98 // expected-warning@-1{{Unsafe cast from base type 'BaseTemplate' to derived type 'DerivedTemplate'}}
99 DerivedTemplate
<int> *derived_reinterpret
= reinterpret_cast<DerivedTemplate
<int>*>(base
);
100 // expected-warning@-1{{Unsafe cast from base type 'BaseTemplate' to derived type 'DerivedTemplate'}}
101 DerivedTemplate
<int> *derived_c
= (DerivedTemplate
<int>*)base
;
102 // expected-warning@-1{{Unsafe cast from base type 'BaseTemplate' to derived type 'DerivedTemplate'}}
103 DerivedTemplate
<int> &derived_static_ref
= static_cast<DerivedTemplate
<int>&>(base_ref
);
104 // expected-warning@-1{{Unsafe cast from base type 'BaseTemplate' to derived type 'DerivedTemplate'}}
105 DerivedTemplate
<int> &derived_reinterpret_ref
= reinterpret_cast<DerivedTemplate
<int>&>(base_ref
);
106 // expected-warning@-1{{Unsafe cast from base type 'BaseTemplate' to derived type 'DerivedTemplate'}}
107 DerivedTemplate
<int> &derived_c_ref
= (DerivedTemplate
<int>&)base_ref
;
108 // expected-warning@-1{{Unsafe cast from base type 'BaseTemplate' to derived type 'DerivedTemplate'}}
111 #define CAST_MACRO_STATIC(X,Y) (static_cast<Y>(X))
112 #define CAST_MACRO_REINTERPRET(X,Y) (reinterpret_cast<Y>(X))
113 #define CAST_MACRO_C(X,Y) ((Y)X)
115 void test_macro_static(Base
*base
, Derived
*derived
, Base
&base_ref
) {
116 Derived
*derived_static
= CAST_MACRO_STATIC(base
, Derived
*);
117 // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}}
118 Derived
&derived_static_ref
= CAST_MACRO_STATIC(base_ref
, Derived
&);
119 // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}}
120 Base
*base_static_same
= CAST_MACRO_STATIC(base
, Base
*); // no warning
121 Base
*base_static_upcast
= CAST_MACRO_STATIC(derived
, Base
*); // no warning
124 void test_macro_reinterpret(Base
*base
, Derived
*derived
, Base
&base_ref
) {
125 Derived
*derived_reinterpret
= CAST_MACRO_REINTERPRET(base
, Derived
*);
126 // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}}
127 Derived
&derived_reinterpret_ref
= CAST_MACRO_REINTERPRET(base_ref
, Derived
&);
128 // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}}
129 Base
*base_reinterpret_same
= CAST_MACRO_REINTERPRET(base
, Base
*); // no warning
130 Base
*base_reinterpret_upcast
= CAST_MACRO_REINTERPRET(derived
, Base
*); // no warning
133 void test_macro_c(Base
*base
, Derived
*derived
, Base
&base_ref
) {
134 Derived
*derived_c
= CAST_MACRO_C(base
, Derived
*);
135 // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}}
136 Derived
&derived_c_ref
= CAST_MACRO_C(base_ref
, Derived
&);
137 // expected-warning@-1{{Unsafe cast from base type 'Base' to derived type 'Derived'}}
138 Base
*base_c_same
= CAST_MACRO_C(base
, Base
*); // no warning
139 Base
*base_c_upcast
= CAST_MACRO_C(derived
, Base
*); // no warning
142 struct BaseStructCpp
{
144 void increment() { t
++; }
146 struct DerivedStructCpp
: BaseStructCpp
{
147 void increment_t() {increment();}
150 void test_struct_cpp_pointers(struct BaseStructCpp
*base_struct
) {
151 struct DerivedStructCpp
*derived_static
= static_cast<struct DerivedStructCpp
*>(base_struct
);
152 // expected-warning@-1{{Unsafe cast from base type 'BaseStructCpp' to derived type 'DerivedStructCpp'}}
153 struct DerivedStructCpp
*derived_reinterpret
= reinterpret_cast<struct DerivedStructCpp
*>(base_struct
);
154 // expected-warning@-1{{Unsafe cast from base type 'BaseStructCpp' to derived type 'DerivedStructCpp'}}
155 struct DerivedStructCpp
*derived_c
= (struct DerivedStructCpp
*)base_struct
;
156 // expected-warning@-1{{Unsafe cast from base type 'BaseStructCpp' to derived type 'DerivedStructCpp'}}
159 typedef struct BaseStructCpp BStructCpp
;
160 typedef struct DerivedStructCpp DStructCpp
;
162 void test_struct_cpp_refs(BStructCpp
&base_struct
, DStructCpp
&derived_struct
) {
163 DStructCpp
&derived_static
= static_cast<DStructCpp
&>(base_struct
);
164 // expected-warning@-1{{Unsafe cast from base type 'BaseStructCpp' to derived type 'DerivedStructCpp'}}
165 DStructCpp
&derived_reinterpret
= reinterpret_cast<DStructCpp
&>(base_struct
);
166 // expected-warning@-1{{Unsafe cast from base type 'BaseStructCpp' to derived type 'DerivedStructCpp'}}
167 DStructCpp
&derived_c
= (DStructCpp
&)base_struct
;
168 // expected-warning@-1{{Unsafe cast from base type 'BaseStructCpp' to derived type 'DerivedStructCpp'}}
169 BStructCpp
&base
= (BStructCpp
&)derived_struct
; // no warning
170 BStructCpp
&base_static
= static_cast<BStructCpp
&>(derived_struct
); // no warning
171 BStructCpp
&base_reinterpret
= reinterpret_cast<BStructCpp
&>(derived_struct
); // no warning
176 #define STACK_OF(type) struct stack_st_##type
178 void test_stack(stack_st
*base
) {
179 STACK_OF(void) *derived
= (STACK_OF(void)*)base
;
180 // expected-warning@-1{{Unsafe cast from type 'stack_st' to an unrelated type 'stack_st_void'}}
184 class Child1
: public Parent
{ };
185 class Child2
: public Parent
{ };
187 void test_common_parent(Child1
*c1
, Child2
*c2
) {
188 Child2
*c2_cstyle
= (Child2
*)c1
;
189 // expected-warning@-1{{Unsafe cast from type 'Child1' to an unrelated type 'Child2'}}
190 Child2
*c2_reinterpret
= reinterpret_cast<Child2
*>(c1
);
191 // expected-warning@-1{{Unsafe cast from type 'Child1' to an unrelated type 'Child2'}}
197 void test_unrelated_ref(Type1
&t1
, Type2
&t2
) {
198 Type2
&t2_cstyle
= (Type2
&)t1
;
199 // expected-warning@-1{{Unsafe cast from type 'Type1' to an unrelated type 'Type2'}}
200 Type2
&t2_reinterpret
= reinterpret_cast<Type2
&>(t1
);
201 // expected-warning@-1{{Unsafe cast from type 'Type1' to an unrelated type 'Type2'}}
202 Type2
&t2_same
= reinterpret_cast<Type2
&>(t2
); // no warning
206 class VirtualClass1
{
207 virtual void virtual_base_function();
210 class VirtualClass2
{
211 void virtual_base_function();
214 void test_unrelated_virtual(VirtualClass1
&v1
) {
215 VirtualClass2
&v2
= dynamic_cast<VirtualClass2
&>(v1
);
216 // expected-warning@-1{{Unsafe cast from type 'VirtualClass1' to an unrelated type 'VirtualClass2'}}
222 typedef struct StructA StA
;
223 typedef struct StructB StB
;
225 void test_struct_unrelated_refs(StA
&a
, StB
&b
) {
226 StB
&b_reinterpret
= reinterpret_cast<StB
&>(a
);
227 // expected-warning@-1{{Unsafe cast from type 'StructA' to an unrelated type 'StructB'}}
229 // expected-warning@-1{{Unsafe cast from type 'StructA' to an unrelated type 'StructB'}}
230 StA
&a_local
= (StA
&)b
;
231 // expected-warning@-1{{Unsafe cast from type 'StructB' to an unrelated type 'StructA'}}
232 StA
&a_reinterpret
= reinterpret_cast<StA
&>(b
);
233 // expected-warning@-1{{Unsafe cast from type 'StructB' to an unrelated type 'StructA'}}
234 StA
&a_same
= (StA
&)a
; // no warning
238 class DeferrableRefCounted
{
241 auto this_to_T
= static_cast<const T
*>(this); // no warning
245 class SomeArrayClass
: public DeferrableRefCounted
<SomeArrayClass
> { };
247 void test_this_to_template(SomeArrayClass
*ptr
) {
251 template<typename WeakPtrFactoryType
>
252 class CanMakeWeakPtrBase
{
254 void initializeWeakPtrFactory() const {
255 auto &this_to_T
= static_cast<const WeakPtrFactoryType
&>(*this);
260 using CanMakeWeakPtr
= CanMakeWeakPtrBase
<T
>;
262 class EventLoop
: public CanMakeWeakPtr
<EventLoop
> { };
264 void test_this_to_template_ref(EventLoop
*ptr
) {
265 ptr
->initializeWeakPtrFactory();