summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--base/bind_internal.h94
-rw-r--r--base/bind_internal.h.pump9
-rw-r--r--base/bind_unittest.cc8
3 files changed, 72 insertions, 39 deletions
diff --git a/base/bind_internal.h b/base/bind_internal.h
index 404b795..7beba51 100644
--- a/base/bind_internal.h
+++ b/base/bind_internal.h
@@ -14,6 +14,7 @@
#include "base/bind_helpers.h"
#include "base/callback_internal.h"
+#include "base/memory/raw_scoped_refptr_mismatch_checker.h"
#include "base/memory/weak_ptr.h"
#include "base/template_util.h"
#include "build/build_config.h"
@@ -1815,7 +1816,8 @@ class InvokerStorage1 : public InvokerStorageBase {
// scoped_refptr check because the binder itself takes care of this. We also
// disallow binding of an array as the method's target object.
COMPILE_ASSERT(IsMethod::value ||
- !internal::UnsafeBindtoRefCountedArg<P1>::value,
+ internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P1>::StorageType>::value == 0,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
@@ -1862,12 +1864,14 @@ class InvokerStorage2 : public InvokerStorageBase {
// scoped_refptr check because the binder itself takes care of this. We also
// disallow binding of an array as the method's target object.
COMPILE_ASSERT(IsMethod::value ||
- !internal::UnsafeBindtoRefCountedArg<P1>::value,
+ internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P1>::StorageType>::value == 0,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
- COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P2>::value,
- p2_is_refcounted_type_and_needs_scoped_refptr);
+ COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P2>::StorageType>::value == 0,
+ p2_is_refcounted_type_and_needs_scoped_refptr);
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
@@ -1915,14 +1919,17 @@ class InvokerStorage3 : public InvokerStorageBase {
// scoped_refptr check because the binder itself takes care of this. We also
// disallow binding of an array as the method's target object.
COMPILE_ASSERT(IsMethod::value ||
- !internal::UnsafeBindtoRefCountedArg<P1>::value,
+ internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P1>::StorageType>::value == 0,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
- COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P2>::value,
- p2_is_refcounted_type_and_needs_scoped_refptr);
- COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P3>::value,
- p3_is_refcounted_type_and_needs_scoped_refptr);
+ COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P2>::StorageType>::value == 0,
+ p2_is_refcounted_type_and_needs_scoped_refptr);
+ COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P3>::StorageType>::value == 0,
+ p3_is_refcounted_type_and_needs_scoped_refptr);
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
@@ -1974,16 +1981,20 @@ class InvokerStorage4 : public InvokerStorageBase {
// scoped_refptr check because the binder itself takes care of this. We also
// disallow binding of an array as the method's target object.
COMPILE_ASSERT(IsMethod::value ||
- !internal::UnsafeBindtoRefCountedArg<P1>::value,
+ internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P1>::StorageType>::value == 0,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
- COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P2>::value,
- p2_is_refcounted_type_and_needs_scoped_refptr);
- COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P3>::value,
- p3_is_refcounted_type_and_needs_scoped_refptr);
- COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P4>::value,
- p4_is_refcounted_type_and_needs_scoped_refptr);
+ COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P2>::StorageType>::value == 0,
+ p2_is_refcounted_type_and_needs_scoped_refptr);
+ COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P3>::StorageType>::value == 0,
+ p3_is_refcounted_type_and_needs_scoped_refptr);
+ COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P4>::StorageType>::value == 0,
+ p4_is_refcounted_type_and_needs_scoped_refptr);
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
@@ -2040,18 +2051,23 @@ class InvokerStorage5 : public InvokerStorageBase {
// scoped_refptr check because the binder itself takes care of this. We also
// disallow binding of an array as the method's target object.
COMPILE_ASSERT(IsMethod::value ||
- !internal::UnsafeBindtoRefCountedArg<P1>::value,
+ internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P1>::StorageType>::value == 0,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
- COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P2>::value,
- p2_is_refcounted_type_and_needs_scoped_refptr);
- COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P3>::value,
- p3_is_refcounted_type_and_needs_scoped_refptr);
- COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P4>::value,
- p4_is_refcounted_type_and_needs_scoped_refptr);
- COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P5>::value,
- p5_is_refcounted_type_and_needs_scoped_refptr);
+ COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P2>::StorageType>::value == 0,
+ p2_is_refcounted_type_and_needs_scoped_refptr);
+ COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P3>::StorageType>::value == 0,
+ p3_is_refcounted_type_and_needs_scoped_refptr);
+ COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P4>::StorageType>::value == 0,
+ p4_is_refcounted_type_and_needs_scoped_refptr);
+ COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P5>::StorageType>::value == 0,
+ p5_is_refcounted_type_and_needs_scoped_refptr);
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
@@ -2113,20 +2129,26 @@ class InvokerStorage6 : public InvokerStorageBase {
// scoped_refptr check because the binder itself takes care of this. We also
// disallow binding of an array as the method's target object.
COMPILE_ASSERT(IsMethod::value ||
- !internal::UnsafeBindtoRefCountedArg<P1>::value,
+ internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P1>::StorageType>::value == 0,
p1_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!IsMethod::value || !is_array<P1>::value,
first_bound_argument_to_method_cannot_be_array);
- COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P2>::value,
- p2_is_refcounted_type_and_needs_scoped_refptr);
- COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P3>::value,
- p3_is_refcounted_type_and_needs_scoped_refptr);
- COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P4>::value,
- p4_is_refcounted_type_and_needs_scoped_refptr);
- COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P5>::value,
- p5_is_refcounted_type_and_needs_scoped_refptr);
- COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P6>::value,
- p6_is_refcounted_type_and_needs_scoped_refptr);
+ COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P2>::StorageType>::value == 0,
+ p2_is_refcounted_type_and_needs_scoped_refptr);
+ COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P3>::StorageType>::value == 0,
+ p3_is_refcounted_type_and_needs_scoped_refptr);
+ COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P4>::StorageType>::value == 0,
+ p4_is_refcounted_type_and_needs_scoped_refptr);
+ COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P5>::StorageType>::value == 0,
+ p5_is_refcounted_type_and_needs_scoped_refptr);
+ COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P6>::StorageType>::value == 0,
+ p6_is_refcounted_type_and_needs_scoped_refptr);
// Do not allow binding a non-const reference parameter. Non-const reference
// parameters are disallowed by the Google style guide. Also, binding a
diff --git a/base/bind_internal.h.pump b/base/bind_internal.h.pump
index 532fe3d..429e13f 100644
--- a/base/bind_internal.h.pump
+++ b/base/bind_internal.h.pump
@@ -17,6 +17,7 @@ $var MAX_ARITY = 6
#include "base/bind_helpers.h"
#include "base/callback_internal.h"
+#include "base/memory/raw_scoped_refptr_mismatch_checker.h"
#include "base/memory/weak_ptr.h"
#include "base/template_util.h"
#include "build/build_config.h"
@@ -334,14 +335,16 @@ $if BOUND_ARG == 1 [[
// scoped_refptr check because the binder itself takes care of this. We also
// disallow binding of an array as the method's target object.
COMPILE_ASSERT(IsMethod::value ||
- !internal::UnsafeBindtoRefCountedArg<P$(BOUND_ARG)>::value,
+ internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P$(BOUND_ARG)>::StorageType>::value == 0,
p$(BOUND_ARG)_is_refcounted_type_and_needs_scoped_refptr);
COMPILE_ASSERT(!IsMethod::value || !is_array<P$(BOUND_ARG)>::value,
first_bound_argument_to_method_cannot_be_array);
]] $else [[
- COMPILE_ASSERT(!internal::UnsafeBindtoRefCountedArg<P$(BOUND_ARG)>::value,
- p$(BOUND_ARG)_is_refcounted_type_and_needs_scoped_refptr);
+ COMPILE_ASSERT(internal::NeedsScopedRefptrButGetsRawPtr<
+ typename ParamTraits<P$(BOUND_ARG)>::StorageType>::value == 0,
+ p$(BOUND_ARG)_is_refcounted_type_and_needs_scoped_refptr);
]] $$ $if BOUND_ARG
]] $$ $for BOUND_ARG
diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc
index 0c24710..648096d 100644
--- a/base/bind_unittest.cc
+++ b/base/bind_unittest.cc
@@ -15,6 +15,8 @@ using ::testing::StrictMock;
namespace base {
namespace {
+class IncompleteType;
+
class NoRef {
public:
NoRef() {}
@@ -362,6 +364,7 @@ TEST_F(BindTest, IgnoreReturn) {
// - Argument binding to a literal string.
// - Argument binding with template function.
// - Argument binding to an object.
+// - Argument binding to pointer to incomplete type.
// - Argument gets type converted.
// - Pointer argument gets converted.
// - Const Reference forces conversion.
@@ -391,6 +394,11 @@ TEST_F(BindTest, ArgumentBinding) {
Callback<int(void)> bind_object_cb = Bind(&UnwrapNoRefParent, p);
EXPECT_EQ(5, bind_object_cb.Run());
+ IncompleteType* incomplete_ptr = reinterpret_cast<IncompleteType*>(123);
+ Callback<IncompleteType*(void)> bind_incomplete_ptr_cb =
+ Bind(&PolymorphicIdentity<IncompleteType*>, incomplete_ptr);
+ EXPECT_EQ(incomplete_ptr, bind_incomplete_ptr_cb.Run());
+
NoRefChild c;
c.value = 6;
Callback<int(void)> bind_promotes_cb = Bind(&UnwrapNoRefParent, c);