PR c++/85118 - wrong error with generic lambda and std::bind.
authorJason Merrill <jason@redhat.com>
Wed, 4 Apr 2018 16:42:44 +0000 (12:42 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 4 Apr 2018 16:42:44 +0000 (12:42 -0400)
* call.c (add_template_conv_candidate): Disable if there are any
call operators.

From-SVN: r259090

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic17.C [new file with mode: 0644]

index 8ab7cce4732106ac88d5f477906880e85b0f1b74..f0927e82b36d14b8498ea248cb645c3f78b6bc2e 100644 (file)
@@ -1,5 +1,9 @@
 2018-04-04  Jason Merrill  <jason@redhat.com>
 
+       PR c++/85118 - wrong error with generic lambda and std::bind.
+       * call.c (add_template_conv_candidate): Disable if there are any
+       call operators.
+
        PR c++/85141 - ICE with compound assignment and static member fn.
        * typeck.c (cp_build_modify_expr): Call decay_conversion for RHS of
        compound assignment.
index 901f18c43e6717483e4b65b71d038de607bbcbaa..f81773157b6ee0d012d3589ae4af7bb2e7f1557f 100644 (file)
@@ -3274,10 +3274,10 @@ add_template_conv_candidate (struct z_candidate **candidates, tree tmpl,
                             tree return_type, tree access_path,
                             tree conversion_path, tsubst_flags_t complain)
 {
-  /* Making this work broke PR 71117, so until the committee resolves core
-     issue 2189, let's disable this candidate if there are any viable call
+  /* Making this work broke PR 71117 and 85118, so until the committee resolves
+     core issue 2189, let's disable this candidate if there are any call
      operators.  */
-  if (any_strictly_viable (*candidates))
+  if (*candidates)
     return NULL;
 
   return
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic17.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic17.C
new file mode 100644 (file)
index 0000000..4a7392f
--- /dev/null
@@ -0,0 +1,125 @@
+// PR c++/85118
+// { dg-do compile { target c++14 } }
+
+namespace std
+{
+  template<typename _Tp>
+    struct remove_const
+    { typedef _Tp type; };
+
+  template<typename _Tp>
+    struct remove_const<_Tp const>
+    { typedef _Tp type; };
+
+
+  template<typename _Tp>
+    struct remove_volatile
+    { typedef _Tp type; };
+
+  template<typename _Tp>
+    struct remove_volatile<_Tp volatile>
+    { typedef _Tp type; };
+
+
+  template<typename _Tp>
+    struct remove_cv
+    {
+      typedef typename
+      remove_const<typename remove_volatile<_Tp>::type>::type type;
+    };
+
+  template<typename _Tp>
+    struct remove_reference
+    { typedef _Tp type; };
+
+  template<typename _Tp>
+    struct remove_reference<_Tp&>
+    { typedef _Tp type; };
+
+  template<typename _Tp>
+    struct remove_reference<_Tp&&>
+    { typedef _Tp type; };
+
+  template<typename _Tp>
+    struct decay
+    {
+      using type = typename remove_reference<typename remove_const<_Tp>::type>::type;
+    };
+
+  template<typename _Tp>
+    _Tp&&
+    declval() noexcept;
+
+  template<typename _Tp>
+    constexpr _Tp&&
+    forward(typename std::remove_reference<_Tp>::type& __t) noexcept
+    { return static_cast<_Tp&&>(__t); }
+
+
+  template<typename _Arg>
+    struct _Mu
+    {
+      template<typename _CVArg, typename _Tuple>
+         _CVArg&&
+         operator()(_CVArg&& __arg, _Tuple&) const volatile
+         { return std::forward<_CVArg>(__arg); }
+    };
+
+   template<typename _Functor, typename _Bound_args>
+    struct _Bind
+    {
+      _Functor _M_f;
+      _Bound_args _M_bound_args;
+
+      template<typename _Args, typename _Result
+         = decltype( std::declval<_Functor&>()(
+               _Mu<_Bound_args>()( std::declval<_Bound_args&>(),
+              std::declval<_Args&>() ) ) )>
+         _Result
+      operator()(_Args&& __args) { return {}; }
+
+      template<typename _Args, typename _Result
+         = decltype( std::declval<volatile _Functor&>()(
+               _Mu<_Bound_args>()( std::declval<volatile _Bound_args&>(),
+              std::declval<_Args&>() ) ) )>
+         _Result
+         operator()(_Args&& __args) volatile;
+
+    };
+
+  template<typename _Func, typename _BoundArgs>
+    _Bind<typename decay<_Func>::type, typename decay<_BoundArgs>::type>
+    bind(_Func&& __f, _BoundArgs&& __args)
+    {
+      return {
+        std::forward<_Func>(__f),
+          std::forward<_BoundArgs>(__args)
+      };
+    }
+
+} // namespace std
+
+
+template <typename T>
+bool isOneOf(const T& )
+{
+    return false;
+}
+
+template <typename T, typename FirstType, typename... Tail>
+bool isOneOf(const T& t, const FirstType& firstValue, const Tail&... tail)
+{
+    return t == firstValue || isOneOf(t, tail...);
+}
+
+int main()
+{
+    const auto isOneOfHelper = [](auto&&... params)
+    {
+      return isOneOf(std::forward<decltype(params)>(params)...);
+    };
+
+    auto isO = std::bind(isOneOfHelper, 'o');
+
+    isO('o');
+}