diff options
author | willchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-15 09:31:33 +0000 |
---|---|---|
committer | willchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-15 09:31:33 +0000 |
commit | f258ba2e2403ada7c5c72fb9950637ddea86a014 (patch) | |
tree | fe4f332f054a99bc10b9d781f0723adabd0055d8 /base | |
parent | 968ca7b38235bdcae6ec82173e1fe01bcf248eb1 (diff) | |
download | chromium_src-f258ba2e2403ada7c5c72fb9950637ddea86a014.zip chromium_src-f258ba2e2403ada7c5c72fb9950637ddea86a014.tar.gz chromium_src-f258ba2e2403ada7c5c72fb9950637ddea86a014.tar.bz2 |
Revert 69243 - Reland 69237 - Fix raw_scoped_refptr_mismatch_checker.h.
Damn, missed a unittest.
BUG=28083
TEST=none
Review URL: http://codereview.chromium.org/3549010
TBR=willchan@chromium.org
Review URL: http://codereview.chromium.org/5885001
TBR=phajdan.jr@chromium.org
Review URL: http://codereview.chromium.org/5887001
TBR=willchan@chromium.org
Review URL: http://codereview.chromium.org/5888001
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@69244 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r-- | base/callback.h | 5 | ||||
-rw-r--r-- | base/raw_scoped_refptr_mismatch_checker.h | 225 | ||||
-rw-r--r-- | base/task.h | 15 | ||||
-rw-r--r-- | base/template_util.h | 47 |
4 files changed, 141 insertions, 151 deletions
diff --git a/base/callback.h b/base/callback.h index e5ea771..7f2eb70 100644 --- a/base/callback.h +++ b/base/callback.h @@ -206,9 +206,8 @@ template <class T, class Method, class Params> class UnboundMethod { public: UnboundMethod(Method m, const Params& p) : m_(m), p_(p) { - COMPILE_ASSERT( - (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value), - badunboundmethodparams); + COMPILE_ASSERT((MethodUsesScopedRefptrCorrectly<Method, Params>::value), + badunboundmethodparams); } void Run(T* obj) const { DispatchToMethod(obj, m_, p_); diff --git a/base/raw_scoped_refptr_mismatch_checker.h b/base/raw_scoped_refptr_mismatch_checker.h index b79cfb5..d2913e7 100644 --- a/base/raw_scoped_refptr_mismatch_checker.h +++ b/base/raw_scoped_refptr_mismatch_checker.h @@ -7,124 +7,165 @@ #pragma once #include "base/ref_counted.h" -#include "base/template_util.h" #include "base/tuple.h" -#include "build/build_config.h" -// It is dangerous to post a task with a T* argument where T is a subtype of -// RefCounted(Base|ThreadSafeBase), since by the time the parameter is used, the -// object may already have been deleted since it was not held with a -// scoped_refptr. Example: http://crbug.com/27191 +// It is dangerous to post a task with a raw pointer argument to a function +// that expects a scoped_refptr<>. The compiler will happily accept the +// situation, but it will not attempt to increase the refcount until the task +// runs. Callers expecting the argument to be refcounted up at post time are +// in for a nasty surprise! Example: http://crbug.com/27191 // The following set of traits are designed to generate a compile error // whenever this antipattern is attempted. - -namespace base { - -// This is a base internal implementation file used by task.h and callback.h. -// Not for public consumption, so we wrap it in namespace internal. -namespace internal { - -template <typename T> -struct NeedsScopedRefptrButGetsRawPtr { -#if defined(OS_WIN) - enum { - value = base::false_type::value - }; -#else - enum { - // Human readable translation: you needed to be a scoped_refptr if you are a - // raw pointer type and are convertible to a RefCounted(Base|ThreadSafeBase) - // type. - value = (is_pointer<T>::value && - (is_convertible<T, subtle::RefCountedBase*>::value || - is_convertible<T, subtle::RefCountedThreadSafeBase*>::value)) - }; -#endif -}; - -template <typename Params> -struct ParamsUseScopedRefptrCorrectly { +template <class A, class B> +struct ExpectsScopedRefptrButGetsRawPtr { enum { value = 0 }; }; -template <> -struct ParamsUseScopedRefptrCorrectly<Tuple0> { +template <class A, class B> +struct ExpectsScopedRefptrButGetsRawPtr<scoped_refptr<A>, B*> { enum { value = 1 }; }; -template <typename A> -struct ParamsUseScopedRefptrCorrectly<Tuple1<A> > { - enum { value = !NeedsScopedRefptrButGetsRawPtr<A>::value }; +template <class Function, class Params> +struct FunctionUsesScopedRefptrCorrectly { + enum { value = 1 }; }; -template <typename A, typename B> -struct ParamsUseScopedRefptrCorrectly<Tuple2<A, B> > { - enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || - NeedsScopedRefptrButGetsRawPtr<B>::value) }; +template <class A1, class A2> +struct FunctionUsesScopedRefptrCorrectly<void (*)(A1), Tuple1<A2> > { + enum { value = !ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value }; }; -template <typename A, typename B, typename C> -struct ParamsUseScopedRefptrCorrectly<Tuple3<A, B, C> > { - enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || - NeedsScopedRefptrButGetsRawPtr<B>::value || - NeedsScopedRefptrButGetsRawPtr<C>::value) }; +template <class A1, class B1, class A2, class B2> +struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1), Tuple2<A2, B2> > { + enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || + ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value) }; }; -template <typename A, typename B, typename C, typename D> -struct ParamsUseScopedRefptrCorrectly<Tuple4<A, B, C, D> > { - enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || - NeedsScopedRefptrButGetsRawPtr<B>::value || - NeedsScopedRefptrButGetsRawPtr<C>::value || - NeedsScopedRefptrButGetsRawPtr<D>::value) }; +template <class A1, class B1, class C1, class A2, class B2, class C2> +struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1), + Tuple3<A2, B2, C2> > { + enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || + ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || + ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value) }; }; -template <typename A, typename B, typename C, typename D, typename E> -struct ParamsUseScopedRefptrCorrectly<Tuple5<A, B, C, D, E> > { - enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || - NeedsScopedRefptrButGetsRawPtr<B>::value || - NeedsScopedRefptrButGetsRawPtr<C>::value || - NeedsScopedRefptrButGetsRawPtr<D>::value || - NeedsScopedRefptrButGetsRawPtr<E>::value) }; +template <class A1, class B1, class C1, class D1, + class A2, class B2, class C2, class D2> +struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1), + Tuple4<A2, B2, C2, D2> > { + enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || + ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || + ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || + ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value) }; }; -template <typename A, typename B, typename C, typename D, typename E, - typename F> -struct ParamsUseScopedRefptrCorrectly<Tuple6<A, B, C, D, E, F> > { - enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || - NeedsScopedRefptrButGetsRawPtr<B>::value || - NeedsScopedRefptrButGetsRawPtr<C>::value || - NeedsScopedRefptrButGetsRawPtr<D>::value || - NeedsScopedRefptrButGetsRawPtr<E>::value || - NeedsScopedRefptrButGetsRawPtr<F>::value) }; +template <class A1, class B1, class C1, class D1, class E1, + class A2, class B2, class C2, class D2, class E2> +struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1), + Tuple5<A2, B2, C2, D2, E2> > { + enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || + ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || + ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || + ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || + ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value) }; }; -template <typename A, typename B, typename C, typename D, typename E, - typename F, typename G> -struct ParamsUseScopedRefptrCorrectly<Tuple7<A, B, C, D, E, F, G> > { - enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || - NeedsScopedRefptrButGetsRawPtr<B>::value || - NeedsScopedRefptrButGetsRawPtr<C>::value || - NeedsScopedRefptrButGetsRawPtr<D>::value || - NeedsScopedRefptrButGetsRawPtr<E>::value || - NeedsScopedRefptrButGetsRawPtr<F>::value || - NeedsScopedRefptrButGetsRawPtr<G>::value) }; +template <class A1, class B1, class C1, class D1, class E1, class F1, + class A2, class B2, class C2, class D2, class E2, class F2> +struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1, F1), + Tuple6<A2, B2, C2, D2, E2, F2> > { + enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || + ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || + ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || + ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || + ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value || + ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value) }; }; -template <typename A, typename B, typename C, typename D, typename E, - typename F, typename G, typename H> -struct ParamsUseScopedRefptrCorrectly<Tuple8<A, B, C, D, E, F, G, H> > { - enum { value = !(NeedsScopedRefptrButGetsRawPtr<A>::value || - NeedsScopedRefptrButGetsRawPtr<B>::value || - NeedsScopedRefptrButGetsRawPtr<C>::value || - NeedsScopedRefptrButGetsRawPtr<D>::value || - NeedsScopedRefptrButGetsRawPtr<E>::value || - NeedsScopedRefptrButGetsRawPtr<F>::value || - NeedsScopedRefptrButGetsRawPtr<G>::value || - NeedsScopedRefptrButGetsRawPtr<H>::value) }; +template <class A1, class B1, class C1, class D1, class E1, class F1, class G1, + class A2, class B2, class C2, class D2, class E2, class F2, class G2> +struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1, F1, G1), + Tuple7<A2, B2, C2, D2, E2, F2, G2> > { + enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || + ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || + ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || + ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || + ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value || + ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value || + ExpectsScopedRefptrButGetsRawPtr<G1, G2>::value) }; }; -} // namespace internal +template <class Method, class Params> +struct MethodUsesScopedRefptrCorrectly { + enum { value = 1 }; +}; -} // namespace base +template <class T, class A1, class A2> +struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1), Tuple1<A2> > { + enum { value = !ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value }; +}; + +template <class T, class A1, class B1, class A2, class B2> +struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1), Tuple2<A2, B2> > { + enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || + ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value) }; +}; + +template <class T, class A1, class B1, class C1, + class A2, class B2, class C2> +struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1), + Tuple3<A2, B2, C2> > { + enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || + ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || + ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value) }; +}; + +template <class T, class A1, class B1, class C1, class D1, + class A2, class B2, class C2, class D2> +struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1), + Tuple4<A2, B2, C2, D2> > { + enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || + ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || + ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || + ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value) }; +}; + +template <class T, class A1, class B1, class C1, class D1, class E1, + class A2, class B2, class C2, class D2, class E2> +struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1, E1), + Tuple5<A2, B2, C2, D2, E2> > { + enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || + ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || + ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || + ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || + ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value) }; +}; + +template <class T, class A1, class B1, class C1, class D1, class E1, class F1, + class A2, class B2, class C2, class D2, class E2, class F2> +struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1, E1, F1), + Tuple6<A2, B2, C2, D2, E2, F2> > { + enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || + ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || + ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || + ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || + ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value || + ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value) }; +}; + +template <class T, + class A1, class B1, class C1, class D1, class E1, class F1, class G1, + class A2, class B2, class C2, class D2, class E2, class F2, class G2> +struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1, E1, F1, G1), + Tuple7<A2, B2, C2, D2, E2, F2, G2> > { + enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value || + ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value || + ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value || + ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value || + ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value || + ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value || + ExpectsScopedRefptrButGetsRawPtr<G1, G2>::value) }; +}; #endif // BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ diff --git a/base/task.h b/base/task.h index 1949e74..b21ccd8 100644 --- a/base/task.h +++ b/base/task.h @@ -149,9 +149,8 @@ class ScopedRunnableMethodFactory { : obj_(obj), meth_(meth), params_(params) { - COMPILE_ASSERT( - (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value), - badscopedrunnablemethodparams); + COMPILE_ASSERT((MethodUsesScopedRefptrCorrectly<Method, Params>::value), + badscopedrunnablemethodparams); } virtual void Run() { @@ -318,9 +317,8 @@ class RunnableMethod : public CancelableTask { RunnableMethod(T* obj, Method meth, const Params& params) : obj_(obj), meth_(meth), params_(params) { traits_.RetainCallee(obj_); - COMPILE_ASSERT( - (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value), - badrunnablemethodparams); + COMPILE_ASSERT((MethodUsesScopedRefptrCorrectly<Method, Params>::value), + badrunnablemethodparams); } ~RunnableMethod() { @@ -431,9 +429,8 @@ class RunnableFunction : public CancelableTask { public: RunnableFunction(Function function, const Params& params) : function_(function), params_(params) { - COMPILE_ASSERT( - (base::internal::ParamsUseScopedRefptrCorrectly<Params>::value), - badrunnablefunctionparams); + COMPILE_ASSERT((FunctionUsesScopedRefptrCorrectly<Function, Params>::value), + badrunnablefunctionparams); } ~RunnableFunction() { diff --git a/base/template_util.h b/base/template_util.h index 27bdb73..2cfe04c 100644 --- a/base/template_util.h +++ b/base/template_util.h @@ -6,8 +6,6 @@ #define BASE_TEMPLATE_UTIL_H_ #pragma once -#include "build/build_config.h" - namespace base { // template definitions from tr1 @@ -27,51 +25,6 @@ typedef integral_constant<bool, false> false_type; template <class T> struct is_pointer : false_type {}; template <class T> struct is_pointer<T*> : true_type {}; -namespace internal { - -// Types small_ and big_ are guaranteed such that sizeof(small_) < -// sizeof(big_) -typedef char small_; - -struct big_ { - small_ dummy[2]; -}; - -#if !defined(OS_WIN) - -// This class is an implementation detail for is_convertible, and you -// don't need to know how it works to use is_convertible. For those -// who care: we declare two different functions, one whose argument is -// of type To and one with a variadic argument list. We give them -// return types of different size, so we can use sizeof to trick the -// compiler into telling us which function it would have chosen if we -// had called it with an argument of type From. See Alexandrescu's -// _Modern C++ Design_ for more details on this sort of trick. - -template <typename From, typename To> -struct ConvertHelper { - static small_ Test(To); - static big_ Test(...); - static From Create(); -}; - -#endif // !defined(OS_WIN) - -} // namespace internal - -#if !defined(OS_WIN) - -// Inherits from true_type if From is convertible to To, false_type otherwise. -template <typename From, typename To> -struct is_convertible - : integral_constant<bool, - sizeof(internal::ConvertHelper<From, To>::Test( - internal::ConvertHelper<From, To>::Create())) - == sizeof(internal::small_)> { -}; - -#endif // !defined(OS_WIN) - } // namespace base #endif // BASE_TEMPLATE_UTIL_H_ |