[PATCH] D37104: [libc++] PR34298: Change std::function constructor and move assignment operator SFINAE checks to allow std::function with an incomplete return type
Alex Lorenz via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 24 04:31:29 PDT 2017
arphaman created this revision.
This patch fixes PR34298 (https://bugs.llvm.org/show_bug.cgi?id=34298). Since Clang changed in r284549, Clang and libc++ prohibit the use of `std::function` with an incomplete return type, like in the example below:
struct Continuation {
std::function<Continuation ()> fn;
};
This code failed to compile because of the way SFINAE checks were performed in libc++. Essentially when `Continuation` was defining a copy-constructor, it tried to find a matching overload for the copy constructor of `fn`, and thus tried to instantiate `std::function`s `function(_Fp)` constructor with a `std::function<Continuation ()>` substitute for `_Fp`. That constructor did check against `function` in its SFINAE checks, but it did so after trying to invoke `_Fp`. This caused an error while evaluating `__invokable_r` because `Continuation` is incomplete, and the incomplete type checker for `__invokable_r` didn't take `std::function<>` types into account.
This patch ensures that the SFINAE check verify that `_Fp` is not a `std::function` before trying to figure out if `_Fp` is invokable.
Repository:
rL LLVM
https://reviews.llvm.org/D37104
Files:
include/functional
test/libcxx/utilities/function.objects/func.require/incomplete_return_type.pass.cpp
Index: test/libcxx/utilities/function.objects/func.require/incomplete_return_type.pass.cpp
===================================================================
--- /dev/null
+++ test/libcxx/utilities/function.objects/func.require/incomplete_return_type.pass.cpp
@@ -0,0 +1,23 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// Non-standard extension:
+// std::function is allowed to take a function with an incomplete return type.
+
+// [func.require]
+
+#include <functional>
+
+struct IncompleteReturnType {
+ std::function<IncompleteReturnType ()> fn;
+};
+
+int main() {
+ return 0;
+}
Index: include/functional
===================================================================
--- include/functional
+++ include/functional
@@ -1623,7 +1623,10 @@
function(const function&);
function(function&&) _NOEXCEPT;
template<class _Fp, class = typename enable_if<
- __callable<_Fp>::value && !is_same<_Fp, function>::value
+ is_same<typename enable_if<!is_same<_Fp, function>::value>::type,
+ void
+ >::value &&
+ __callable<_Fp>::value
>::type>
function(_Fp);
@@ -1648,8 +1651,11 @@
template<class _Fp>
typename enable_if
<
- __callable<typename decay<_Fp>::type>::value &&
- !is_same<typename remove_reference<_Fp>::type, function>::value,
+ is_same<typename enable_if<
+ !is_same<typename remove_reference<_Fp>::type, function>::value>::type,
+ void
+ >::value &&
+ __callable<typename decay<_Fp>::type>::value,
function&
>::type
operator=(_Fp&&);
@@ -1857,8 +1863,11 @@
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,
+ is_same<typename enable_if<
+ !is_same<typename remove_reference<_Fp>::type, function<_Rp(_ArgTypes...)>>::value>::type,
+ void
+ >::value &&
+ function<_Rp(_ArgTypes...)>::template __callable<typename decay<_Fp>::type>::value,
function<_Rp(_ArgTypes...)>&
>::type
function<_Rp(_ArgTypes...)>::operator=(_Fp&& __f)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D37104.112537.patch
Type: text/x-patch
Size: 2522 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20170824/22a8438d/attachment-0001.bin>
More information about the cfe-commits
mailing list