| // 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_ |
| #pragma once |
| |
| #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_ |