Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2006-2008 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_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_
      6 #define BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_
      7 
      8 #include "base/ref_counted.h"
      9 #include "base/tuple.h"
     10 
     11 // It is dangerous to post a task with a raw pointer argument to a function
     12 // that expects a scoped_refptr<>.  The compiler will happily accept the
     13 // situation, but it will not attempt to increase the refcount until the task
     14 // runs.  Callers expecting the argument to be refcounted up at post time are
     15 // in for a nasty surprise!  Example: http://crbug.com/27191
     16 // The following set of traits are designed to generate a compile error
     17 // whenever this antipattern is attempted.
     18 template <class A, class B>
     19 struct ExpectsScopedRefptrButGetsRawPtr {
     20   enum { value = 0 };
     21 };
     22 
     23 template <class A, class B>
     24 struct ExpectsScopedRefptrButGetsRawPtr<scoped_refptr<A>, B*> {
     25   enum { value = 1 };
     26 };
     27 
     28 template <class Function, class Params>
     29 struct FunctionUsesScopedRefptrCorrectly {
     30   enum { value = 1 };
     31 };
     32 
     33 template <class A1, class A2>
     34 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1), Tuple1<A2> > {
     35   enum { value = !ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value };
     36 };
     37 
     38 template <class A1, class B1, class A2, class B2>
     39 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1), Tuple2<A2, B2> > {
     40   enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
     41                    ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value) };
     42 };
     43 
     44 template <class A1, class B1, class C1, class A2, class B2, class C2>
     45 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1),
     46                                          Tuple3<A2, B2, C2> > {
     47   enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
     48                    ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
     49                    ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value) };
     50 };
     51 
     52 template <class A1, class B1, class C1, class D1,
     53           class A2, class B2, class C2, class D2>
     54 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1),
     55                                          Tuple4<A2, B2, C2, D2> > {
     56   enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
     57                    ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
     58                    ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
     59                    ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value) };
     60 };
     61 
     62 template <class A1, class B1, class C1, class D1, class E1,
     63           class A2, class B2, class C2, class D2, class E2>
     64 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1),
     65                                          Tuple5<A2, B2, C2, D2, E2> > {
     66   enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
     67                    ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
     68                    ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
     69                    ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value ||
     70                    ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value) };
     71 };
     72 
     73 template <class A1, class B1, class C1, class D1, class E1, class F1,
     74           class A2, class B2, class C2, class D2, class E2, class F2>
     75 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1, F1),
     76                                          Tuple6<A2, B2, C2, D2, E2, F2> > {
     77   enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
     78                    ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
     79                    ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
     80                    ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value ||
     81                    ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value ||
     82                    ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value) };
     83 };
     84 
     85 template <class A1, class B1, class C1, class D1, class E1, class F1, class G1,
     86           class A2, class B2, class C2, class D2, class E2, class F2, class G2>
     87 struct FunctionUsesScopedRefptrCorrectly<void (*)(A1, B1, C1, D1, E1, F1, G1),
     88                                          Tuple7<A2, B2, C2, D2, E2, F2, G2> > {
     89   enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
     90                    ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
     91                    ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
     92                    ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value ||
     93                    ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value ||
     94                    ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value ||
     95                    ExpectsScopedRefptrButGetsRawPtr<G1, G2>::value) };
     96 };
     97 
     98 template <class Method, class Params>
     99 struct MethodUsesScopedRefptrCorrectly {
    100   enum { value = 1 };
    101 };
    102 
    103 template <class T, class A1, class A2>
    104 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1), Tuple1<A2> > {
    105   enum { value = !ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value };
    106 };
    107 
    108 template <class T, class A1, class B1, class A2, class B2>
    109 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1), Tuple2<A2, B2> > {
    110   enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
    111                    ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value) };
    112 };
    113 
    114 template <class T, class A1, class B1, class C1,
    115                    class A2, class B2, class C2>
    116 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1),
    117                                        Tuple3<A2, B2, C2> > {
    118   enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
    119                    ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
    120                    ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value) };
    121 };
    122 
    123 template <class T, class A1, class B1, class C1, class D1,
    124           class A2, class B2, class C2, class D2>
    125 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1),
    126                                        Tuple4<A2, B2, C2, D2> > {
    127   enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
    128                    ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
    129                    ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
    130                    ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value) };
    131 };
    132 
    133 template <class T, class A1, class B1, class C1, class D1, class E1,
    134                    class A2, class B2, class C2, class D2, class E2>
    135 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1, E1),
    136                                        Tuple5<A2, B2, C2, D2, E2> > {
    137   enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
    138                    ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
    139                    ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
    140                    ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value ||
    141                    ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value) };
    142 };
    143 
    144 template <class T, class A1, class B1, class C1, class D1, class E1, class F1,
    145                    class A2, class B2, class C2, class D2, class E2, class F2>
    146 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1, E1, F1),
    147                                        Tuple6<A2, B2, C2, D2, E2, F2> > {
    148   enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
    149                    ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
    150                    ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
    151                    ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value ||
    152                    ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value ||
    153                    ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value) };
    154 };
    155 
    156 template <class T,
    157           class A1, class B1, class C1, class D1, class E1, class F1, class G1,
    158           class A2, class B2, class C2, class D2, class E2, class F2, class G2>
    159 struct MethodUsesScopedRefptrCorrectly<void (T::*)(A1, B1, C1, D1, E1, F1, G1),
    160                                        Tuple7<A2, B2, C2, D2, E2, F2, G2> > {
    161   enum { value = !(ExpectsScopedRefptrButGetsRawPtr<A1, A2>::value ||
    162                    ExpectsScopedRefptrButGetsRawPtr<B1, B2>::value ||
    163                    ExpectsScopedRefptrButGetsRawPtr<C1, C2>::value ||
    164                    ExpectsScopedRefptrButGetsRawPtr<D1, D2>::value ||
    165                    ExpectsScopedRefptrButGetsRawPtr<E1, E2>::value ||
    166                    ExpectsScopedRefptrButGetsRawPtr<F1, F2>::value ||
    167                    ExpectsScopedRefptrButGetsRawPtr<G1, G2>::value) };
    168 };
    169 
    170 #endif  // BASE_RAW_SCOPED_REFPTR_MISMATCH_CHECKER_H_
    171