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 3 // found in the LICENSE file. 4 5 #ifndef BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ 6 #define BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ 7 8 #include "base/ref_counted.h" 9 #include "base/tuple.h" 10 11 // It is dangerous to post a task with a raw pointer argument to a function 12 // that expects a scoped_refptr<>. The compiler will happily accept the 13 // situation, but it will not attempt to increase the refcount until the task 14 // runs. Callers expecting the argument to be refcounted up at post time are 15 // in for a nasty surprise! Example: http://crbug.com/27191 16 // The following set of traits are designed to generate a compile error 17 // whenever this antipattern is attempted. 18 template <class A, class B> 19 struct ExpectsScopedRefptrButGetsRawPtr { 20 enum { value = 0 }; 21 }; 22 23 template <class A, class B> 24 struct ExpectsScopedRefptrButGetsRawPtr<scoped_refptr<A>, B*> { 25 enum { value = 1 }; 26 }; 27 28 template <class Function, class Params> 29 struct FunctionUsesScopedRefptrCorrectly { 30 enum { value = 1 }; 31 }; 32 33 template <class A1, class A2> 34 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1), Tuple1<A2> > { 35 enum { value = !ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value }; 36 }; 37 38 template <class A1, class B1, class A2, class B2> 39 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1), Tuple2<A2, B2> > { 40 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || 41 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value) }; 42 }; 43 44 template <class A1, class B1, class C1, class A2, class B2, class C2> 45 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1), 46 Tuple3<A2, B2, C2> > { 47 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || 48 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || 49 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value) }; 50 }; 51 52 template <class A1, class B1, class C1, class D1, 53 class A2, class B2, class C2, class D2> 54 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1), 55 Tuple4<A2, B2, C2, D2> > { 56 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || 57 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || 58 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || 59 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value) }; 60 }; 61 62 template <class A1, class B1, class C1, class D1, class E1, 63 class A2, class B2, class C2, class D2, class E2> 64 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1), 65 Tuple5<A2, B2, C2, D2, E2> > { 66 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || 67 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || 68 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || 69 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || 70 ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value) }; 71 }; 72 73 template <class A1, class B1, class C1, class D1, class E1, class F1, 74 class A2, class B2, class C2, class D2, class E2, class F2> 75 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1, F1), 76 Tuple6<A2, B2, C2, D2, E2, F2> > { 77 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || 78 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || 79 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || 80 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || 81 ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value || 82 ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value) }; 83 }; 84 85 template <class A1, class B1, class C1, class D1, class E1, class F1, class G1, 86 class A2, class B2, class C2, class D2, class E2, class F2, class G2> 87 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1, F1, G1), 88 Tuple7<A2, B2, C2, D2, E2, F2, G2> > { 89 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || 90 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || 91 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || 92 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || 93 ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value || 94 ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value || 95 ExpectsScopedRefptrButGetsRawPtr<G1, G2>::value) }; 96 }; 97 98 template <class Method, class Params> 99 struct MethodUsesScopedRefptrCorrectly { 100 enum { value = 1 }; 101 }; 102 103 template <class T, class A1, class A2> 104 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1), Tuple1<A2> > { 105 enum { value = !ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value }; 106 }; 107 108 template <class T, class A1, class B1, class A2, class B2> 109 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1), Tuple2<A2, B2> > { 110 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || 111 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value) }; 112 }; 113 114 template <class T, class A1, class B1, class C1, 115 class A2, class B2, class C2> 116 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1), 117 Tuple3<A2, B2, C2> > { 118 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || 119 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || 120 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value) }; 121 }; 122 123 template <class T, class A1, class B1, class C1, class D1, 124 class A2, class B2, class C2, class D2> 125 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1), 126 Tuple4<A2, B2, C2, D2> > { 127 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || 128 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || 129 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || 130 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value) }; 131 }; 132 133 template <class T, class A1, class B1, class C1, class D1, class E1, 134 class A2, class B2, class C2, class D2, class E2> 135 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1, E1), 136 Tuple5<A2, B2, C2, D2, E2> > { 137 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || 138 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || 139 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || 140 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || 141 ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value) }; 142 }; 143 144 template <class T, class A1, class B1, class C1, class D1, class E1, class F1, 145 class A2, class B2, class C2, class D2, class E2, class F2> 146 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1, E1, F1), 147 Tuple6<A2, B2, C2, D2, E2, F2> > { 148 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || 149 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || 150 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || 151 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || 152 ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value || 153 ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value) }; 154 }; 155 156 template <class T, 157 class A1, class B1, class C1, class D1, class E1, class F1, class G1, 158 class A2, class B2, class C2, class D2, class E2, class F2, class G2> 159 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1, E1, F1, G1), 160 Tuple7<A2, B2, C2, D2, E2, F2, G2> > { 161 enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || 162 ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || 163 ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || 164 ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || 165 ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value || 166 ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value || 167 ExpectsScopedRefptrButGetsRawPtr<G1, G2>::value) }; 168 }; 169 170 #endif // BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ 171