| 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 |