re PR c/36489 (Warning "initialized field overwritten" wrongly triggers with multidimensional arrays)

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.

From-SVN: r142998
This commit is contained in:
Jakub Jelinek 2009-01-01 20:40:03 +01:00 committed by Jakub Jelinek
parent 91a96b33a9
commit b295aee2b1
6 changed files with 119 additions and 47 deletions

View file

@ -1,3 +1,22 @@
2009-01-01 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.
2008-12-31 Uros Bizjak <ubizjak@gmail.com>
* sched-deps.c (sched_analyze_2) [UNSPEC_VOLATILE]: Flush pending

View file

@ -1,6 +1,6 @@
/* Parser for C and Objective-C.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
Free Software Foundation, Inc.
Parser actions based on the old Bison parser; structure somewhat
@ -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, struct c_expr *after)
&& 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,

View file

@ -1,6 +1,7 @@
/* Definitions for C parsing and type checking.
Copyright (C) 1987, 1993, 1994, 1995, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2009
Free Software Foundation, Inc.
This file is part of GCC.
@ -575,7 +576,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);

View file

@ -1,6 +1,6 @@
/* Build expressions with type checking for C compiler.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
@ -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;
}
@ -5908,10 +5908,15 @@ set_init_label (tree fieldname)
/* Add a new initializer to the tree of pending initializers. PURPOSE
identifies the initializer, either array index or field in a structure.
VALUE is the value of that index or field. */
VALUE is the value of that index or field.
IMPLICIT is true if value comes from pop_init_level (1),
the new initializer has been merged with the existing one
and thus no warnings should be emitted about overriding an
existing initializer. */
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 +5934,13 @@ add_pending_init (tree purpose, tree value)
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 +5960,13 @@ add_pending_init (tree purpose, tree value)
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 +6151,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 +6241,7 @@ set_nonincremental_init_from_string (tree str)
}
value = build_int_cst_wide (type, val[1], val[0]);
add_pending_init (purpose, value);
add_pending_init (purpose, value, false);
}
constructor_incremental = 0;
@ -6303,11 +6314,16 @@ find_init_member (tree field)
PENDING if non-nil means output pending elements that belong
right after this element. (PENDING is normally 1;
it is 0 while outputting pending elements, to avoid recursion.) */
it is 0 while outputting pending elements, to avoid recursion.)
IMPLICIT is true if value comes from pop_init_level (1),
the new initializer has been merged with the existing one
and thus no warnings should be emitted about overriding an
existing initializer. */
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 +6402,7 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
&& 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 +6428,21 @@ output_init_element (tree value, bool strict_string, tree type, tree field,
}
}
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 +6513,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 +6566,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))
{
@ -6609,10 +6629,15 @@ output_pending_init_elements (int all)
to handle a partly-braced initializer.
Once this has found the correct level for the new element,
it calls output_init_element. */
it calls output_init_element.
IMPLICIT is true if value comes from pop_init_level (1),
the new initializer has been merged with the existing one
and thus no warnings should be emitted about overriding an
existing initializer. */
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 +6678,12 @@ process_init_element (struct c_expr value)
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 +6750,7 @@ process_init_element (struct c_expr value)
{
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 +6840,7 @@ process_init_element (struct c_expr value)
{
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 +6890,7 @@ process_init_element (struct c_expr value)
{
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 +6919,7 @@ process_init_element (struct c_expr value)
/* 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 +6944,7 @@ process_init_element (struct c_expr value)
{
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 +6960,14 @@ process_init_element (struct c_expr value)
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);

View file

@ -1,3 +1,8 @@
2009-01-01 Jakub Jelinek <jakub@redhat.com>
PR c/36489
* gcc.dg/pr36489.c: New test.
2008-12-31 Daniel Franke <franke.daniel@gmail.com>
* gfortran.dg/mapping_2.f90: Fixed testcase.

View file

@ -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" } */