1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
|
// 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_
|