Hi!

The changed code in build_new_op_1 ICEs on the following testcase,
because conv is user_conv_p with kind == ck_ambig, for which next_conversion
returns NULL.  It seems in other spots where for user_conv_p we are walking
the conversion chain we also don't assume there must be ck_user, so this
patch just uses the first conv if ck_user is not found (so that the previous
diagnostics about ambiguous conversion is emitted).

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2019-11-29  Jakub Jelinek  <ja...@redhat.com>

        PR c++/92705
        * call.c (build_new_op_1): For user_conv_p, if there is no
        ck_user conversion, use the first one.

        * g++.dg/conversion/ambig4.C: New test.

--- gcc/cp/call.c.jj    2019-11-29 12:50:09.664608879 +0100
+++ gcc/cp/call.c       2019-11-29 14:09:54.311718859 +0100
@@ -6370,8 +6370,12 @@ build_new_op_1 (const op_location_t &loc
          conv = cand->convs[0];
          if (conv->user_conv_p)
            {
-             while (conv->kind != ck_user)
-               conv = next_conversion (conv);
+             for (conversion *t = conv; t; t = next_conversion (t))
+               if (t->kind == ck_user)
+                 {
+                   conv = t;
+                   break;
+                 }
              arg1 = convert_like (conv, arg1, complain);
            }
 
@@ -6380,8 +6384,12 @@ build_new_op_1 (const op_location_t &loc
              conv = cand->convs[1];
              if (conv->user_conv_p)
                {
-                 while (conv->kind != ck_user)
-                   conv = next_conversion (conv);
+                 for (conversion *t = conv; t; t = next_conversion (t))
+                   if (t->kind == ck_user)
+                     {
+                       conv = t;
+                       break;
+                     }
                  arg2 = convert_like (conv, arg2, complain);
                }
            }
@@ -6391,8 +6399,12 @@ build_new_op_1 (const op_location_t &loc
              conv = cand->convs[2];
              if (conv->user_conv_p)
                {
-                 while (conv->kind != ck_user)
-                   conv = next_conversion (conv);
+                 for (conversion *t = conv; t; t = next_conversion (t))
+                   if (t->kind == ck_user)
+                     {
+                       conv = t;
+                       break;
+                     }
                  arg3 = convert_like (conv, arg3, complain);
                }
            }
--- gcc/testsuite/g++.dg/conversion/ambig4.C.jj 2019-11-29 14:11:35.239183848 
+0100
+++ gcc/testsuite/g++.dg/conversion/ambig4.C    2019-11-29 14:11:07.006613238 
+0100
@@ -0,0 +1,14 @@
+// PR c++/92705
+// { dg-do compile }
+
+struct A {};
+struct B {};
+struct C { operator B * (); }; // { dg-message "candidate" }
+struct D { operator B * (); }; // { dg-message "candidate" }
+struct E : C, D { operator A * (); };
+
+void
+foo (E e, int B::* pmf)
+{
+  int i = e->*pmf;     // { dg-error "is ambiguous" }
+}

        Jakub

Reply via email to