public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH v3] c++: designated init of char array by string constant [PR55227]
@ 2022-01-17 19:23 will wray
  2022-01-17 19:29 ` will wray
  0 siblings, 1 reply; 3+ messages in thread
From: will wray @ 2022-01-17 19:23 UTC (permalink / raw)
  To: gcc-patches List; +Cc: Marek Polacek, Jason Merrill

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<constructor_elt, va_gc> *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 00000000000..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 <class T>
+void t()
+{
+  C ca[] = { {.a=""}, {.a={""}}, };
+
+}
+
+void u()
+{
+  return t<void>();
+}
-- 
2.35.0-rc1

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v3] c++: designated init of char array by string constant [PR55227]
  2022-01-17 19:23 [PATCH v3] c++: designated init of char array by string constant [PR55227] will wray
@ 2022-01-17 19:29 ` will wray
  2022-01-23 22:28   ` Jason Merrill
  0 siblings, 1 reply; 3+ messages in thread
From: will wray @ 2022-01-17 19:29 UTC (permalink / raw)
  To: gcc-patches List; +Cc: Marek Polacek, Jason Merrill

[-- Attachment #1: Type: text/plain, Size: 76 bytes --]

Attached
(the cut n paste looks like it removed some whitespace formatting)

[-- Attachment #2: 0001-c-designated-init-of-char-array-by-string-constant-P.patch --]
[-- Type: application/octet-stream, Size: 5092 bytes --]

From 415596f6ba978f999e00bf4990e0d3b99f903903 Mon Sep 17 00:00:00 2001
From: Will Wray <wjwray@gmail.com>
Date: Fri, 14 Jan 2022 19:28:53 -0500
Subject: [PATCH] c++: designated init of char array by string constant
 [PR55227]

Also address "FIXME: this code is duplicated from reshape_init" in
cp_complete_array_type by always calling reshape_init on init-list.
V3 undoes variable renames back from arr_init to str_init, addresses
Jason's review point.

	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<constructor_elt, va_gc> *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 00000000000..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 <class T>
+void t()
+{
+  C ca[] = { {.a=""}, {.a={""}}, };
+
+}
+
+void u()
+{
+  return t<void>();
+}
-- 
2.35.0-rc1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v3] c++: designated init of char array by string constant [PR55227]
  2022-01-17 19:29 ` will wray
@ 2022-01-23 22:28   ` Jason Merrill
  0 siblings, 0 replies; 3+ messages in thread
From: Jason Merrill @ 2022-01-23 22:28 UTC (permalink / raw)
  To: will wray, gcc-patches List; +Cc: Marek Polacek

On 1/17/22 14:29, will wray wrote:
> Attached
> (the cut n paste looks like it removed some whitespace formatting)

Pushed, thanks!  I incorporated the introduction from your initial email 
in the commit message.

Jason


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-01-23 22:28 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-17 19:23 [PATCH v3] c++: designated init of char array by string constant [PR55227] will wray
2022-01-17 19:29 ` will wray
2022-01-23 22:28   ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).