[gcc r17-3290] c++: clarify reshape_init designator handling

Jason Merrill via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:34fd4c49fbe6ff643fc6f5f2cccca03c86535ee0

commit r17-3290-g34fd4c49fbe6ff643fc6f5f2cccca03c86535ee0
Author: Jason Merrill <[email protected]>
Date:   Tue Aug 4 19:45:17 2026 -0400

    c++: clarify reshape_init designator handling
    
    While looking at r17-3010, I found the handling of designators in
    reshape_init* unclear, particularly in reshape_init_r.  Jakub's patch
    recurses directly from reshape_init_class to itself to avoid this confusion.
    
    With this patch, if we see a designator in reshape_init_r, it designates a
    member of TYPE, which means brace elision if !first_initializer_p.  For this
    to be true I needed to adjust reshape_init_array_1 to use
    reshape_single_init from c++/103337.  And then if we see a designator and
    TYPE is a class or array, we know we're initializing an element so we don't
    consider initializing TYPE directly.
    
    gcc/cp/ChangeLog:
    
            * decl.cc (reshape_single_init): Declare sooner.
            (reshape_init_array_1): Use it.
            (reshape_init_class): Drop "subclass" case.
            (reshape_init_r): d->cur->index always means initializing
            an element.

Diff:
---
 gcc/cp/decl.cc | 50 ++++++++++++++++++++++++--------------------------
 1 file changed, 24 insertions(+), 26 deletions(-)

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index cb3eb74c3a1c..cd533217ec40 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -7477,6 +7477,7 @@ struct reshape_iter
 };
 
 static tree reshape_init_r (tree, reshape_iter *, tree, tsubst_flags_t);
+static tree reshape_single_init (tree, tree, tsubst_flags_t);
 
 /* FIELD is an element of TYPE_FIELDS or NULL.  In the former case, the value
    returned is the next FIELD_DECL (possibly FIELD itself) that can be
@@ -7663,6 +7664,11 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
 	    }
 	  TREE_TYPE (elt_init) = elt_type;
 	}
+      else if (d->cur->index)
+	{
+	  elt_init = reshape_single_init (elt_type, d->cur->value, complain);
+	  d->cur++;
+	}
       else
 	elt_init = reshape_init_r (elt_type, d,
 				   /*first_initializer_p=*/NULL_TREE,
@@ -7860,7 +7866,6 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
       constructor_elt *old_cur = d->cur;
       unsigned old_raw_idx = d->raw_idx;
       bool direct_desig = false;
-      bool subclass = false;
 
       /* Handle C++20 designated initializers.  */
       if (d->cur->index)
@@ -8020,7 +8025,6 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
 	      gcc_assert (aafield);
 	      field = aafield;
 	      direct_desig = false;
-	      subclass = true;
 	    }
 	}
 
@@ -8052,18 +8056,6 @@ reshape_init_class (tree type, reshape_iter *d, bool first_initializer_p,
 					    d->cur->value, complain);
 	  d->cur++;
 	}
-      else if (subclass)
-	{
-	  if (complain & tf_warning)
-	    warning (OPT_Wmissing_braces,
-		     "missing braces around initializer for %qT",
-		     TREE_TYPE (field));
-	  field_init = reshape_init_class (TREE_TYPE (field), d,
-					   /*first_initializer_p=*/NULL_TREE,
-					   complain);
-	  if (TREE_CODE (field_init) == CONSTRUCTOR)
-	    CONSTRUCTOR_BRACES_ELIDED_P (field_init) = true;
-	}
       else
 	field_init = reshape_init_r (TREE_TYPE (field), d,
 				     /*first_initializer_p=*/NULL_TREE,
@@ -8189,6 +8181,21 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p,
       return init;
     }
 
+  /* If we have a designator, d doesn't initialize TYPE directly, it
+     initializes an element, with brace elision if !first_initializer_p.  But
+     if TYPE is non-aggregate (and we didn't already return error_mark_node),
+     we should have errored about the designator in has_designator_problem, so
+     now ignore it for error recovery.  */
+  if (d->cur->index)
+    {
+      /* Deliberately not CP_AGGREGATE_TYPE_P to get a better diagnostic for
+	 trying to designate a member of a non-aggregate class.  */
+      if (AGGREGATE_TYPE_P (type))
+	goto skip_single;
+      else
+	gcc_checking_assert (seen_error ());
+    }
+
   /* A non-aggregate type is always initialized with a single
      initializer.  */
   if (!CP_AGGREGATE_TYPE_P (type)
@@ -8239,8 +8246,6 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p,
      initialized from that element."  Even if T is an aggregate.  */
   if (cxx_dialect >= cxx11 && (CLASS_TYPE_P (type) || VECTOR_TYPE_P (type))
       && first_initializer_p
-      /* But not if it's a designated init.  */
-      && !d->cur->index
       && d->end - d->cur == 1
       && TREE_CODE (init) != RAW_DATA_CST
       && reference_related_p (type, TREE_TYPE (init)))
@@ -8273,6 +8278,8 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p,
 			      LOOKUP_NORMAL, complain)))
     return consume_init (init, d);
 
+ skip_single:
+
   /* [dcl.init.string]
 
       A char array (whether plain char, signed char, or unsigned char)
@@ -8317,7 +8324,7 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p,
   bool braces_elided_p = false;
   if (!first_initializer_p)
     {
-      if (TREE_CODE (stripped_init) == CONSTRUCTOR)
+      if (TREE_CODE (stripped_init) == CONSTRUCTOR && !d->cur->index)
 	{
 	  tree init_type = TREE_TYPE (init);
 	  if (init_type && TYPE_PTRMEMFUNC_P (init_type))
@@ -8330,15 +8337,6 @@ 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))
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.