Arcoth created this revision.
Herald added a reviewer: EricWF.

See https://bugs.llvm.org/show_bug.cgi?id=32856. Basically, as this code was 
written before placeholder return types for functions were a
thing, the function call operators of __bind apply decltype on the call 
expression to infer the return type. This can lead to hard errors when we pass 
template functors. Another consequence of this is that the validity or 
invalidity of these call expressions influences overload resolution (via 
SFINAE), hence the const version could be selected where the __bind object was 
non-const, which is not the prescribed behaviour. This is fixed by 
using placeholder return types.


https://reviews.llvm.org/D32824

Files:
  include/functional


Index: include/functional
===================================================================
--- include/functional
+++ include/functional
@@ -1006,7 +1006,7 @@
 {
     _Predicate __pred_;
 public:
-    _LIBCPP_INLINE_VISIBILITY explicit _LIBCPP_CONSTEXPR_AFTER_CXX11 
+    _LIBCPP_INLINE_VISIBILITY explicit _LIBCPP_CONSTEXPR_AFTER_CXX11
     binary_negate(const _Predicate& __pred) : __pred_(__pred) {}
 
     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
@@ -1793,7 +1793,7 @@
         typedef __function::__func<_Fp, _Alloc, _Rp(_ArgTypes...)> _FF;
         typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap;
         _Ap __a(__a0);
-        if (sizeof(_FF) <= sizeof(__buf_) && 
+        if (sizeof(_FF) <= sizeof(__buf_) &&
             is_nothrow_copy_constructible<_Fp>::value && 
is_nothrow_copy_constructible<_Ap>::value)
         {
             __f_ = ::new((void*)&__buf_) _FF(_VSTD::move(__f), _Alloc(__a));
@@ -2254,16 +2254,24 @@
 
     template <class ..._Args>
         _LIBCPP_INLINE_VISIBILITY
+#ifndef __cpp_decltype_auto
         typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type
+#else
+        decltype(auto)
+#endif
         operator()(_Args&& ...__args)
         {
             return __apply_functor(__f_, __bound_args_, __indices(),
                                   
tuple<_Args&&...>(_VSTD::forward<_Args>(__args)...));
         }
 
     template <class ..._Args>
         _LIBCPP_INLINE_VISIBILITY
+#ifndef __cpp_decltype_auto
         typename __bind_return<const _Fd, const _Td, tuple<_Args&&...> >::type
+#else
+        decltype(auto)
+#endif
         operator()(_Args&& ...__args) const
         {
             return __apply_functor(__f_, __bound_args_, __indices(),


Index: include/functional
===================================================================
--- include/functional
+++ include/functional
@@ -1006,7 +1006,7 @@
 {
     _Predicate __pred_;
 public:
-    _LIBCPP_INLINE_VISIBILITY explicit _LIBCPP_CONSTEXPR_AFTER_CXX11 
+    _LIBCPP_INLINE_VISIBILITY explicit _LIBCPP_CONSTEXPR_AFTER_CXX11
     binary_negate(const _Predicate& __pred) : __pred_(__pred) {}
 
     _LIBCPP_CONSTEXPR_AFTER_CXX11 _LIBCPP_INLINE_VISIBILITY
@@ -1793,7 +1793,7 @@
         typedef __function::__func<_Fp, _Alloc, _Rp(_ArgTypes...)> _FF;
         typedef typename __rebind_alloc_helper<__alloc_traits, _FF>::type _Ap;
         _Ap __a(__a0);
-        if (sizeof(_FF) <= sizeof(__buf_) && 
+        if (sizeof(_FF) <= sizeof(__buf_) &&
             is_nothrow_copy_constructible<_Fp>::value && is_nothrow_copy_constructible<_Ap>::value)
         {
             __f_ = ::new((void*)&__buf_) _FF(_VSTD::move(__f), _Alloc(__a));
@@ -2254,16 +2254,24 @@
 
     template <class ..._Args>
         _LIBCPP_INLINE_VISIBILITY
+#ifndef __cpp_decltype_auto
         typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type
+#else
+        decltype(auto)
+#endif
         operator()(_Args&& ...__args)
         {
             return __apply_functor(__f_, __bound_args_, __indices(),
                                   tuple<_Args&&...>(_VSTD::forward<_Args>(__args)...));
         }
 
     template <class ..._Args>
         _LIBCPP_INLINE_VISIBILITY
+#ifndef __cpp_decltype_auto
         typename __bind_return<const _Fd, const _Td, tuple<_Args&&...> >::type
+#else
+        decltype(auto)
+#endif
         operator()(_Args&& ...__args) const
         {
             return __apply_functor(__f_, __bound_args_, __indices(),
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to