OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ | 5 #ifndef BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ |
6 #define BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ | 6 #define BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ |
7 #pragma once | 7 #pragma once |
8 | 8 |
9 #include "base/ref_counted.h" | 9 #include "base/ref_counted.h" |
| 10 #include "base/template_util.h" |
10 #include "base/tuple.h" | 11 #include "base/tuple.h" |
| 12 #include "build/build_config.h" |
11 | 13 |
12 // It is dangerous to post a task with a raw pointer argument to a function | 14 // It is dangerous to post a task with a T* argument where T is a subtype of |
13 // that expects a scoped_refptr<>. The compiler will happily accept the | 15 // RefCounted(Base|ThreadSafeBase), since by the time the parameter is used, the |
14 // situation, but it will not attempt to increase the refcount until the task | 16 // object may already have been deleted since it was not held with a |
15 // runs. Callers expecting the argument to be refcounted up at post time are | 17 // scoped_refptr. Example: http://crbug.com/27191 |
16 // in for a nasty surprise! Example: http://crbug.com/27191 | |
17 // The following set of traits are designed to generate a compile error | 18 // The following set of traits are designed to generate a compile error |
18 // whenever this antipattern is attempted. | 19 // whenever this antipattern is attempted. |
19 template <class A, class B> | 20 |
20 struct ExpectsScopedRefptrButGetsRawPtr { | 21 namespace base { |
| 22 |
| 23 // This is a base internal implementation file used by task.h and callback.h. |
| 24 // Not for public consumption, so we wrap it in namespace internal. |
| 25 namespace internal { |
| 26 |
| 27 template <typename T> |
| 28 struct NeedsScopedRefptrButGetsRawPtr { |
| 29 #if defined(OS_WIN) |
| 30 enum { |
| 31 value = base::false_type::value |
| 32 }; |
| 33 #else |
| 34 enum { |
| 35 // Human readable translation: you needed to be a scoped_refptr if you are a |
| 36 // raw pointer type and are convertible to a RefCounted(Base|ThreadSafeBase) |
| 37 // type. |
| 38 value = (is_pointer<T>::value && |
| 39 (is_convertible<T, subtle::RefCountedBase*>::value || |
| 40 is_convertible<T, subtle::RefCountedThreadSafeBase*>::value)) |
| 41 }; |
| 42 #endif |
| 43 }; |
| 44 |
| 45 template <typename Params> |
| 46 struct ParamsUseScopedRefptrCorrectly { |
21 enum { value = 0 }; | 47 enum { value = 0 }; |
22 }; | 48 }; |
23 | 49 |
24 template <class A, class B> | 50 template <> |
25 struct ExpectsScopedRefptrButGetsRawPtr<scoped_refptr<A>, B*> { | 51 struct ParamsUseScopedRefptrCorrectly<Tuple0> { |
26 enum { value = 1 }; | 52 enum { value = 1 }; |
27 }; | 53 }; |
28 | 54 |
29 template <class Function, class Params> | 55 template <typename A> |
30 struct FunctionUsesScopedRefptrCorrectly { | 56 struct ParamsUseScopedRefptrCorrectly<Tuple1<A> > { |
31 enum { value = 1 }; | 57 enum { value = !NeedsScopedRefptrButGetsRawPtr<A>::value }; |
32 }; | 58 }; |
33 | 59 |
34 template <class A1, class A2> | 60 template <typename A, typename B> |
35 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1), Tuple1<A2> > { | 61 struct ParamsUseScopedRefptrCorrectly<Tuple2<A, B> > { |
36 enum { value = !ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value }; | 62 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || |
| 63 NeedsScopedRefptrButGetsRawPtr<B>::value) }; |
37 }; | 64 }; |
38 | 65 |
39 template <class A1, class B1, class A2, class B2> | 66 template <typename A, typename B, typename C> |
40 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1), Tuple2<A2, B2> > { | 67 struct ParamsUseScopedRefptrCorrectly<Tuple3<A, B, C> > { |
41 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || | 68 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || |
42 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value) }; | 69 NeedsScopedRefptrButGetsRawPtr<B>::value || |
| 70 NeedsScopedRefptrButGetsRawPtr<C>::value) }; |
43 }; | 71 }; |
44 | 72 |
45 template <class A1, class B1, class C1, class A2, class B2, class C2> | 73 template <typename A, typename B, typename C, typename D> |
46 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1), | 74 struct ParamsUseScopedRefptrCorrectly<Tuple4<A, B, C, D> > { |
47 Tuple3<A2, B2, C2> > { | 75 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || |
48 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || | 76 NeedsScopedRefptrButGetsRawPtr<B>::value || |
49 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || | 77 NeedsScopedRefptrButGetsRawPtr<C>::value || |
50 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value) }; | 78 NeedsScopedRefptrButGetsRawPtr<D>::value) }; |
51 }; | 79 }; |
52 | 80 |
53 template <class A1, class B1, class C1, class D1, | 81 template <typename A, typename B, typename C, typename D, typename E> |
54 class A2, class B2, class C2, class D2> | 82 struct ParamsUseScopedRefptrCorrectly<Tuple5<A, B, C, D, E> > { |
55 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1), | 83 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || |
56 Tuple4<A2, B2, C2, D2> > { | 84 NeedsScopedRefptrButGetsRawPtr<B>::value || |
57 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || | 85 NeedsScopedRefptrButGetsRawPtr<C>::value || |
58 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || | 86 NeedsScopedRefptrButGetsRawPtr<D>::value || |
59 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || | 87 NeedsScopedRefptrButGetsRawPtr<E>::value) }; |
60 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value) }; | |
61 }; | 88 }; |
62 | 89 |
63 template <class A1, class B1, class C1, class D1, class E1, | 90 template <typename A, typename B, typename C, typename D, typename E, |
64 class A2, class B2, class C2, class D2, class E2> | 91 typename F> |
65 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1), | 92 struct ParamsUseScopedRefptrCorrectly<Tuple6<A, B, C, D, E, F> > { |
66 Tuple5<A2, B2, C2, D2, E2> > { | 93 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || |
67 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || | 94 NeedsScopedRefptrButGetsRawPtr<B>::value || |
68 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || | 95 NeedsScopedRefptrButGetsRawPtr<C>::value || |
69 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || | 96 NeedsScopedRefptrButGetsRawPtr<D>::value || |
70 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || | 97 NeedsScopedRefptrButGetsRawPtr<E>::value || |
71 ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value) }; | 98 NeedsScopedRefptrButGetsRawPtr<F>::value) }; |
72 }; | 99 }; |
73 | 100 |
74 template <class A1, class B1, class C1, class D1, class E1, class F1, | 101 template <typename A, typename B, typename C, typename D, typename E, |
75 class A2, class B2, class C2, class D2, class E2, class F2> | 102 typename F, typename G> |
76 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1, F1), | 103 struct ParamsUseScopedRefptrCorrectly<Tuple7<A, B, C, D, E, F, G> > { |
77 Tuple6<A2, B2, C2, D2, E2, F2> > { | 104 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || |
78 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || | 105 NeedsScopedRefptrButGetsRawPtr<B>::value || |
79 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || | 106 NeedsScopedRefptrButGetsRawPtr<C>::value || |
80 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || | 107 NeedsScopedRefptrButGetsRawPtr<D>::value || |
81 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || | 108 NeedsScopedRefptrButGetsRawPtr<E>::value || |
82 ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value || | 109 NeedsScopedRefptrButGetsRawPtr<F>::value || |
83 ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value) }; | 110 NeedsScopedRefptrButGetsRawPtr<G>::value) }; |
84 }; | 111 }; |
85 | 112 |
86 template <class A1, class B1, class C1, class D1, class E1, class F1, class G1, | 113 template <typename A, typename B, typename C, typename D, typename E, |
87 class A2, class B2, class C2, class D2, class E2, class F2, class G2> | 114 typename F, typename G, typename H> |
88 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1, F1, G1), | 115 struct ParamsUseScopedRefptrCorrectly<Tuple8<A, B, C, D, E, F, G, H> > { |
89 Tuple7<A2, B2, C2, D2, E2, F2, G2> > { | 116 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || |
90 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || | 117 NeedsScopedRefptrButGetsRawPtr<B>::value || |
91 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || | 118 NeedsScopedRefptrButGetsRawPtr<C>::value || |
92 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || | 119 NeedsScopedRefptrButGetsRawPtr<D>::value || |
93 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || | 120 NeedsScopedRefptrButGetsRawPtr<E>::value || |
94 ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value || | 121 NeedsScopedRefptrButGetsRawPtr<F>::value || |
95 ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value || | 122 NeedsScopedRefptrButGetsRawPtr<G>::value || |
96 ExpectsScopedRefptrButGetsRawPtr<G1, G2>::value) }; | 123 NeedsScopedRefptrButGetsRawPtr<H>::value) }; |
97 }; | 124 }; |
98 | 125 |
99 template <class Method, class Params> | 126 } // namespace internal |
100 struct MethodUsesScopedRefptrCorrectly { | |
101 enum { value = 1 }; | |
102 }; | |
103 | 127 |
104 template <class T, class A1, class A2> | 128 } // namespace base |
105 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1), Tuple1<A2> > { | |
106 enum { value = !ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value }; | |
107 }; | |
108 | |
109 template <class T, class A1, class B1, class A2, class B2> | |
110 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1), Tuple2<A2, B2> > { | |
111 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || | |
112 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value) }; | |
113 }; | |
114 | |
115 template <class T, class A1, class B1, class C1, | |
116 class A2, class B2, class C2> | |
117 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1), | |
118 Tuple3<A2, B2, C2> > { | |
119 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || | |
120 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || | |
121 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value) }; | |
122 }; | |
123 | |
124 template <class T, class A1, class B1, class C1, class D1, | |
125 class A2, class B2, class C2, class D2> | |
126 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1), | |
127 Tuple4<A2, B2, C2, D2> > { | |
128 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || | |
129 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || | |
130 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || | |
131 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value) }; | |
132 }; | |
133 | |
134 template <class T, class A1, class B1, class C1, class D1, class E1, | |
135 class A2, class B2, class C2, class D2, class E2> | |
136 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1, E1), | |
137 Tuple5<A2, B2, C2, D2, E2> > { | |
138 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || | |
139 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || | |
140 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || | |
141 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || | |
142 ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value) }; | |
143 }; | |
144 | |
145 template <class T, class A1, class B1, class C1, class D1, class E1, class F1, | |
146 class A2, class B2, class C2, class D2, class E2, class F2> | |
147 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1, E1, F1), | |
148 Tuple6<A2, B2, C2, D2, E2, F2> > { | |
149 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || | |
150 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || | |
151 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || | |
152 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || | |
153 ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value || | |
154 ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value) }; | |
155 }; | |
156 | |
157 template <class T, | |
158 class A1, class B1, class C1, class D1, class E1, class F1, class G1, | |
159 class A2, class B2, class C2, class D2, class E2, class F2, class G2> | |
160 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1, E1, F1, G1), | |
161 Tuple7<A2, B2, C2, D2, E2, F2, G2> > { | |
162 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || | |
163 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || | |
164 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || | |
165 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || | |
166 ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value || | |
167 ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value || | |
168 ExpectsScopedRefptrButGetsRawPtr<G1, G2>::value) }; | |
169 }; | |
170 | 129 |
171 #endif // BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ | 130 #endif // BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ |
OLD | NEW |