Re: [PATCH 2/3] c++: P1997 array-copy extensions: Initialization [PR103238]

2021-11-27 Thread Jason Merrill via Gcc-patches

On 11/21/21 21:51, Will Wray via Gcc-patches wrote:

This patch implements initializations of arrays from array values.

The first of two 'array-copy' patches, it adds the option -farray-copy
(flag_array_copy) to enable all features of P1997 (copy related or not),
documented as experimental extensions.

It deals with initialization of array variables and member array fields.

Initialization of an array variable from an array of the same type performs
array copy-initialization; elementwise move or copy from an rvalue or lvalue
array respectively, in index order from begin to end. The existing code path
for a structured binding declaration with array initializer, auto[e...]{a};
performs the same array copy-initialization (as a special case superpower).
Borrowing from that, this was a relatively quick and easy change.

Initialization of member arrays proved much more difficult to do in general.
I resorted to trial and error, running gcc in gdb with test cases to work out
where and what to change, until eventually converging on this set of changes.

One starting point was the C special case of char array initialization from
string literals (as char array lvalue constants). However, a long-standing
bug in designated initialization of char arrays by string literals blocked
the task of extending this special case to general array type initializers.
A bugfix patch was separated out, to be merged ahead of these patches:

 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55227
 https://gcc.gnu.org/pipermail/gcc-patches/2021-November/584897.html

Other cases to consider, array initializations:

 * by optionally brace-enclosed or paren-enclosed array values
 * by possibly-designated array-valued aggregate initializers
   (within possibly-elided braced init-lists)
 * by brace or paren-enclosed array values in member initialization lists
 * by array-valued member initializers

The patch adds tests for these cases, and for inner initializations of nested
array elements of array type.

The work has diverged in details from the P1997 wording, including catching
up with C++20 changes such as parenthesised initialization of aggregates.
The paper will be revised to reflect the implementation experience.

It is likely that there are omissions, errors in the conditions or that changed
code is inappropriate. For example, I inserted a new call to build_array_copy
in typeck2.c:digest_init_r which may not be correct for move-enabled elements.
Please review carefully with this in mind and suggest test cases to exercise.


You would want a testcase with an array of move-only type, e.g. (untested)

struct A { A(int); A(A&&); int i; };
using Ar = A[2];
struct B { A a[2]; };
B b = { Ar{1,2} }; // should move

I don't think the new call to build_array_copy needs to change, but it's 
good to test.



PR c++/103238

gcc/c-family/ChangeLog:

* c-common.c (complete_array_type): Accept array type initial_value.
* c.opt: New option -farray-copy "experimental extensions for P1997".

gcc/cp/ChangeLog:

* decl.c (do_aggregate_paren_init): Accept single array type init.
(maybe_deduce_size_from_array_init): Include same-type array inits,
or complain for not same-type arrays.
(reshape_init_r): Extend string-literal handling to all array types.
* init.c (build_aggr_init): Follow existing path for array rhs.
* typeck.c (cp_build_modify_expr): Follow path for synthetic op=.
* typeck2.c (digest_init_r): Add call to build_array_copy for
same-type arrays ('copy' feels wrong for move-eligible rhs).

gcc/ChangeLog:

* doc/invoke.texi: -farray-copy help info documentation.

gcc/testsuite/ChangeLog:

* g++.dg/init/array-copy1.C: New test. Variable init 'before' XFAILs
* g++.dg/init/array-copy2.C: New test. Variable init 'after' PASSes
* g++.dg/init/array-copy3.C: New test. Member init 'before' XFAILs
* g++.dg/init/array-copy4.C: New test. Member init 'after' PASSes
* g++.dg/init/array-copy5.C: New test. Member nsdmi & desig XFAILs
* g++.dg/init/array-copy6.C: New test. Member nsdmi & desig PASSes
---
  gcc/c-family/c-common.c |  5 +++
  gcc/c-family/c.opt  |  4 ++
  gcc/cp/decl.c   | 61 -
  gcc/cp/init.c   |  6 ++-
  gcc/cp/typeck.c |  9 +++--
  gcc/cp/typeck2.c| 30 +++
  gcc/doc/invoke.texi |  6 +++
  gcc/testsuite/g++.dg/init/array-copy1.C | 66 
  gcc/testsuite/g++.dg/init/array-copy2.C | 68 +
  gcc/testsuite/g++.dg/init/array-copy3.C | 41 
  gcc/testsuite/g++.dg/init/array-copy4.C | 42 
  gcc/testsuite/g++.dg/init/array-copy5.C | 36 +
  gcc/testsuite/g++.dg/init/array-copy6.C | 51 

[PATCH 2/3] c++: P1997 array-copy extensions: Initialization [PR103238]

2021-11-21 Thread Will Wray via Gcc-patches
This patch implements initializations of arrays from array values.

The first of two 'array-copy' patches, it adds the option -farray-copy
(flag_array_copy) to enable all features of P1997 (copy related or not),
documented as experimental extensions.

It deals with initialization of array variables and member array fields.

Initialization of an array variable from an array of the same type performs
array copy-initialization; elementwise move or copy from an rvalue or lvalue
array respectively, in index order from begin to end. The existing code path
for a structured binding declaration with array initializer, auto[e...]{a};
performs the same array copy-initialization (as a special case superpower).
Borrowing from that, this was a relatively quick and easy change.

Initialization of member arrays proved much more difficult to do in general.
I resorted to trial and error, running gcc in gdb with test cases to work out
where and what to change, until eventually converging on this set of changes.

One starting point was the C special case of char array initialization from
string literals (as char array lvalue constants). However, a long-standing
bug in designated initialization of char arrays by string literals blocked
the task of extending this special case to general array type initializers.
A bugfix patch was separated out, to be merged ahead of these patches:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55227
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/584897.html

Other cases to consider, array initializations:

* by optionally brace-enclosed or paren-enclosed array values
* by possibly-designated array-valued aggregate initializers
  (within possibly-elided braced init-lists)
* by brace or paren-enclosed array values in member initialization lists
* by array-valued member initializers

The patch adds tests for these cases, and for inner initializations of nested
array elements of array type.

The work has diverged in details from the P1997 wording, including catching
up with C++20 changes such as parenthesised initialization of aggregates.
The paper will be revised to reflect the implementation experience.

It is likely that there are omissions, errors in the conditions or that changed
code is inappropriate. For example, I inserted a new call to build_array_copy
in typeck2.c:digest_init_r which may not be correct for move-enabled elements.
Please review carefully with this in mind and suggest test cases to exercise.

PR c++/103238

gcc/c-family/ChangeLog:

* c-common.c (complete_array_type): Accept array type initial_value.
* c.opt: New option -farray-copy "experimental extensions for P1997".

gcc/cp/ChangeLog:

* decl.c (do_aggregate_paren_init): Accept single array type init.
(maybe_deduce_size_from_array_init): Include same-type array inits,
or complain for not same-type arrays.
(reshape_init_r): Extend string-literal handling to all array types.
* init.c (build_aggr_init): Follow existing path for array rhs.
* typeck.c (cp_build_modify_expr): Follow path for synthetic op=.
* typeck2.c (digest_init_r): Add call to build_array_copy for
same-type arrays ('copy' feels wrong for move-eligible rhs).

gcc/ChangeLog:

* doc/invoke.texi: -farray-copy help info documentation.

gcc/testsuite/ChangeLog:

* g++.dg/init/array-copy1.C: New test. Variable init 'before' XFAILs
* g++.dg/init/array-copy2.C: New test. Variable init 'after' PASSes
* g++.dg/init/array-copy3.C: New test. Member init 'before' XFAILs
* g++.dg/init/array-copy4.C: New test. Member init 'after' PASSes
* g++.dg/init/array-copy5.C: New test. Member nsdmi & desig XFAILs
* g++.dg/init/array-copy6.C: New test. Member nsdmi & desig PASSes
---
 gcc/c-family/c-common.c |  5 +++
 gcc/c-family/c.opt  |  4 ++
 gcc/cp/decl.c   | 61 -
 gcc/cp/init.c   |  6 ++-
 gcc/cp/typeck.c |  9 +++--
 gcc/cp/typeck2.c| 30 +++
 gcc/doc/invoke.texi |  6 +++
 gcc/testsuite/g++.dg/init/array-copy1.C | 66 
 gcc/testsuite/g++.dg/init/array-copy2.C | 68 +
 gcc/testsuite/g++.dg/init/array-copy3.C | 41 
 gcc/testsuite/g++.dg/init/array-copy4.C | 42 
 gcc/testsuite/g++.dg/init/array-copy5.C | 36 +
 gcc/testsuite/g++.dg/init/array-copy6.C | 51 +
 13 files changed, 395 insertions(+), 30 deletions(-)

diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 86c007f53de..fb0b1ef294f 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -6796,6 +6796,11 @@ complete_array_type (tree *ptype, tree initial_value, 
bool do_default)
=