// 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_