public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r11-9678] c++: designated init and aggregate members [PR103337]
@ 2022-03-22  5:18 Jason Merrill
  0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2022-03-22  5:18 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:2b2f575e6f27acc0c7ba6a3affc760bf2b96a84b

commit r11-9678-g2b2f575e6f27acc0c7ba6a3affc760bf2b96a84b
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Mar 21 09:57:28 2022 -0400

    c++: designated init and aggregate members [PR103337]
    
    Our C++20 designated initializer handling was broken with members of class
    type; we would find the relevant member and then try to find a member of
    the member with the same name.  Or we would sometimes ignore the designator
    entirely.  The former problem is fixed by the change to reshape_init_class,
    the latter by the change to reshape_init_r.
    
            PR c++/103337
            PR c++/102740
            PR c++/103299
            PR c++/102538
    
    gcc/cp/ChangeLog:
    
            * decl.c (reshape_init_class): Avoid looking for designator
            after we found it.
            (reshape_init_r): Keep looking for designator.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/ext/flexary3.C: Remove one error.
            * g++.dg/parse/pr43765.C: Likewise.
            * g++.dg/cpp2a/desig22.C: New test.
            * g++.dg/cpp2a/desig23.C: New test.
            * g++.dg/cpp2a/desig24.C: New test.
            * g++.dg/cpp2a/desig25.C: New test.

Diff:
---
 gcc/cp/decl.c                        | 47 ++++++++++++++++++++++++++++++++----
 gcc/testsuite/g++.dg/cpp2a/desig22.C | 11 +++++++++
 gcc/testsuite/g++.dg/cpp2a/desig23.C | 20 +++++++++++++++
 gcc/testsuite/g++.dg/cpp2a/desig24.C | 11 +++++++++
 gcc/testsuite/g++.dg/cpp2a/desig25.C | 13 ++++++++++
 gcc/testsuite/g++.dg/ext/flexary3.C  |  2 +-
 gcc/testsuite/g++.dg/parse/pr43765.C |  6 ++---
 7 files changed, 101 insertions(+), 9 deletions(-)

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 6d3e764fb14..1ba648be1cc 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6409,8 +6409,9 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
     {
       tree field_init;
       constructor_elt *old_cur = d->cur;
+      bool direct_desig = false;
 
-      /* Handle designated initializers, as an extension.  */
+      /* Handle C++20 designated initializers.  */
       if (d->cur->index)
 	{
 	  if (d->cur->index == error_mark_node)
@@ -6428,7 +6429,10 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
 		}
 	    }
 	  else if (TREE_CODE (d->cur->index) == IDENTIFIER_NODE)
-	    field = get_class_binding (type, d->cur->index);
+	    {
+	      field = get_class_binding (type, d->cur->index);
+	      direct_desig = true;
+	    }
 	  else
 	    {
 	      if (complain & tf_error)
@@ -6474,6 +6478,7 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
 		  break;
 	      gcc_assert (aafield);
 	      field = aafield;
+	      direct_desig = false;
 	    }
 	}
 
@@ -6488,9 +6493,32 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
 	   assumed to correspond to no elements of the initializer list.  */
 	goto continue_;
 
-      field_init = reshape_init_r (TREE_TYPE (field), d,
-				   /*first_initializer_p=*/NULL_TREE,
-				   complain);
+      if (direct_desig)
+	{
+	  /* The designated field F is initialized from this one element:
+	     Temporarily clear the designator so a recursive reshape_init_class
+	     doesn't try to find it again in F, and adjust d->end so we don't
+	     try to use the next initializer to initialize another member of F.
+
+	     Note that we don't want these changes if we found the designator
+	     inside an anon aggr above; we leave them alone to implement:
+
+	     "If the element is an anonymous union member and the initializer
+	     list is a brace-enclosed designated- initializer-list, the element
+	     is initialized by the designated-initializer-list { D }, where D
+	     is the designated- initializer-clause naming a member of the
+	     anonymous union member."  */
+	  auto end_ = make_temp_override (d->end, d->cur + 1);
+	  auto idx_ = make_temp_override (d->cur->index, NULL_TREE);
+	  field_init = reshape_init_r (TREE_TYPE (field), d,
+				       /*first_initializer_p=*/NULL_TREE,
+				       complain);
+	}
+      else
+	field_init = reshape_init_r (TREE_TYPE (field), d,
+				     /*first_initializer_p=*/NULL_TREE,
+				     complain);
+
       if (field_init == error_mark_node)
 	return error_mark_node;
 
@@ -6742,6 +6770,15 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p,
 	     to handle initialization of arrays and similar.  */
 	  else if (COMPOUND_LITERAL_P (stripped_init))
 	    gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (stripped_init));
+	  /* If we have an unresolved designator, we need to find the member it
+	     designates within TYPE, so proceed to the routines below.  For
+	     FIELD_DECL or INTEGER_CST designators, we're already initializing
+	     the designated element.  */
+	  else if (d->cur->index
+		   && TREE_CODE (d->cur->index) == IDENTIFIER_NODE)
+	    /* Brace elision with designators is only permitted for anonymous
+	       aggregates.  */
+	    gcc_checking_assert (ANON_AGGR_TYPE_P (type));
 	  /* A CONSTRUCTOR of the target's type is a previously
 	     digested initializer.  */
 	  else if (same_type_ignoring_top_level_qualifiers_p (type, init_type))
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig22.C b/gcc/testsuite/g++.dg/cpp2a/desig22.C
new file mode 100644
index 00000000000..ba083f8e3d5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/desig22.C
@@ -0,0 +1,11 @@
+// PR c++/103337
+// { dg-do compile { target c++20 } }
+
+struct op_t {
+  struct put_t {
+    int x;
+  } put;
+};
+
+op_t x{0};       // OK
+op_t y{.put=0};  // bogus error: 'op_t::put_t' has no non-static data member named 'put'
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig23.C b/gcc/testsuite/g++.dg/cpp2a/desig23.C
new file mode 100644
index 00000000000..4354e644f6a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/desig23.C
@@ -0,0 +1,20 @@
+// PR c++/102740
+// { dg-do compile { target c++20 } }
+// { dg-additional-options -Wmissing-braces }
+
+typedef struct {
+    union {
+        struct {
+            const void* content;
+        } put;
+    };
+} op_t;
+
+op_t f(const char* alias) {
+    return op_t{
+        .put =
+            {
+                .content = alias,
+            },
+    };				// { dg-warning "missing braces" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig24.C b/gcc/testsuite/g++.dg/cpp2a/desig24.C
new file mode 100644
index 00000000000..219cc9c3b8e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/desig24.C
@@ -0,0 +1,11 @@
+// PR c++/103299
+// { dg-do compile { target c++20 } }
+
+struct foo {
+  union {
+    int fp1{};
+    char fp2;
+  };
+};
+
+static_assert(foo{.fp2={}}.fp2 == 0);
diff --git a/gcc/testsuite/g++.dg/cpp2a/desig25.C b/gcc/testsuite/g++.dg/cpp2a/desig25.C
new file mode 100644
index 00000000000..9da958c29e9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/desig25.C
@@ -0,0 +1,13 @@
+// PR c++/102538
+// { dg-do run { target c++20 } }
+
+struct X { union { char r8[8]; int r32[2]; }; };
+struct Y { X v[1]; };
+Y x = { { { .r32 = { 5, 6 } } } };
+
+int
+main ()
+{
+  if (x.v[0].r32[0] != 5 || x.v[0].r32[1] != 6)
+    __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/ext/flexary3.C b/gcc/testsuite/g++.dg/ext/flexary3.C
index 34b17254f8c..8344b42dd16 100644
--- a/gcc/testsuite/g++.dg/ext/flexary3.C
+++ b/gcc/testsuite/g++.dg/ext/flexary3.C
@@ -16,7 +16,7 @@ struct s {
 
 int main()
 {
-    struct s s = { .c = 0 };	// { dg-error "initializer" }
+    struct s s = { .c = 0 };
     // { dg-error "non-static initialization of a flexible array member" "" { target *-*-* } .-1 }
     return 0;
 }
diff --git a/gcc/testsuite/g++.dg/parse/pr43765.C b/gcc/testsuite/g++.dg/parse/pr43765.C
index 5e602204007..aa099a4d20b 100644
--- a/gcc/testsuite/g++.dg/parse/pr43765.C
+++ b/gcc/testsuite/g++.dg/parse/pr43765.C
@@ -12,6 +12,6 @@ SomeType vals[] =
     {
         { 0, values : temp, },	 // { dg-error "either all initializer clauses should be designated or none of them should be" "" { target c++2a } }
         0
-    };   // { dg-error "GNU-style designated initializer for an array|cannot convert" }
-// (note the error above is on the wrong line)
-	 // { dg-error "initialization of flexible array member in a nested context" "" { target *-*-* } .-2 }
+    };
+// (note the error below is on the wrong line)
+// { dg-error "initialization of flexible array member in a nested context" "" { target *-*-* } .-2 }


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-03-22  5:18 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-22  5:18 [gcc r11-9678] c++: designated init and aggregate members [PR103337] 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).