Author: ericwf Date: Mon Dec 22 23:54:34 2014 New Revision: 224753 URL: http://llvm.org/viewvc/llvm-project?rev=224753&view=rev Log: 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 Added: libcxx/trunk/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_function_object.pass.cpp Modified: libcxx/trunk/include/functional Modified: libcxx/trunk/include/functional URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/functional?rev=224753&r1=224752&r2=224753&view=diff ============================================================================== --- libcxx/trunk/include/functional (original) +++ libcxx/trunk/include/functional Mon Dec 22 23:54:34 2014 @@ -1863,10 +1863,10 @@ __mu_expand(_Ti& __ti, tuple<_Uj...>& __ template <class _Ti, class ..._Uj> 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) { Added: libcxx/trunk/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_function_object.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_function_object.pass.cpp?rev=224753&view=auto ============================================================================== --- libcxx/trunk/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_function_object.pass.cpp (added) +++ libcxx/trunk/test/std/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_function_object.pass.cpp Mon Dec 22 23:54:34 2014 @@ -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); +} _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
