Bug 56078 - causes cc1 to crash
Summary: causes cc1 to crash
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.6.3
: P3 minor
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-01-22 17:27 UTC by Stan Tomlinson
Modified: 2014-03-13 18:15 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.6.4, 4.7.3, 4.8.0
Last reconfirmed: 2013-01-22 00:00:00


Attachments
gcc48-pr56078.patch (957 bytes, patch)
2013-01-24 13:27 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Stan Tomlinson 2013-01-22 17:27:53 UTC
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...
Comment 1 Andrew Pinski 2013-01-22 22:37:43 UTC
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
Comment 2 Marek Polacek 2013-01-23 07:29:53 UTC
Fails with 4.8.0, 4.7.3, 4.6.4 and even 4.5.4.
Comment 3 Jakub Jelinek 2013-01-23 08:06:57 UTC
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.
Comment 4 Jakub Jelinek 2013-01-23 14:23:30 UTC
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' };
?
Comment 5 Jakub Jelinek 2013-01-23 14:32:31 UTC
--- 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.
Comment 6 jsm-csl@polyomino.org.uk 2013-01-23 17:53:16 UTC
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.
Comment 7 Jakub Jelinek 2013-01-24 13:27:55 UTC
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?
Comment 8 Jakub Jelinek 2013-01-24 13:33:13 UTC
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.
Comment 9 Jakub Jelinek 2013-01-24 16:59:56 UTC
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
Comment 10 Jakub Jelinek 2013-01-24 17:01:57 UTC
Fixed on the trunk so far.
Comment 11 Marek Polacek 2014-03-13 18:15:53 UTC
Fixed.