re PR c++/92705 (ICE: Segmentation fault (in build_new_op_1))
authorJason Merrill <jason@redhat.com>
Tue, 3 Dec 2019 08:20:18 +0000 (09:20 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 3 Dec 2019 08:20:18 +0000 (09:20 +0100)
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

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/conversion/ambig4.C [new file with mode: 0644]

index 1565d72..2513bee 100644 (file)
@@ -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
index acc7e13..062cff4 100644 (file)
@@ -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
index edd1869..307e251 100644 (file)
@@ -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 (file)
index 0000000..8a77181
--- /dev/null
@@ -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" }
+}