• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// 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"
7#include "base/memory/ref_counted.h"
8
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
25class HasRef : public NoRef, public base::RefCounted<HasRef> {
26};
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
81#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"size of array is negative"]
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"size of array is negative"]
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"size of array is negative"]
172
173// Refcounted types should not be bound as a raw pointer.
174void WontCompile() {
175  HasRef for_raw_ptr;
176  int a;
177  Callback<void(void)> ref_count_as_raw_ptr_a =
178      Bind(&VoidPolymorphic1<int*>, &a);
179  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"size of array is negative"]
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
194#elif defined(NCTEST_DISALLOW_ASSIGN_DIFFERENT_TYPES)  // [r"conversion from 'base::Callback<void\(int\)>' to non-scalar type"]
195
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
204