Re: [PATCH 3/3] c++: P1997 array-copy extensions: Assignment, return, etc. [PR103238]

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

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

This second patch completes the work of the first 'array-copy' patch to
provide first-cut implementations of all P1997 features. It adds:

  * Assignments to arrays from array values,a = b;
  * Placeholder auto in array declarations, auto cp[] = a;
  * Array as a return type from functions WIP,  auto f() -> T[N];
  * Parsing of array pseudo-destructors a.~A()
(only parsing for now, untested)


Let's not accept the pseudo-destructor and silently ignore it.  Either 
we should delay the parsing change until the semantics are implemented, 
or parse it and give a sorry().



Assignments a = b were easily allowed by changing branch conditions.
Assignments a = {e...} were trickier (a case not mentioned in P1997):

 int a[16]; a = {0,1,1,2}; a = {}; // assignments from init-lists

The semantics is the same as for struct aggregates:
(1) Aggregate initialization of an rhs array of the lhs type
 (so trailing elements with no initializer are value initialized)
(2) Copy-initialization of the lhs from the rhs.

The special case of an optionally-braced array value is allowed so that
a = b and a = {b} are generally equivalent for same type arrays a and b.
However, the now special-special case of assignment from a braced string-
literal currently only supports exact-match (same as for other arrays):

 char a[4]; a={"c++"} /* OK */; a={"c"} /* FAILs but should work */;

Array return from function is work in progress. The tests show what works.
I'm stuck in unfamiliar territory so it's best to submit what I have to be
reviewed for hints on how to progress.


Let's split out array return into a separate patch for now.  It also has 
ABI implications.



Please try the patch; play, stress it, and report the FAILS.

PR c++/103238

gcc/c/ChangeLog:

* c-decl.c (grokdeclarator): Don't complain of array returns.

gcc/cp/ChangeLog:

* call.c (can_convert_array): Extend to include array inits.
(standard_conversion): No decay for same-type array. Call build_conv.
(implicit_conversion_1): Call reshape_init for arrays too.
* decl.c (grokdeclarator): Don't complain of array returns.
* parser.c (cp_parser_postfix_dot_deref_expression): parse array ~A().
* pt.c (tsubst_function_type): Array type return is not a failure.
(do_auto_deduction): Placeholder auto deduction of array element type.
* tree.c (lvalue_kind): clk_class should include array (I think?).
* typeck.c (cp_build_modify_expr): Call reshape init to strip optional
braces. Allow NOP_EXPR for array assignment.
(convert_for_assignment): New if-block for same-type array convert,
strips optional braces, but rejects STRING_CST rhs shorter than lhs.

gcc/testsuite/ChangeLog:

* g++.dg/init/array-copy10.C: New test. auto[] deduce 'after' PASSes
* g++.dg/init/array-copy11.C: New test. Array return 'before' XFAILs
* g++.dg/init/array-copy12.C: New test. Array return 'after' PASSes
* g++.dg/init/array-copy7.C: New test. Array assign 'before' XFAILs
* g++.dg/init/array-copy8.C: New test. Array assign 'after' PASSes
* g++.dg/init/array-copy9.C: New test. auto[] deduce 'before' XFAILs
---
  gcc/c/c-decl.c   |  2 +-
  gcc/cp/call.c| 43 +++--
  gcc/cp/decl.c|  2 +-
  gcc/cp/parser.c  |  4 +-
  gcc/cp/pt.c  | 13 +-
  gcc/cp/tree.c|  3 +-
  gcc/cp/typeck.c  | 26 +--
  gcc/testsuite/g++.dg/init/array-copy10.C | 57 +++
  gcc/testsuite/g++.dg/init/array-copy11.C | 13 ++
  gcc/testsuite/g++.dg/init/array-copy12.C | 79 
  gcc/testsuite/g++.dg/init/array-copy7.C  | 40 
  gcc/testsuite/g++.dg/init/array-copy8.C  | 56 ++
  gcc/testsuite/g++.dg/init/array-copy9.C  | 57 +++
  13 files changed, 372 insertions(+), 23 deletions(-)

diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 3e28a038095..031c43d189f 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -7055,7 +7055,7 @@ grokdeclarator (const struct c_declarator *declarator,
"returning a function");
type = integer_type_node;
  }
-   if (TREE_CODE (type) == ARRAY_TYPE)
+   if (TREE_CODE (type) == ARRAY_TYPE && !flag_array_copy)
  {
if (name)
  error_at (loc, "%qE declared as function returning an array",
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 4ee21c7bdbd..c73fb73d86e 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -908,29 +908,34 @@ static bool
  can_convert_array (tree atype, tree from, int flags, tsubst_flags_t complain)
  {
tree elttype = TREE_TYPE (atype);
-  unsigne

Re: [PATCH 3/3] c++: P1997 array-copy extensions: Assignment, return, etc. [PR103238]

2021-11-22 Thread will wray via Gcc-patches
On Mon, Nov 22, 2021 at 3:42 PM Joseph Myers  wrote:
>
> On Sun, 21 Nov 2021, Will Wray via Gcc-patches wrote:
>
> > gcc/c/ChangeLog:
> >
> >   * c-decl.c (grokdeclarator): Don't complain of array returns.
>
> A C front-end change like this doesn't belong in a C++ patch

Of course, thanks. I'll remove it.
Hopefully it'll be back before long, in a compatible C array-copy patchset.


Re: [PATCH 3/3] c++: P1997 array-copy extensions: Assignment, return, etc. [PR103238]

2021-11-22 Thread Joseph Myers
On Sun, 21 Nov 2021, Will Wray via Gcc-patches wrote:

> gcc/c/ChangeLog:
> 
>   * c-decl.c (grokdeclarator): Don't complain of array returns.

A C front-end change like this doesn't belong in a C++ patch (I don't see 
any reason why this C++ patch would need such a C front-end change, it's 
not e.g. changing the interface to a function called from shared code but 
defined separately for both front ends).

-- 
Joseph S. Myers
jos...@codesourcery.com


[PATCH 3/3] c++: P1997 array-copy extensions: Assignment, return, etc. [PR103238]

2021-11-21 Thread Will Wray via Gcc-patches
This second patch completes the work of the first 'array-copy' patch to
provide first-cut implementations of all P1997 features. It adds:

 * Assignments to arrays from array values,a = b;
 * Placeholder auto in array declarations, auto cp[] = a;
 * Array as a return type from functions WIP,  auto f() -> T[N];
 * Parsing of array pseudo-destructors a.~A()
   (only parsing for now, untested)

Assignments a = b were easily allowed by changing branch conditions.
Assignments a = {e...} were trickier (a case not mentioned in P1997):

int a[16]; a = {0,1,1,2}; a = {}; // assignments from init-lists

The semantics is the same as for struct aggregates:
(1) Aggregate initialization of an rhs array of the lhs type
(so trailing elements with no initializer are value initialized)
(2) Copy-initialization of the lhs from the rhs.

The special case of an optionally-braced array value is allowed so that
a = b and a = {b} are generally equivalent for same type arrays a and b.
However, the now special-special case of assignment from a braced string-
literal currently only supports exact-match (same as for other arrays):

char a[4]; a={"c++"} /* OK */; a={"c"} /* FAILs but should work */;

Array return from function is work in progress. The tests show what works.
I'm stuck in unfamiliar territory so it's best to submit what I have to be
reviewed for hints on how to progress.

Please try the patch; play, stress it, and report the FAILS.

PR c++/103238

gcc/c/ChangeLog:

* c-decl.c (grokdeclarator): Don't complain of array returns.

gcc/cp/ChangeLog:

* call.c (can_convert_array): Extend to include array inits.
(standard_conversion): No decay for same-type array. Call build_conv.
(implicit_conversion_1): Call reshape_init for arrays too.
* decl.c (grokdeclarator): Don't complain of array returns.
* parser.c (cp_parser_postfix_dot_deref_expression): parse array ~A().
* pt.c (tsubst_function_type): Array type return is not a failure.
(do_auto_deduction): Placeholder auto deduction of array element type.
* tree.c (lvalue_kind): clk_class should include array (I think?).
* typeck.c (cp_build_modify_expr): Call reshape init to strip optional
braces. Allow NOP_EXPR for array assignment.
(convert_for_assignment): New if-block for same-type array convert,
strips optional braces, but rejects STRING_CST rhs shorter than lhs.

gcc/testsuite/ChangeLog:

* g++.dg/init/array-copy10.C: New test. auto[] deduce 'after' PASSes
* g++.dg/init/array-copy11.C: New test. Array return 'before' XFAILs
* g++.dg/init/array-copy12.C: New test. Array return 'after' PASSes
* g++.dg/init/array-copy7.C: New test. Array assign 'before' XFAILs
* g++.dg/init/array-copy8.C: New test. Array assign 'after' PASSes
* g++.dg/init/array-copy9.C: New test. auto[] deduce 'before' XFAILs
---
 gcc/c/c-decl.c   |  2 +-
 gcc/cp/call.c| 43 +++--
 gcc/cp/decl.c|  2 +-
 gcc/cp/parser.c  |  4 +-
 gcc/cp/pt.c  | 13 +-
 gcc/cp/tree.c|  3 +-
 gcc/cp/typeck.c  | 26 +--
 gcc/testsuite/g++.dg/init/array-copy10.C | 57 +++
 gcc/testsuite/g++.dg/init/array-copy11.C | 13 ++
 gcc/testsuite/g++.dg/init/array-copy12.C | 79 
 gcc/testsuite/g++.dg/init/array-copy7.C  | 40 
 gcc/testsuite/g++.dg/init/array-copy8.C  | 56 ++
 gcc/testsuite/g++.dg/init/array-copy9.C  | 57 +++
 13 files changed, 372 insertions(+), 23 deletions(-)

diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 3e28a038095..031c43d189f 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -7055,7 +7055,7 @@ grokdeclarator (const struct c_declarator *declarator,
"returning a function");
type = integer_type_node;
  }
-   if (TREE_CODE (type) == ARRAY_TYPE)
+   if (TREE_CODE (type) == ARRAY_TYPE && !flag_array_copy)
  {
if (name)
  error_at (loc, "%qE declared as function returning an array",
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 4ee21c7bdbd..c73fb73d86e 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -908,29 +908,34 @@ static bool
 can_convert_array (tree atype, tree from, int flags, tsubst_flags_t complain)
 {
   tree elttype = TREE_TYPE (atype);
-  unsigned i;
 
   if (TREE_CODE (from) == CONSTRUCTOR)
 {
-  for (i = 0; i < CONSTRUCTOR_NELTS (from); ++i)
+  for (auto&& ce : CONSTRUCTOR_ELTS (from))
{
- tree val = CONSTRUCTOR_ELT (from, i)->value;
- bool ok;
- if (TREE_CODE (elttype) == ARRAY_TYPE)
-   ok = can_convert_array (elttype, val, flags, complain)