From 60b3df404e59b3b795858299e8818b1c977f7e50 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Tue, 23 Dec 2014 05:54:34 +0000 Subject: [PATCH] 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 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 --- include/functional | 4 +- .../invoke_function_object.pass.cpp | 49 +++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_function_object.pass.cpp diff --git a/include/functional b/include/functional index 416a9a97..d14b46bb 100644 --- a/include/functional +++ b/include/functional @@ -1863,10 +1863,10 @@ __mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __tuple_indices<_Indx...>) template inline _LIBCPP_INLINE_VISIBILITY -typename enable_if +typename __lazy_enable_if < is_bind_expression<_Ti>::value, - typename __invoke_of<_Ti&, _Uj...>::type + __invoke_of<_Ti&, _Uj...> >::type __mu(_Ti& __ti, tuple<_Uj...>& __uj) { diff --git a/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_function_object.pass.cpp b/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_function_object.pass.cpp new file mode 100644 index 00000000..33bf0185 --- /dev/null +++ b/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_function_object.pass.cpp @@ -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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// unspecified bind(Fn, Types...); +// template +// unspecified bind(Fn, Types...); + +// http://llvm.org/bugs/show_bug.cgi?id=22003 + +#include + +struct DummyUnaryFunction +{ + template + int operator()(S const & s) const { return 0; } +}; + +struct BadUnaryFunction +{ + template + 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. + static_assert(!std::is_same::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(DummyUnaryFunction(), BadUnaryFunction()); + b2(0); +}