[libcxx] r224753 - Prevent ill-formed instantiation of __invoke_of<...> during the evaluation of a bind expression. Fixes PR22003.

Eric Fiselier eric at efcs.ca
Mon Dec 22 21:54:34 PST 2014


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);
+}





More information about the cfe-commits mailing list