[libcxx] r318835 - Merging r312892:
Tom Stellard via cfe-commits
cfe-commits at lists.llvm.org
Wed Nov 22 06:45:26 PST 2017
Author: tstellar
Date: Wed Nov 22 06:45:26 2017
New Revision: 318835
URL: http://llvm.org/viewvc/llvm-project?rev=318835&view=rev
Log:
Merging r312892:
------------------------------------------------------------------------
r312892 | ericwf | 2017-09-10 16:41:20 -0700 (Sun, 10 Sep 2017) | 10 lines
Fix PR34298 - Allow std::function with an incomplete return type.
This patch fixes llvm.org/PR34298. Previously libc++ incorrectly evaluated
the __invokable trait via the converting constructor `function(Tp)` [with Tp = std::function]
whenever the copy constructor or copy assignment operator
was required. This patch further constrains that constructor to short
circut before evaluating the troublesome SFINAE when `Tp` matches
std::function.
The original patch is from Alex Lorenz.
------------------------------------------------------------------------
Modified:
libcxx/branches/release_50/include/functional
libcxx/branches/release_50/include/type_traits
libcxx/branches/release_50/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F_incomplete.pass.cpp
Modified: libcxx/branches/release_50/include/functional
URL: http://llvm.org/viewvc/llvm-project/libcxx/branches/release_50/include/functional?rev=318835&r1=318834&r2=318835&view=diff
==============================================================================
--- libcxx/branches/release_50/include/functional (original)
+++ libcxx/branches/release_50/include/functional Wed Nov 22 06:45:26 2017
@@ -1597,9 +1597,11 @@ class _LIBCPP_TEMPLATE_VIS function<_Rp(
return reinterpret_cast<__base*>(p);
}
- template <class _Fp, bool = !is_same<_Fp, function>::value &&
- __invokable<_Fp&, _ArgTypes...>::value>
- struct __callable;
+ template <class _Fp, bool = __lazy_and<
+ integral_constant<bool, !is_same<__uncvref_t<_Fp>, function>::value>,
+ __invokable<_Fp&, _ArgTypes...>
+ >::value>
+ struct __callable;
template <class _Fp>
struct __callable<_Fp, true>
{
@@ -1612,6 +1614,9 @@ class _LIBCPP_TEMPLATE_VIS function<_Rp(
{
static const bool value = false;
};
+
+ template <class _Fp>
+ using _EnableIfCallable = typename enable_if<__callable<_Fp>::value>::type;
public:
typedef _Rp result_type;
@@ -1622,9 +1627,7 @@ public:
function(nullptr_t) _NOEXCEPT : __f_(0) {}
function(const function&);
function(function&&) _NOEXCEPT;
- template<class _Fp, class = typename enable_if<
- __callable<_Fp>::value && !is_same<_Fp, function>::value
- >::type>
+ template<class _Fp, class = _EnableIfCallable<_Fp>>
function(_Fp);
#if _LIBCPP_STD_VER <= 14
@@ -1638,21 +1641,15 @@ public:
function(allocator_arg_t, const _Alloc&, const function&);
template<class _Alloc>
function(allocator_arg_t, const _Alloc&, function&&);
- template<class _Fp, class _Alloc, class = typename enable_if<__callable<_Fp>::value>::type>
+ template<class _Fp, class _Alloc, class = _EnableIfCallable<_Fp>>
function(allocator_arg_t, const _Alloc& __a, _Fp __f);
#endif
function& operator=(const function&);
function& operator=(function&&) _NOEXCEPT;
function& operator=(nullptr_t) _NOEXCEPT;
- template<class _Fp>
- typename enable_if
- <
- __callable<typename decay<_Fp>::type>::value &&
- !is_same<typename remove_reference<_Fp>::type, function>::value,
- function&
- >::type
- operator=(_Fp&&);
+ template<class _Fp, class = _EnableIfCallable<_Fp>>
+ function& operator=(_Fp&&);
~function();
@@ -1854,13 +1851,8 @@ function<_Rp(_ArgTypes...)>::operator=(n
}
template<class _Rp, class ..._ArgTypes>
-template <class _Fp>
-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
+template <class _Fp, class>
+function<_Rp(_ArgTypes...)>&
function<_Rp(_ArgTypes...)>::operator=(_Fp&& __f)
{
function(_VSTD::forward<_Fp>(__f)).swap(*this);
Modified: libcxx/branches/release_50/include/type_traits
URL: http://llvm.org/viewvc/llvm-project/libcxx/branches/release_50/include/type_traits?rev=318835&r1=318834&r2=318835&view=diff
==============================================================================
--- libcxx/branches/release_50/include/type_traits (original)
+++ libcxx/branches/release_50/include/type_traits Wed Nov 22 06:45:26 2017
@@ -4339,8 +4339,8 @@ struct __invokable_r
using _Result = decltype(
_VSTD::__invoke(_VSTD::declval<_Fp>(), _VSTD::declval<_Args>()...));
- static const bool value =
- conditional<
+ using type =
+ typename conditional<
!is_same<_Result, __nat>::value,
typename conditional<
is_void<_Ret>::value,
@@ -4348,7 +4348,8 @@ struct __invokable_r
is_convertible<_Result, _Ret>
>::type,
false_type
- >::type::value;
+ >::type;
+ static const bool value = type::value;
};
template <class _Fp, class ..._Args>
Modified: libcxx/branches/release_50/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F_incomplete.pass.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/branches/release_50/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F_incomplete.pass.cpp?rev=318835&r1=318834&r2=318835&view=diff
==============================================================================
--- libcxx/branches/release_50/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F_incomplete.pass.cpp (original)
+++ libcxx/branches/release_50/test/std/utilities/function.objects/func.wrap/func.wrap.func/func.wrap.func.con/F_incomplete.pass.cpp Wed Nov 22 06:45:26 2017
@@ -16,6 +16,7 @@
// Allow incomplete argument types in the __is_callable check
#include <functional>
+#include <cassert>
struct X{
typedef std::function<void(X&)> callback_type;
@@ -24,6 +25,40 @@ private:
callback_type _cb;
};
-int main()
+struct IncompleteReturnType {
+ 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);
+ }
+ {
+ IncompleteReturnType Empty;
+ IncompleteReturnType X2 = Empty;
+ assert(!X2.fn);
+ }
+}
+
+int main() {
+ test_pr34298();
}
More information about the cfe-commits
mailing list