diff mbox

[C++] PR 25137

Message ID 4FC0DB08.4090704@oracle.com
State New
Headers show

Commit Message

Paolo Carlini May 26, 2012, 1:30 p.m. UTC
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.carlini@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.carlini@oracle.com>

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

Patch

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;