diff --git a/llvm/include/llvm/ADT/FunctionExtras.h b/llvm/include/llvm/ADT/FunctionExtras.h --- a/llvm/include/llvm/ADT/FunctionExtras.h +++ b/llvm/include/llvm/ADT/FunctionExtras.h @@ -64,11 +64,16 @@ using EnableUnlessSameType = std::enable_if_t, ThisT>::value>; template -using EnableIfCallable = - std::enable_if_t::value || - std::is_convertible()( - std::declval()...)), - Ret>::value>; +using EnableIfCallable = std::enable_if_t, + std::is_same()(std::declval()...)), + Ret>, + std::is_same()( + std::declval()...)), + Ret>, + std::is_convertible()( + std::declval()...)), + Ret>>::value>; template class UniqueFunctionBase { protected: diff --git a/llvm/unittests/ADT/FunctionExtrasTest.cpp b/llvm/unittests/ADT/FunctionExtrasTest.cpp --- a/llvm/unittests/ADT/FunctionExtrasTest.cpp +++ b/llvm/unittests/ADT/FunctionExtrasTest.cpp @@ -291,4 +291,23 @@ unique_function *()> IncompleteResultPointer; } +// Incomplete function returning an incomplete type +Incomplete incompleteFunction(); +const Incomplete incompleteFunctionConst(); + +// Check that we can assign a callable to a unique_function when the +// callable return value is incomplete. +TEST(UniqueFunctionTest, IncompleteCallableType) { + unique_function IncompleteReturnInCallable{incompleteFunction}; + unique_function IncompleteReturnInCallableConst{ + incompleteFunctionConst}; + unique_function IncompleteReturnInCallableConstConversion{ + incompleteFunction}; +} + +// Define the incomplete function +class Incomplete {}; +Incomplete incompleteFunction() { return {}; } +const Incomplete incompleteFunctionConst() { return {}; } + } // anonymous namespace