[C++] PR c++/92745 - bogus error when initializing array of vectors.

Message ID 20191220202752.GE3116@redhat.com
State New
Headers show
Series
  • [C++] PR c++/92745 - bogus error when initializing array of vectors.
Related show

Commit Message

Marek Polacek Dec. 20, 2019, 8:27 p.m.
In r268428 I changed reshape_init_r in such a way that when it sees
a nested { } in a CONSTRUCTOR with missing braces, it just returns
the initializer:
+     else if (COMPOUND_LITERAL_P (stripped_init)
...
+         ++d->cur;
+         gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));
+         return init;

But as this test shows, that's incorrect: if TYPE is an array, we need
to proceed to reshape_init_array_1 which will iterate over the array
initializers:
 6006   /* Loop until there are no more initializers.  */
 6007   for (index = 0;
 6008        d->cur != d->end && (!sized_array_p || index <= max_index_cst);
 6009        ++index)
 6010     {
and update d.cur accordingly.  In other words, when reshape_init gets

{{col[0][0], col[1][0], col[2][0], col[3][0]},
 {col[0][1], col[1][1], col[2][1], col[3][1]},
 {col[0][2], col[1][2], col[2][2], col[3][2]},
 {col[0][3], col[1][3], col[2][3], col[3][3]}}

we recurse on the first element:
  {col[0][0], col[1][0], col[2][0], col[3][0]}
and we can't just move d.cur to point to
  {col[0][1], col[1][1], col[2][1], col[3][1]}
and return; we need to iterate, so that d.cur ends up being properly
updated, and after all initializers have been seen, points to d.end.
Currently we skip the loop, wherefore we hit this:

 6502   /* Make sure all the element of the constructor were used. Otherwise,
 6503      issue an error about exceeding initializers.  */
 6504   if (d.cur != d.end)
 6505     {
 6506       if (complain & tf_error)
 6507         error ("too many initializers for %qT", type);
 6508       return error_mark_node;
 6509     }

Bootstrapped/regtested on x86_64-linux, built cmcstl2, ok for trunk
and branches?

2019-12-20  Marek Polacek  <polacek@redhat.com>

	PR c++/92745 - bogus error when initializing array of vectors.
	* decl.c (reshape_init_r): For a nested compound literal, do
	call reshape_init_{class,array,vector}.

	* g++.dg/cpp0x/initlist118.C: New test.

Comments

Jason Merrill Dec. 20, 2019, 10:54 p.m. | #1
On 12/20/19 3:27 PM, Marek Polacek wrote:
> In r268428 I changed reshape_init_r in such a way that when it sees

> a nested { } in a CONSTRUCTOR with missing braces, it just returns

> the initializer:

> +     else if (COMPOUND_LITERAL_P (stripped_init)

> ...

> +         ++d->cur;

> +         gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));

> +         return init;

> 

> But as this test shows, that's incorrect: if TYPE is an array, we need

> to proceed to reshape_init_array_1 which will iterate over the array

> initializers:

>   6006   /* Loop until there are no more initializers.  */

>   6007   for (index = 0;

>   6008        d->cur != d->end && (!sized_array_p || index <= max_index_cst);

>   6009        ++index)

>   6010     {

> and update d.cur accordingly.  In other words, when reshape_init gets

> 

> {{col[0][0], col[1][0], col[2][0], col[3][0]},

>   {col[0][1], col[1][1], col[2][1], col[3][1]},

>   {col[0][2], col[1][2], col[2][2], col[3][2]},

>   {col[0][3], col[1][3], col[2][3], col[3][3]}}

> 

> we recurse on the first element:

>    {col[0][0], col[1][0], col[2][0], col[3][0]}

> and we can't just move d.cur to point to

>    {col[0][1], col[1][1], col[2][1], col[3][1]}

> and return; we need to iterate, so that d.cur ends up being properly

> updated, and after all initializers have been seen, points to d.end.

> Currently we skip the loop, wherefore we hit this:

> 

>   6502   /* Make sure all the element of the constructor were used. Otherwise,

>   6503      issue an error about exceeding initializers.  */

>   6504   if (d.cur != d.end)

>   6505     {

>   6506       if (complain & tf_error)

>   6507         error ("too many initializers for %qT", type);

>   6508       return error_mark_node;

>   6509     }

> 

> Bootstrapped/regtested on x86_64-linux, built cmcstl2, ok for trunk

> and branches?


OK.

> 2019-12-20  Marek Polacek  <polacek@redhat.com>

> 

> 	PR c++/92745 - bogus error when initializing array of vectors.

> 	* decl.c (reshape_init_r): For a nested compound literal, do

> 	call reshape_init_{class,array,vector}.

> 

> 	* g++.dg/cpp0x/initlist118.C: New test.

> 

> diff --git gcc/cp/decl.c gcc/cp/decl.c

> index 7d4c947fb58..c15cbfa3bd3 100644

> --- gcc/cp/decl.c

> +++ gcc/cp/decl.c

> @@ -6399,14 +6399,13 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,

>   	       by the front end.  Here we have e.g. {.__pfn=0B, .__delta=0},

>   	       which is missing outermost braces.  We should warn below, and

>   	       one of the routines below will wrap it in additional { }.  */;

> -	  /* For a nested compound literal, there is no need to reshape since

> -	     we called reshape_init in finish_compound_literal, before calling

> -	     digest_init.  */

> -	  else if (COMPOUND_LITERAL_P (stripped_init)

> -		   /* Similarly, a CONSTRUCTOR of the target's type is a

> -		      previously digested initializer.  */

> -		   || same_type_ignoring_top_level_qualifiers_p (type,

> -								 init_type))

> +	  /* For a nested compound literal, proceed to specialized routines,

> +	     to handle initialization of arrays and similar.  */

> +	  else if (COMPOUND_LITERAL_P (stripped_init))

> +	    gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));

> +	  /* A CONSTRUCTOR of the target's type is a previously

> +	     digested initializer.  */

> +	  else if (same_type_ignoring_top_level_qualifiers_p (type, init_type))

>   	    {

>   	      ++d->cur;

>   	      gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));

> diff --git gcc/testsuite/g++.dg/cpp0x/initlist118.C gcc/testsuite/g++.dg/cpp0x/initlist118.C

> new file mode 100644

> index 00000000000..2e1b96953e3

> --- /dev/null

> +++ gcc/testsuite/g++.dg/cpp0x/initlist118.C

> @@ -0,0 +1,25 @@

> +// PR c++/92745 - bogus error when initializing array of vectors.

> +// { dg-do compile { target c++11 } }

> +

> +template <typename a, int b> struct c {

> +  typedef a d[b];

> +};

> +

> +template <typename a, int b> struct array {

> +  typename c<a, b>::d e;

> +  a operator[](long);

> +};

> +

> +template<class T>

> +using vec4_t __attribute__((vector_size(4*sizeof(T)))) = float;

> +

> +array<vec4_t<float>, 4>

> +transpose(array<vec4_t<float>, 4> col)

> +{

> +  array<vec4_t<float>, 4>

> +    ret{vec4_t<float>{col[0][0], col[1][0], col[2][0], col[3][0]},

> +        vec4_t<float>{col[0][1], col[1][1], col[2][1], col[3][1]},

> +        vec4_t<float>{col[0][2], col[1][2], col[2][2], col[3][2]},

> +        vec4_t<float>{col[0][3], col[1][3], col[2][3], col[3][3]}};

> +  return ret;

> +}

>
Jason Merrill Dec. 20, 2019, 10:56 p.m. | #2
On 12/20/19 3:27 PM, Marek Polacek wrote:
> In r268428 I changed reshape_init_r in such a way that when it sees

> a nested { } in a CONSTRUCTOR with missing braces, it just returns

> the initializer:

> +     else if (COMPOUND_LITERAL_P (stripped_init)

> ...

> +         ++d->cur;

> +         gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));

> +         return init;

> 

> But as this test shows, that's incorrect: if TYPE is an array, we need

> to proceed to reshape_init_array_1 which will iterate over the array

> initializers:

>   6006   /* Loop until there are no more initializers.  */

>   6007   for (index = 0;

>   6008        d->cur != d->end && (!sized_array_p || index <= max_index_cst);

>   6009        ++index)

>   6010     {

> and update d.cur accordingly.  In other words, when reshape_init gets

> 

> {{col[0][0], col[1][0], col[2][0], col[3][0]},

>   {col[0][1], col[1][1], col[2][1], col[3][1]},

>   {col[0][2], col[1][2], col[2][2], col[3][2]},

>   {col[0][3], col[1][3], col[2][3], col[3][3]}}

> 

> we recurse on the first element:

>    {col[0][0], col[1][0], col[2][0], col[3][0]}

> and we can't just move d.cur to point to

>    {col[0][1], col[1][1], col[2][1], col[3][1]}

> and return; we need to iterate, so that d.cur ends up being properly

> updated, and after all initializers have been seen, points to d.end.

> Currently we skip the loop, wherefore we hit this:

> 

>   6502   /* Make sure all the element of the constructor were used. Otherwise,

>   6503      issue an error about exceeding initializers.  */

>   6504   if (d.cur != d.end)

>   6505     {

>   6506       if (complain & tf_error)

>   6507         error ("too many initializers for %qT", type);

>   6508       return error_mark_node;

>   6509     }

> 

> Bootstrapped/regtested on x86_64-linux, built cmcstl2, ok for trunk

> and branches?

> 

> 2019-12-20  Marek Polacek  <polacek@redhat.com>

> 

> 	PR c++/92745 - bogus error when initializing array of vectors.

> 	* decl.c (reshape_init_r): For a nested compound literal, do

> 	call reshape_init_{class,array,vector}.

> 

> 	* g++.dg/cpp0x/initlist118.C: New test.

> 

> diff --git gcc/cp/decl.c gcc/cp/decl.c

> index 7d4c947fb58..c15cbfa3bd3 100644

> --- gcc/cp/decl.c

> +++ gcc/cp/decl.c

> @@ -6399,14 +6399,13 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,

>   	       by the front end.  Here we have e.g. {.__pfn=0B, .__delta=0},

>   	       which is missing outermost braces.  We should warn below, and

>   	       one of the routines below will wrap it in additional { }.  */;

> -	  /* For a nested compound literal, there is no need to reshape since

> -	     we called reshape_init in finish_compound_literal, before calling

> -	     digest_init.  */

> -	  else if (COMPOUND_LITERAL_P (stripped_init)

> -		   /* Similarly, a CONSTRUCTOR of the target's type is a

> -		      previously digested initializer.  */

> -		   || same_type_ignoring_top_level_qualifiers_p (type,

> -								 init_type))

> +	  /* For a nested compound literal, proceed to specialized routines,

> +	     to handle initialization of arrays and similar.  */

> +	  else if (COMPOUND_LITERAL_P (stripped_init))

> +	    gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));

> +	  /* A CONSTRUCTOR of the target's type is a previously

> +	     digested initializer.  */

> +	  else if (same_type_ignoring_top_level_qualifiers_p (type, init_type))

>   	    {

>   	      ++d->cur;

>   	      gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));


Incidentally, asserting !BRACE_ENCLOSED_INITIALIZER_P seems pretty 
pointless, since that checks for init_list_type_node, and a compound 
literal won't have that type, nor will we see that type if we just 
checked that it's something else.

Jason
Marek Polacek Dec. 20, 2019, 11:22 p.m. | #3
On Fri, Dec 20, 2019 at 05:56:39PM -0500, Jason Merrill wrote:
> On 12/20/19 3:27 PM, Marek Polacek wrote:

> > In r268428 I changed reshape_init_r in such a way that when it sees

> > a nested { } in a CONSTRUCTOR with missing braces, it just returns

> > the initializer:

> > +     else if (COMPOUND_LITERAL_P (stripped_init)

> > ...

> > +         ++d->cur;

> > +         gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));

> > +         return init;

> > 

> > But as this test shows, that's incorrect: if TYPE is an array, we need

> > to proceed to reshape_init_array_1 which will iterate over the array

> > initializers:

> >   6006   /* Loop until there are no more initializers.  */

> >   6007   for (index = 0;

> >   6008        d->cur != d->end && (!sized_array_p || index <= max_index_cst);

> >   6009        ++index)

> >   6010     {

> > and update d.cur accordingly.  In other words, when reshape_init gets

> > 

> > {{col[0][0], col[1][0], col[2][0], col[3][0]},

> >   {col[0][1], col[1][1], col[2][1], col[3][1]},

> >   {col[0][2], col[1][2], col[2][2], col[3][2]},

> >   {col[0][3], col[1][3], col[2][3], col[3][3]}}

> > 

> > we recurse on the first element:

> >    {col[0][0], col[1][0], col[2][0], col[3][0]}

> > and we can't just move d.cur to point to

> >    {col[0][1], col[1][1], col[2][1], col[3][1]}

> > and return; we need to iterate, so that d.cur ends up being properly

> > updated, and after all initializers have been seen, points to d.end.

> > Currently we skip the loop, wherefore we hit this:

> > 

> >   6502   /* Make sure all the element of the constructor were used. Otherwise,

> >   6503      issue an error about exceeding initializers.  */

> >   6504   if (d.cur != d.end)

> >   6505     {

> >   6506       if (complain & tf_error)

> >   6507         error ("too many initializers for %qT", type);

> >   6508       return error_mark_node;

> >   6509     }

> > 

> > Bootstrapped/regtested on x86_64-linux, built cmcstl2, ok for trunk

> > and branches?

> > 

> > 2019-12-20  Marek Polacek  <polacek@redhat.com>

> > 

> > 	PR c++/92745 - bogus error when initializing array of vectors.

> > 	* decl.c (reshape_init_r): For a nested compound literal, do

> > 	call reshape_init_{class,array,vector}.

> > 

> > 	* g++.dg/cpp0x/initlist118.C: New test.

> > 

> > diff --git gcc/cp/decl.c gcc/cp/decl.c

> > index 7d4c947fb58..c15cbfa3bd3 100644

> > --- gcc/cp/decl.c

> > +++ gcc/cp/decl.c

> > @@ -6399,14 +6399,13 @@ reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,

> >   	       by the front end.  Here we have e.g. {.__pfn=0B, .__delta=0},

> >   	       which is missing outermost braces.  We should warn below, and

> >   	       one of the routines below will wrap it in additional { }.  */;

> > -	  /* For a nested compound literal, there is no need to reshape since

> > -	     we called reshape_init in finish_compound_literal, before calling

> > -	     digest_init.  */

> > -	  else if (COMPOUND_LITERAL_P (stripped_init)

> > -		   /* Similarly, a CONSTRUCTOR of the target's type is a

> > -		      previously digested initializer.  */

> > -		   || same_type_ignoring_top_level_qualifiers_p (type,

> > -								 init_type))

> > +	  /* For a nested compound literal, proceed to specialized routines,

> > +	     to handle initialization of arrays and similar.  */

> > +	  else if (COMPOUND_LITERAL_P (stripped_init))

> > +	    gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));

> > +	  /* A CONSTRUCTOR of the target's type is a previously

> > +	     digested initializer.  */

> > +	  else if (same_type_ignoring_top_level_qualifiers_p (type, init_type))

> >   	    {

> >   	      ++d->cur;

> >   	      gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));

> 

> Incidentally, asserting !BRACE_ENCLOSED_INITIALIZER_P seems pretty

> pointless, since that checks for init_list_type_node, and a compound literal

> won't have that type, nor will we see that type if we just checked that it's

> something else.


True, would an obvious patch to remove that assert be OK?

--
Marek Polacek • Red Hat, Inc. • 300 A St, Boston, MA
Jason Merrill Dec. 25, 2019, 11:49 p.m. | #4
On Fri, Dec 20, 2019, 6:22 PM Marek Polacek <polacek@redhat.com> wrote:

> On Fri, Dec 20, 2019 at 05:56:39PM -0500, Jason Merrill wrote:

> > On 12/20/19 3:27 PM, Marek Polacek wrote:

> > > In r268428 I changed reshape_init_r in such a way that when it sees

> > > a nested { } in a CONSTRUCTOR with missing braces, it just returns

> > > the initializer:

> > > +     else if (COMPOUND_LITERAL_P (stripped_init)

> > > ...

> > > +         ++d->cur;

> > > +         gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));

> > > +         return init;

> > >

> > > But as this test shows, that's incorrect: if TYPE is an array, we need

> > > to proceed to reshape_init_array_1 which will iterate over the array

> > > initializers:

> > >   6006   /* Loop until there are no more initializers.  */

> > >   6007   for (index = 0;

> > >   6008        d->cur != d->end && (!sized_array_p || index <=

> max_index_cst);

> > >   6009        ++index)

> > >   6010     {

> > > and update d.cur accordingly.  In other words, when reshape_init gets

> > >

> > > {{col[0][0], col[1][0], col[2][0], col[3][0]},

> > >   {col[0][1], col[1][1], col[2][1], col[3][1]},

> > >   {col[0][2], col[1][2], col[2][2], col[3][2]},

> > >   {col[0][3], col[1][3], col[2][3], col[3][3]}}

> > >

> > > we recurse on the first element:

> > >    {col[0][0], col[1][0], col[2][0], col[3][0]}

> > > and we can't just move d.cur to point to

> > >    {col[0][1], col[1][1], col[2][1], col[3][1]}

> > > and return; we need to iterate, so that d.cur ends up being properly

> > > updated, and after all initializers have been seen, points to d.end.

> > > Currently we skip the loop, wherefore we hit this:

> > >

> > >   6502   /* Make sure all the element of the constructor were used.

> Otherwise,

> > >   6503      issue an error about exceeding initializers.  */

> > >   6504   if (d.cur != d.end)

> > >   6505     {

> > >   6506       if (complain & tf_error)

> > >   6507         error ("too many initializers for %qT", type);

> > >   6508       return error_mark_node;

> > >   6509     }

> > >

> > > Bootstrapped/regtested on x86_64-linux, built cmcstl2, ok for trunk

> > > and branches?

> > >

> > > 2019-12-20  Marek Polacek  <polacek@redhat.com>

> > >

> > >     PR c++/92745 - bogus error when initializing array of vectors.

> > >     * decl.c (reshape_init_r): For a nested compound literal, do

> > >     call reshape_init_{class,array,vector}.

> > >

> > >     * g++.dg/cpp0x/initlist118.C: New test.

> > >

> > > diff --git gcc/cp/decl.c gcc/cp/decl.c

> > > index 7d4c947fb58..c15cbfa3bd3 100644

> > > --- gcc/cp/decl.c

> > > +++ gcc/cp/decl.c

> > > @@ -6399,14 +6399,13 @@ reshape_init_r (tree type, reshape_iter *d,

> bool first_initializer_p,

> > >            by the front end.  Here we have e.g. {.__pfn=0B,

> .__delta=0},

> > >            which is missing outermost braces.  We should warn below,

> and

> > >            one of the routines below will wrap it in additional { }.

> */;

> > > -     /* For a nested compound literal, there is no need to reshape

> since

> > > -        we called reshape_init in finish_compound_literal, before

> calling

> > > -        digest_init.  */

> > > -     else if (COMPOUND_LITERAL_P (stripped_init)

> > > -              /* Similarly, a CONSTRUCTOR of the target's type is a

> > > -                 previously digested initializer.  */

> > > -              || same_type_ignoring_top_level_qualifiers_p (type,

> > > -

> init_type))

> > > +     /* For a nested compound literal, proceed to specialized

> routines,

> > > +        to handle initialization of arrays and similar.  */

> > > +     else if (COMPOUND_LITERAL_P (stripped_init))

> > > +       gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));

> > > +     /* A CONSTRUCTOR of the target's type is a previously

> > > +        digested initializer.  */

> > > +     else if (same_type_ignoring_top_level_qualifiers_p (type,

> init_type))

> > >         {

> > >           ++d->cur;

> > >           gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));

> >

> > Incidentally, asserting !BRACE_ENCLOSED_INITIALIZER_P seems pretty

> > pointless, since that checks for init_list_type_node, and a compound

> literal

> > won't have that type, nor will we see that type if we just checked that

> it's

> > something else.

>

> True, would an obvious patch to remove that assert be OK?

>


Yes.

--
> Marek Polacek • Red Hat, Inc. • 300 A St, Boston, MA

>

>
Jakub Jelinek Dec. 29, 2019, 11:50 p.m. | #5
On Fri, Dec 20, 2019 at 06:22:10PM -0500, Marek Polacek wrote:
> > > 2019-12-20  Marek Polacek  <polacek@redhat.com>

> > > 

> > > 	PR c++/92745 - bogus error when initializing array of vectors.

> > > 	* decl.c (reshape_init_r): For a nested compound literal, do

> > > 	call reshape_init_{class,array,vector}.

> > > 

> > > 	* g++.dg/cpp0x/initlist118.C: New test.


I've missed that the testcase FAILs on i686-linux, with
/home/jakub/src/gcc/gcc/testsuite/g++.dg/cpp0x/initlist118.C: In function 'array<__vector(4) float, 4> transpose(array<__vector(4) float, 4>)':
/home/jakub/src/gcc/gcc/testsuite/g++.dg/cpp0x/initlist118.C:20:28: warning: SSE vector return without SSE enabled changes the ABI [-Wpsabi]
/home/jakub/src/gcc/gcc/testsuite/g++.dg/cpp0x/initlist118.C:17:1: note: the ABI for passing parameters with 16-byte alignment has changed in GCC 4.6
FAIL: g++.dg/cpp0x/initlist118.C  -std=c++11 (test for excess errors)
Excess errors:
/home/jakub/src/gcc/gcc/testsuite/g++.dg/cpp0x/initlist118.C:20:28: warning: SSE vector return without SSE enabled changes the ABI [-Wpsabi]
etc.

Fixed thusly, tested on {x86_64,i686}-linux, committed to trunk as obvious.
The -w in there is for targets which don't use -Wno-psabi for their
ABI warnings.

2019-12-30  Jakub Jelinek  <jakub@redhat.com>

	PR c++/92745
	* g++.dg/cpp0x/initlist118.C: Add -Wno-psabi -w to dg-options.

--- gcc/testsuite/g++.dg/cpp0x/initlist118.C.jj	2019-12-21 00:50:54.405407491 +0100
+++ gcc/testsuite/g++.dg/cpp0x/initlist118.C	2019-12-30 00:15:59.429857194 +0100
@@ -1,5 +1,6 @@
 // PR c++/92745 - bogus error when initializing array of vectors.
 // { dg-do compile { target c++11 } }
+// { dg-options "-Wno-psabi -w" }
 
 template <typename a, int b> struct c {
   typedef a d[b];


	Jakub
Christophe Lyon Jan. 2, 2020, 2:41 p.m. | #6
On Fri, 20 Dec 2019 at 21:28, Marek Polacek <polacek@redhat.com> wrote:

> In r268428 I changed reshape_init_r in such a way that when it sees

> a nested { } in a CONSTRUCTOR with missing braces, it just returns

> the initializer:

> +     else if (COMPOUND_LITERAL_P (stripped_init)

> ...

> +         ++d->cur;

> +         gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));

> +         return init;

>

> But as this test shows, that's incorrect: if TYPE is an array, we need

> to proceed to reshape_init_array_1 which will iterate over the array

> initializers:

>  6006   /* Loop until there are no more initializers.  */

>  6007   for (index = 0;

>  6008        d->cur != d->end && (!sized_array_p || index <=

> max_index_cst);

>  6009        ++index)

>  6010     {

> and update d.cur accordingly.  In other words, when reshape_init gets

>

> {{col[0][0], col[1][0], col[2][0], col[3][0]},

>  {col[0][1], col[1][1], col[2][1], col[3][1]},

>  {col[0][2], col[1][2], col[2][2], col[3][2]},

>  {col[0][3], col[1][3], col[2][3], col[3][3]}}

>

> we recurse on the first element:

>   {col[0][0], col[1][0], col[2][0], col[3][0]}

> and we can't just move d.cur to point to

>   {col[0][1], col[1][1], col[2][1], col[3][1]}

> and return; we need to iterate, so that d.cur ends up being properly

> updated, and after all initializers have been seen, points to d.end.

> Currently we skip the loop, wherefore we hit this:

>

>  6502   /* Make sure all the element of the constructor were used.

> Otherwise,

>  6503      issue an error about exceeding initializers.  */

>  6504   if (d.cur != d.end)

>  6505     {

>  6506       if (complain & tf_error)

>  6507         error ("too many initializers for %qT", type);

>  6508       return error_mark_node;

>  6509     }

>

> Bootstrapped/regtested on x86_64-linux, built cmcstl2, ok for trunk

> and branches?

>

> 2019-12-20  Marek Polacek  <polacek@redhat.com>

>

>         PR c++/92745 - bogus error when initializing array of vectors.

>         * decl.c (reshape_init_r): For a nested compound literal, do

>         call reshape_init_{class,array,vector}.

>

>         * g++.dg/cpp0x/initlist118.C: New test.

>

> Hi,


The new test fails on aarch64:
    g++.dg/cpp0x/initlist118.C  -std=c++14 (internal compiler error)
    g++.dg/cpp0x/initlist118.C  -std=c++14 (test for excess errors)
    g++.dg/cpp0x/initlist118.C  -std=c++17 (internal compiler error)
    g++.dg/cpp0x/initlist118.C  -std=c++17 (test for excess errors)
    g++.dg/cpp0x/initlist118.C  -std=c++2a (internal compiler error)
    g++.dg/cpp0x/initlist118.C  -std=c++2a (test for excess errors)

The log says:
during RTL pass: reload
/gcc/testsuite/g++.dg/cpp0x/initlist118.C: In function 'array<__vector(4)
float,
 4> transpose(array<__vector(4) float, 4>)':
/gcc/testsuite/g++.dg/cpp0x/initlist118.C:25:1: internal compiler error:
maximum
 number of generated reload insns per insn achieved (90)
0xd7686f lra_constraints(bool)
        /gcc/lra-constraints.c:4946
0xd5d834 lra(_IO_FILE*)
        /gcc/lra.c:2437
0xd10209 do_reload
        /gcc/ira.c:5526
0xd10209 execute
        /gcc/ira.c:5712
Please submit a full bug report,

Christophe

 diff --git gcc/cp/decl.c gcc/cp/decl.c
> index 7d4c947fb58..c15cbfa3bd3 100644

> --- gcc/cp/decl.c

> +++ gcc/cp/decl.c

> @@ -6399,14 +6399,13 @@ reshape_init_r (tree type, reshape_iter *d, bool

> first_initializer_p,

>                by the front end.  Here we have e.g. {.__pfn=0B,

> .__delta=0},

>                which is missing outermost braces.  We should warn below,

> and

>                one of the routines below will wrap it in additional { }.

> */;

> -         /* For a nested compound literal, there is no need to reshape

> since

> -            we called reshape_init in finish_compound_literal, before

> calling

> -            digest_init.  */

> -         else if (COMPOUND_LITERAL_P (stripped_init)

> -                  /* Similarly, a CONSTRUCTOR of the target's type is a

> -                     previously digested initializer.  */

> -                  || same_type_ignoring_top_level_qualifiers_p (type,

> -

> init_type))

> +         /* For a nested compound literal, proceed to specialized

> routines,

> +            to handle initialization of arrays and similar.  */

> +         else if (COMPOUND_LITERAL_P (stripped_init))

> +           gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));

> +         /* A CONSTRUCTOR of the target's type is a previously

> +            digested initializer.  */

> +         else if (same_type_ignoring_top_level_qualifiers_p (type,

> init_type))

>             {

>               ++d->cur;

>               gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));

> diff --git gcc/testsuite/g++.dg/cpp0x/initlist118.C

> gcc/testsuite/g++.dg/cpp0x/initlist118.C

> new file mode 100644

> index 00000000000..2e1b96953e3

> --- /dev/null

> +++ gcc/testsuite/g++.dg/cpp0x/initlist118.C

> @@ -0,0 +1,25 @@

> +// PR c++/92745 - bogus error when initializing array of vectors.

> +// { dg-do compile { target c++11 } }

> +

> +template <typename a, int b> struct c {

> +  typedef a d[b];

> +};

> +

> +template <typename a, int b> struct array {

> +  typename c<a, b>::d e;

> +  a operator[](long);

> +};

> +

> +template<class T>

> +using vec4_t __attribute__((vector_size(4*sizeof(T)))) = float;

> +

> +array<vec4_t<float>, 4>

> +transpose(array<vec4_t<float>, 4> col)

> +{

> +  array<vec4_t<float>, 4>

> +    ret{vec4_t<float>{col[0][0], col[1][0], col[2][0], col[3][0]},

> +        vec4_t<float>{col[0][1], col[1][1], col[2][1], col[3][1]},

> +        vec4_t<float>{col[0][2], col[1][2], col[2][2], col[3][2]},

> +        vec4_t<float>{col[0][3], col[1][3], col[2][3], col[3][3]}};

> +  return ret;

> +}

>

>
Jakub Jelinek Jan. 2, 2020, 2:45 p.m. | #7
On Thu, Jan 02, 2020 at 03:41:30PM +0100, Christophe Lyon wrote:
> The new test fails on aarch64:

>     g++.dg/cpp0x/initlist118.C  -std=c++14 (internal compiler error)

>     g++.dg/cpp0x/initlist118.C  -std=c++14 (test for excess errors)

>     g++.dg/cpp0x/initlist118.C  -std=c++17 (internal compiler error)

>     g++.dg/cpp0x/initlist118.C  -std=c++17 (test for excess errors)

>     g++.dg/cpp0x/initlist118.C  -std=c++2a (internal compiler error)

>     g++.dg/cpp0x/initlist118.C  -std=c++2a (test for excess errors)

> 

> The log says:

> during RTL pass: reload

> /gcc/testsuite/g++.dg/cpp0x/initlist118.C: In function 'array<__vector(4)

> float,

>  4> transpose(array<__vector(4) float, 4>)':

> /gcc/testsuite/g++.dg/cpp0x/initlist118.C:25:1: internal compiler error:

> maximum

>  number of generated reload insns per insn achieved (90)


That doesn't seem to be a fault of the patch that went in, but either a
backend bug or LRA bug.
So:
> Please submit a full bug report,

...

Thanks.

	Jakub
Christophe Lyon Jan. 2, 2020, 3:04 p.m. | #8
On Thu, 2 Jan 2020 at 15:45, Jakub Jelinek <jakub@redhat.com> wrote:

> On Thu, Jan 02, 2020 at 03:41:30PM +0100, Christophe Lyon wrote:

> > The new test fails on aarch64:

> >     g++.dg/cpp0x/initlist118.C  -std=c++14 (internal compiler error)

> >     g++.dg/cpp0x/initlist118.C  -std=c++14 (test for excess errors)

> >     g++.dg/cpp0x/initlist118.C  -std=c++17 (internal compiler error)

> >     g++.dg/cpp0x/initlist118.C  -std=c++17 (test for excess errors)

> >     g++.dg/cpp0x/initlist118.C  -std=c++2a (internal compiler error)

> >     g++.dg/cpp0x/initlist118.C  -std=c++2a (test for excess errors)

> >

> > The log says:

> > during RTL pass: reload

> > /gcc/testsuite/g++.dg/cpp0x/initlist118.C: In function 'array<__vector(4)

> > float,

> >  4> transpose(array<__vector(4) float, 4>)':

> > /gcc/testsuite/g++.dg/cpp0x/initlist118.C:25:1: internal compiler error:

> > maximum

> >  number of generated reload insns per insn achieved (90)

>

> That doesn't seem to be a fault of the patch that went in, but either a

> backend bug or LRA bug.

> So:

> > Please submit a full bug report,

>


OK, I've filed PR93135.


> ...

>

> Thanks.

>

>         Jakub

>

>

Patch

diff --git gcc/cp/decl.c gcc/cp/decl.c
index 7d4c947fb58..c15cbfa3bd3 100644
--- gcc/cp/decl.c
+++ gcc/cp/decl.c
@@ -6399,14 +6399,13 @@  reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
 	       by the front end.  Here we have e.g. {.__pfn=0B, .__delta=0},
 	       which is missing outermost braces.  We should warn below, and
 	       one of the routines below will wrap it in additional { }.  */;
-	  /* For a nested compound literal, there is no need to reshape since
-	     we called reshape_init in finish_compound_literal, before calling
-	     digest_init.  */
-	  else if (COMPOUND_LITERAL_P (stripped_init)
-		   /* Similarly, a CONSTRUCTOR of the target's type is a
-		      previously digested initializer.  */
-		   || same_type_ignoring_top_level_qualifiers_p (type,
-								 init_type))
+	  /* For a nested compound literal, proceed to specialized routines,
+	     to handle initialization of arrays and similar.  */
+	  else if (COMPOUND_LITERAL_P (stripped_init))
+	    gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));
+	  /* A CONSTRUCTOR of the target's type is a previously
+	     digested initializer.  */
+	  else if (same_type_ignoring_top_level_qualifiers_p (type, init_type))
 	    {
 	      ++d->cur;
 	      gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));
diff --git gcc/testsuite/g++.dg/cpp0x/initlist118.C gcc/testsuite/g++.dg/cpp0x/initlist118.C
new file mode 100644
index 00000000000..2e1b96953e3
--- /dev/null
+++ gcc/testsuite/g++.dg/cpp0x/initlist118.C
@@ -0,0 +1,25 @@ 
+// PR c++/92745 - bogus error when initializing array of vectors.
+// { dg-do compile { target c++11 } }
+
+template <typename a, int b> struct c {
+  typedef a d[b];
+};
+
+template <typename a, int b> struct array {
+  typename c<a, b>::d e;
+  a operator[](long);
+};
+
+template<class T>
+using vec4_t __attribute__((vector_size(4*sizeof(T)))) = float;
+
+array<vec4_t<float>, 4>
+transpose(array<vec4_t<float>, 4> col)
+{
+  array<vec4_t<float>, 4>
+    ret{vec4_t<float>{col[0][0], col[1][0], col[2][0], col[3][0]},
+        vec4_t<float>{col[0][1], col[1][1], col[2][1], col[3][1]},
+        vec4_t<float>{col[0][2], col[1][2], col[2][2], col[3][2]},
+        vec4_t<float>{col[0][3], col[1][3], col[2][3], col[3][3]}};
+  return ret;
+}