Re: [PATCH] c++: designated init of char array by string constant [PR55227]

2021-11-17 Thread will wray via Gcc-patches
Thanks for the review Marek;
I'll post the updated patch in a follow-on message and on bugzilla.

On Mon, Nov 15, 2021 at 8:03 PM Marek Polacek  wrote:

> I also noticed the C++ FE rejects
>
>   struct A { char x[4]; };
>   struct B { struct A a; };
>   struct B b = { .a.x = "abc" };
> but the C FE accepts it.  But that's for another time.

Yes, the nested case is invalid for C++, valid for C.
c.f. cppreference aggregate init.

> > +  reshape_iter stripd = {};
>
> Since the previous variables spell it "stripped" maybe call it stripped_iter.

I've left it as "stripd"; the top level reshape_iter is just "d", non-verbose,
so "stripped_d" inappropriately over-verbose.

> > @@ -6836,7 +6838,8 @@ reshape_init_r (tree type, reshape_iter *d, tree 
> > first_initializer_p,
> >array types (one value per array element).  */
> >if (TREE_CODE (stripped_str_init) == STRING_CST)
> >   {
> > -   if (has_designator_problem (d, complain))
>
> So the logic here is that...

Yes, you get the logic exactly... took me a few rounds to get it.

> Nice to finally remove this, but let's keep this part of the comment.

Agreed, and reinstated.

> BRACE_ENCLOSED_INITIALIZER_P checks that it gets a CONSTRUCTOR so you
> can remove the first check.

Nice, thanks; missed that.

> > +// { dg-do compile }
> > +// { dg-options "-pedantic" }
>
> FWIW, if you remove the dg-options, -pedantic-errors will be used so you could
> drop it and then use dg-error instead of dg-warning below but this is OK too.

I'd copied that from another desigN.C test, now I've copied the simpler:

+// { dg-options "" }

and removed all of the noisy dg-warning tests

> We should probably test more:
> - nested structs
> - anonymous unions
> - test when the initializer is too long
> - multidim arrays:

Cut-n-paste'd your multidim array test, and added a couple more

> Hope this is useful...

Very useful, thanks again


Re: [PATCH] c++: designated init of char array by string constant [PR55227]

2021-11-17 Thread will wray via Gcc-patches
V2 Patch
https://gcc.gnu.org/bugzilla/attachment.cgi?id=51828

On Wed, Nov 17, 2021 at 10:06 PM will wray  wrote:
>
> Thanks for the review Marek;
> I'll post the updated patch in a follow-on message and on bugzilla.
>
> On Mon, Nov 15, 2021 at 8:03 PM Marek Polacek  wrote:
>
> > I also noticed the C++ FE rejects
> >
> >   struct A { char x[4]; };
> >   struct B { struct A a; };
> >   struct B b = { .a.x = "abc" };
> > but the C FE accepts it.  But that's for another time.
>
> Yes, the nested case is invalid for C++, valid for C.
> c.f. cppreference aggregate init.
>
> > > +  reshape_iter stripd = {};
> >
> > Since the previous variables spell it "stripped" maybe call it 
> > stripped_iter.
>
> I've left it as "stripd"; the top level reshape_iter is just "d", non-verbose,
> so "stripped_d" inappropriately over-verbose.
>
> > > @@ -6836,7 +6838,8 @@ reshape_init_r (tree type, reshape_iter *d, tree 
> > > first_initializer_p,
> > >array types (one value per array element).  */
> > >if (TREE_CODE (stripped_str_init) == STRING_CST)
> > >   {
> > > -   if (has_designator_problem (d, complain))
> >
> > So the logic here is that...
>
> Yes, you get the logic exactly... took me a few rounds to get it.
>
> > Nice to finally remove this, but let's keep this part of the comment.
>
> Agreed, and reinstated.
>
> > BRACE_ENCLOSED_INITIALIZER_P checks that it gets a CONSTRUCTOR so you
> > can remove the first check.
>
> Nice, thanks; missed that.
>
> > > +// { dg-do compile }
> > > +// { dg-options "-pedantic" }
> >
> > FWIW, if you remove the dg-options, -pedantic-errors will be used so you 
> > could
> > drop it and then use dg-error instead of dg-warning below but this is OK 
> > too.
>
> I'd copied that from another desigN.C test, now I've copied the simpler:
>
> +// { dg-options "" }
>
> and removed all of the noisy dg-warning tests
>
> > We should probably test more:
> > - nested structs
> > - anonymous unions
> > - test when the initializer is too long
> > - multidim arrays:
>
> Cut-n-paste'd your multidim array test, and added a couple more
>
> > Hope this is useful...
>
> Very useful, thanks again


[PATCH v2] c++: designated init of char array by string constant [PR55227]

2021-11-18 Thread Will Wray via Gcc-patches
Also address "FIXME: this code is duplicated from reshape_init" in
cp_complete_array_type by always calling reshape_init on init-list.

PR c++/55227

gcc/cp/ChangeLog:

* decl.c (reshape_init_r): Only call has_designator_check when
   first_initializer_p or for the inner constructor element.
(cp_complete_array_type): Call reshape_init on braced-init-list.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/desig20.C: New test.
---
 gcc/cp/decl.c| 42 +--
 gcc/testsuite/g++.dg/cpp2a/desig20.C | 48 
 2 files changed, 65 insertions(+), 25 deletions(-)

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 2ddf0e4a524..83a2d3bf8f1 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6824,28 +6824,31 @@ reshape_init_r (tree type, reshape_iter *d, tree 
first_initializer_p,
   if (TREE_CODE (type) == ARRAY_TYPE
   && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type
 {
-  tree str_init = init;
-  tree stripped_str_init = stripped_init;
+  tree arr_init = init;
+  tree stripped_arr_init = stripped_init;
+  reshape_iter stripd = {};
 
   /* Strip one level of braces if and only if they enclose a single
 element (as allowed by [dcl.init.string]).  */
   if (!first_initializer_p
- && TREE_CODE (stripped_str_init) == CONSTRUCTOR
- && CONSTRUCTOR_NELTS (stripped_str_init) == 1)
+ && TREE_CODE (stripped_arr_init) == CONSTRUCTOR
+ && CONSTRUCTOR_NELTS (stripped_arr_init) == 1)
{
- str_init = (*CONSTRUCTOR_ELTS (stripped_str_init))[0].value;
- stripped_str_init = tree_strip_any_location_wrapper (str_init);
+ stripd.cur = CONSTRUCTOR_ELT (stripped_arr_init, 0);
+ arr_init = stripd.cur->value;
+ stripped_arr_init = tree_strip_any_location_wrapper (arr_init);
}
 
   /* If it's a string literal, then it's the initializer for the array
 as a whole. Otherwise, continue with normal initialization for
 array types (one value per array element).  */
-  if (TREE_CODE (stripped_str_init) == STRING_CST)
+  if (TREE_CODE (stripped_arr_init) == STRING_CST)
{
- if (has_designator_problem (d, complain))
+ if ((first_initializer_p && has_designator_problem (d, complain))
+ || (stripd.cur && has_designator_problem (&stripd, complain)))
return error_mark_node;
  d->cur++;
- return str_init;
+ return arr_init;
}
 }
 
@@ -9545,22 +9548,11 @@ cp_complete_array_type (tree *ptype, tree 
initial_value, bool do_default)
   if (initial_value)
 {
   /* An array of character type can be initialized from a
-brace-enclosed string constant.
-
-FIXME: this code is duplicated from reshape_init. Probably
-we should just call reshape_init here?  */
-  if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (*ptype)))
- && TREE_CODE (initial_value) == CONSTRUCTOR
- && !vec_safe_is_empty (CONSTRUCTOR_ELTS (initial_value)))
-   {
- vec *v = CONSTRUCTOR_ELTS (initial_value);
- tree value = (*v)[0].value;
- STRIP_ANY_LOCATION_WRAPPER (value);
-
- if (TREE_CODE (value) == STRING_CST
- && v->length () == 1)
-   initial_value = value;
-   }
+brace-enclosed string constant so call reshape_init to
+remove the optional braces from a braced string literal.  */
+  if (BRACE_ENCLOSED_INITIALIZER_P (initial_value))
+   initial_value = reshape_init (*ptype, initial_value,
+ tf_warning_or_error);
 
   /* If any of the elements are parameter packs, we can't actually
 complete this type now because the array size is dependent.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig20.C 
b/gcc/testsuite/g++.dg/cpp2a/desig20.C
new file mode 100644
index 000..7904fcace7f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/desig20.C
@@ -0,0 +1,48 @@
+// PR c++/55227 
+// Test designated initializer for char array by string constant
+
+// { dg-options "" }
+
+struct C {char a[2];};
+
+/* Case a, designated, unbraced, string-literal of the exact same size
+   as the initialized char array; valid and accepted before and after.  */
+C a = {.a="a"};
+
+/* Cases b,c,d, designated, braced or mimatched-size, string literal,
+   previously rejected; "C99 designator 'a' outside aggregate initializer".  */
+C b = {.a=""};
+C c = {.a={""}};
+C d = {.a={"a"}};
+
+/* Case e, designated char array field and braced, designated array element(s)
+   (with GNU [N]= extension) valid and accepted before and after.  */
+C e = {.a={[0]='a'}};
+
+/* Cases f,g,h, braced string literal, 'designated' within inner braces;
+   invalid, previously accepted as positional with 'designator' ignored.  */
+C f = {{[0]="a"}}; // { dg-error "C99 designator .0. outside aggregate 
initializer" }
+C g = {

Re: [PATCH] c++: designated init of char array by string constant [PR55227]

2021-11-18 Thread will wray via Gcc-patches
V2 Patch mailing list post
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/584897.html

On Thu, Nov 18, 2021 at 10:36 AM Marek Polacek  wrote:
>
> On Wed, Nov 17, 2021 at 10:23:58PM -0500, will wray wrote:
> > V2 Patch
> > https://gcc.gnu.org/bugzilla/attachment.cgi?id=51828
>
> Can you please post the v2 here on the mailing list?  It will be easier
> for us to reply.  Preferably with the subject adjusted to say [PATCH v2] ...
>
> > On Wed, Nov 17, 2021 at 10:06 PM will wray  wrote:
> > >
> > > Thanks for the review Marek;
> > > I'll post the updated patch in a follow-on message and on bugzilla.
> > >
> > > On Mon, Nov 15, 2021 at 8:03 PM Marek Polacek  wrote:
> > >
> > > > I also noticed the C++ FE rejects
> > > >
> > > >   struct A { char x[4]; };
> > > >   struct B { struct A a; };
> > > >   struct B b = { .a.x = "abc" };
> > > > but the C FE accepts it.  But that's for another time.
> > >
> > > Yes, the nested case is invalid for C++, valid for C.
> > > c.f. cppreference aggregate init.
> > >
> > > > > +  reshape_iter stripd = {};
> > > >
> > > > Since the previous variables spell it "stripped" maybe call it 
> > > > stripped_iter.
> > >
> > > I've left it as "stripd"; the top level reshape_iter is just "d", 
> > > non-verbose,
> > > so "stripped_d" inappropriately over-verbose.
> > >
> > > > > @@ -6836,7 +6838,8 @@ reshape_init_r (tree type, reshape_iter *d, 
> > > > > tree first_initializer_p,
> > > > >array types (one value per array element).  */
> > > > >if (TREE_CODE (stripped_str_init) == STRING_CST)
> > > > >   {
> > > > > -   if (has_designator_problem (d, complain))
> > > >
> > > > So the logic here is that...
> > >
> > > Yes, you get the logic exactly... took me a few rounds to get it.
> > >
> > > > Nice to finally remove this, but let's keep this part of the comment.
> > >
> > > Agreed, and reinstated.
> > >
> > > > BRACE_ENCLOSED_INITIALIZER_P checks that it gets a CONSTRUCTOR so you
> > > > can remove the first check.
> > >
> > > Nice, thanks; missed that.
> > >
> > > > > +// { dg-do compile }
> > > > > +// { dg-options "-pedantic" }
> > > >
> > > > FWIW, if you remove the dg-options, -pedantic-errors will be used so 
> > > > you could
> > > > drop it and then use dg-error instead of dg-warning below but this is 
> > > > OK too.
> > >
> > > I'd copied that from another desigN.C test, now I've copied the simpler:
> > >
> > > +// { dg-options "" }
> > >
> > > and removed all of the noisy dg-warning tests
> > >
> > > > We should probably test more:
> > > > - nested structs
> > > > - anonymous unions
> > > > - test when the initializer is too long
> > > > - multidim arrays:
> > >
> > > Cut-n-paste'd your multidim array test, and added a couple more
> > >
> > > > Hope this is useful...
> > >
> > > Very useful, thanks again
> >
>
> Marek
>


[PATCH 0/3] P1997 'array-copy' patchset [PR103238]

2021-11-21 Thread Will Wray via Gcc-patches
([PATCH 1/3] already submitted fix for PR c++/55227, is a dependency here.)

These patches implement C++ proposal P1997 "Relaxing restrictions on array"
that adds:

  C array copy semantics:
* array-array initializations
* array-array assignments
* array return-by-value from functions
 (array formal parameters are unchanged; there's no pass-by-value).

  Plus, C++ specific:
* array pseudo-destructors
* array element type deduction
 (i.e. admitting placeholder auto in array variable declarations).

The features are added as an experimental extension, disabled by default.
The patches should have no effect until enabled by the new option:

-farray-copy (flag_array_copy, a single flag to enable all features)

The extension is documented as experimental with no guarantee of stability;
features may be added, removed or changed in detail. In particular, there's
no guarantee of ABI stability; allowing array as a function return type has
ABI implications for calling conventions of the array return slot and, for
C++, name-mangling conventions must be defined.

The plan is to first merge array-copy as experimental, with ABI defined as
'what the code does', and then to go ahead with ABI work.

Will Wray (3):
  c++: designated init of char array by string constant [PR55227]
  c++: P1997 array-copy extensions: Initialization [PR103238]
  c++: P1997 array-copy extensions: Assignment, return, etc. [PR103238]

 gcc/c-family/c-common.c  |   5 ++
 gcc/c-family/c.opt   |   4 ++
 gcc/c/c-decl.c   |   2 +-
 gcc/cp/call.c|  43 +++-
 gcc/cp/decl.c| 111 ++-
 gcc/cp/init.c|   6 +-
 gcc/cp/parser.c  |   4 +-
 gcc/cp/pt.c  |  13 +++-
 gcc/cp/tree.c|   3 +-
 gcc/cp/typeck.c  |  35 --
 gcc/cp/typeck2.c |  30 ++---
 gcc/doc/invoke.texi  |   6 ++
 gcc/testsuite/g++.dg/cpp2a/desig20.C |  48 +
 gcc/testsuite/g++.dg/init/array-copy1.C  |  66 ++
 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-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 ++
 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 
 25 files changed, 835 insertions(+), 81 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/desig20.C
 create mode 100644 gcc/testsuite/g++.dg/init/array-copy1.C
 create mode 100644 gcc/testsuite/g++.dg/init/array-copy10.C
 create mode 100644 gcc/testsuite/g++.dg/init/array-copy11.C
 create mode 100644 gcc/testsuite/g++.dg/init/array-copy12.C
 create mode 100644 gcc/testsuite/g++.dg/init/array-copy2.C
 create mode 100644 gcc/testsuite/g++.dg/init/array-copy3.C
 create mode 100644 gcc/testsuite/g++.dg/init/array-copy4.C
 create mode 100644 gcc/testsuite/g++.dg/init/array-copy5.C
 create mode 100644 gcc/testsuite/g++.dg/init/array-copy6.C
 create mode 100644 gcc/testsuite/g++.dg/init/array-copy7.C
 create mode 100644 gcc/testsuite/g++.dg/init/array-copy8.C
 create mode 100644 gcc/testsuite/g++.dg/init/array-copy9.C

-- 
2.31.1



[PATCH 1/3] c++: designated init of char array by string constant [PR55227]

2021-11-21 Thread Will Wray via Gcc-patches
Also address "FIXME: this code is duplicated from reshape_init" in
cp_complete_array_type by always calling reshape_init on init-list.

PR c++/55227

gcc/cp/ChangeLog:

* decl.c (reshape_init_r): Only call has_designator_check when
   first_initializer_p or for the inner constructor element.
(cp_complete_array_type): Call reshape_init on braced-init-list.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/desig20.C: New test.
---
 gcc/cp/decl.c| 42 +--
 gcc/testsuite/g++.dg/cpp2a/desig20.C | 48 
 2 files changed, 65 insertions(+), 25 deletions(-)

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 2ddf0e4a524..83a2d3bf8f1 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6824,28 +6824,31 @@ reshape_init_r (tree type, reshape_iter *d, tree 
first_initializer_p,
   if (TREE_CODE (type) == ARRAY_TYPE
   && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type
 {
-  tree str_init = init;
-  tree stripped_str_init = stripped_init;
+  tree arr_init = init;
+  tree stripped_arr_init = stripped_init;
+  reshape_iter stripd = {};
 
   /* Strip one level of braces if and only if they enclose a single
 element (as allowed by [dcl.init.string]).  */
   if (!first_initializer_p
- && TREE_CODE (stripped_str_init) == CONSTRUCTOR
- && CONSTRUCTOR_NELTS (stripped_str_init) == 1)
+ && TREE_CODE (stripped_arr_init) == CONSTRUCTOR
+ && CONSTRUCTOR_NELTS (stripped_arr_init) == 1)
{
- str_init = (*CONSTRUCTOR_ELTS (stripped_str_init))[0].value;
- stripped_str_init = tree_strip_any_location_wrapper (str_init);
+ stripd.cur = CONSTRUCTOR_ELT (stripped_arr_init, 0);
+ arr_init = stripd.cur->value;
+ stripped_arr_init = tree_strip_any_location_wrapper (arr_init);
}
 
   /* If it's a string literal, then it's the initializer for the array
 as a whole. Otherwise, continue with normal initialization for
 array types (one value per array element).  */
-  if (TREE_CODE (stripped_str_init) == STRING_CST)
+  if (TREE_CODE (stripped_arr_init) == STRING_CST)
{
- if (has_designator_problem (d, complain))
+ if ((first_initializer_p && has_designator_problem (d, complain))
+ || (stripd.cur && has_designator_problem (&stripd, complain)))
return error_mark_node;
  d->cur++;
- return str_init;
+ return arr_init;
}
 }
 
@@ -9545,22 +9548,11 @@ cp_complete_array_type (tree *ptype, tree 
initial_value, bool do_default)
   if (initial_value)
 {
   /* An array of character type can be initialized from a
-brace-enclosed string constant.
-
-FIXME: this code is duplicated from reshape_init. Probably
-we should just call reshape_init here?  */
-  if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (*ptype)))
- && TREE_CODE (initial_value) == CONSTRUCTOR
- && !vec_safe_is_empty (CONSTRUCTOR_ELTS (initial_value)))
-   {
- vec *v = CONSTRUCTOR_ELTS (initial_value);
- tree value = (*v)[0].value;
- STRIP_ANY_LOCATION_WRAPPER (value);
-
- if (TREE_CODE (value) == STRING_CST
- && v->length () == 1)
-   initial_value = value;
-   }
+brace-enclosed string constant so call reshape_init to
+remove the optional braces from a braced string literal.  */
+  if (BRACE_ENCLOSED_INITIALIZER_P (initial_value))
+   initial_value = reshape_init (*ptype, initial_value,
+ tf_warning_or_error);
 
   /* If any of the elements are parameter packs, we can't actually
 complete this type now because the array size is dependent.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig20.C 
b/gcc/testsuite/g++.dg/cpp2a/desig20.C
new file mode 100644
index 000..daadfa58855
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/desig20.C
@@ -0,0 +1,48 @@
+// PR c++/55227 
+// Test designated initializer for char array by string constant
+
+// { dg-options "" }
+
+struct C {char a[2];};
+
+/* Case a, designated, unbraced, string-literal of the exact same size
+   as the initialized char array; valid and accepted before and after.  */
+C a = {.a="a"};
+
+/* Cases b,c,d, designated, braced or mimatched-size, string literal,
+   previously rejected; "C99 designator 'a' outside aggregate initializer".  */
+C b = {.a=""};
+C c = {.a={""}};
+C d = {.a={"a"}};
+
+/* Case e, designated char array field and braced, designated array element(s)
+   (with GNU [N]= extension) valid and accepted before and after.  */
+C e = {.a={[0]='a'}};
+
+/* Cases f,g,h, braced string literal, 'designated' within inner braces;
+   invalid, previously accepted as positional with 'designator' ignored.  */
+C f = {{[0]="a"}}; // { dg-error "C99 designator .0. outside aggregate 
initializer" }
+C g = {

[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)
= int_s

[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)

Re: [PATCH] c++: __builtin_bit_cast To C array target type [PR103140]

2021-11-22 Thread will wray via Gcc-patches
Ping.

Another use case; casting arrays of char to arrays of unsigned char
(useful in some crypto APIs).

On Mon, Nov 15, 2021 at 6:32 PM will wray  wrote:
>
> Yes - direct use of any builtin is not to be encouraged, in user code.
>
> This __builtin_bit_cast patch is intended to encourage experimentation
> with array copy semantics now, on truck, in preparation for P1997.
>
> The builtin bit_cast is strictly more powerful than the std::bit_cast
> library function that it helps implement, is available in any -std mode
> and might also be useful in C, independent of any standardization effort.
>
> The semantics of bit_cast is clear - it's just the resulting rvalue array
> itself is unfamiliar and tricky to handle within current language rules.
>
> On Mon, Nov 15, 2021 at 12:21 PM Jakub Jelinek  wrote:
> >
> > On Mon, Nov 15, 2021 at 12:12:22PM -0500, will wray via Gcc-patches wrote:
> > > One motivation for allowing builtin bit_cast to builtin array is that
> > > it enables direct bitwise constexpr comparisons via memcmp:
> > >
> > > template
> > > constexpr int bit_equal(A const& a, B const& b)
> > > {
> > >   static_assert( sizeof a == sizeof b,
> > >   "bit_equal(a,b) requires same sizeof" );
> > >   using bytes = unsigned char[sizeof(A)];
> > >   return __builtin_memcmp(
> > >  __builtin_bit_cast(bytes,a),
> > >  __builtin_bit_cast(bytes,b),
> > >  sizeof(A)) == 0;
> > > }
> >
> > IMNSHO people shouldn't use this builtin directly, and we shouldn't
> > encourage such uses, the standard interface is std::bit_cast.
> >
> > For the above, I don't see a reason to do it that way, you can
> > instead portably:
> >   struct bytes { unsigned char data[sizeof(A)]; };
> >   bytes ab = std::bit_cast(bytes, a);
> >   bytes bb = std::bit_cast(bytes, a);
> >   for (size_t i = 0; i < sizeof(A); ++i)
> > if (ab.data[i] != bb.data[i])
> >   return false;
> >   return true;
> > - __builtin_memcmp isn't portable either and memcmp isn't constexpr.
> >
> > If P1997 is in, it is easy to support it in std::bit_cast and easy to
> > explain what __builtin_bit_cast does for array types, but otherwise
> > it is quite unclear what it exactly does...
> >
> > Jakub
> >


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.


[PATCH] c++ PR 55227: designated init of char array by string constant

2021-11-04 Thread will wray via Gcc-patches
This patch aims to fix PR 55227; two underlying bugs that have caused:

(1) Rejection of valid designated initialization of char array fields by
string literals (a) when enclosed in optional braces or (b) unbraced
when the string literal is shorter than the target char array field.

(2) Acceptance of an invalid designator appearing within the braces of a
braced string literal, in which case the 'designator' was entirely
ignored and the string literal treated as a positional initializer.

Please review these changes carefully; I'm fairly new to this, so likely
to have made errors of omission, logic or an anon anomaly.

The fixes above also allow to address a FIXME in cp_complete_array_type,
otherwise obstructed by the designator bugs (see relevant comment here
https://patchwork.ozlabs.org/project/gcc/list/?series=199783)

Please suggest test cases for the newly inserted call to reshape_init.

(This patch is split from my upcoming 'P1997 array copy-semantic' patch,
 which will then extend this from string literal to any array value.)
Boostraps/regtests on x86_64-pc-linux-gnu.

PR c++/55227

gcc/cp/ChangeLog:

* decl.c (reshape_init_r): restrict has_designator_check,
(cp_complete_array_type): do reshape_init on braced-init-list.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/desig20.C: New test.
---
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 7c2a134e406..3bd6ed68a45 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6820,6 +6820,7 @@ reshape_init_r (tree type, reshape_iter *d, tree
first_initializer_p,
 {
   tree str_init = init;
   tree stripped_str_init = stripped_init;
+  reshape_iter stripd = {};

   /* Strip one level of braces if and only if they enclose a single
  element (as allowed by [dcl.init.string]).  */
@@ -6827,7 +6828,8 @@ reshape_init_r (tree type, reshape_iter *d, tree
first_initializer_p,
&& TREE_CODE (stripped_str_init) == CONSTRUCTOR
&& CONSTRUCTOR_NELTS (stripped_str_init) == 1)
  {
-   str_init = (*CONSTRUCTOR_ELTS (stripped_str_init))[0].value;
+   stripd.cur = CONSTRUCTOR_ELT (stripped_str_init, 0);
+   str_init = stripd.cur->value;
stripped_str_init = tree_strip_any_location_wrapper (str_init);
  }

@@ -6836,7 +6838,8 @@ reshape_init_r (tree type, reshape_iter *d, tree
first_initializer_p,
  array types (one value per array element).  */
   if (TREE_CODE (stripped_str_init) == STRING_CST)
  {
-   if (has_designator_problem (d, complain))
+   if ((first_initializer_p && has_designator_problem (d, complain))
+   || (stripd.cur && has_designator_problem (&stripd, complain)))
  return error_mark_node;
d->cur++;
return str_init;
@@ -9541,23 +9544,10 @@ cp_complete_array_type (tree *ptype, tree
initial_value, bool do_default)
   unsigned HOST_WIDE_INT i;
   tree value;

-  /* An array of character type can be initialized from a
- brace-enclosed string constant.
-
- FIXME: this code is duplicated from reshape_init. Probably
- we should just call reshape_init here?  */
-  if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (*ptype)))
-   && TREE_CODE (initial_value) == CONSTRUCTOR
-   && !vec_safe_is_empty (CONSTRUCTOR_ELTS (initial_value)))
- {
-   vec *v = CONSTRUCTOR_ELTS (initial_value);
-   tree value = (*v)[0].value;
-   STRIP_ANY_LOCATION_WRAPPER (value);
-
-   if (TREE_CODE (value) == STRING_CST
-   && v->length () == 1)
- initial_value = value;
- }
+  if (TREE_CODE (initial_value) == CONSTRUCTOR
+   && BRACE_ENCLOSED_INITIALIZER_P (initial_value))
+ initial_value = reshape_init (*ptype, initial_value,
+   tf_warning_or_error);

   /* If any of the elements are parameter packs, we can't actually
  complete this type now because the array size is dependent.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig20.C
b/gcc/testsuite/g++.dg/cpp2a/desig20.C
new file mode 100644
index 000..eb3ef5eda08
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/desig20.C
@@ -0,0 +1,47 @@
+// PR c++/55227
+// Test designated initializer for char array by string constant
+
+// { dg-do compile }
+// { dg-options "-pedantic" }
+
+struct C {char a[2];};
+
+/* Case a, designated, unbraced, string-literal of the exact same size
+   as the initialized char array; valid and accepted before and after.
+*/
+C a = {.a="a"}; // { dg-warning "designated initializers only
available with" "" { target c++17_down } .-0 }
+
+/* Cases b,c,d, designated, braced or mimatched-size, string literal,
+   previously rejected; "C99 designator 'a' outside aggregate initializer".
+*/
+C b = {.a=""}; // { dg-warning "designated initializers only
available with" "" { target c++17_down } .-0 }
+C c = {.a={""}}; // { dg-warning "designated initializers only
available with" "" { target c++17_down } .-0 }
+C d = {.a={"a"}}; // { dg-warning "designated initializers only
available with" "" { target c++17_down } .-0 }
+
+/* Case e, designated char array field and braced, designated array element(s)
+   (with GNU [N]= extensio

[PATCH] c++: designated init of char array by string constant [PR55227]

2021-11-06 Thread Will Wray via Gcc-patches
This patch aims to fix https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55227.

There are two underlying bugs in the designated initialization of char array
fields by string literals that cause:

(1) Rejection of valid cases with:
  (a) brace-enclosed string literal initializer (of any valid size), or
  (b) unbraced string literal shorter than the target char array field.

(2) Acceptance of invalid cases with designators appearing within the braces
of a braced string literal, in which case the bogus 'designator' was being
entirely ignored and the string literal treated as a positional initializer.

Please review these changes carefully; there are likely errors of omission,
logic or an anon anomaly.

The fixes above allow to address a FIXME in cp_complete_array_type:

  /* FIXME: this code is duplicated from reshape_init.
 Probably we should just call reshape_init here?  */

I believe that this was obstructed by the designator bugs (see comment here
https://patchwork.ozlabs.org/project/gcc/list/?series=199783)

Boostraps/regtests on x86_64-pc-linux-gnu.

PR c++/55227

gcc/cp/ChangeLog:

* decl.c (reshape_init_r): restrict has_designator_check,
(cp_complete_array_type): do reshape_init on braced-init-list.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/desig20.C: New test.
---
 gcc/cp/decl.c| 28 ++--
 gcc/testsuite/g++.dg/cpp2a/desig20.C | 48 
 2 files changed, 57 insertions(+), 19 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/desig20.C

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 947bbfc6637..f01655c5c14 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6820,6 +6820,7 @@ reshape_init_r (tree type, reshape_iter *d, tree 
first_initializer_p,
 {
   tree str_init = init;
   tree stripped_str_init = stripped_init;
+  reshape_iter stripd = {};
 
   /* Strip one level of braces if and only if they enclose a single
 element (as allowed by [dcl.init.string]).  */
@@ -6827,7 +6828,8 @@ reshape_init_r (tree type, reshape_iter *d, tree 
first_initializer_p,
  && TREE_CODE (stripped_str_init) == CONSTRUCTOR
  && CONSTRUCTOR_NELTS (stripped_str_init) == 1)
{
- str_init = (*CONSTRUCTOR_ELTS (stripped_str_init))[0].value;
+ stripd.cur = CONSTRUCTOR_ELT (stripped_str_init, 0);
+ str_init = stripd.cur->value;
  stripped_str_init = tree_strip_any_location_wrapper (str_init);
}
 
@@ -6836,7 +6838,8 @@ reshape_init_r (tree type, reshape_iter *d, tree 
first_initializer_p,
 array types (one value per array element).  */
   if (TREE_CODE (stripped_str_init) == STRING_CST)
{
- if (has_designator_problem (d, complain))
+ if ((first_initializer_p && has_designator_problem (d, complain))
+ || (stripd.cur && has_designator_problem (&stripd, complain)))
return error_mark_node;
  d->cur++;
  return str_init;
@@ -9538,23 +9541,10 @@ cp_complete_array_type (tree *ptype, tree 
initial_value, bool do_default)
 
   if (initial_value)
 {
-  /* An array of character type can be initialized from a
-brace-enclosed string constant.
-
-FIXME: this code is duplicated from reshape_init. Probably
-we should just call reshape_init here?  */
-  if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (*ptype)))
- && TREE_CODE (initial_value) == CONSTRUCTOR
- && !vec_safe_is_empty (CONSTRUCTOR_ELTS (initial_value)))
-   {
- vec *v = CONSTRUCTOR_ELTS (initial_value);
- tree value = (*v)[0].value;
- STRIP_ANY_LOCATION_WRAPPER (value);
-
- if (TREE_CODE (value) == STRING_CST
- && v->length () == 1)
-   initial_value = value;
-   }
+  if (TREE_CODE (initial_value) == CONSTRUCTOR
+ && BRACE_ENCLOSED_INITIALIZER_P (initial_value))
+   initial_value = reshape_init (*ptype, initial_value,
+ tf_warning_or_error);
 
   /* If any of the elements are parameter packs, we can't actually
 complete this type now because the array size is dependent.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig20.C 
b/gcc/testsuite/g++.dg/cpp2a/desig20.C
new file mode 100644
index 000..03eab764325
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/desig20.C
@@ -0,0 +1,48 @@
+// PR c++/55227 
+// Test designated initializer for char array by string constant
+
+// { dg-do compile }
+// { dg-options "-pedantic" }
+
+struct C {char a[2];};
+
+/* Case a; designated, unbraced, string-literal of the same size as the target
+   char array to be initialized; valid and accepted before and after.  */
+
+C a = {.a="a"}; // { dg-warning "designated initializers only available with" 
"" { target c++17_down } .-0 }
+
+/* Cases b,c,d; designated mismatched-size string literal, or designated braced
+   string literal (of any size less than or equal to

[PATCH] c++: __builtin_bit_cast To C array target type [PR103140]

2021-11-08 Thread Will Wray via Gcc-patches
This patch allows __builtin_bit_cast to materialize a C array as its To type.

It was developed as part of an implementation of P1997, array copy-semantics,
but is independent, so makes sense to submit, review and merge ahead of it.

gcc/cp/ChangeLog:

* constexpr.c (check_bit_cast_type): handle ARRAY_TYPE check,
(cxx_eval_bit_cast): handle ARRAY_TYPE copy.
* semantics.c (cp_build_bit_cast): warn only on unbounded/VLA.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/bit-cast2.C: update XFAIL tests.
* g++.dg/cpp2a/bit-cast-to-array1.C: New test.
---
 gcc/cp/constexpr.c  |  8 -
 gcc/cp/semantics.c  |  7 ++---
 gcc/testsuite/g++.dg/cpp2a/bit-cast-to-array1.C | 40 +
 gcc/testsuite/g++.dg/cpp2a/bit-cast2.C  |  8 ++---
 4 files changed, 53 insertions(+), 10 deletions(-)

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 453007c686b..be1cdada6f8 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -4124,6 +4124,11 @@ static bool
 check_bit_cast_type (const constexpr_ctx *ctx, location_t loc, tree type,
 tree orig_type)
 {
+  if (TREE_CODE (type) == ARRAY_TYPE)
+  return check_bit_cast_type (ctx, loc,
+ TYPE_MAIN_VARIANT (TREE_TYPE (type)),
+ orig_type);
+
   if (TREE_CODE (type) == UNION_TYPE)
 {
   if (!ctx->quiet)
@@ -4280,7 +4285,8 @@ cxx_eval_bit_cast (const constexpr_ctx *ctx, tree t, bool 
*non_constant_p,
   tree r = NULL_TREE;
   if (can_native_interpret_type_p (TREE_TYPE (t)))
 r = native_interpret_expr (TREE_TYPE (t), ptr, len);
-  else if (TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE)
+  else if (TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE
+  || TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
 {
   r = native_interpret_aggregate (TREE_TYPE (t), ptr, 0, len);
   if (r != NULL_TREE)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 2443d032749..b3126b12abc 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -11562,13 +11562,10 @@ cp_build_bit_cast (location_t loc, tree type, tree 
arg,
 {
   if (!complete_type_or_maybe_complain (type, NULL_TREE, complain))
return error_mark_node;
-  if (TREE_CODE (type) == ARRAY_TYPE)
+  if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
{
- /* std::bit_cast for destination ARRAY_TYPE is not possible,
-as functions may not return an array, so don't bother trying
-to support this (and then deal with VLAs etc.).  */
  error_at (loc, "%<__builtin_bit_cast%> destination type %qT "
-"is an array type", type);
+"is a VLA variable-length array type", type);
  return error_mark_node;
}
   if (!trivially_copyable_p (type))
diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast-to-array1.C 
b/gcc/testsuite/g++.dg/cpp2a/bit-cast-to-array1.C
new file mode 100644
index 000..e6e50c06389
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast-to-array1.C
@@ -0,0 +1,40 @@
+// { dg-do compile }
+
+class S { int s; };
+S s();
+class U { int a, b; };
+U u();
+
+void
+foo (int *q)
+{
+  __builtin_bit_cast (int [1], 0);
+  __builtin_bit_cast (S [1], 0);
+  __builtin_bit_cast (U [1], u);
+}
+
+template 
+void
+bar (int *q)
+{
+  int intN[N] = {};
+  int int2N[2*N] = {};
+  __builtin_bit_cast (int [N], intN);
+  __builtin_bit_cast (S [N], intN);
+  __builtin_bit_cast (U [N], int2N);
+}
+
+template 
+void
+baz (T1 ia, T2 sa, T3 ua)
+{
+  __builtin_bit_cast (T1, *ia);
+  __builtin_bit_cast (T2, *sa);
+  __builtin_bit_cast (T3, *ua);
+}
+
+void
+qux (S* sp, int *ip, U* up)
+{
+  baz  (ip, sp, up);
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast2.C 
b/gcc/testsuite/g++.dg/cpp2a/bit-cast2.C
index 6bb1760e621..7f1836ee4e9 100644
--- a/gcc/testsuite/g++.dg/cpp2a/bit-cast2.C
+++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast2.C
@@ -14,7 +14,7 @@ foo (int *q)
   __builtin_bit_cast (int, s); // { dg-error "'__builtin_bit_cast' 
source type 'S' is not trivially copyable" }
   __builtin_bit_cast (S, 0);   // { dg-error "'__builtin_bit_cast' 
destination type 'S' is not trivially copyable" }
   __builtin_bit_cast (int &, q);   // { dg-error "'__builtin_bit_cast' 
destination type 'int&' is not trivially copyable" }
-  __builtin_bit_cast (int [1], 0); // { dg-error "'__builtin_bit_cast' 
destination type \[^\n\r]* is an array type" }
+  __builtin_bit_cast (S [1], 0);   // { dg-error "'__builtin_bit_cast' 
destination type \[^\n\r]* is not trivially copyable" }
   __builtin_bit_cast (V, 0);   // { dg-error "invalid use of 
incomplete type 'struct V'" }
   __builtin_bit_cast (int, v);
   __builtin_bit_cast (int, *p);// { dg-error "invalid use of 
incomplete type 'struct V'" }
@@ -29,7 +29,7 @@ bar (int *q)
   __builtin_bit_cast (int, s); // { dg-er

Re: [PATCH] c++: __builtin_bit_cast To C array target type [PR103140]

2021-11-15 Thread will wray via Gcc-patches
Ping.

One motivation for allowing builtin bit_cast to builtin array is that
it enables direct bitwise constexpr comparisons via memcmp:

template
constexpr int bit_equal(A const& a, B const& b)
{
  static_assert( sizeof a == sizeof b,
  "bit_equal(a,b) requires same sizeof" );
  using bytes = unsigned char[sizeof(A)];
  return __builtin_memcmp(
 __builtin_bit_cast(bytes,a),
 __builtin_bit_cast(bytes,b),
 sizeof(A)) == 0;
}


On Mon, Nov 8, 2021 at 3:03 PM Will Wray  wrote:
>
> This patch allows __builtin_bit_cast to materialize a C array as its To type.
>
> It was developed as part of an implementation of P1997, array copy-semantics,
> but is independent, so makes sense to submit, review and merge ahead of it.
>
> gcc/cp/ChangeLog:
>
> * constexpr.c (check_bit_cast_type): handle ARRAY_TYPE check,
> (cxx_eval_bit_cast): handle ARRAY_TYPE copy.
> * semantics.c (cp_build_bit_cast): warn only on unbounded/VLA.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/cpp2a/bit-cast2.C: update XFAIL tests.
> * g++.dg/cpp2a/bit-cast-to-array1.C: New test.
> ---
>  gcc/cp/constexpr.c  |  8 -
>  gcc/cp/semantics.c  |  7 ++---
>  gcc/testsuite/g++.dg/cpp2a/bit-cast-to-array1.C | 40 
> +
>  gcc/testsuite/g++.dg/cpp2a/bit-cast2.C  |  8 ++---
>  4 files changed, 53 insertions(+), 10 deletions(-)
>
> diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
> index 453007c686b..be1cdada6f8 100644
> --- a/gcc/cp/constexpr.c
> +++ b/gcc/cp/constexpr.c
> @@ -4124,6 +4124,11 @@ static bool
>  check_bit_cast_type (const constexpr_ctx *ctx, location_t loc, tree type,
>  tree orig_type)
>  {
> +  if (TREE_CODE (type) == ARRAY_TYPE)
> +  return check_bit_cast_type (ctx, loc,
> + TYPE_MAIN_VARIANT (TREE_TYPE (type)),
> + orig_type);
> +
>if (TREE_CODE (type) == UNION_TYPE)
>  {
>if (!ctx->quiet)
> @@ -4280,7 +4285,8 @@ cxx_eval_bit_cast (const constexpr_ctx *ctx, tree t, 
> bool *non_constant_p,
>tree r = NULL_TREE;
>if (can_native_interpret_type_p (TREE_TYPE (t)))
>  r = native_interpret_expr (TREE_TYPE (t), ptr, len);
> -  else if (TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE)
> +  else if (TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE
> +  || TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
>  {
>r = native_interpret_aggregate (TREE_TYPE (t), ptr, 0, len);
>if (r != NULL_TREE)
> diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
> index 2443d032749..b3126b12abc 100644
> --- a/gcc/cp/semantics.c
> +++ b/gcc/cp/semantics.c
> @@ -11562,13 +11562,10 @@ cp_build_bit_cast (location_t loc, tree type, tree 
> arg,
>  {
>if (!complete_type_or_maybe_complain (type, NULL_TREE, complain))
> return error_mark_node;
> -  if (TREE_CODE (type) == ARRAY_TYPE)
> +  if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
> {
> - /* std::bit_cast for destination ARRAY_TYPE is not possible,
> -as functions may not return an array, so don't bother trying
> -to support this (and then deal with VLAs etc.).  */
>   error_at (loc, "%<__builtin_bit_cast%> destination type %qT "
> -"is an array type", type);
> +"is a VLA variable-length array type", type);
>   return error_mark_node;
> }
>if (!trivially_copyable_p (type))
> diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast-to-array1.C 
> b/gcc/testsuite/g++.dg/cpp2a/bit-cast-to-array1.C
> new file mode 100644
> index 000..e6e50c06389
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast-to-array1.C
> @@ -0,0 +1,40 @@
> +// { dg-do compile }
> +
> +class S { int s; };
> +S s();
> +class U { int a, b; };
> +U u();
> +
> +void
> +foo (int *q)
> +{
> +  __builtin_bit_cast (int [1], 0);
> +  __builtin_bit_cast (S [1], 0);
> +  __builtin_bit_cast (U [1], u);
> +}
> +
> +template 
> +void
> +bar (int *q)
> +{
> +  int intN[N] = {};
> +  int int2N[2*N] = {};
> +  __builtin_bit_cast (int [N], intN);
> +  __builtin_bit_cast (S [N], intN);
> +  __builtin_bit_cast (U [N], int2N);
> +}
> +
> +template 
> +void
> +baz (T1 ia, T2 sa, T3 ua)
> +{
> +  __builtin_bit_cast (T1, *ia);
> +  __builtin_bit_cast (T2, *sa);
> +  __builtin_bit_cast (T3, *ua);
> +}
> +
> +void
> +qux (S* sp, int *ip, U* up)
> +{
> +  baz  (ip, sp, up);
> +}
> diff --git a/gcc/testsuite/g++.dg/cpp2a/bit-cast2.C 
> b/gcc/testsuite/g++.dg/cpp2a/bit-cast2.C
> index 6bb1760e621..7f1836ee4e9 100644
> --- a/gcc/testsuite/g++.dg/cpp2a/bit-cast2.C
> +++ b/gcc/testsuite/g++.dg/cpp2a/bit-cast2.C
> @@ -14,7 +14,7 @@ foo (int *q)
>__builtin_bit_cast (int, s); // { dg-error "'__builtin_bit_cast' 
> source type 'S' is not trivially copyable" }
>__builtin_bit_cast (S, 0);  

PING: [PATCH] c++: designated init of char array by string constant [PR55227]

2021-11-15 Thread will wray via Gcc-patches
The fixes test out, as does the FIXME that's fixed based on the fixes...

Note that the bug causes bogus rejection of any designated initialization
of char array from a string literal, except for the singular case where the
string literal initializer size exactly matches the target char array size
and is not enclosed in optional braces:

  typedef struct
  C { char id[4]; } C;

  C a = {.id = "abc"};   // g++ accepts iff sizeof(C::c) == sizeof("abc")

  C b = {.id = {"abc"}}; // g++ rejects valid (gcc accepts)
  C c = {.id = "a"}; // g++ rejects valid (gcc accepts)

I'd expect this to be common in C code bases, so the bug would be hit in
any attempt to compile with g++. From the bugzilla comments, it seems that
the following 'workaround' is being used:

  C d = {{.id = "a"}};   // g++ accepts invalid (gcc rejects)

which 'works' in this case but is completely borked, consider:

  struct name {char first[32], second[32], third[32];};
  name DMR {{.first = "Dennis"}, {.third = "Ritchie"}};

Only g++ accepts, ignores the designators, interprets as positional,
and generates correspondingly invalid output:

DMR:
.string "Dennis"
.zero   25
.string "Ritchie"
.zero   24
.zero   32


Re: [PATCH] c++: __builtin_bit_cast To C array target type [PR103140]

2021-11-15 Thread will wray via Gcc-patches
Yes - direct use of any builtin is not to be encouraged, in user code.

This __builtin_bit_cast patch is intended to encourage experimentation
with array copy semantics now, on truck, in preparation for P1997.

The builtin bit_cast is strictly more powerful than the std::bit_cast
library function that it helps implement, is available in any -std mode
and might also be useful in C, independent of any standardization effort.

The semantics of bit_cast is clear - it's just the resulting rvalue array
itself is unfamiliar and tricky to handle within current language rules.

On Mon, Nov 15, 2021 at 12:21 PM Jakub Jelinek  wrote:
>
> On Mon, Nov 15, 2021 at 12:12:22PM -0500, will wray via Gcc-patches wrote:
> > One motivation for allowing builtin bit_cast to builtin array is that
> > it enables direct bitwise constexpr comparisons via memcmp:
> >
> > template
> > constexpr int bit_equal(A const& a, B const& b)
> > {
> >   static_assert( sizeof a == sizeof b,
> >   "bit_equal(a,b) requires same sizeof" );
> >   using bytes = unsigned char[sizeof(A)];
> >   return __builtin_memcmp(
> >  __builtin_bit_cast(bytes,a),
> >  __builtin_bit_cast(bytes,b),
> >  sizeof(A)) == 0;
> > }
>
> IMNSHO people shouldn't use this builtin directly, and we shouldn't
> encourage such uses, the standard interface is std::bit_cast.
>
> For the above, I don't see a reason to do it that way, you can
> instead portably:
>   struct bytes { unsigned char data[sizeof(A)]; };
>   bytes ab = std::bit_cast(bytes, a);
>   bytes bb = std::bit_cast(bytes, a);
>   for (size_t i = 0; i < sizeof(A); ++i)
> if (ab.data[i] != bb.data[i])
>   return false;
>   return true;
> - __builtin_memcmp isn't portable either and memcmp isn't constexpr.
>
> If P1997 is in, it is easy to support it in std::bit_cast and easy to
> explain what __builtin_bit_cast does for array types, but otherwise
> it is quite unclear what it exactly does...
>
> Jakub
>


[PATCH v3] c++: designated init of char array by string constant [PR55227]

2022-01-17 Thread will wray via Gcc-patches
V3  addresses Jason's review point - it.undoes unnecessary variable renames
(back from arr_init to str_init)

Also address "FIXME: this code is duplicated from reshape_init" in
cp_complete_array_type by always calling reshape_init on init-list.

PR c++/55227

gcc/cp/ChangeLog:

* decl.c (reshape_init_r): Only call has_designator_check when
   first_initializer_p or for the inner constructor element.
(cp_complete_array_type): Call reshape_init on braced-init-list.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/desig20.C: New test.
---
 gcc/cp/decl.c| 28 
 gcc/testsuite/g++.dg/cpp2a/desig20.C | 48 +++
 2 files changed, 58 insertions(+), 18 deletions(-)

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 0e37f1a59bc..425840b1cd9 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6811,6 +6811,7 @@ reshape_init_r (tree type, reshape_iter *d, tree
first_initializer_p,
 {
   tree str_init = init;
   tree stripped_str_init = stripped_init;
+  reshape_iter stripd = {};

   /* Strip one level of braces if and only if they enclose a single
  element (as allowed by [dcl.init.string]).  */
@@ -6818,7 +6819,8 @@ reshape_init_r (tree type, reshape_iter *d, tree
first_initializer_p,
&& TREE_CODE (stripped_str_init) == CONSTRUCTOR
&& CONSTRUCTOR_NELTS (stripped_str_init) == 1)
  {
-   str_init = (*CONSTRUCTOR_ELTS (stripped_str_init))[0].value;
+   stripd.cur = CONSTRUCTOR_ELT (stripped_str_init, 0);
+   str_init = stripd.cur->value;
stripped_str_init = tree_strip_any_location_wrapper (str_init);
  }

@@ -6827,7 +6829,8 @@ reshape_init_r (tree type, reshape_iter *d, tree
first_initializer_p,
  array types (one value per array element).  */
   if (TREE_CODE (stripped_str_init) == STRING_CST)
  {
-   if (has_designator_problem (d, complain))
+   if ((first_initializer_p && has_designator_problem (d, complain))
+   || (stripd.cur && has_designator_problem (&stripd, complain)))
  return error_mark_node;
d->cur++;
return str_init;
@@ -9544,22 +9547,11 @@ cp_complete_array_type (tree *ptype, tree
initial_value, bool do_default)
   if (initial_value)
 {
   /* An array of character type can be initialized from a
- brace-enclosed string constant.
-
- FIXME: this code is duplicated from reshape_init. Probably
- we should just call reshape_init here?  */
-  if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (*ptype)))
-   && TREE_CODE (initial_value) == CONSTRUCTOR
-   && !vec_safe_is_empty (CONSTRUCTOR_ELTS (initial_value)))
- {
-   vec *v = CONSTRUCTOR_ELTS (initial_value);
-   tree value = (*v)[0].value;
-   STRIP_ANY_LOCATION_WRAPPER (value);
-
-   if (TREE_CODE (value) == STRING_CST
-   && v->length () == 1)
- initial_value = value;
- }
+ brace-enclosed string constant so call reshape_init to
+ remove the optional braces from a braced string literal.  */
+  if (BRACE_ENCLOSED_INITIALIZER_P (initial_value))
+ initial_value = reshape_init (*ptype, initial_value,
+   tf_warning_or_error);

   /* If any of the elements are parameter packs, we can't actually
  complete this type now because the array size is dependent.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig20.C
b/gcc/testsuite/g++.dg/cpp2a/desig20.C
new file mode 100644
index 000..daadfa58855
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/desig20.C
@@ -0,0 +1,48 @@
+// PR c++/55227
+// Test designated initializer for char array by string constant
+
+// { dg-options "" }
+
+struct C {char a[2];};
+
+/* Case a, designated, unbraced, string-literal of the exact same size
+   as the initialized char array; valid and accepted before and after.  */
+C a = {.a="a"};
+
+/* Cases b,c,d, designated, braced or mimatched-size, string literal,
+   previously rejected; "C99 designator 'a' outside aggregate initializer".  */
+C b = {.a=""};
+C c = {.a={""}};
+C d = {.a={"a"}};
+
+/* Case e, designated char array field and braced, designated array element(s)
+   (with GNU [N]= extension) valid and accepted before and after.  */
+C e = {.a={[0]='a'}};
+
+/* Cases f,g,h, braced string literal, 'designated' within inner braces;
+   invalid, previously accepted as positional with 'designator' ignored.  */
+C f = {{[0]="a"}}; // { dg-error "C99 designator .0. outside
aggregate initializer" }
+C g = {{.a="a"}}; // { dg-error "C99 designator .a. outside aggregate
initializer" }
+C h = {{.b="a"}}; // { dg-error "C99 designator .b. outside aggregate
initializer" }
+
+char a2[][10] = { [0] = { "aaa" } };
+
+struct D { C c; int a[8]; };
+
+D x = { .c {.a={"a"}}, .a={1,2,3,4,5,6,7,8} };
+
+struct A { union { int a; char c[4]; }; };
+
+A non = { .c = "c++" };
+
+template 
+void t()
+{
+  C ca[] = { {.a=""}, {.a={""}}, };
+
+}
+
+void u()
+{
+  return t();
+}
-- 
2.35.0-rc1


Re: [PATCH v3] c++: designated init of char array by string constant [PR55227]

2022-01-17 Thread will wray via Gcc-patches
Attached
(the cut n paste looks like it removed some whitespace formatting)


0001-c-designated-init-of-char-array-by-string-constant-P.patch
Description: Binary data