[go: nahoru, domu]

Bug 65673 - [11/12/13/14/15 Regression] Compound literal with initializer for zero-sized array drops other initializers
Summary: [11/12/13/14/15 Regression] Compound literal with initializer for zero-sized ...
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.9.1
: P2 normal
Target Milestone: 11.5
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2015-04-05 06:42 UTC by Alexey Neyman
Modified: 2024-04-26 10:30 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.1.2
Known to fail: 13.0, 4.4.7
Last reconfirmed: 2022-12-20 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Alexey Neyman 2015-04-05 06:42:09 UTC
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.
Comment 1 Marek Polacek 2015-04-17 07:09:41 UTC
Confirmed.  It seems weird to drop the initializer.
Comment 2 Marek Polacek 2015-04-17 13:03:29 UTC
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);
Comment 3 Marek Polacek 2015-04-20 10:38:04 UTC
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));
Comment 4 Alexey Neyman 2017-12-21 02:00:32 UTC
Any chance of this patch getting applied?
Comment 5 Andrew Pinski 2022-01-03 20:34:08 UTC
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
Comment 6 Richard Biener 2022-05-27 09:35:35 UTC
GCC 9 branch is being closed
Comment 7 Jakub Jelinek 2022-06-28 10:31:26 UTC
GCC 10.4 is being released, retargeting bugs to GCC 10.5.
Comment 8 Richard Biener 2022-12-20 13:00:48 UTC
Another option would be to report an error for this?  Anyway, re-confirmed.  Marek - you had a patch, any updates here?
Comment 9 Po Lu 2023-01-31 01:29:20 UTC
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.
Comment 10 Richard Biener 2023-07-07 10:30:40 UTC
GCC 10 branch is being closed.