I am seeing a strange behavior when a compound initializer is used in a structure initialization. A test case: [[[ struct s { int y; unsigned long *x; }; struct s foo = { .y = 25, .x = (unsigned long [SZ]){}, }; ]]] If SZ is defined to non-zero, the expected output is produced: [[[ /tmp$ gcc -S -o- 1.c -Wall -DSZ=1 .file "1.c" .local __compound_literal.0 .comm __compound_literal.0,8,8 .globl foo .data .align 16 .type foo, @object .size foo, 16 foo: .long 25 .zero 4 .quad __compound_literal.0 .ident "GCC: (Ubuntu 4.9.1-16ubuntu6) 4.9.1" .section .note.GNU-stack,"",@progbits ]]] If SZ is zero, the initializer for .y (".y = 25") member is dropped as well: [[[ /tmp$ gcc -S -o- 1.c -Wall -DSZ=0 .file "1.c" .globl foo .bss .align 16 .type foo, @object .size foo, 16 foo: .zero 16 .ident "GCC: (Ubuntu 4.9.1-16ubuntu6) 4.9.1" .section .note.GNU-stack,"",@progbits ]]] Tested with GCC 4.6.3 and 4.9.1, both exhibit the same behavior. With -Wextra, the code rightfully complains that the initializer for .x is missing - but why the .y initializer is dropped even if there is no initializer for .x? In the mailing list, this was some discussion of this issue: [[[ But in this case, the code attempts to create an unnanmed temporary array of zero elements which, IMO, makes no sense. At the same time, I wouldn't expect gcc to simply omit the initialization for foo.x. I suggest to open a gcc bug for it. ]]] I'd add that this was a reduced test case from a bigger aggregate type - which was an array of such structures. When one of the elements became unused and the size of the bitmap (which was the purpose of the compound literal initializer) was set to zero, the whole array lost its initializers - i.e., even other 'struct s' members of the array, not just the member with a zero-sized array compound literal.
Confirmed. It seems weird to drop the initializer.
What happens here is that pop_init_level returns error_mark_node because initializing a zero-length array member with {} is discarded: 7565 /* Silently discard empty initializations. The parser will 7566 already have pedwarned for empty brackets. */ 7567 if (integer_zerop (constructor_unfilled_index)) 7568 constructor_type = NULL_TREE; thus ret.value is NULL: 7718 if (ret.value == 0 && constructor_stack == 0) 7719 ret.value = error_mark_node; 7720 return ret; output_init_element then sees that value == error_mark_node, so it marks the ctor as erroneous: 8388 if (type == error_mark_node || value == error_mark_node) 8389 { 8390 constructor_erroneous = 1; 8391 return; 8392 } And because the ctor is erroneous, we don't build a CONSTRUCTOR for it: 7668 if (constructor_erroneous) 7669 ret.value = error_mark_node; 7670 else 7671 { 7672 ret.value = build_constructor (constructor_type, 7673 constructor_elements);
The following seems to work and regtests cleanly. But I have to say I'm somewhat dubious now about changing this at all. I suppose I should try to compile e.g. the Linux kernel with this patch and see if anything breaks. diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c index ebe4c73..590e235 100644 --- gcc/c/c-typeck.c +++ gcc/c/c-typeck.c @@ -7565,7 +7565,7 @@ pop_init_level (location_t loc, int implicit, /* Silently discard empty initializations. The parser will already have pedwarned for empty brackets. */ if (integer_zerop (constructor_unfilled_index)) - constructor_type = NULL_TREE; + /* Do nothing. */; else { gcc_assert (!TYPE_SIZE (constructor_type));
Any chance of this patch getting applied?
GCC 4.1.2 produces: foo: .long 25 .zero 4 .quad __compound_literal.0 .local __compound_literal.0 .comm __compound_literal.0,0,8 While 4.4.7 (and above) produces: foo: .zero 16
GCC 9 branch is being closed
GCC 10.4 is being released, retargeting bugs to GCC 10.5.
Another option would be to report an error for this? Anyway, re-confirmed. Marek - you had a patch, any updates here?
This bug still exists, both in GCC 12.2 and trunk: struct sfnt_generic_test_args { unsigned int *expected_stack; int expected_stack_elements; int expected_trap : 1; int expected_IP; }; struct sfnt_generic_test_args stack_underflow_test_args = { (unsigned int [0]) { }, 0, 1, 4, }; on: Using built-in specs. COLLECT_GCC=/usr/bin/gcc COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/12/lto-wrapper OFFLOAD_TARGET_NAMES=nvptx-none OFFLOAD_TARGET_DEFAULT=1 Target: x86_64-redhat-linux Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,objc,obj-c++,ada,go,d,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-gcc-major-version-only --enable-libstdcxx-backtrace --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --with-isl=/builddir/build/BUILD/gcc-12.2.1-20220819/obj-x86_64-redhat-linux/isl-install --enable-offload-targets=nvptx-none --without-cuda-driver --enable-offload-defaulted --enable-gnu-indirect-function --enable-cet --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux --with-build-config=bootstrap-lto --enable-link-serialization=1 Thread model: posix Supported LTO compression algorithms: zlib zstd gcc version 12.2.1 20220819 (Red Hat 12.2.1-2) (GCC) and Using built-in specs. COLLECT_GCC=/opt/compiler-explorer/gcc-snapshot/bin/gcc Target: x86_64-linux-gnu Configured with: ../gcc-trunk-20230129/configure --prefix=/opt/compiler-explorer/gcc-build/staging --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu --disable-bootstrap --enable-multiarch --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --enable-clocale=gnu --enable-languages=c,c++,fortran,ada,objc,obj-c++,go,d,rust --enable-ld=yes --enable-gold=yes --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-linker-build-id --enable-lto --enable-plugins --enable-threads=posix --with-pkgversion=Compiler-Explorer-Build-gcc-ee2c965ee205ae12bc78d8641337380df3b1d3f3-binutils-2.38 Thread model: posix Supported LTO compression algorithms: zlib gcc version 13.0.1 20230129 (experimental) (Compiler-Explorer-Build-gcc-ee2c965ee205ae12bc78d8641337380df3b1d3f3-binutils-2.38) COLLECT_GCC_OPTIONS='-fdiagnostics-color=always' '-g' '-o' '/app/output.s' '-S' '-v' '-mtune=generic' '-march=x86-64' '-dumpdir' '/app/' /opt/compiler-explorer/gcc-trunk-20230129/bin/../libexec/gcc/x86_64-linux-gnu/13.0.1/cc1 -quiet -v -imultiarch x86_64-linux-gnu -iprefix /opt/compiler-explorer/gcc-trunk-20230129/bin/../lib/gcc/x86_64-linux-gnu/13.0.1/ <source> -quiet -dumpdir /app/ -dumpbase output.c -dumpbase-ext .c -mtune=generic -march=x86-64 -g -version -fdiagnostics-color=always -o /app/output.s GNU C17 (Compiler-Explorer-Build-gcc-ee2c965ee205ae12bc78d8641337380df3b1d3f3-binutils-2.38) version 13.0.1 20230129 (experimental) (x86_64-linux-gnu) compiled by GNU C version 9.4.0, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version isl-0.24-GMP GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096 ignoring nonexistent directory "/opt/compiler-explorer/gcc-trunk-20230129/bin/../lib/gcc/x86_64-linux-gnu/13.0.1/../../../../x86_64-linux-gnu/include" ignoring duplicate directory "/opt/compiler-explorer/gcc-trunk-20230129/bin/../lib/gcc/../../lib/gcc/x86_64-linux-gnu/13.0.1/include" ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu" ignoring duplicate directory "/opt/compiler-explorer/gcc-trunk-20230129/bin/../lib/gcc/../../lib/gcc/x86_64-linux-gnu/13.0.1/include-fixed/x86_64-linux-gnu" ignoring duplicate directory "/opt/compiler-explorer/gcc-trunk-20230129/bin/../lib/gcc/../../lib/gcc/x86_64-linux-gnu/13.0.1/include-fixed" ignoring nonexistent directory "/opt/compiler-explorer/gcc-trunk-20230129/bin/../lib/gcc/../../lib/gcc/x86_64-linux-gnu/13.0.1/../../../../x86_64-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /opt/compiler-explorer/gcc-trunk-20230129/bin/../lib/gcc/x86_64-linux-gnu/13.0.1/include /opt/compiler-explorer/gcc-trunk-20230129/bin/../lib/gcc/x86_64-linux-gnu/13.0.1/include-fixed/x86_64-linux-gnu /opt/compiler-explorer/gcc-trunk-20230129/bin/../lib/gcc/x86_64-linux-gnu/13.0.1/include-fixed /usr/local/include /opt/compiler-explorer/gcc-trunk-20230129/bin/../lib/gcc/../../include /usr/include/x86_64-linux-gnu /usr/include End of search list. GNU C17 (Compiler-Explorer-Build-gcc-ee2c965ee205ae12bc78d8641337380df3b1d3f3-binutils-2.38) version 13.0.1 20230129 (experimental) (x86_64-linux-gnu) compiled by GNU C version 9.4.0, GMP version 6.2.1, MPFR version 4.1.0, MPC version 1.2.1, isl version isl-0.24-GMP GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096 Compiler executable checksum: ad17c4694b07a4272f6162e91fa92744 COMPILER_PATH=/opt/compiler-explorer/gcc-trunk-20230129/bin/../libexec/gcc/x86_64-linux-gnu/13.0.1/:/opt/compiler-explorer/gcc-trunk-20230129/bin/../libexec/gcc/x86_64-linux-gnu/:/opt/compiler-explorer/gcc-trunk-20230129/bin/../libexec/gcc/:/opt/compiler-explorer/gcc-trunk-20230129/bin/../lib/gcc/x86_64-linux-gnu/13.0.1/../../../../x86_64-linux-gnu/bin/ LIBRARY_PATH=/opt/compiler-explorer/gcc-trunk-20230129/bin/../lib/gcc/x86_64-linux-gnu/13.0.1/:/opt/compiler-explorer/gcc-trunk-20230129/bin/../lib/gcc/x86_64-linux-gnu/:/opt/compiler-explorer/gcc-trunk-20230129/bin/../lib/gcc/:/opt/compiler-explorer/gcc-trunk-20230129/bin/../lib/gcc/x86_64-linux-gnu/13.0.1/../../../../lib64/:/lib/x86_64-linux-gnu/:/lib/../lib64/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib64/:/opt/compiler-explorer/gcc-trunk-20230129/bin/../lib/gcc/x86_64-linux-gnu/13.0.1/../../../../x86_64-linux-gnu/lib/:/opt/compiler-explorer/gcc-trunk-20230129/bin/../lib/gcc/x86_64-linux-gnu/13.0.1/../../../:/lib/:/usr/lib/ COLLECT_GCC_OPTIONS='-fdiagnostics-color=always' '-g' '-o' '/app/output.s' '-S' '-v' '-mtune=generic' '-march=x86-64' '-dumpdir' '/app/output.' Compiler returned: 0 results in the structure being generated as a .zero section of size 24, while it should really be: .quad <address of compound literal array of size 0> .long 0 .byte 1 .zero 3 .long 4 .zero 4 I hope it can be fixed, because this is causing real problems for Emacs. Thanks in advance.
GCC 10 branch is being closed.
GCC 11 branch is being closed.