[C++ PATCH] Fix pretty-print of enumerator ids (PR c++/87364)

2018-10-08 Thread will wray
Hi,

A PR to fix Bug 87364 - Pretty print of enumerator never prints the id,
always falls back to C-style cast output

The fix is tested with the code attached to the bug report and additional
usage over the past few weeks.

Bootstrap and regtested on x86_64-linux. OK for trunk?


2018-10-08  Will Wray  

PR c++/87364
* c-pretty-print.c (pp_c_enumeration_constant): fix comparison.
* cxx-pretty-print.c (pp_cxx_enumeration_constant): New; add
nested-specifiers prefix to enum id plus enum type for scoped enum.

Index: gcc/c-family/c-pretty-print.h
===
--- gcc/c-family/c-pretty-print.h (revision 264938)
+++ gcc/c-family/c-pretty-print.h (working copy)
@@ -128,11 +128,13 @@ void pp_c_logical_or_expression (c_prett
 void pp_c_expression_list (c_pretty_printer *, tree);
 void pp_c_constructor_elts (c_pretty_printer *, vec *);
 void pp_c_call_argument_list (c_pretty_printer *, tree);
+void pp_c_type_cast (c_pretty_printer *, tree);
 void pp_c_cast_expression (c_pretty_printer *, tree);
 void pp_c_init_declarator (c_pretty_printer *, tree);
 void pp_c_ws_string (c_pretty_printer *, const char *);
 void pp_c_identifier (c_pretty_printer *, const char *);
 void pp_c_string_literal (c_pretty_printer *, tree);
+void pp_c_integer_constant (c_pretty_printer *, tree);

 void print_c_tree (FILE *file, tree t);

Index: gcc/c-family/c-pretty-print.c
===
--- gcc/c-family/c-pretty-print.c (revision 264938)
+++ gcc/c-family/c-pretty-print.c (working copy)
@@ -192,7 +192,7 @@ pp_c_cv_qualifiers (c_pretty_printer *pp

 /* Pretty-print T using the type-cast notation '( type-name )'.  */

-static void
+void
 pp_c_type_cast (c_pretty_printer *pp, tree t)
 {
   pp_c_left_paren (pp);
@@ -908,7 +908,7 @@ pp_c_void_constant (c_pretty_printer *pp

 /* Pretty-print an INTEGER literal.  */

-static void
+void
 pp_c_integer_constant (c_pretty_printer *pp, tree i)
 {
   if (tree_fits_shwi_p (i))
@@ -968,21 +968,20 @@ pp_c_bool_constant (c_pretty_printer *pp
 pp_unsupported_tree (pp, b);
 }

-/* Attempt to print out an ENUMERATOR.  Return true on success.  Else
return
-   false; that means the value was obtained by a cast, in which case
-   print out the type-id part of the cast-expression -- the casted value
-   is then printed by pp_c_integer_literal.  */
+/* Given a value e of ENUMERAL_TYPE:
+   Print out the first ENUMERATOR id with value e, if one is found,
+   else print out the value as a C-style cast (type-id)value.  */

-static bool
+static void
 pp_c_enumeration_constant (c_pretty_printer *pp, tree e)
 {
-  bool value_is_named = true;
   tree type = TREE_TYPE (e);
   tree value;

   /* Find the name of this constant.  */
   for (value = TYPE_VALUES (type);
-   value != NULL_TREE && !tree_int_cst_equal (TREE_VALUE (value), e);
+   value != NULL_TREE
+   && !tree_int_cst_equal (DECL_INITIAL (TREE_VALUE (value)), e);
value = TREE_CHAIN (value))
 ;

@@ -992,10 +991,8 @@ pp_c_enumeration_constant (c_pretty_prin
 {
   /* Value must have been cast.  */
   pp_c_type_cast (pp, type);
-  value_is_named = false;
+  pp_c_integer_constant (pp, e);
 }
-
-  return value_is_named;
 }

 /* Print out a REAL value as a decimal-floating-constant.  */
@@ -1140,9 +1137,8 @@ c_pretty_printer::constant (tree e)
pp_c_bool_constant (this, e);
  else if (type == char_type_node)
pp_c_character_constant (this, e);
- else if (TREE_CODE (type) == ENUMERAL_TYPE
- && pp_c_enumeration_constant (this, e))
-   ;
+ else if (TREE_CODE (type) == ENUMERAL_TYPE)
+   pp_c_enumeration_constant (this, e);
  else
pp_c_integer_constant (this, e);
   }
Index: gcc/cp/cxx-pretty-print.c
===
--- gcc/cp/cxx-pretty-print.c (revision 264938)
+++ gcc/cp/cxx-pretty-print.c (working copy)
@@ -294,6 +294,39 @@ pp_cxx_qualified_id (cxx_pretty_printer
 }
 }

+/* Given a value e of ENUMERAL_TYPE:
+   Print out the first ENUMERATOR id with value e, if one is found,
+   (including nested names but excluding the enum name if unscoped)
+   else print out the value as a C-style cast (type-id)value.  */
+
+static void
+pp_cxx_enumeration_constant (cxx_pretty_printer *pp, tree e)
+{
+  tree type = TREE_TYPE (e);
+  tree value;
+
+  /* Find the name of this constant.  */
+  for (value = TYPE_VALUES (type);
+   value != NULL_TREE
+   && !tree_int_cst_equal (DECL_INITIAL (TREE_VALUE (value)), e);
+   value = TREE_CHAIN (value))
+;
+
+  if (value != NULL_TREE)
+{
+  if (!ENUM_IS_SCOPED (type))
+ type = get_containing_scope (type);
+  pp_cxx_nested_name_specifier (pp, type);
+  pp->id_expression (TREE_PURPOSE (value));
+}
+  else
+{
+  /* Value must have been cast.  */
+   pp_c_type_cast (pp, type);
+   pp_c_integer_constant (pp, e);
+}
+}
+

 void
 cx

Re: [C++ PATCH] Fix pretty-print of enumerator ids (PR c++/87364)

2018-10-12 Thread will wray
Thanks for the commit, for fixing the formatting issues and for writing the
detailed ChangeLog entry.
Sorry for those issues; all looks good now - there are only whitespace
diffs between trunk and my patched version.
My tests pass, including the test code attached to the bug report.

Will

IIRC I cut-n-pasted the patch from terminal to gmail, that must've messed
with formatting.
The patch was also attached to the bug report. I'll attach as text to the
email next time.

On Fri, Oct 12, 2018 at 3:39 AM Christophe Lyon 
wrote:

> On Fri, 12 Oct 2018 at 07:47, Christophe Lyon
>  wrote:
> >
> > On Fri, 12 Oct 2018 at 05:37, Jeff Law  wrote:
> > >
> > > On 10/8/18 11:12 AM, will wray wrote:
> > > > Hi,
> > > >
> > > > A PR to fix Bug 87364 - Pretty print of enumerator never prints the
> id,
> > > > always falls back to C-style cast output
> > > >
> > > > The fix is tested with the code attached to the bug report and
> additional
> > > > usage over the past few weeks.
> > > >
> > > > Bootstrap and regtested on x86_64-linux. OK for trunk?
> > > >
> > > >
> > > > 2018-10-08  Will Wray  
> > > >
> > > > PR c++/87364
> > > > * c-pretty-print.c (pp_c_enumeration_constant): fix comparison.
> > > > * cxx-pretty-print.c (pp_cxx_enumeration_constant): New; add
> > > > nested-specifiers prefix to enum id plus enum type for scoped enum.
> > > THanks.  I fixed up some whitespace issues and the ChangeLog entry
> > > before committing to the trunk.
> > >
> > > Also note for any future contributions, it looks like your mailer is
> > > messing up tabs and wrapping lines. That makes applying the patch more
> > > difficult than it should be.
> > >
> >
> > Hi,
> >
> > This commit broke the GCC builds:
> >
> /tmp/3768585_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/c-family/c-pretty-print.c:
> > In member function 'virtual void c_pretty_printer::constant(tree)':
> >
> /tmp/3768585_6.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/gcc/c-family/c-pretty-print.c:1141:39:
> > error: expected ';' before ')' token
> > pp_c_enumeration_constant (this, e))
> >^
> > make[2]: *** [c-family/c-pretty-print.o] Error 1
> >
>
> I fixed the build with the obvious r265078:
>
> 2018-10-12  Christophe Lyon  
>
>PR c++/87364
>* c-pretty-print.c (c_pretty_printer::constant): Fix typo.
>
> Index: gcc/c-family/c-pretty-print.c
> ===
> --- gcc/c-family/c-pretty-print.c   (revision 265077)
> +++ gcc/c-family/c-pretty-print.c   (revision 265078)
> @@ -1138,7 +1138,7 @@
> else if (type == char_type_node)
>   pp_c_character_constant (this, e);
> else if (TREE_CODE (type) == ENUMERAL_TYPE)
> - pp_c_enumeration_constant (this, e))
> + pp_c_enumeration_constant (this, e);
> else
>   pp_c_integer_constant (this, e);
>}
>


Re: [C++ PATCH] preview: Fix braces around scalar initializer (C++/88572) Inbox x

2019-02-20 Thread will wray
I've updated the patch to address both comments; the first conditional
now deals only with C++98, an extra 'else if' block deals with both
empty scalar var init and scalar sub-object init with too many braces.

I'll bump from 'preview' to 'proposed' -
please review for inclusion on trunk and possible backports.

I've stressed the patch with my own code which does SFINAE on these errors;
all is working as expected, portable with Clang trunk.

It bootstraps and regtests for me on x86_64-linux.

On Fri, Feb 15, 2019 at 11:15 PM Jason Merrill  wrote:

> On 2/14/19 7:09 PM, will wray wrote:
> > Thanks Jason.
> > Adding this 'else if' condition afterwards seems to work:
> >
> >   else if (BRACE_ENCLOSED_INITIALIZER_P (CONSTRUCTOR_ELT
> > (stripped_init,0)->value))
> > {
> >if (complain & tf_error)
> >   error ("too many braces around scalar initializer for
> > type %qT", type);
> >init = error_mark_node;
> >  }
> >
> > I'll regtest that and run through the rest of the reshape logic again.
>
> I think the first_initializer_p check should be part of this condition
> rather than the C++98 condition.
> > What do you think about the fact that this patch now rejects empty
> > brace inits like int{{}}
> > that was previously accepted? It's a breaking change for any code that
> > was incorrectly doing that.
>
> The change makes sense to me; I would hope that such code is rare.
>
> Jason
>
> > On Thu, Feb 14, 2019 at 6:02 PM Jason Merrill  wrote:
> >>
> >> On 2/12/19 6:04 PM, will wray wrote:
> >>> A proposed patch for Bug 88572 is attached to the bug report along
> >>> with a short description and Change Log (a link there gives a pretty
> >>> diff of the patch):
> >>>
> >>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88572#c15
> >>>
> >>> I'd appreciate any review of this patch, as well as testing on more
> >>> platforms. The patch with updated tests passes for me on x86_64.
> >>>
> >>> There's also test code in bug comment #1 that demonstrates SFINAE
> >>> based on the nesting of braces. It could also be added to the
> >>> testsuite - I'm not sure how to do that or if it is needed.
> >>
> >>> + if (cxx_dialect < cxx11 || first_initializer_p)
> >>
> >> I would expect this to miss the error in
> >>
> >> struct A { int i; } a = {{{42}}};
> >>
> >> I see that we end up complaining about this in convert_like_real because
> >> implicit_conversion catches the problem here, but I think we ought to
> >> catch it in reshape_init_r as well.  So, also complain if the element of
> >> the CONSTRUCTOR is also BRACE_ENCLOSED_INITIALIZER_P.
> >>
> >> Jason
>
>


[C++ PATCH] preview: Fix braces around scalar initializer (C++/88572) Inbox x

2019-02-12 Thread will wray
A proposed patch for Bug 88572 is attached to the bug report along
with a short description and Change Log (a link there gives a pretty
diff of the patch):

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88572#c15

I'd appreciate any review of this patch, as well as testing on more
platforms. The patch with updated tests passes for me on x86_64.

There's also test code in bug comment #1 that demonstrates SFINAE
based on the nesting of braces. It could also be added to the
testsuite - I'm not sure how to do that or if it is needed.


braces_patch
Description: Binary data


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);
&

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