1 // Copyright (c) 2011 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_MEMORY_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ 6 #define BASE_MEMORY_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ 7 8 #include "base/memory/ref_counted.h" 9 #include "base/template_util.h" 10 #include "base/tuple.h" 11 #include "build/build_config.h" 12 13 // It is dangerous to post a task with a T* argument where T is a subtype of 14 // RefCounted(Base|ThreadSafeBase), since by the time the parameter is used, the 15 // object may already have been deleted since it was not held with a 16 // scoped_refptr. Example: http://crbug.com/27191 17 // The following set of traits are designed to generate a compile error 18 // whenever this antipattern is attempted. 19 20 namespace base { 21 22 // This is a base internal implementation file used by task.h and callback.h. 23 // Not for public consumption, so we wrap it in namespace internal. 24 namespace internal { 25 26 template <typename T> 27 struct NeedsScopedRefptrButGetsRawPtr { 28 #if defined(OS_WIN) 29 enum { 30 value = base::false_type::value 31 }; 32 #else 33 enum { 34 // Human readable translation: you needed to be a scoped_refptr if you are a 35 // raw pointer type and are convertible to a RefCounted(Base|ThreadSafeBase) 36 // type. 37 value = (is_pointer<T>::value && 38 (is_convertible<T, subtle::RefCountedBase*>::value || 39 is_convertible<T, subtle::RefCountedThreadSafeBase*>::value)) 40 }; 41 #endif 42 }; 43 44 template <typename Params> 45 struct ParamsUseScopedRefptrCorrectly { 46 enum { value = 0 }; 47 }; 48 49 template <> 50 struct ParamsUseScopedRefptrCorrectly<Tuple0> { 51 enum { value = 1 }; 52 }; 53 54 template <typename A> 55 struct ParamsUseScopedRefptrCorrectly<Tuple1<A> > { 56 enum { value = !NeedsScopedRefptrButGetsRawPtr<A>::value }; 57 }; 58 59 template <typename A, typename B> 60 struct ParamsUseScopedRefptrCorrectly<Tuple2<A, B> > { 61 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || 62 NeedsScopedRefptrButGetsRawPtr<B>::value) }; 63 }; 64 65 template <typename A, typename B, typename C> 66 struct ParamsUseScopedRefptrCorrectly<Tuple3<A, B, C> > { 67 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || 68 NeedsScopedRefptrButGetsRawPtr<B>::value || 69 NeedsScopedRefptrButGetsRawPtr<C>::value) }; 70 }; 71 72 template <typename A, typename B, typename C, typename D> 73 struct ParamsUseScopedRefptrCorrectly<Tuple4<A, B, C, D> > { 74 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || 75 NeedsScopedRefptrButGetsRawPtr<B>::value || 76 NeedsScopedRefptrButGetsRawPtr<C>::value || 77 NeedsScopedRefptrButGetsRawPtr<D>::value) }; 78 }; 79 80 template <typename A, typename B, typename C, typename D, typename E> 81 struct ParamsUseScopedRefptrCorrectly<Tuple5<A, B, C, D, E> > { 82 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || 83 NeedsScopedRefptrButGetsRawPtr<B>::value || 84 NeedsScopedRefptrButGetsRawPtr<C>::value || 85 NeedsScopedRefptrButGetsRawPtr<D>::value || 86 NeedsScopedRefptrButGetsRawPtr<E>::value) }; 87 }; 88 89 template <typename A, typename B, typename C, typename D, typename E, 90 typename F> 91 struct ParamsUseScopedRefptrCorrectly<Tuple6<A, B, C, D, E, F> > { 92 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || 93 NeedsScopedRefptrButGetsRawPtr<B>::value || 94 NeedsScopedRefptrButGetsRawPtr<C>::value || 95 NeedsScopedRefptrButGetsRawPtr<D>::value || 96 NeedsScopedRefptrButGetsRawPtr<E>::value || 97 NeedsScopedRefptrButGetsRawPtr<F>::value) }; 98 }; 99 100 template <typename A, typename B, typename C, typename D, typename E, 101 typename F, typename G> 102 struct ParamsUseScopedRefptrCorrectly<Tuple7<A, B, C, D, E, F, G> > { 103 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || 104 NeedsScopedRefptrButGetsRawPtr<B>::value || 105 NeedsScopedRefptrButGetsRawPtr<C>::value || 106 NeedsScopedRefptrButGetsRawPtr<D>::value || 107 NeedsScopedRefptrButGetsRawPtr<E>::value || 108 NeedsScopedRefptrButGetsRawPtr<F>::value || 109 NeedsScopedRefptrButGetsRawPtr<G>::value) }; 110 }; 111 112 template <typename A, typename B, typename C, typename D, typename E, 113 typename F, typename G, typename H> 114 struct ParamsUseScopedRefptrCorrectly<Tuple8<A, B, C, D, E, F, G, H> > { 115 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || 116 NeedsScopedRefptrButGetsRawPtr<B>::value || 117 NeedsScopedRefptrButGetsRawPtr<C>::value || 118 NeedsScopedRefptrButGetsRawPtr<D>::value || 119 NeedsScopedRefptrButGetsRawPtr<E>::value || 120 NeedsScopedRefptrButGetsRawPtr<F>::value || 121 NeedsScopedRefptrButGetsRawPtr<G>::value || 122 NeedsScopedRefptrButGetsRawPtr<H>::value) }; 123 }; 124 125 } // namespace internal 126 127 } // namespace base 128 129 #endif // BASE_MEMORY_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ 130