blob: 069092cff199e43d13295d0ac293383d122765c4 [file] [log] [blame]
[email protected]81814bce2011-09-10 03:03:001// Copyright (c) 2011 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#include "base/callback.h"
6#include "base/bind.h"
[email protected]7296f2762011-11-21 19:23:447#include "base/memory/ref_counted.h"
[email protected]81814bce2011-09-10 03:03:008
9namespace base {
10
11// Do not put everything inside an anonymous namespace. If you do, many of the
12// helper function declarations will generate unused definition warnings unless
13// unused definition warnings.
14
15static const int kParentValue = 1;
16static const int kChildValue = 2;
17
18class NoRef {
19 public:
20 void VoidMethod0() {}
21 void VoidConstMethod0() const {}
22 int IntMethod0() { return 1; }
23};
24
[email protected]7296f2762011-11-21 19:23:4425class HasRef : public NoRef, public base::RefCounted<HasRef> {
[email protected]81814bce2011-09-10 03:03:0026};
27
28class Parent {
29 public:
30 void AddRef(void) const {}
31 void Release(void) const {}
32 virtual void VirtualSet() { value = kParentValue; }
33 void NonVirtualSet() { value = kParentValue; }
34 int value;
35};
36
37class Child : public Parent {
38 public:
39 virtual void VirtualSet() { value = kChildValue; }
40 void NonVirtualSet() { value = kChildValue; }
41};
42
43class NoRefParent {
44 public:
45 virtual void VirtualSet() { value = kParentValue; }
46 void NonVirtualSet() { value = kParentValue; }
47 int value;
48};
49
50class NoRefChild : public NoRefParent {
51 virtual void VirtualSet() { value = kChildValue; }
52 void NonVirtualSet() { value = kChildValue; }
53};
54
55template <typename T>
56T PolymorphicIdentity(T t) {
57 return t;
58}
59
60int UnwrapParentRef(Parent& p) {
61 return p.value;
62}
63
64template <typename T>
65void VoidPolymorphic1(T t) {
66}
67
68#if defined(NCTEST_METHOD_ON_CONST_OBJECT) // [r"invalid conversion from 'const base::NoRef\*' to 'base::NoRef\*'"]
69
70// Method bound to const-object.
71//
72// Only const methods should be allowed to work with const objects.
73void WontCompile() {
74 HasRef has_ref;
75 const HasRef* const_has_ref_ptr_ = &has_ref;
76 Callback<void(void)> method_to_const_cb =
77 Bind(&HasRef::VoidMethod0, const_has_ref_ptr_);
78 method_to_const_cb.Run();
79}
80
[email protected]81814bce2011-09-10 03:03:0081#elif defined(NCTEST_METHOD_BIND_NEEDS_REFCOUNTED_OBJECT) // [r"has no member named 'AddRef'"]
82
83// Method bound to non-refcounted object.
84//
85// We require refcounts unless you have Unretained().
86void WontCompile() {
87 NoRef no_ref;
88 Callback<void(void)> no_ref_cb =
89 Bind(&NoRef::VoidMethod0, &no_ref);
90 no_ref_cb.Run();
91}
92
93#elif defined(NCTEST_CONST_METHOD_NEEDS_REFCOUNTED_OBJECT) // [r"has no member named 'AddRef'"]
94
95// Const Method bound to non-refcounted object.
96//
97// We require refcounts unless you have Unretained().
98void WontCompile() {
99 NoRef no_ref;
100 Callback<void(void)> no_ref_const_cb =
101 Bind(&NoRef::VoidConstMethod0, &no_ref);
102 no_ref_const_cb.Run();
103}
104
105#elif defined(NCTEST_CONST_POINTER) // [r"invalid conversion from 'const base::NoRef\*' to 'base::NoRef\*'"]
106
107// Const argument used with non-const pointer parameter of same type.
108//
109// This is just a const-correctness check.
110void WontCompile() {
111 const NoRef* const_no_ref_ptr;
112 Callback<NoRef*(void)> pointer_same_cb =
113 Bind(&PolymorphicIdentity<NoRef*>, const_no_ref_ptr);
114 pointer_same_cb.Run();
115}
116
117#elif defined(NCTEST_CONST_POINTER_SUBTYPE) // [r"'const base::NoRefParent\*' to 'base::NoRefParent\*'"]
118
119// Const argument used with non-const pointer parameter of super type.
120//
121// This is just a const-correctness check.
122void WontCompile() {
123 const NoRefChild* const_child_ptr;
124 Callback<NoRefParent*(void)> pointer_super_cb =
125 Bind(&PolymorphicIdentity<NoRefParent*>, const_child_ptr);
126 pointer_super_cb.Run();
127}
128
129#elif defined(DISABLED_NCTEST_DISALLOW_NON_CONST_REF_PARAM) // [r"badstring"]
130// I think there's a type safety promotion issue here where we can pass a const
131// ref to a non const-ref function, or vice versa accidentally. Or we make a
132// copy accidentally. Check.
133
134// Functions with reference parameters, unsupported.
135//
136// First, non-const reference parameters are disallowed by the Google
137// style guide. Second, since we are doing argument forwarding it becomes
138// very tricky to avoid copies, maintain const correctness, and not
139// accidentally have the function be modifying a temporary, or a copy.
140void WontCompile() {
141 Parent p;
142 Callback<int(Parent&)> ref_arg_cb = Bind(&UnwrapParentRef);
143 ref_arg_cb.Run(p);
144}
145
146#elif defined(NCTEST_DISALLOW_BIND_TO_NON_CONST_REF_PARAM) // [r"creating array with negative size"]
147
148// Binding functions with reference parameters, unsupported.
149//
150// See comment in NCTEST_DISALLOW_NON_CONST_REF_PARAM
151void WontCompile() {
152 Parent p;
153 Callback<int(void)> ref_cb = Bind(&UnwrapParentRef, p);
154 ref_cb.Run();
155}
156
157#elif defined(NCTEST_NO_IMPLICIT_ARRAY_PTR_CONVERSION) // [r"creating array with negative size"]
158
159// A method should not be bindable with an array of objects.
160//
161// This is likely not wanted behavior. We specifically check for it though
162// because it is possible, depending on how you implement prebinding, to
163// implicitly convert an array type to a pointer type.
164void WontCompile() {
165 HasRef p[10];
166 Callback<void(void)> method_bound_to_array_cb =
167 Bind(&HasRef::VoidMethod0, p);
168 method_bound_to_array_cb.Run();
169}
170
171#elif defined(NCTEST_NO_RAW_PTR_FOR_REFCOUNTED_TYPES) // [r"creating array with negative size"]
172
173// Refcounted types should not be bound as a raw pointer.
174void WontCompile() {
175 HasRef for_raw_ptr;
[email protected]7296f2762011-11-21 19:23:44176 int a;
177 Callback<void(void)> ref_count_as_raw_ptr_a =
178 Bind(&VoidPolymorphic1<int*>, &a);
[email protected]81814bce2011-09-10 03:03:00179 Callback<void(void)> ref_count_as_raw_ptr =
180 Bind(&VoidPolymorphic1<HasRef*>, &for_raw_ptr);
181}
182
183#elif defined(NCTEST_WEAKPTR_BIND_MUST_RETURN_VOID) // [r"creating array with negative size"]
184
185// WeakPtrs cannot be bound to methods with return types.
186void WontCompile() {
187 NoRef no_ref;
188 WeakPtrFactory<NoRef> weak_factory(&no_ref);
189 Callback<int(void)> weak_ptr_with_non_void_return_type =
190 Bind(&NoRef::IntMethod0, weak_factory.GetWeakPtr());
191 weak_ptr_with_non_void_return_type.Run();
192}
193
[email protected]7296f2762011-11-21 19:23:44194#elif defined(NCTEST_DISALLOW_ASSIGN_DIFFERINT_TYPES) // [r"invalid conversion from"]
[email protected]81814bce2011-09-10 03:03:00195
196// Bind result cannot be assigned to Callbacks with a mismatching type.
197void WontCompile() {
198 Closure callback_mismatches_bind_type = Bind(&VoidPolymorphic1<int>);
199}
200
201#endif
202
203} // namespace base