tested with 4.6.3 and 3.3.2 possibly illegal syntax, but... --------------------------- #include <stdio.h> struct Test { int number; char name[]; }; struct Test T1 = { .number = 'q', .name = "zabc", .name[0] = 'q' }; main () { printf( "%s:%c\n", T1.name, T1.number ); } -------------------- n.c:11:2: internal compiler error: Segmentation fault Please submit a full bug report...
Confirmed: t.c:11:5: internal compiler error: Segmentation fault .name[0] = 'q' ^ 0x8dc42f crash_signal ../../gcc/toplev.c:332 0xabf217 contains_struct_check ../../gcc/tree.h:3992 0xabf217 tree_int_cst_lt(tree_node const*, tree_node const*) ../../gcc/tree.c:6538 0x51af5e set_nonincremental_init_from_string ../../gcc/c/c-typeck.c:7577 0x51af5e push_init_level(int, obstack*) ../../gcc/c/c-typeck.c:6872 0x51b4e6 set_designator ../../gcc/c/c-typeck.c:7126 0x51b5b9 set_init_index(tree_node*, tree_node*, obstack*) ../../gcc/c/c-typeck.c:7162 0x533929 c_parser_initelt ../../gcc/c/c-parser.c:3938 0x533929 c_parser_braced_init ../../gcc/c/c-parser.c:3758 0x538583 c_parser_initializer ../../gcc/c/c-parser.c:3716 0x538583 c_parser_declaration_or_fndef ../../gcc/c/c-parser.c:1649 0x53d5ab c_parser_external_declaration ../../gcc/c/c-parser.c:1361 0x53e016 c_parser_translation_unit ../../gcc/c/c-parser.c:1249 0x53e016 c_parse_file() ../../gcc/c/c-parser.c:10880 0x5830b4 c_common_parse_file() ../../gcc/c-family/c-opts.c:1022
Fails with 4.8.0, 4.7.3, 4.6.4 and even 4.5.4.
struct T { int a; char b[]; }; struct T t = { .a = 1, .b = "abc", .b[0] = '2' }; is enough, fails even with 3.2, so doesn't look like a regression.
Note, the code is not valid ISO C99, which forbids initialization of flexible array members, but a GNU extension, apparently not sufficiently well defined. E.g. in struct T t2 = { .a = 1, .b[0] = 'a' }; the .b[0] initializer is ignored with a warning, only initializing it as whole, whether as in #c3 without that extra ", .b[0] = '2'", or e.g. as in struct T t3 = { .a = 1, .b = { [0] = 'a', [1] = 'b', [2] = 'c' } }; So the question is how exactly we want to handle the flexible array members vs. designated initializers, if we take the size from the first initializer and all further ones will be either ignored (if beyond that size) or overwrite the initializer, or if we e.g. take the highest array index ever seen anywhere. So, say, is struct T t4 = { .a = 1, .b[5] = '5', .b[7] = '7' }; the same as struct T t4 = { .a = 1, .b = { 0, 0, 0, 0, 0, '5' }; with warning or: struct T t4 = { .a = 1, .b = { 0, 0, 0, 0, 0, '5', 0, '7' }; ?
--- gcc/c/c-typeck.c.jj 2013-01-11 09:02:31.000000000 +0100 +++ gcc/c/c-typeck.c 2013-01-23 15:24:50.839173887 +0100 @@ -7574,7 +7574,9 @@ set_nonincremental_init_from_string (tre end = p + TREE_STRING_LENGTH (str); for (purpose = bitsize_zero_node; - p < end && !tree_int_cst_lt (constructor_max_index, purpose); + p < end + && (constructor_max_index == NULL_TREE + || !tree_int_cst_lt (constructor_max_index, purpose)); purpose = size_binop (PLUS_EXPR, purpose, bitsize_one_node)) { if (wchar_bytes == 1) makes this ICE go away, and #c3 then is handled with a warning the same as struct T t = { .a = 1, .b = "abc" }; alone, so it is the same issue as t2 then. The rest I guess depends on how do we want to exactly define the extension.
I think taking the highest array index seen (determining the array bounds so that none of the initializers for a flexible array will ever be outside the bounds of the array) is the best interpretation of this extension.
Created attachment 29264 [details] gcc48-pr56078.patch Patch I've bootstrapped/regtested. It seems in most places constructor_max_index == NULL was treated as unlimited bound (compared to e.g. constructor_max_index being -1 as zero size bound with nothing allowed), but these two spots either didn't handle it at all, or incorrectly. The patch fixes the new testcase, both that it doesn't ICE and behaves expectedly, but unfortunately at the same time regresses gcc.c-torture/compile/20030305-1.c testcase, which is no longer accepted. It was filed as ice-on-invalid, is it really supposed to be a valid GNU C99 testcase?
Before my patch we got: 20030305-1.c:15:5: warning: excess elements in struct initializer [enabled by default] 20030305-1.c:15:5: warning: (near initialization for ‘s2_array[0]’) [enabled by default] 20030305-1.c:16:5: warning: excess elements in struct initializer [enabled by default] 20030305-1.c:16:5: warning: (near initialization for ‘s2_array[1]’) [enabled by default] 20030305-1.c:17:5: warning: excess elements in struct initializer [enabled by default] 20030305-1.c:17:5: warning: (near initialization for ‘s2_array[2]’) [enabled by default] and with the patch: 20030305-1.c:15:5: error: initialization of flexible array member in a nested context 20030305-1.c:15:5: error: (near initialization for ‘s2_array[0].s1_array’) 20030305-1.c:16:5: error: initialization of flexible array member in a nested context 20030305-1.c:16:5: error: (near initialization for ‘s2_array[1].s1_array’) 20030305-1.c:17:5: error: initialization of flexible array member in a nested context 20030305-1.c:17:5: error: (near initialization for ‘s2_array[2].s1_array’) instead. I'd lean towards the errors being correct, Joseph, do you agree? If so, I'll move the 20030305-1.c testcase into gcc.dg and add dg-error comments.
Author: jakub Date: Thu Jan 24 16:59:44 2013 New Revision: 195432 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=195432 Log: PR c/56078 * c-typeck.c (set_nonincremental_init_from_string): If constructor_max_index is NULL, treat it as if tree_int_cst_lt returned false. (process_init_element): Likewise. * gcc.dg/pr56078.c: New test. * gcc.c-torture/compile/20030305-1.c: Add dg-error lines. Added: trunk/gcc/testsuite/gcc.dg/pr56078.c Modified: trunk/gcc/c/ChangeLog trunk/gcc/c/c-typeck.c trunk/gcc/testsuite/ChangeLog trunk/gcc/testsuite/gcc.c-torture/compile/20030305-1.c
Fixed on the trunk so far.
Fixed.