On 11/29/19 6:33 PM, Jakub Jelinek wrote:
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).
It seems like various places could use a function to strip down to the
first ck_user, ck_ambig, ck_list, ck_aggr, or ck_identity conversion
encountered: source_type, the user-defined conversion comparision in
compare_ics, and now here. Mind doing that refactoring? Maybe call it
strip_standard_conversion.
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