On 21 February 2016 at 12:32, Prasad Ghangal <prasad.ghan...@gmail.com> wrote: > I was working on PR68425, > > my untested patch : > > > diff --git a/trunk/gcc/c/c-typeck.c b/trunk/gcc/c/c-typeck.c > --- a/trunk/gcc/c/c-typeck.c (revision 232768) > +++ b/trunk/gcc/c/c-typeck.c (working copy) > @@ -5856,7 +5856,7 @@ > component name is taken from the spelling stack. */ > > static void > -pedwarn_init (location_t location, int opt, const char *gmsgid) > +pedwarn_init (location_t location, int opt, const char *gmsgid, ...) You can't just forward arguments to pedwarn() from pedwarn_init() that way. You will need to wrap them in va_list. Perhaps write a version of pedwarn() taking va_list or replicate body of pedwarn() in pedwarn_init() > { > char *ofwhat; > bool warned; > @@ -9269,8 +9269,10 @@ > && (tree_int_cst_lt (constructor_max_index, constructor_index) > || integer_all_onesp (constructor_max_index))) > { > - pedwarn_init (loc, 0, > - "excess elements in array initializer"); > + pedwarn_init (loc, 0, "excess elements in array initializer " > + "(%lu elements, expected %lu)", > + tree_to_uhwi (constructor_index) + 1, > + tree_to_uhwi (constructor_max_index) + 1); > break; > } > > > > for test case: > > const int array[2] = { 1, 2, 3}; > const int array1[3] = { 1, 2, 3 ,6}; > const int array2[4] = { 1, 2, 3 ,6 ,89}; > const int array3[5] = { 1, 2, 3 ,6 ,89 ,193}; > > > It gives : > > 68425.c: In function ‘main’: > 68425.c:3:34: warning: excess elements in array initializer (3 > elements, expected 2) > const int array[2] = { 1, 2, 3}; > ^ > 68425.c:3:34: note: (near initialization for ‘array’) > 68425.c:4:38: warning: excess elements in array initializer (4 > elements, expected 3) > const int array1[3] = { 1, 2, 3 ,6}; > ^ > 68425.c:4:38: note: (near initialization for ‘array1’) > 68425.c:5:41: warning: excess elements in array initializer (5 > elements, expected 4) > const int array2[4] = { 1, 2, 3 ,6 ,89}; > ^~ > 68425.c:5:41: note: (near initialization for ‘array2’) > 68425.c:6:45: warning: excess elements in array initializer (6 > elements, expected 5) > const int array3[5] = { 1, 2, 3 ,6 ,89 ,193}; > ^~~ > 68425.c:6:45: note: (near initialization for ‘array3’) > > > > Which is as described on https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68425 > > > > But as we discussed in this thread, > > for test case like : > > int array[3] = { 1, 2, 3 ,6 ,89 ,193}; > > > It gives: > > 68425_1.c: In function ‘main’: > 68425_1.c:3:31: warning: excess elements in array initializer (4 > elements, expected 3) > int array[3] = { 1, 2, 3 ,6 ,89 ,193}; > ^ > 68425_1.c:3:31: note: (near initialization for ‘array’) > 68425_1.c:3:34: warning: excess elements in array initializer (4 > elements, expected 3) > int array[3] = { 1, 2, 3 ,6 ,89 ,193}; > ^~ > 68425_1.c:3:34: note: (near initialization for ‘array’) > 68425_1.c:3:38: warning: excess elements in array initializer (4 > elements, expected 3) > int array[3] = { 1, 2, 3 ,6 ,89 ,193}; > ^~~ > 68425_1.c:3:38: note: (near initialization for ‘array’) > > > Should I submit the patch ? It would be nice if we can avoid warning multiple times. It appears to me the warning is emitted multiple times because process_init_element is called from c_parser_initval, which is called from c_parser_initelt, which is called in a loop from c_parser_braced_init. I attached an untested patch that prevents multiple warnings.
eg: void foo(void) { int a[2] = { 1, 2, 3, 4, 5 }; } c-test.c: In function 'foo': c-test.c:3:22: warning: excess elements in array initializer int a[2] = { 1, 2, 3, 4, 5 }; ^ c-test.c:3:22: note: (near initialization for 'a') It uses a flag (warn_extra_init) to see if warning for extra initializer has already been emitted. Perhaps you can try modifying it to emit array sizes. There could also be a better way to avoid multiple warnings. Thanks, Prathamesh > > > > On 20 February 2016 at 01:20, Manuel López-Ibáñez <lopeziba...@gmail.com> > wrote: >> On 19 February 2016 at 19:13, David Malcolm <dmalc...@redhat.com> wrote: >>>> 68425.c:3:34: warning: excess elements in array initializer (6 >>>> elements, >>>> expected 2) >>>> const int array[2] = { 1, 2, 3 ,6 ,89 ,193}; >>>> ^~~~~~~~~~~~~ >>> >>> Yes, that would be ideal. Unfortunately, not every tree expression >>> node has a location stored for it, so implementing the underlined range >>> might be tricky to do. (in particular, INTEGER_CST doesn't. I hope to >>> look into that for gcc 7, perhaps with a wrapper node to provide >>> locations for expr nodes that don't have them). >> >> Do you think that would be better than storing the locations in the >> parent expression? That is, instead of adding extra wrapper nodes, >> with all those tree nodes wasting space just to provide a location, >> add extra location slots to every tree that may have an operand. Or >> perhaps you are thinking about adding some lighter wrapper which is >> just a loc+tree* or something like that. >> >> In the case above (for C), struct constructor_stack could keep track >> of token locations passed by the parser (all tokens have locations, >> but those locations are not saved in all trees). In fact, I see that >> there is already a lot of location passing in the corresponding code, >> but probably all of them refer to input_location or some such. >> >> Cheers, >> >> Manuel. > > > > -- > Thanks and Regards, > Prasad Ghangal
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 7a27244..58708da 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -1295,9 +1295,9 @@ static struct c_type_name *c_parser_type_name (c_parser *); static struct c_expr c_parser_initializer (c_parser *); static struct c_expr c_parser_braced_init (c_parser *, tree, bool, struct obstack *); -static void c_parser_initelt (c_parser *, struct obstack *); +static void c_parser_initelt (c_parser *, struct obstack *, bool *); static void c_parser_initval (c_parser *, struct c_expr *, - struct obstack *); + struct obstack *, bool *); static tree c_parser_compound_statement (c_parser *); static void c_parser_compound_statement_nostart (c_parser *); static void c_parser_label (c_parser *); @@ -4352,9 +4352,10 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p, { /* Parse a non-empty initializer list, possibly with a trailing comma. */ + bool warn_extra_init = true; while (true) { - c_parser_initelt (parser, &braced_init_obstack); + c_parser_initelt (parser, &braced_init_obstack, &warn_extra_init); if (parser->error) break; if (c_parser_next_token_is (parser, CPP_COMMA)) @@ -4387,7 +4388,7 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p, /* Parse a nested initializer, including designators. */ static void -c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack) +c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack, bool *warn_extra_init) { /* Parse any designator or designator list. A single array designator may have the subsequent "=" omitted in GNU C, but a @@ -4439,7 +4440,7 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack) c_parser_error (parser, "expected identifier"); c_parser_skip_until_found (parser, CPP_COMMA, NULL); process_init_element (input_location, init, false, - braced_init_obstack); + braced_init_obstack); return; } } @@ -4521,7 +4522,7 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack) /* Now parse and process the remainder of the initializer, starting with this message expression as a primary-expression. */ - c_parser_initval (parser, &mexpr, braced_init_obstack); + c_parser_initval (parser, &mexpr, braced_init_obstack, warn_extra_init); return; } c_parser_consume_token (parser); @@ -4575,13 +4576,13 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack) c_parser_error (parser, "expected %<=%>"); c_parser_skip_until_found (parser, CPP_COMMA, NULL); process_init_element (input_location, init, false, - braced_init_obstack); + braced_init_obstack); return; } } } } - c_parser_initval (parser, NULL, braced_init_obstack); + c_parser_initval (parser, NULL, braced_init_obstack, warn_extra_init); } /* Parse a nested initializer; as c_parser_initializer but parses @@ -4592,7 +4593,7 @@ c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack) static void c_parser_initval (c_parser *parser, struct c_expr *after, - struct obstack * braced_init_obstack) + struct obstack * braced_init_obstack, bool *warn_extra_init) { struct c_expr init; gcc_assert (!after || c_dialect_objc ()); @@ -4609,7 +4610,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after, && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR) init = convert_lvalue_to_rvalue (loc, init, true, true); } - process_init_element (loc, init, false, braced_init_obstack); + process_init_element (loc, init, false, braced_init_obstack, warn_extra_init); } /* Parse a compound statement (possibly a function body) (C90 6.6.2, diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index 96ab049..6b9d442 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -631,7 +631,7 @@ extern struct c_expr pop_init_level (location_t, int, struct obstack *); extern void set_init_index (location_t, tree, tree, struct obstack *); extern void set_init_label (location_t, tree, struct obstack *); extern void process_init_element (location_t, struct c_expr, bool, - struct obstack *); + struct obstack *, bool *warn_extra_init = NULL); extern tree build_compound_literal (location_t, tree, tree, bool); extern void check_compound_literal_type (location_t, struct c_type_name *); extern tree c_start_case (location_t, location_t, tree, bool); diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 1122a88..d0cbcfc 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -8967,7 +8967,7 @@ output_pending_init_elements (int all, struct obstack * braced_init_obstack) void process_init_element (location_t loc, struct c_expr value, bool implicit, - struct obstack * braced_init_obstack) + struct obstack * braced_init_obstack, bool *warn_extra_init) { tree orig_value = value.value; int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST; @@ -9269,9 +9269,13 @@ process_init_element (location_t loc, struct c_expr value, bool implicit, && (tree_int_cst_lt (constructor_max_index, constructor_index) || integer_all_onesp (constructor_max_index))) { - pedwarn_init (loc, 0, - "excess elements in array initializer"); - break; + if (warn_extra_init && *warn_extra_init == true) + { + pedwarn_init (loc, 0, + "excess elements in array initializer"); + *warn_extra_init = false; + break; + } } /* Now output the actual element. */