This is an archive of the discontinued LLVM Phabricator instance.

[libc++] PR34298: Change std::function constructor and move assignment operator SFINAE checks to allow std::function with an incomplete return type
AbandonedPublic

Authored by EricWF on Aug 24 2017, 4:31 AM.

Details

Summary

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::functions 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.

Diff Detail

Repository
rL LLVM

Event Timeline

arphaman created this revision.Aug 24 2017, 4:31 AM
EricWF edited edge metadata.Aug 27 2017, 2:15 PM

@arphaman Do you mind if I commit my own version of this?

Not at all, go ahead

FYI, I'd like to see this merged into LLVM5 if it's still possible, but it's not super critical

mclow.lists added inline comments.Aug 28 2017, 10:39 AM
test/libcxx/utilities/function.objects/func.require/incomplete_return_type.pass.cpp
1

Is this file in the right place?
If it's supposed to test functionality that is required by the standard, it should go in test/std somewhere.
If it's supposed to test a libc++ extension, then it should go into test/libcxx.

1

Never mind - I missed the "Non-standard extension" bit.

rsmith added a subscriber: rsmith.Aug 28 2017, 10:53 AM
rsmith added inline comments.
test/libcxx/utilities/function.objects/func.require/incomplete_return_type.pass.cpp
17–19

Would it make sense to also check that this struct is copy-constructible? As-is, whether this test tests anything is entirely dependent on what amount to implementation details of the constructor.

mclow.lists added inline comments.Aug 31 2017, 9:39 AM
test/libcxx/utilities/function.objects/func.require/incomplete_return_type.pass.cpp
22

Is copy constructible; can be instantiated.

static_assert( std::is_copy_constructible<IncompleteReturnType>::value, "" );
IncompleteReturnType ir;
assert( ir.fn == nullptr );
EricWF commandeered this revision.Sep 10 2017, 4:17 PM
EricWF edited reviewers, added: arphaman; removed: EricWF.

I committed a different version of this fix in r312890.

Commandeering and closing this review. @arphaman Thanks for the initial patch.

EricWF abandoned this revision.Sep 10 2017, 4:17 PM