[PATCH] Fix C -Woverride-init warning (PR c/36489)

Jakub Jelinek jakub@redhat.com
Tue Dec 30 00:54:00 GMT 2008


Hi!

add_pending_init and output_init_element warn with -Woverride-init
(or with initializers with side-effects) even for deeper designated
initializers when no overriding happens.  The following patch
fixes it by not warning when process_init_element pop_init_level(1),
where initializers are merged together.  We only want to warn at the
lowest level, as shown on the testcase.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2008-12-30  Jakub Jelinek  <jakub@redhat.com>

	PR c/36489
	* c-typeck.c (add_pending_init): Add IMPLICIT argument.  Only
	warn about overwriting initializer with side-effects or
	-Woverride-init if !IMPLICIT.
	(output_init_element): Likewise.  Pass IMPLICIT down to
	add_pending_init.
	(process_init_element): Add IMPLICIT argument.  Pass it down
	to output_init_element.
	(push_init_element, pop_init_level, set_designator): Adjust
	process_init_element callers.
	(set_nonincremental_init, set_nonincremental_init_from_string):
	Adjust add_pending_init callers.
	(output_pending_init_elements): Adjust output_init_element callers.
	* c-tree.h (process_init_element): Adjust prototype.
	* c-parser.c (c_parser_initelt, c_parser_initval): Adjust
	process_init_element callers.

	* gcc.dg/pr36489.c: New test.

--- gcc/c-typeck.c.jj	2008-12-11 09:46:57.000000000 +0100
+++ gcc/c-typeck.c	2008-12-29 23:59:02.000000000 +0100
@@ -92,11 +92,11 @@ static int spelling_length (void);
 static char *print_spelling (char *);
 static void warning_init (int, const char *);
 static tree digest_init (tree, tree, bool, int);
-static void output_init_element (tree, bool, tree, tree, int);
+static void output_init_element (tree, bool, tree, tree, int, bool);
 static void output_pending_init_elements (int);
 static int set_designator (int);
 static void push_range_stack (tree);
-static void add_pending_init (tree, tree);
+static void add_pending_init (tree, tree, bool);
 static void set_nonincremental_init (void);
 static void set_nonincremental_init_from_string (tree);
 static tree find_init_member (tree);
@@ -5389,12 +5389,12 @@ push_init_level (int implicit)
 	  if ((TREE_CODE (constructor_type) == RECORD_TYPE
 	       || TREE_CODE (constructor_type) == UNION_TYPE)
 	      && constructor_fields == 0)
-	    process_init_element (pop_init_level (1));
+	    process_init_element (pop_init_level (1), true);
 	  else if (TREE_CODE (constructor_type) == ARRAY_TYPE
 		   && constructor_max_index
 		   && tree_int_cst_lt (constructor_max_index,
 				       constructor_index))
-	    process_init_element (pop_init_level (1));
+	    process_init_element (pop_init_level (1), true);
 	  else
 	    break;
 	}
@@ -5588,7 +5588,7 @@ pop_init_level (int implicit)
       /* When we come to an explicit close brace,
 	 pop any inner levels that didn't have explicit braces.  */
       while (constructor_stack->implicit)
-	process_init_element (pop_init_level (1));
+	process_init_element (pop_init_level (1), true);
 
       gcc_assert (!constructor_range_stack);
     }
@@ -5747,7 +5747,7 @@ set_designator (int array)
       /* Designator list starts at the level of closest explicit
 	 braces.  */
       while (constructor_stack->implicit)
-	process_init_element (pop_init_level (1));
+	process_init_element (pop_init_level (1), true);
       constructor_designated = 1;
       return 0;
     }
@@ -5911,7 +5911,7 @@ set_init_label (tree fieldname)
    VALUE is the value of that index or field.  */
 
 static void
-add_pending_init (tree purpose, tree value)
+add_pending_init (tree purpose, tree value, bool implicit)
 {
   struct init_node *p, **q, *r;
 
@@ -5929,10 +5929,13 @@ add_pending_init (tree purpose, tree val
 	    q = &p->right;
 	  else
 	    {
-	      if (TREE_SIDE_EFFECTS (p->value))
-		warning_init (0, "initialized field with side-effects overwritten");
-	      else if (warn_override_init)
-		warning_init (OPT_Woverride_init, "initialized field overwritten");
+	      if (!implicit)
+		{
+		  if (TREE_SIDE_EFFECTS (p->value))
+		    warning_init (0, "initialized field with side-effects overwritten");
+		  else if (warn_override_init)
+		    warning_init (OPT_Woverride_init, "initialized field overwritten");
+		}
 	      p->value = value;
 	      return;
 	    }
@@ -5952,10 +5955,13 @@ add_pending_init (tree purpose, tree val
 	    q = &p->right;
 	  else
 	    {
-	      if (TREE_SIDE_EFFECTS (p->value))
-		warning_init (0, "initialized field with side-effects overwritten");
-	      else if (warn_override_init)
-		warning_init (OPT_Woverride_init, "initialized field overwritten");
+	      if (!implicit)
+		{
+		  if (TREE_SIDE_EFFECTS (p->value))
+		    warning_init (0, "initialized field with side-effects overwritten");
+		  else if (warn_override_init)
+		    warning_init (OPT_Woverride_init, "initialized field overwritten");
+		}
 	      p->value = value;
 	      return;
 	    }
@@ -6140,7 +6146,7 @@ set_nonincremental_init (void)
     return;
 
   FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
-    add_pending_init (index, value);
+    add_pending_init (index, value, false);
   constructor_elements = 0;
   if (TREE_CODE (constructor_type) == RECORD_TYPE)
     {
@@ -6230,7 +6236,7 @@ set_nonincremental_init_from_string (tre
 	}
 
       value = build_int_cst_wide (type, val[1], val[0]);
-      add_pending_init (purpose, value);
+      add_pending_init (purpose, value, false);
     }
 
   constructor_incremental = 0;
@@ -6307,7 +6313,7 @@ find_init_member (tree field)
 
 static void
 output_init_element (tree value, bool strict_string, tree type, tree field,
-		     int pending)
+		     int pending, bool implicit)
 {
   constructor_elt *celt;
 
@@ -6386,7 +6392,7 @@ output_init_element (tree value, bool st
 	  && tree_int_cst_lt (field, constructor_unfilled_index))
 	set_nonincremental_init ();
 
-      add_pending_init (field, value);
+      add_pending_init (field, value, implicit);
       return;
     }
   else if (TREE_CODE (constructor_type) == RECORD_TYPE
@@ -6412,17 +6418,21 @@ output_init_element (tree value, bool st
 	    }
 	}
 
-      add_pending_init (field, value);
+      add_pending_init (field, value, implicit);
       return;
     }
   else if (TREE_CODE (constructor_type) == UNION_TYPE
 	   && !VEC_empty (constructor_elt, constructor_elements))
     {
-      if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt,
-				       constructor_elements)->value))
-	warning_init (0, "initialized field with side-effects overwritten");
-      else if (warn_override_init)
-	warning_init (OPT_Woverride_init, "initialized field overwritten");
+      if (!implicit)
+	{
+	  if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt,
+					   constructor_elements)->value))
+	    warning_init (0,
+			  "initialized field with side-effects overwritten");
+	  else if (warn_override_init)
+	    warning_init (OPT_Woverride_init, "initialized field overwritten");
+	}
 
       /* We can have just one union field set.  */
       constructor_elements = 0;
@@ -6493,7 +6503,7 @@ output_pending_init_elements (int all)
 				  constructor_unfilled_index))
 	    output_init_element (elt->value, true,
 				 TREE_TYPE (constructor_type),
-				 constructor_unfilled_index, 0);
+				 constructor_unfilled_index, 0, false);
 	  else if (tree_int_cst_lt (constructor_unfilled_index,
 				    elt->purpose))
 	    {
@@ -6546,7 +6556,7 @@ output_pending_init_elements (int all)
 	    {
 	      constructor_unfilled_fields = elt->purpose;
 	      output_init_element (elt->value, true, TREE_TYPE (elt->purpose),
-				   elt->purpose, 0);
+				   elt->purpose, 0, false);
 	    }
 	  else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
 	    {
@@ -6612,7 +6622,7 @@ output_pending_init_elements (int all)
    it calls output_init_element.  */
 
 void
-process_init_element (struct c_expr value)
+process_init_element (struct c_expr value, bool implicit)
 {
   tree orig_value = value.value;
   int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST;
@@ -6653,12 +6663,12 @@ process_init_element (struct c_expr valu
       if ((TREE_CODE (constructor_type) == RECORD_TYPE
 	   || TREE_CODE (constructor_type) == UNION_TYPE)
 	  && constructor_fields == 0)
-	process_init_element (pop_init_level (1));
+	process_init_element (pop_init_level (1), true);
       else if (TREE_CODE (constructor_type) == ARRAY_TYPE
 	       && (constructor_max_index == 0
 		   || tree_int_cst_lt (constructor_max_index,
 				       constructor_index)))
-	process_init_element (pop_init_level (1));
+	process_init_element (pop_init_level (1), true);
       else
 	break;
     }
@@ -6725,7 +6735,7 @@ process_init_element (struct c_expr valu
 	    {
 	      push_member_name (constructor_fields);
 	      output_init_element (value.value, strict_string,
-				   fieldtype, constructor_fields, 1);
+				   fieldtype, constructor_fields, 1, implicit);
 	      RESTORE_SPELLING_DEPTH (constructor_depth);
 	    }
 	  else
@@ -6815,7 +6825,7 @@ process_init_element (struct c_expr valu
 	    {
 	      push_member_name (constructor_fields);
 	      output_init_element (value.value, strict_string,
-				   fieldtype, constructor_fields, 1);
+				   fieldtype, constructor_fields, 1, implicit);
 	      RESTORE_SPELLING_DEPTH (constructor_depth);
 	    }
 	  else
@@ -6865,7 +6875,7 @@ process_init_element (struct c_expr valu
 	    {
 	      push_array_bounds (tree_low_cst (constructor_index, 1));
 	      output_init_element (value.value, strict_string,
-				   elttype, constructor_index, 1);
+				   elttype, constructor_index, 1, implicit);
 	      RESTORE_SPELLING_DEPTH (constructor_depth);
 	    }
 
@@ -6894,7 +6904,7 @@ process_init_element (struct c_expr valu
 	  /* Now output the actual element.  */
 	  if (value.value)
 	    output_init_element (value.value, strict_string,
-				 elttype, constructor_index, 1);
+				 elttype, constructor_index, 1, implicit);
 
 	  constructor_index
 	    = size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
@@ -6919,7 +6929,7 @@ process_init_element (struct c_expr valu
 	{
 	  if (value.value)
 	    output_init_element (value.value, strict_string,
-				 constructor_type, NULL_TREE, 1);
+				 constructor_type, NULL_TREE, 1, implicit);
 	  constructor_fields = 0;
 	}
 
@@ -6935,14 +6945,14 @@ process_init_element (struct c_expr valu
 	  while (constructor_stack != range_stack->stack)
 	    {
 	      gcc_assert (constructor_stack->implicit);
-	      process_init_element (pop_init_level (1));
+	      process_init_element (pop_init_level (1), true);
 	    }
 	  for (p = range_stack;
 	       !p->range_end || tree_int_cst_equal (p->index, p->range_end);
 	       p = p->prev)
 	    {
 	      gcc_assert (constructor_stack->implicit);
-	      process_init_element (pop_init_level (1));
+	      process_init_element (pop_init_level (1), true);
 	    }
 
 	  p->index = size_binop (PLUS_EXPR, p->index, bitsize_one_node);
--- gcc/c-tree.h.jj	2008-10-27 08:26:46.000000000 +0100
+++ gcc/c-tree.h	2008-12-29 16:35:17.000000000 +0100
@@ -575,7 +575,7 @@ extern void push_init_level (int);
 extern struct c_expr pop_init_level (int);
 extern void set_init_index (tree, tree);
 extern void set_init_label (tree);
-extern void process_init_element (struct c_expr);
+extern void process_init_element (struct c_expr, bool);
 extern tree build_compound_literal (tree, tree);
 extern tree c_start_case (tree);
 extern void c_finish_case (tree);
--- gcc/c-parser.c.jj	2008-12-06 09:56:49.000000000 +0100
+++ gcc/c-parser.c	2008-12-29 16:35:30.000000000 +0100
@@ -3090,7 +3090,7 @@ c_parser_initelt (c_parser *parser)
 		  init.original_code = ERROR_MARK;
 		  c_parser_error (parser, "expected identifier");
 		  c_parser_skip_until_found (parser, CPP_COMMA, NULL);
-		  process_init_element (init);
+		  process_init_element (init, false);
 		  return;
 		}
 	    }
@@ -3213,7 +3213,7 @@ c_parser_initelt (c_parser *parser)
 		  init.original_code = ERROR_MARK;
 		  c_parser_error (parser, "expected %<=%>");
 		  c_parser_skip_until_found (parser, CPP_COMMA, NULL);
-		  process_init_element (init);
+		  process_init_element (init, false);
 		  return;
 		}
 	    }
@@ -3243,7 +3243,7 @@ c_parser_initval (c_parser *parser, stru
 	  && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
 	init = default_function_array_conversion (init);
     }
-  process_init_element (init);
+  process_init_element (init, false);
 }
 
 /* Parse a compound statement (possibly a function body) (C90 6.6.2,
--- gcc/testsuite/gcc.dg/pr36489.c.jj	2008-12-29 16:45:41.000000000 +0100
+++ gcc/testsuite/gcc.dg/pr36489.c	2008-12-29 23:56:38.000000000 +0100
@@ -0,0 +1,22 @@
+/* PR c/36489 */
+/* { dg-do compile } */
+/* { dg-options "-Woverride-init" } */
+
+struct A { int a; int b[3]; };
+union B { int a; int b[3]; };
+int t1[10][10]
+  = { [1][2] = 11, [1][3] = 12 };
+int t2[10][10]
+  = { [1][2] = 11, [1] = { [3] = 12 } };	/* { dg-warning "initializ" } */
+int t3[10][10]
+  = { [1][2] = 11, [1][2] = 12 };		/* { dg-warning "initializ" } */
+struct A t4[2]
+  = { [0].b[0] = 1, [0].b[1] = 2, [0].b[2] = 3 };
+struct A t5[2]
+  = { [0].b[0] = 1, [0].b[1] = 2, [0].b = { 3 } }; /* { dg-warning "initializ" } */
+union B t6
+  = { .b[0] = 1, .b[1] = 2, .b[2] = 3 };
+union B t7
+  = { .b[0] = 1, .b[1] = 2, .b = { 2 } };	/* { dg-warning "initializ" } */
+union B t8
+  = { .b[0] = 1, .b[1] = 2, .b[1] = 3 };	/* { dg-warning "initializ" } */

	Jakub



More information about the Gcc-patches mailing list