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;