blob: 5e9cff82bded8e713f1b70d527b7a72f6aae4328 [file] [log] [blame]
ajwong@chromium.org505386d2011-09-10 12:03:00 +09001// 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
scheib5616e122015-10-20 04:29:55 +09005// This is a "No Compile Test" suite.
6// http://dev.chromium.org/developers/testing/no-compile-tests
7
ajwong@chromium.org505386d2011-09-10 12:03:00 +09008#include "base/bind.h"
avia6a6a682015-12-27 07:15:14 +09009#include "base/callback.h"
10#include "base/macros.h"
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090011#include "base/memory/ref_counted.h"
ajwong@chromium.org505386d2011-09-10 12:03:00 +090012
13namespace base {
14
15// Do not put everything inside an anonymous namespace. If you do, many of the
viettrungluu@chromium.orgd6f02922014-02-22 01:24:13 +090016// helper function declarations will generate unused definition warnings.
ajwong@chromium.org505386d2011-09-10 12:03:00 +090017
18static const int kParentValue = 1;
19static const int kChildValue = 2;
20
21class NoRef {
22 public:
23 void VoidMethod0() {}
24 void VoidConstMethod0() const {}
25 int IntMethod0() { return 1; }
26};
27
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +090028class HasRef : public NoRef, public base::RefCounted<HasRef> {
ajwong@chromium.org505386d2011-09-10 12:03:00 +090029};
30
31class Parent {
32 public:
tzik260fab52015-12-19 18:18:46 +090033 void AddRef() const {}
34 void Release() const {}
ajwong@chromium.org505386d2011-09-10 12:03:00 +090035 virtual void VirtualSet() { value = kParentValue; }
36 void NonVirtualSet() { value = kParentValue; }
37 int value;
38};
39
40class Child : public Parent {
41 public:
42 virtual void VirtualSet() { value = kChildValue; }
43 void NonVirtualSet() { value = kChildValue; }
44};
45
46class NoRefParent {
47 public:
48 virtual void VirtualSet() { value = kParentValue; }
49 void NonVirtualSet() { value = kParentValue; }
50 int value;
51};
52
53class NoRefChild : public NoRefParent {
54 virtual void VirtualSet() { value = kChildValue; }
55 void NonVirtualSet() { value = kChildValue; }
56};
57
58template <typename T>
59T PolymorphicIdentity(T t) {
60 return t;
61}
62
63int UnwrapParentRef(Parent& p) {
64 return p.value;
65}
66
67template <typename T>
68void VoidPolymorphic1(T t) {
69}
70
tzikfa7381d2016-05-12 08:05:05 +090071#if defined(NCTEST_METHOD_ON_CONST_OBJECT) // [r"fatal error: binding value of type 'const base::HasRef' to reference to type 'base::NoRef' drops 'const' qualifier"]
ajwong@chromium.org505386d2011-09-10 12:03:00 +090072
73// Method bound to const-object.
74//
75// Only const methods should be allowed to work with const objects.
76void WontCompile() {
77 HasRef has_ref;
78 const HasRef* const_has_ref_ptr_ = &has_ref;
tzik260fab52015-12-19 18:18:46 +090079 Callback<void()> method_to_const_cb =
ajwong@chromium.org505386d2011-09-10 12:03:00 +090080 Bind(&HasRef::VoidMethod0, const_has_ref_ptr_);
81 method_to_const_cb.Run();
82}
83
dchengc7fd8322014-11-04 06:29:30 +090084#elif defined(NCTEST_METHOD_BIND_NEEDS_REFCOUNTED_OBJECT) // [r"fatal error: no member named 'AddRef' in 'base::NoRef'"]
ajwong@chromium.org505386d2011-09-10 12:03:00 +090085
86// Method bound to non-refcounted object.
87//
88// We require refcounts unless you have Unretained().
89void WontCompile() {
90 NoRef no_ref;
tzik260fab52015-12-19 18:18:46 +090091 Callback<void()> no_ref_cb =
ajwong@chromium.org505386d2011-09-10 12:03:00 +090092 Bind(&NoRef::VoidMethod0, &no_ref);
93 no_ref_cb.Run();
94}
95
dchengc7fd8322014-11-04 06:29:30 +090096#elif defined(NCTEST_CONST_METHOD_NEEDS_REFCOUNTED_OBJECT) // [r"fatal error: no member named 'AddRef' in 'base::NoRef'"]
ajwong@chromium.org505386d2011-09-10 12:03:00 +090097
98// Const Method bound to non-refcounted object.
99//
100// We require refcounts unless you have Unretained().
101void WontCompile() {
102 NoRef no_ref;
tzik260fab52015-12-19 18:18:46 +0900103 Callback<void()> no_ref_const_cb =
ajwong@chromium.org505386d2011-09-10 12:03:00 +0900104 Bind(&NoRef::VoidConstMethod0, &no_ref);
105 no_ref_const_cb.Run();
106}
107
tzik1c6525c2016-02-16 12:46:07 +0900108#elif defined(NCTEST_CONST_POINTER) // [r"fatal error: cannot initialize a parameter of type 'base::NoRef \*' with an lvalue of type 'const base::NoRef \*const'"]
ajwong@chromium.org505386d2011-09-10 12:03:00 +0900109
110// Const argument used with non-const pointer parameter of same type.
111//
112// This is just a const-correctness check.
113void WontCompile() {
114 const NoRef* const_no_ref_ptr;
tzik260fab52015-12-19 18:18:46 +0900115 Callback<NoRef*()> pointer_same_cb =
ajwong@chromium.org505386d2011-09-10 12:03:00 +0900116 Bind(&PolymorphicIdentity<NoRef*>, const_no_ref_ptr);
117 pointer_same_cb.Run();
118}
119
tzik1c6525c2016-02-16 12:46:07 +0900120#elif defined(NCTEST_CONST_POINTER_SUBTYPE) // [r"fatal error: cannot initialize a parameter of type 'base::NoRefParent \*' with an lvalue of type 'const base::NoRefChild \*const'"]
ajwong@chromium.org505386d2011-09-10 12:03:00 +0900121
122// Const argument used with non-const pointer parameter of super type.
123//
124// This is just a const-correctness check.
125void WontCompile() {
126 const NoRefChild* const_child_ptr;
tzik260fab52015-12-19 18:18:46 +0900127 Callback<NoRefParent*()> pointer_super_cb =
ajwong@chromium.org505386d2011-09-10 12:03:00 +0900128 Bind(&PolymorphicIdentity<NoRefParent*>, const_child_ptr);
129 pointer_super_cb.Run();
130}
131
dchengc7fd8322014-11-04 06:29:30 +0900132#elif defined(DISABLED_NCTEST_DISALLOW_NON_CONST_REF_PARAM) // [r"fatal error: no member named 'AddRef' in 'base::NoRef'"]
133// TODO(dcheng): I think there's a type safety promotion issue here where we can
134// pass a const ref to a non const-ref function, or vice versa accidentally. Or
135// we make a copy accidentally. Check.
ajwong@chromium.org505386d2011-09-10 12:03:00 +0900136
137// Functions with reference parameters, unsupported.
138//
139// First, non-const reference parameters are disallowed by the Google
140// style guide. Second, since we are doing argument forwarding it becomes
141// very tricky to avoid copies, maintain const correctness, and not
142// accidentally have the function be modifying a temporary, or a copy.
143void WontCompile() {
144 Parent p;
145 Callback<int(Parent&)> ref_arg_cb = Bind(&UnwrapParentRef);
146 ref_arg_cb.Run(p);
147}
148
tzik587f17f2015-12-11 15:39:06 +0900149#elif defined(NCTEST_DISALLOW_BIND_TO_NON_CONST_REF_PARAM) // [r"fatal error: static_assert failed \"do not bind functions with nonconst ref\""]
ajwong@chromium.org505386d2011-09-10 12:03:00 +0900150
151// Binding functions with reference parameters, unsupported.
152//
153// See comment in NCTEST_DISALLOW_NON_CONST_REF_PARAM
154void WontCompile() {
155 Parent p;
tzik260fab52015-12-19 18:18:46 +0900156 Callback<int()> ref_cb = Bind(&UnwrapParentRef, p);
ajwong@chromium.org505386d2011-09-10 12:03:00 +0900157 ref_cb.Run();
158}
159
tzik587f17f2015-12-11 15:39:06 +0900160#elif defined(NCTEST_NO_IMPLICIT_ARRAY_PTR_CONVERSION) // [r"fatal error: static_assert failed \"first bound argument to method cannot be array\""]
ajwong@chromium.org505386d2011-09-10 12:03:00 +0900161
162// A method should not be bindable with an array of objects.
163//
164// This is likely not wanted behavior. We specifically check for it though
165// because it is possible, depending on how you implement prebinding, to
166// implicitly convert an array type to a pointer type.
167void WontCompile() {
168 HasRef p[10];
tzik260fab52015-12-19 18:18:46 +0900169 Callback<void()> method_bound_to_array_cb =
ajwong@chromium.org505386d2011-09-10 12:03:00 +0900170 Bind(&HasRef::VoidMethod0, p);
171 method_bound_to_array_cb.Run();
172}
173
tzik587f17f2015-12-11 15:39:06 +0900174#elif defined(NCTEST_NO_RAW_PTR_FOR_REFCOUNTED_TYPES) // [r"fatal error: static_assert failed \"a parameter is a refcounted type and needs scoped_refptr\""]
ajwong@chromium.org505386d2011-09-10 12:03:00 +0900175
176// Refcounted types should not be bound as a raw pointer.
177void WontCompile() {
178 HasRef for_raw_ptr;
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900179 int a;
tzik260fab52015-12-19 18:18:46 +0900180 Callback<void()> ref_count_as_raw_ptr_a =
ajwong@chromium.orgc9c79af2011-11-22 04:23:44 +0900181 Bind(&VoidPolymorphic1<int*>, &a);
tzik260fab52015-12-19 18:18:46 +0900182 Callback<void()> ref_count_as_raw_ptr =
ajwong@chromium.org505386d2011-09-10 12:03:00 +0900183 Bind(&VoidPolymorphic1<HasRef*>, &for_raw_ptr);
184}
185
tzik587f17f2015-12-11 15:39:06 +0900186#elif defined(NCTEST_WEAKPTR_BIND_MUST_RETURN_VOID) // [r"fatal error: static_assert failed \"weak_ptrs can only bind to methods without return values\""]
ajwong@chromium.org505386d2011-09-10 12:03:00 +0900187
188// WeakPtrs cannot be bound to methods with return types.
189void WontCompile() {
190 NoRef no_ref;
191 WeakPtrFactory<NoRef> weak_factory(&no_ref);
tzik260fab52015-12-19 18:18:46 +0900192 Callback<int()> weak_ptr_with_non_void_return_type =
ajwong@chromium.org505386d2011-09-10 12:03:00 +0900193 Bind(&NoRef::IntMethod0, weak_factory.GetWeakPtr());
194 weak_ptr_with_non_void_return_type.Run();
195}
196
tzik817518d2016-02-12 22:54:37 +0900197#elif defined(NCTEST_DISALLOW_ASSIGN_DIFFERENT_TYPES) // [r"fatal error: no viable conversion from 'Callback<MakeUnboundRunType<void \(\*\)\(int\)>>' to 'Callback<void \(\)>'"]
ajwong@chromium.org505386d2011-09-10 12:03:00 +0900198
199// Bind result cannot be assigned to Callbacks with a mismatching type.
200void WontCompile() {
201 Closure callback_mismatches_bind_type = Bind(&VoidPolymorphic1<int>);
202}
203
204#endif
205
206} // namespace base