Revert "Fix PR34298 - Allow std::function with an incomplete return type."

This reverts commit r312890 because the test case fails to compile for
older versions of Clang that reject initializing a const object without
a user defined constructor.

Since this patch should go into 5.0.1, I want to keep it an atomic change,
and will re-commit it with a fixed test case.

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@312891 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Fiselier
2017-09-10 23:37:47 +00:00
parent f83132a4d1
commit d5a494e058
3 changed files with 26 additions and 54 deletions

View File

@@ -1597,10 +1597,8 @@ class _LIBCPP_TEMPLATE_VIS function<_Rp(_ArgTypes...)>
return reinterpret_cast<__base*>(p); return reinterpret_cast<__base*>(p);
} }
template <class _Fp, bool = __lazy_and< template <class _Fp, bool = !is_same<_Fp, function>::value &&
integral_constant<bool, !is_same<__uncvref_t<_Fp>, function>::value>, __invokable<_Fp&, _ArgTypes...>::value>
__invokable<_Fp&, _ArgTypes...>
>::value>
struct __callable; struct __callable;
template <class _Fp> template <class _Fp>
struct __callable<_Fp, true> struct __callable<_Fp, true>
@@ -1614,9 +1612,6 @@ class _LIBCPP_TEMPLATE_VIS function<_Rp(_ArgTypes...)>
{ {
static const bool value = false; static const bool value = false;
}; };
template <class _Fp>
using _EnableIfCallable = typename enable_if<__callable<_Fp>::value>::type;
public: public:
typedef _Rp result_type; typedef _Rp result_type;
@@ -1627,7 +1622,9 @@ public:
function(nullptr_t) _NOEXCEPT : __f_(0) {} function(nullptr_t) _NOEXCEPT : __f_(0) {}
function(const function&); function(const function&);
function(function&&) _NOEXCEPT; function(function&&) _NOEXCEPT;
template<class _Fp, class = _EnableIfCallable<_Fp>> template<class _Fp, class = typename enable_if<
__callable<_Fp>::value && !is_same<_Fp, function>::value
>::type>
function(_Fp); function(_Fp);
#if _LIBCPP_STD_VER <= 14 #if _LIBCPP_STD_VER <= 14
@@ -1641,15 +1638,21 @@ public:
function(allocator_arg_t, const _Alloc&, const function&); function(allocator_arg_t, const _Alloc&, const function&);
template<class _Alloc> template<class _Alloc>
function(allocator_arg_t, const _Alloc&, function&&); function(allocator_arg_t, const _Alloc&, function&&);
template<class _Fp, class _Alloc, class = _EnableIfCallable<_Fp>> template<class _Fp, class _Alloc, class = typename enable_if<__callable<_Fp>::value>::type>
function(allocator_arg_t, const _Alloc& __a, _Fp __f); function(allocator_arg_t, const _Alloc& __a, _Fp __f);
#endif #endif
function& operator=(const function&); function& operator=(const function&);
function& operator=(function&&) _NOEXCEPT; function& operator=(function&&) _NOEXCEPT;
function& operator=(nullptr_t) _NOEXCEPT; function& operator=(nullptr_t) _NOEXCEPT;
template<class _Fp, class = _EnableIfCallable<_Fp>> template<class _Fp>
function& operator=(_Fp&&); typename enable_if
<
__callable<typename decay<_Fp>::type>::value &&
!is_same<typename remove_reference<_Fp>::type, function>::value,
function&
>::type
operator=(_Fp&&);
~function(); ~function();
@@ -1851,8 +1854,13 @@ function<_Rp(_ArgTypes...)>::operator=(nullptr_t) _NOEXCEPT
} }
template<class _Rp, class ..._ArgTypes> template<class _Rp, class ..._ArgTypes>
template <class _Fp, class> template <class _Fp>
function<_Rp(_ArgTypes...)>& typename enable_if
<
function<_Rp(_ArgTypes...)>::template __callable<typename decay<_Fp>::type>::value &&
!is_same<typename remove_reference<_Fp>::type, function<_Rp(_ArgTypes...)>>::value,
function<_Rp(_ArgTypes...)>&
>::type
function<_Rp(_ArgTypes...)>::operator=(_Fp&& __f) function<_Rp(_ArgTypes...)>::operator=(_Fp&& __f)
{ {
function(_VSTD::forward<_Fp>(__f)).swap(*this); function(_VSTD::forward<_Fp>(__f)).swap(*this);

View File

@@ -4339,8 +4339,8 @@ struct __invokable_r
using _Result = decltype( using _Result = decltype(
_VSTD::__invoke(_VSTD::declval<_Fp>(), _VSTD::declval<_Args>()...)); _VSTD::__invoke(_VSTD::declval<_Fp>(), _VSTD::declval<_Args>()...));
using type = static const bool value =
typename conditional< conditional<
!is_same<_Result, __nat>::value, !is_same<_Result, __nat>::value,
typename conditional< typename conditional<
is_void<_Ret>::value, is_void<_Ret>::value,
@@ -4348,8 +4348,7 @@ struct __invokable_r
is_convertible<_Result, _Ret> is_convertible<_Result, _Ret>
>::type, >::type,
false_type false_type
>::type; >::type::value;
static const bool value = type::value;
}; };
template <class _Fp, class ..._Args> template <class _Fp, class ..._Args>

View File

@@ -16,7 +16,6 @@
// Allow incomplete argument types in the __is_callable check // Allow incomplete argument types in the __is_callable check
#include <functional> #include <functional>
#include <cassert>
struct X{ struct X{
typedef std::function<void(X&)> callback_type; typedef std::function<void(X&)> callback_type;
@@ -25,40 +24,6 @@ private:
callback_type _cb; callback_type _cb;
}; };
struct IncompleteReturnType { int main()
std::function<IncompleteReturnType ()> fn;
};
int called = 0;
IncompleteReturnType test_fn() {
++called;
IncompleteReturnType I;
return I;
}
// See llvm.org/PR34298
void test_pr34298()
{ {
static_assert(std::is_copy_constructible<IncompleteReturnType>::value, "");
static_assert(std::is_copy_assignable<IncompleteReturnType>::value, "");
{
IncompleteReturnType X;
X.fn = test_fn;
const IncompleteReturnType& CX = X;
IncompleteReturnType X2 = CX;
assert(X2.fn);
assert(called == 0);
X2.fn();
assert(called == 1);
}
{
const IncompleteReturnType Empty;
IncompleteReturnType X2 = Empty;
assert(!X2.fn);
}
}
int main() {
test_pr34298();
} }