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:
parent
91a96b33a9
commit
b295aee2b1
6 changed files with 119 additions and 47 deletions
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
107
gcc/c-typeck.c
107
gcc/c-typeck.c
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
22
gcc/testsuite/gcc.dg/pr36489.c
Normal file
22
gcc/testsuite/gcc.dg/pr36489.c
Normal 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" } */
|
Loading…
Add table
Reference in a new issue