aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2019-12-03 09:20:18 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2019-12-03 09:20:18 +0100
commite0daa2c86b74364a8ae13fc8e3f4a06c48139719 (patch)
tree506b6dc9336252d86b95701bfda9102c64cc9c6f /gcc
parent5558a0da3248524d5fc081dc0580ab4f9e6eb0e2 (diff)
downloadgcc-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/ChangeLog9
-rw-r--r--gcc/cp/call.c47
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/g++.dg/conversion/ambig4.C14
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" }
+}