On 2/13/20 8:56 PM, Marek Polacek wrote:
My P0388R4 patch changed build_array_conv to create an identity
conversion at the start of the conversion chain.

Hmm, an identity conversion of {} suggests that it has a type, which it doesn't in the language. I'm not strongly against it, but what was the reason for this change?

That was a sound change but now we crash in convert_like_real

  7457     case ck_identity:
  7458       if (BRACE_ENCLOSED_INITIALIZER_P (expr))
  7459         {
  7460           int nelts = CONSTRUCTOR_NELTS (expr);
  7461           if (nelts == 0)
  7462             expr = build_value_init (totype, complain);
  7463           else if (nelts == 1)
  7464             expr = CONSTRUCTOR_ELT (expr, 0)->value;
  7465           else
  7466             gcc_unreachable ();  // HERE
  7467         }

Right, this is assuming that any other {} will either be ill-formed or handled by ck_aggr or ck_list. How are we getting here without going through one of those?

in a test like this

   int f (int const (&)[2])
   {
     return f({1, " "});
   }

I considered fixing this when performing overload resolution (clang says
"no matching function for call to 'f'"), but then it occured to me that
we crash in different contexts too, so I'm just turning the assert into
an early return.

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

2020-02-13  Marek Polacek  <pola...@redhat.com>

        PR c++/93712 - ICE with ill-formed array list-initialization.
        * call.c (convert_like_real): Turn an assert into a return.

        * g++.dg/cpp0x/initlist-array11.C: New test.
---
  gcc/cp/call.c                                 |  2 +-
  gcc/testsuite/g++.dg/cpp0x/initlist-array11.C | 10 ++++++++++
  2 files changed, 11 insertions(+), 1 deletion(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist-array11.C

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 51621b7dd87..eba0ed8041d 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -7463,7 +7463,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, 
int argnum,
          else if (nelts == 1)
            expr = CONSTRUCTOR_ELT (expr, 0)->value;
          else
-           gcc_unreachable ();
+           return error_mark_node;
        }
        expr = mark_use (expr, /*rvalue_p=*/!convs->rvaluedness_matches_p,
                       /*read_p=*/true, UNKNOWN_LOCATION,
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-array11.C 
b/gcc/testsuite/g++.dg/cpp0x/initlist-array11.C
new file mode 100644
index 00000000000..7e76b588471
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-array11.C
@@ -0,0 +1,10 @@
+// PR c++/93712 - ICE with ill-formed array list-initialization.
+// { dg-do compile { target c++11 } }
+
+int f (const int (&)[2]);
+
+int g ()
+{
+  const int (&r)[2] = {1, "foo"}; // { dg-error "invalid conversion" }
+  return f({1, "foo"}); // { dg-error "invalid conversion" }
+}

base-commit: 1d69147af203d4dcd2270429f90c93f1a37ddfff


Reply via email to