Prevent ill-formed instantiation of __invoke_of<...> during the evaluation of a bind expression. Fixes PR22003.
The SFINAE on the function __mu(Fn, Args...) that evaluates nested bind expressions always tries to deduce the return type for Fn(Args...) even when Fn is not a nested bind expression. This can cause hard compile errors when the instantation of Fn(Args...) is ill-formed. This patch prevents the instantation of __invoke_of<Fn, Args...> unless Fn is actually a bind expression. Bug reportand patch from Michel Morin. http://llvm.org/bugs/show_bug.cgi?id=22003 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@224753 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -1863,10 +1863,10 @@ __mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __tuple_indices<_Indx...>)
|
|||||||
|
|
||||||
template <class _Ti, class ..._Uj>
|
template <class _Ti, class ..._Uj>
|
||||||
inline _LIBCPP_INLINE_VISIBILITY
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
typename enable_if
|
typename __lazy_enable_if
|
||||||
<
|
<
|
||||||
is_bind_expression<_Ti>::value,
|
is_bind_expression<_Ti>::value,
|
||||||
typename __invoke_of<_Ti&, _Uj...>::type
|
__invoke_of<_Ti&, _Uj...>
|
||||||
>::type
|
>::type
|
||||||
__mu(_Ti& __ti, tuple<_Uj...>& __uj)
|
__mu(_Ti& __ti, tuple<_Uj...>& __uj)
|
||||||
{
|
{
|
||||||
|
@@ -0,0 +1,49 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// <functional>
|
||||||
|
|
||||||
|
// template<CopyConstructible Fn, CopyConstructible... Types>
|
||||||
|
// unspecified bind(Fn, Types...);
|
||||||
|
// template<Returnable R, CopyConstructible Fn, CopyConstructible... Types>
|
||||||
|
// unspecified bind(Fn, Types...);
|
||||||
|
|
||||||
|
// http://llvm.org/bugs/show_bug.cgi?id=22003
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
struct DummyUnaryFunction
|
||||||
|
{
|
||||||
|
template <typename S>
|
||||||
|
int operator()(S const & s) const { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BadUnaryFunction
|
||||||
|
{
|
||||||
|
template <typename S>
|
||||||
|
constexpr int operator()(S const & s) const
|
||||||
|
{
|
||||||
|
// Trigger a compile error if this function is instantiated.
|
||||||
|
// The constexpr is needed so that it is instantiated while checking
|
||||||
|
// __invoke_of<BadUnaryFunction &, ...>.
|
||||||
|
static_assert(!std::is_same<S, S>::value, "Shit");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
// Check that BadUnaryFunction::operator()(S const &) is not
|
||||||
|
// instantiated when checking if BadUnaryFunction is a nested bind
|
||||||
|
// expression during b(0). See PR22003.
|
||||||
|
auto b = std::bind(DummyUnaryFunction(), BadUnaryFunction());
|
||||||
|
b(0);
|
||||||
|
auto b2 = std::bind<long>(DummyUnaryFunction(), BadUnaryFunction());
|
||||||
|
b2(0);
|
||||||
|
}
|
Reference in New Issue
Block a user