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" | |
11 #include "base/tuple.h" | 10 #include "base/tuple.h" |
12 #include "build/build_config.h" | |
13 | 11 |
14 // It is dangerous to post a task with a T* argument where T is a subtype of | 12 // It is dangerous to post a task with a raw pointer argument to a function |
15 // RefCounted(Base|ThreadSafeBase), since by the time the parameter is used, the | 13 // that expects a scoped_refptr<>. The compiler will happily accept the |
16 // object may already have been deleted since it was not held with a | 14 // situation, but it will not attempt to increase the refcount until the task |
17 // scoped_refptr. Example: http://crbug.com/27191 | 15 // runs. Callers expecting the argument to be refcounted up at post time are |
| 16 // in for a nasty surprise! Example: http://crbug.com/27191 |
18 // The following set of traits are designed to generate a compile error | 17 // The following set of traits are designed to generate a compile error |
19 // whenever this antipattern is attempted. | 18 // whenever this antipattern is attempted. |
20 | 19 template <class A, class B> |
21 namespace base { | 20 struct ExpectsScopedRefptrButGetsRawPtr { |
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 { | |
47 enum { value = 0 }; | 21 enum { value = 0 }; |
48 }; | 22 }; |
49 | 23 |
50 template <> | 24 template <class A, class B> |
51 struct ParamsUseScopedRefptrCorrectly<Tuple0> { | 25 struct ExpectsScopedRefptrButGetsRawPtr<scoped_refptr<A>, B*> { |
52 enum { value = 1 }; | 26 enum { value = 1 }; |
53 }; | 27 }; |
54 | 28 |
55 template <typename A> | 29 template <class Function, class Params> |
56 struct ParamsUseScopedRefptrCorrectly<Tuple1<A> > { | 30 struct FunctionUsesScopedRefptrCorrectly { |
57 enum { value = !NeedsScopedRefptrButGetsRawPtr<A>::value }; | 31 enum { value = 1 }; |
58 }; | 32 }; |
59 | 33 |
60 template <typename A, typename B> | 34 template <class A1, class A2> |
61 struct ParamsUseScopedRefptrCorrectly<Tuple2<A, B> > { | 35 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1), Tuple1<A2> > { |
62 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || | 36 enum { value = !ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value }; |
63 NeedsScopedRefptrButGetsRawPtr<B>::value) }; | |
64 }; | 37 }; |
65 | 38 |
66 template <typename A, typename B, typename C> | 39 template <class A1, class B1, class A2, class B2> |
67 struct ParamsUseScopedRefptrCorrectly<Tuple3<A, B, C> > { | 40 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1), Tuple2<A2, B2> > { |
68 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || | 41 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || |
69 NeedsScopedRefptrButGetsRawPtr<B>::value || | 42 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value) }; |
70 NeedsScopedRefptrButGetsRawPtr<C>::value) }; | |
71 }; | 43 }; |
72 | 44 |
73 template <typename A, typename B, typename C, typename D> | 45 template <class A1, class B1, class C1, class A2, class B2, class C2> |
74 struct ParamsUseScopedRefptrCorrectly<Tuple4<A, B, C, D> > { | 46 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1), |
75 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || | 47 Tuple3<A2, B2, C2> > { |
76 NeedsScopedRefptrButGetsRawPtr<B>::value || | 48 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || |
77 NeedsScopedRefptrButGetsRawPtr<C>::value || | 49 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || |
78 NeedsScopedRefptrButGetsRawPtr<D>::value) }; | 50 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value) }; |
79 }; | 51 }; |
80 | 52 |
81 template <typename A, typename B, typename C, typename D, typename E> | 53 template <class A1, class B1, class C1, class D1, |
82 struct ParamsUseScopedRefptrCorrectly<Tuple5<A, B, C, D, E> > { | 54 class A2, class B2, class C2, class D2> |
83 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || | 55 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1), |
84 NeedsScopedRefptrButGetsRawPtr<B>::value || | 56 Tuple4<A2, B2, C2, D2> > { |
85 NeedsScopedRefptrButGetsRawPtr<C>::value || | 57 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || |
86 NeedsScopedRefptrButGetsRawPtr<D>::value || | 58 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || |
87 NeedsScopedRefptrButGetsRawPtr<E>::value) }; | 59 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || |
| 60 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value) }; |
88 }; | 61 }; |
89 | 62 |
90 template <typename A, typename B, typename C, typename D, typename E, | 63 template <class A1, class B1, class C1, class D1, class E1, |
91 typename F> | 64 class A2, class B2, class C2, class D2, class E2> |
92 struct ParamsUseScopedRefptrCorrectly<Tuple6<A, B, C, D, E, F> > { | 65 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1), |
93 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || | 66 Tuple5<A2, B2, C2, D2, E2> > { |
94 NeedsScopedRefptrButGetsRawPtr<B>::value || | 67 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || |
95 NeedsScopedRefptrButGetsRawPtr<C>::value || | 68 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || |
96 NeedsScopedRefptrButGetsRawPtr<D>::value || | 69 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || |
97 NeedsScopedRefptrButGetsRawPtr<E>::value || | 70 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || |
98 NeedsScopedRefptrButGetsRawPtr<F>::value) }; | 71 ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value) }; |
99 }; | 72 }; |
100 | 73 |
101 template <typename A, typename B, typename C, typename D, typename E, | 74 template <class A1, class B1, class C1, class D1, class E1, class F1, |
102 typename F, typename G> | 75 class A2, class B2, class C2, class D2, class E2, class F2> |
103 struct ParamsUseScopedRefptrCorrectly<Tuple7<A, B, C, D, E, F, G> > { | 76 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1, F1), |
104 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || | 77 Tuple6<A2, B2, C2, D2, E2, F2> > { |
105 NeedsScopedRefptrButGetsRawPtr<B>::value || | 78 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || |
106 NeedsScopedRefptrButGetsRawPtr<C>::value || | 79 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || |
107 NeedsScopedRefptrButGetsRawPtr<D>::value || | 80 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || |
108 NeedsScopedRefptrButGetsRawPtr<E>::value || | 81 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || |
109 NeedsScopedRefptrButGetsRawPtr<F>::value || | 82 ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value || |
110 NeedsScopedRefptrButGetsRawPtr<G>::value) }; | 83 ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value) }; |
111 }; | 84 }; |
112 | 85 |
113 template <typename A, typename B, typename C, typename D, typename E, | 86 template <class A1, class B1, class C1, class D1, class E1, class F1, class G1, |
114 typename F, typename G, typename H> | 87 class A2, class B2, class C2, class D2, class E2, class F2, class G2> |
115 struct ParamsUseScopedRefptrCorrectly<Tuple8<A, B, C, D, E, F, G, H> > { | 88 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1, F1, G1), |
116 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || | 89 Tuple7<A2, B2, C2, D2, E2, F2, G2> > { |
117 NeedsScopedRefptrButGetsRawPtr<B>::value || | 90 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || |
118 NeedsScopedRefptrButGetsRawPtr<C>::value || | 91 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || |
119 NeedsScopedRefptrButGetsRawPtr<D>::value || | 92 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || |
120 NeedsScopedRefptrButGetsRawPtr<E>::value || | 93 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || |
121 NeedsScopedRefptrButGetsRawPtr<F>::value || | 94 ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value || |
122 NeedsScopedRefptrButGetsRawPtr<G>::value || | 95 ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value || |
123 NeedsScopedRefptrButGetsRawPtr<H>::value) }; | 96 ExpectsScopedRefptrButGetsRawPtr<G1, G2>::value) }; |
124 }; | 97 }; |
125 | 98 |
126 } // namespace internal | 99 template <class Method, class Params> |
| 100 struct MethodUsesScopedRefptrCorrectly { |
| 101 enum { value = 1 }; |
| 102 }; |
127 | 103 |
128 } // namespace base | 104 template <class T, class A1, class A2> |
| 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 }; |
129 | 170 |
130 #endif // BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ | 171 #endif // BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ |
OLD | NEW |