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 20namespace 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. 24namespace internal { 25 26template <typename T> 27struct 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 44template <typename Params> 45struct ParamsUseScopedRefptrCorrectly { 46 enum { value = 0 }; 47}; 48 49template <> 50struct ParamsUseScopedRefptrCorrectly<Tuple0> { 51 enum { value = 1 }; 52}; 53 54template <typename A> 55struct ParamsUseScopedRefptrCorrectly<Tuple1<A> > { 56 enum { value = !NeedsScopedRefptrButGetsRawPtr<A>::value }; 57}; 58 59template <typename A, typename B> 60struct ParamsUseScopedRefptrCorrectly<Tuple2<A, B> > { 61 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || 62 NeedsScopedRefptrButGetsRawPtr<B>::value) }; 63}; 64 65template <typename A, typename B, typename C> 66struct ParamsUseScopedRefptrCorrectly<Tuple3<A, B, C> > { 67 enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || 68 NeedsScopedRefptrButGetsRawPtr<B>::value || 69 NeedsScopedRefptrButGetsRawPtr<C>::value) }; 70}; 71 72template <typename A, typename B, typename C, typename D> 73struct 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 80template <typename A, typename B, typename C, typename D, typename E> 81struct 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 89template <typename A, typename B, typename C, typename D, typename E, 90 typename F> 91struct 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 100template <typename A, typename B, typename C, typename D, typename E, 101 typename F, typename G> 102struct 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 112template <typename A, typename B, typename C, typename D, typename E, 113 typename F, typename G, typename H> 114struct 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