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