diff options
author | Jason Merrill <jason@redhat.com> | 2019-12-03 09:20:18 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2019-12-03 09:20:18 +0100 |
commit | e0daa2c86b74364a8ae13fc8e3f4a06c48139719 (patch) | |
tree | 506b6dc9336252d86b95701bfda9102c64cc9c6f /gcc | |
parent | 5558a0da3248524d5fc081dc0580ab4f9e6eb0e2 (diff) | |
download | gcc-e0daa2c86b74364a8ae13fc8e3f4a06c48139719.zip gcc-e0daa2c86b74364a8ae13fc8e3f4a06c48139719.tar.gz gcc-e0daa2c86b74364a8ae13fc8e3f4a06c48139719.tar.bz2 |
re PR c++/92705 (ICE: Segmentation fault (in build_new_op_1))
PR c++/92705
* call.c (strip_standard_conversion): New function.
(build_new_op_1): Use it for user_conv_p.
(compare_ics): Likewise.
(source_type): Likewise.
* g++.dg/conversion/ambig4.C: New test.
From-SVN: r278922
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/call.c | 47 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/conversion/ambig4.C | 14 |
4 files changed, 48 insertions, 25 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1565d72..2513bee 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2019-12-03 Jason Merrill <jason@redhat.com> + Jakub Jelinek <jakub@redhat.com> + + PR c++/92705 + * call.c (strip_standard_conversion): New function. + (build_new_op_1): Use it for user_conv_p. + (compare_ics): Likewise. + (source_type): Likewise. + 2019-12-03 Jakub Jelinek <jakub@redhat.com> PR c++/92695 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index acc7e13..062cff4 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -865,6 +865,22 @@ next_conversion (conversion *conv) return conv->u.next; } +/* Strip to the first ck_user, ck_ambig, ck_list, ck_aggr or ck_identity + encountered. */ + +static conversion * +strip_standard_conversion (conversion *conv) +{ + while (conv + && conv->kind != ck_user + && conv->kind != ck_ambig + && conv->kind != ck_list + && conv->kind != ck_aggr + && conv->kind != ck_identity) + conv = next_conversion (conv); + return conv; +} + /* Subroutine of build_aggr_conv: check whether CTOR, a braced-init-list, is a valid aggregate initializer for array type ATYPE. */ @@ -6370,8 +6386,7 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, conv = cand->convs[0]; if (conv->user_conv_p) { - while (conv->kind != ck_user) - conv = next_conversion (conv); + conv = strip_standard_conversion (conv); arg1 = convert_like (conv, arg1, complain); } @@ -6380,8 +6395,7 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, conv = cand->convs[1]; if (conv->user_conv_p) { - while (conv->kind != ck_user) - conv = next_conversion (conv); + conv = strip_standard_conversion (conv); arg2 = convert_like (conv, arg2, complain); } } @@ -6391,8 +6405,7 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, conv = cand->convs[2]; if (conv->user_conv_p) { - while (conv->kind != ck_user) - conv = next_conversion (conv); + conv = strip_standard_conversion (conv); arg3 = convert_like (conv, arg3, complain); } } @@ -10538,17 +10551,8 @@ compare_ics (conversion *ics1, conversion *ics2) if (ics1->user_conv_p || ics1->kind == ck_list || ics1->kind == ck_aggr || ics2->kind == ck_aggr) { - conversion *t1; - conversion *t2; - - for (t1 = ics1; t1 && t1->kind != ck_user; t1 = next_conversion (t1)) - if (t1->kind == ck_ambig || t1->kind == ck_aggr - || t1->kind == ck_list) - break; - for (t2 = ics2; t2 && t2->kind != ck_user; t2 = next_conversion (t2)) - if (t2->kind == ck_ambig || t2->kind == ck_aggr - || t2->kind == ck_list) - break; + conversion *t1 = strip_standard_conversion (ics1); + conversion *t2 = strip_standard_conversion (ics2); if (!t1 || !t2 || t1->kind != t2->kind) return 0; @@ -10956,14 +10960,7 @@ compare_ics (conversion *ics1, conversion *ics2) static tree source_type (conversion *t) { - for (;; t = next_conversion (t)) - { - if (t->kind == ck_user - || t->kind == ck_ambig - || t->kind == ck_identity) - return t->type; - } - gcc_unreachable (); + return strip_standard_conversion (t)->type; } /* Note a warning about preferring WINNER to LOSER. We do this by storing diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index edd1869..307e251 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2019-12-03 Jakub Jelinek <jakub@redhat.com> + PR c++/92705 + * g++.dg/conversion/ambig4.C: New test. + PR c++/92695 * g++.dg/cpp2a/constexpr-virtual14.C: New test. diff --git a/gcc/testsuite/g++.dg/conversion/ambig4.C b/gcc/testsuite/g++.dg/conversion/ambig4.C new file mode 100644 index 0000000..8a77181 --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/ambig4.C @@ -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" } +} |