Hi,

I found the time to return to this issue, where -Wmissing-braces is often overeager to warn, thus annoying, for example, people using -Wall together with std::array:

    std::array<int, 3> s = { 1, 2, 3 };

I handle the issue following the letter of the suggestion given by Ian at the time: do not warn when the class type has only one field and that field is an aggregate (recursively, of course). Indeed, that seems to me quite conservative. I also make sure to change nothing wrt the designated initializers extension.

Bootstrapped and tested x86_64-linux.

Thanks,
Paolo.

////////////////////////
/cp
2012-05-26  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/25137
        * decl.c (reshape_init_r): Add bool parameter.
        (reshape_init_class): If the struct has only one field and that
        field is an aggregate, don't warn if there is only one set of
        braces in the initializer.
        (reshape_init_array_1, reshape_init_class, reshape_init): Adjust.

/testsuite
2012-05-26  Paolo Carlini  <paolo.carl...@oracle.com>

        PR c++/25137
        * g++.dg/warn/Wbraces3.C: New.

Index: testsuite/g++.dg/warn/Wbraces3.C
===================================================================
--- testsuite/g++.dg/warn/Wbraces3.C    (revision 0)
+++ testsuite/g++.dg/warn/Wbraces3.C    (revision 0)
@@ -0,0 +1,34 @@
+// PR c++/25137
+// { dg-options "-Wmissing-braces" }
+
+struct S { int s[3]; };
+S s1 = { 1, 1, 1 };
+
+struct S1 { int s[3]; };
+struct S2 { struct S1 a; };
+S2 s21 = { 1, 1, 1 }; 
+
+struct S3 { int s[3]; };
+struct S4 { struct S3 a; int b; };
+S4 s41 = { 1, 1, 1, 1 };   // { dg-warning "missing braces around initializer 
for 'S3'" }
+
+struct S5 { int s[3]; };
+struct S6 { struct S5 a; int b; };
+S6 s61 = { { 1, 1, 1 }, 1 };
+
+struct S7 { int s[3]; };
+struct S8 { int a; struct S7 b; };
+S8 s81 = { 1, { 1, 1, 1 } };
+
+struct S9 { int s[2]; };
+struct S10 { struct S9 a; struct S9 b; };
+S10 s101 = { { 1, 1 }, 1, 1 }; // { dg-warning "missing braces around 
initializer for 'S9'" }
+
+struct S11 { int s[2]; };
+struct S12 { struct S11 a; struct S11 b; };
+S12 s121 = { { 1, 1 }, { 1, 1 } };
+
+struct S13 { int i; };
+struct S14 { struct S13 a; };
+struct S15 { struct S14 b; };
+S15 s151 = { 1 };
Index: cp/decl.c
===================================================================
--- cp/decl.c   (revision 187907)
+++ cp/decl.c   (working copy)
@@ -4954,7 +4954,7 @@ typedef struct reshape_iterator_t
   constructor_elt *end;
 } reshape_iter;
 
-static tree reshape_init_r (tree, reshape_iter *, bool, tsubst_flags_t);
+static tree reshape_init_r (tree, reshape_iter *, bool, bool, tsubst_flags_t);
 
 /* FIELD is a FIELD_DECL or NULL.  In the former case, the value
    returned is the next FIELD_DECL (possibly FIELD itself) that can be
@@ -5014,7 +5014,7 @@ reshape_init_array_1 (tree elt_type, tree max_inde
 
       check_array_designated_initializer (d->cur, index);
       elt_init = reshape_init_r (elt_type, d, /*first_initializer_p=*/false,
-                                complain);
+                                /*no_warn_missing_braces=*/false, complain);
       if (elt_init == error_mark_node)
        return error_mark_node;
       CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_init),
@@ -5082,6 +5082,7 @@ reshape_init_class (tree type, reshape_iter *d, bo
 {
   tree field;
   tree new_init;
+  bool no_warn_missing_braces;
 
   gcc_assert (CLASS_TYPE_P (type));
 
@@ -5105,6 +5106,12 @@ reshape_init_class (tree type, reshape_iter *d, bo
       return new_init;
     }
 
+  /* If the struct has only one field and that field is an aggregate,
+     don't warn if there is only one set of braces in the initializer.  */
+  no_warn_missing_braces
+    = (next_initializable_field (DECL_CHAIN (field)) == NULL_TREE
+       && CP_AGGREGATE_TYPE_P (TREE_TYPE (field)));
+
   /* Loop through the initializable fields, gathering initializers.  */
   while (d->cur != d->end)
     {
@@ -5125,7 +5132,10 @@ reshape_init_class (tree type, reshape_iter *d, bo
            /* We already reshaped this.  */
            gcc_assert (d->cur->index == field);
          else
-           field = lookup_field_1 (type, d->cur->index, /*want_type=*/false);
+           {
+             field = lookup_field_1 (type, d->cur->index, /*want_type=*/false);
+             no_warn_missing_braces = false;
+           }
 
          if (!field || TREE_CODE (field) != FIELD_DECL)
            {
@@ -5141,7 +5151,8 @@ reshape_init_class (tree type, reshape_iter *d, bo
        break;
 
       field_init = reshape_init_r (TREE_TYPE (field), d,
-                                  /*first_initializer_p=*/false, complain);
+                                  /*first_initializer_p=*/false,
+                                  no_warn_missing_braces, complain);
       if (field_init == error_mark_node)
        return error_mark_node;
 
@@ -5183,11 +5194,12 @@ has_designator_problem (reshape_iter *d, tsubst_fl
    a CONSTRUCTOR). TYPE is the type of the variable being initialized, D is the
    iterator within the CONSTRUCTOR which points to the initializer to process.
    FIRST_INITIALIZER_P is true if this is the first initializer of the
-   outermost CONSTRUCTOR node.  */
+   outermost CONSTRUCTOR node.  If NO_WARN_MISSING_BRACES is true don't warn
+   about missing braces around initializer.  */
 
 static tree
 reshape_init_r (tree type, reshape_iter *d, bool first_initializer_p,
-               tsubst_flags_t complain)
+               bool no_warn_missing_braces, tsubst_flags_t complain)
 {
   tree init = d->cur->value;
 
@@ -5335,8 +5347,9 @@ reshape_init_r (tree type, reshape_iter *d, bool f
            }
        }
 
-      warning (OPT_Wmissing_braces, "missing braces around initializer for 
%qT",
-              type);
+      if (!no_warn_missing_braces)
+       warning (OPT_Wmissing_braces,
+                "missing braces around initializer for %qT", type);
     }
 
   /* Dispatch to specialized routines.  */
@@ -5385,7 +5398,8 @@ reshape_init (tree type, tree init, tsubst_flags_t
   d.cur = VEC_index (constructor_elt, v, 0);
   d.end = d.cur + VEC_length (constructor_elt, v);
 
-  new_init = reshape_init_r (type, &d, true, complain);
+  new_init = reshape_init_r (type, &d, true, /*no_warn_missing_braces=*/false,
+                            complain);
   if (new_init == error_mark_node)
     return error_mark_node;
 

Reply via email to