diff options
author | jamesr@chromium.org <jamesr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-02 01:44:30 +0000 |
---|---|---|
committer | jamesr@chromium.org <jamesr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-12-02 01:44:30 +0000 |
commit | 7c87290fed96e7620b3702bc9435db6bc957d92c (patch) | |
tree | 43b6be5e45147a6ebc641012da2444446e6f74f3 /base/raw_scoped_refptr_mismatch_checker.h | |
parent | 4559a7d9c3eca928fc19b64b64f19c8032d0ee0f (diff) | |
download | chromium_src-7c87290fed96e7620b3702bc9435db6bc957d92c.zip chromium_src-7c87290fed96e7620b3702bc9435db6bc957d92c.tar.gz chromium_src-7c87290fed96e7620b3702bc9435db6bc957d92c.tar.bz2 |
Tries to catch callbacks expecting scoped_refptr<T> and getting T* using template magic
Review URL: http://codereview.chromium.org/414024
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33531 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/raw_scoped_refptr_mismatch_checker.h')
-rw-r--r-- | base/raw_scoped_refptr_mismatch_checker.h | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/base/raw_scoped_refptr_mismatch_checker.h b/base/raw_scoped_refptr_mismatch_checker.h new file mode 100644 index 0000000..598710f --- /dev/null +++ b/base/raw_scoped_refptr_mismatch_checker.h @@ -0,0 +1,170 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ +#define BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_ + +#include "base/ref_counted.h" +#include "base/tuple.h" + +// 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. +template <class A, class B> +struct ExpectsScopedRefptrButGetsRawPtr { + enum { value = 0 }; +}; + +template <class A, class B> +struct ExpectsScopedRefptrButGetsRawPtr<scoped_refptr<A>, B*> { + enum { value = 1 }; +}; + +template <class Function, class Params> +struct FunctionUsesScopedRefptrCorrectly { + enum { value = 1 }; +}; + +template <class A1, class A2> +struct FunctionUsesScopedRefptrCorrectly<void (*)(A1), Tuple1<A2> > { + enum { value = !ExpectsScopedRefptrButGetsRawPtr<A1, A2>::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 <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 <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 <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 <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 <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) }; +}; + +template <class Method, class Params> +struct MethodUsesScopedRefptrCorrectly { + enum { value = 1 }; +}; + +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_ |