Under some circumstances, const size_t allocation_size = 32768; _Static_assert (allocation_size >= sizeof (struct dirent64), "allocation_size < sizeof (struct dirent64)"); -O0 and non -O0 have different behaviors whether the `const int` operand can be used in a constant expression (-O0: `error: expression in static assertion is not constant`). This is different from a bug "fixed for GCC 8 by r8-4755". git clone https://sourceware.org/git/glibc.git cd glibc mkdir -p out/gcc; cd out/gcc ../../configure --prefix=/tmp/glibc/gcc --disable-werror make -j 20 # you can SIGINT after some needed files used below are generated Comment out some lines to allow -O0 compiles: --- i/include/libc-symbols.h +++ w/include/libc-symbols.h @@ -71,9 +71,9 @@ #define _LIBC 1 /* Some files must be compiled with optimization on. */ -#if !defined __ASSEMBLER__ && !defined __OPTIMIZE__ -# error "glibc cannot be compiled without optimization" -#endif +//#if !defined __ASSEMBLER__ && !defined __OPTIMIZE__ +//# error "glibc cannot be compiled without optimization" +//#endif /* -ffast-math cannot be applied to the C library, as it alters the ABI. Some test components that use -ffast-math are currently not part of # My source dir is at $HOME/Dev/glibc . You may need to adjust. a=(../sysdeps/unix/sysv/linux/dl-opendir.c -std=gnu11 -fgnu89-inline -g -Wall -Wwrite-strings -Wundef -fmerge-all-constants -frounding-math -fno-stack-protector -fno-common -Wstrict-prototypes -Wold-style-definition -fmath-errno -fPIC -fno-stack-protector -DSTACK_PROTECTOR_LEVEL=0 -mno-mmx -ftls-model=initial-exec -I../include -I$HOME/Dev/glibc/out/gcc/elf -I$HOME/Dev/glibc/out/gcc -I../sysdeps/unix/sysv/linux/x86_64/64 -I../sysdeps/unix/sysv/linux/x86_64 -I../sysdeps/unix/sysv/linux/x86/include -I../sysdeps/unix/sysv/linux/x86 -I../sysdeps/x86/nptl -I../sysdeps/unix/sysv/linux/wordsize-64 -I../sysdeps/x86_64/nptl -I../sysdeps/unix/sysv/linux/include -I../sysdeps/unix/sysv/linux -I../sysdeps/nptl -I../sysdeps/pthread -I../sysdeps/gnu -I../sysdeps/unix/inet -I../sysdeps/unix/sysv -I../sysdeps/unix/x86_64 -I../sysdeps/unix -I../sysdeps/posix -I../sysdeps/x86_64/64 -I../sysdeps/x86_64/fpu/multiarch -I../sysdeps/x86_64/fpu -I../sysdeps/x86/fpu -I../sysdeps/x86_64/multiarch -I../sysdeps/x86_64 -I../sysdeps/x86/include -I../sysdeps/x86 -I../sysdeps/ieee754/float128 -I../sysdeps/ieee754/ldbl-96/include -I../sysdeps/ieee754/ldbl-96 -I../sysdeps/ieee754/dbl-64 -I../sysdeps/ieee754/flt-32 -I../sysdeps/wordsize-64 -I../sysdeps/ieee754 -I../sysdeps/generic -I.. -I../libio -I. -D_LIBC_REENTRANT -include $HOME/Dev/glibc/out/gcc/libc-modules.h -include ../include/libc-symbols.h -DPIC -DSHARED -DTOP_NAMESPACE=glibc -fsyntax-only) cd $HOME/Dev/glibc/elf % gcc-11 $=a -O2 # no diagnostic % gcc-11 $=a -O1 # no diagnostic % gcc-11 $=a -O0 In file included from ../include/features.h:488, from ../posix/sys/types.h:25, from ../include/sys/types.h:1, from ../sysdeps/unix/sysv/linux/dirstream.h:21, from ../include/dirent.h:3, from ../sysdeps/unix/sysv/linux/opendir.c:18, from ../sysdeps/unix/sysv/linux/dl-opendir.c:1: ../sysdeps/unix/sysv/linux/opendir.c: In function ‘__alloc_dir’: ../sysdeps/unix/sysv/linux/opendir.c:107:35: error: expression in static assertion is not constant 107 | _Static_assert (allocation_size >= sizeof (struct dirent64), | ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~ ../include/sys/cdefs.h:7:59: note: in definition of macro ‘_Static_assert’ 7 | # define _Static_assert(expr, diagnostic) _Static_assert (expr, diagnostic) | ^~~~ gcc-8, gcc-9, and gcc-10 from Debian testing have the same behavior.
Can you attach the preprocessed source?
Why do you think it is a bug? This is not valid C11 code, and as an extension gcc when optimizations enabled in some cases will accept in constant expressions even something that it doesn't have to. With -pedantic-errors it is properly rejected at all optimization levels. It is also rejected at file scope. If you want to make it valid in C11, use enum { allocation_size = (size_t) 32768 }; instead. const doesn't work in C the same as in C++...
OK, Andrew asked me to file it :) I just wanted to fix glibc and run away from the GCC inconsistency. I know that https://www.iso-9899.info/n1570.html#6.6 p10 says "An implementation may accept other forms of constant expressions." Accepting `const int` in C mode is an extension, but it seems odd to be inconsistent (-O0 and -O2 -Wpedantic reject it while -O2 allows it). % cat reduce.i const int __alloc_dir_allocation_size = 8; void __alloc_dir() { _Static_assert(__alloc_dir_allocation_size, ""); } % gcc reduce.i -c -std=c11 reduce.i: In function ‘__alloc_dir’: reduce.i:2:37: error: expression in static assertion is not constant 2 | void __alloc_dir() { _Static_assert(__alloc_dir_allocation_size, ""); } | ^~~~~~~~~~~~~~~~~~~~~~~~~~~ % gcc reduce.i -c -std=c11 -O1 % gcc reduce.i -c -std=c11 -O2 % gcc reduce.i -c -std=c11 -O2 -Wpedantic reduce.i: In function ‘__alloc_dir’: reduce.i:2:37: warning: expression in static assertion is not an integer constant expression [-Wpedantic] 2 | void __alloc_dir() { _Static_assert(__alloc_dir_allocation_size, ""); } | ^~~~~~~~~~~~~~~~~~~~~~~~~~~ Clang just rejects it in all optimization levels. % clang reduce.i -c -std=c11 -O0 reduce.i:2:37: error: static_assert expression is not an integral constant expression void __alloc_dir() { _Static_assert(__alloc_dir_allocation_size, ""); } ^~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated. % clang reduce.i -c -std=c11 -O1 reduce.i:2:37: error: static_assert expression is not an integral constant expression void __alloc_dir() { _Static_assert(__alloc_dir_allocation_size, ""); } ^~~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated.
(In reply to Jakub Jelinek from comment #2) > Why do you think it is a bug? Because there were other bugs which were fixed where there was an inconsistency, PR 66618, and PR 71983 for an example. There are others. Oh there is an inconsistency when the _Static_assert is not in a function vs inside a function. Take: static const int allocation_size = 32768; _Static_assert (allocation_size, ""); void f(void) { _Static_assert(allocation_size, ""); } The assert inside the function is accepted at -O1 but reject at -O0 while the one outside is always rejected.
(In reply to Andrew Pinski from comment #4) > (In reply to Jakub Jelinek from comment #2) > > Why do you think it is a bug? > > Because there were other bugs which were fixed where there was an > inconsistency, PR 66618, and PR 71983 for an example. There are others. > > Oh there is an inconsistency when the _Static_assert is not in a function vs > inside a function. > Take: > static const int allocation_size = 32768; > _Static_assert (allocation_size, ""); > void f(void) { _Static_assert(allocation_size, ""); } > > The assert inside the function is accepted at -O1 but reject at -O0 while > the one outside is always rejected. But it is an intentional decision, to match the previous behavior in that area plus handle what was needed.