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