$ uname -a Linux m5 3.13.0-37-generic #64-Ubuntu SMP Mon Sep 22 21:28:38 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux $ gcc --version | head -n 1 gcc (Ubuntu 4.8.4-2ubuntu1~14.04) 4.8.4 $ cat bug.c int main(void) { const int not_a_constant = 0; static int n = not_a_constant; /* constraint violation */ return n; /* avoid unused variable warning */ } $ gcc -O0 -c -std=c11 -pedantic-errors -Wall -Wextra bug.c bug.c: In function ‘main’: bug.c:3:5: error: initializer element is not constant static int n = not_a_constant; /* constraint violation */ ^ $ gcc -O1 -c -std=c11 -pedantic-errors -Wall -Wextra bug.c $ In the test program "bug.c", the object "not_a_constant" is defined as "const", but its name is not a constant expression. The initializer for a static expression must be a constant expression; using a non-constant expression is a constraint violation, requiring a diagnostic (N1570 6.7.9p4). With "-O0", gcc correctly diagnoses this. I see the same problem with "-O1", "-O2", and "-O3", and with "-std=c90", "-std=c99", and "-std=c11". This is based on a question posted to Stack Overflow: http://stackoverflow.com/q/30962512/827263 by user "meet". Grzegorz Szpetkowski gets the credit for realizing that the "-O" option triggers the bug.
Confirmed. What's going on here is that digest_init has 6630 inside_init = c_fully_fold (inside_init, require_constant, &maybe_const); 6631 inside_init = decl_constant_value_for_optimization (inside_init); and that decl_constant_value_for_optimization when optimizing is able to turn a "const int" into an integer constant. And an integer constant is fine as an initializer thus we don't error.
Although diagnosing this probably makes sense, it's not required by the standard ("An implementation may accept other forms of constant expressions." - and this expression doesn't contain "assignment, increment, decrement, function-call, or comma operators", so isn't required by the Constraints for constant expressions not to be one).
It would be easier to argue that gcc accepts "other forms of constant expressions" if (a) those other forms were documented and (b) they were accepted at all optimization levels. Admittedly the standard doesn't seem to require such documentation (which I find a little surprising), and you could argue that "gcc -O0" and "gcc -O1" are two different implementations.
Author: jakub Date: Sun Nov 19 17:17:01 2017 New Revision: 254930 URL: https://gcc.gnu.org/viewcvs?rev=254930&root=gcc&view=rev Log: PR c/66618 PR c/69960 c-family/ * c-common.h (c_fully_fold): Add LVAL argument defaulted to false. c/ * c-parser.c (c_parser_omp_atomic): Pass true as LVAL to c_fully_fold where needed. * c-typeck.c (build_unary_op, build_modify_expr, build_asm_expr, handle_omp_array_sections): Likewise. (digest_init): Don't call decl_constant_value_for_optimization. * c-tree.h (decl_constant_value_for_optimization): Removed. * c-fold.c (c_fold_array_ref): New function. (c_fully_fold_internal): Add LVAL argument, propagate it through recursive calls. For VAR_P call decl_constant_value and unshare if not LVAL and either optimizing or IN_INIT. Remove decl_constant_value_for_optimization calls. If IN_INIT and not LVAL, fold ARRAY_REF with STRING_CST and INTEGER_CST operands. (c_fully_fold): Add LVAL argument, pass it through to c_fully_fold_internal. (decl_constant_value_for_optimization): Removed. cp/ * cp-gimplify.c (c_fully_fold): Add LVAL argument, call cp_fold_maybe_rvalue instead of cp_fold_rvalue and pass it !LVAL. testsuite/ * gcc.dg/pr69960.c: New test. * gcc.dg/pr66618.c: New test. * gcc.dg/pr66618-2.c: New test. Added: trunk/gcc/testsuite/gcc.dg/pr66618-2.c trunk/gcc/testsuite/gcc.dg/pr66618.c trunk/gcc/testsuite/gcc.dg/pr69960.c Modified: trunk/gcc/c-family/ChangeLog trunk/gcc/c-family/c-common.h trunk/gcc/c/ChangeLog trunk/gcc/c/c-fold.c trunk/gcc/c/c-parser.c trunk/gcc/c/c-tree.h trunk/gcc/c/c-typeck.c trunk/gcc/cp/ChangeLog trunk/gcc/cp/cp-gimplify.c trunk/gcc/testsuite/ChangeLog
Fixed for 8.1+.
This wasn't fixed properly, or it was broken again before the release of GCC 8.1: In GCC 8.1 and later no warning at all is issued for the example program, even at -O0.
(In reply to Alex Henrie from comment #6) > This wasn't fixed properly, or it was broken again before the release of GCC > 8.1: In GCC 8.1 and later no warning at all is issued for the example > program, even at -O0. The fix was to change it to be a valid constant expression ....
(In reply to Andrew Pinski from comment #7) > (In reply to Alex Henrie from comment #6) > > This wasn't fixed properly, or it was broken again before the release of GCC > > 8.1: In GCC 8.1 and later no warning at all is issued for the example > > program, even at -O0. > > The fix was to change it to be a valid constant expression .... At -O0 even.
(In reply to Andrew Pinski from comment #7) > (In reply to Alex Henrie from comment #6) > > This wasn't fixed properly, or it was broken again before the release of GCC > > 8.1: In GCC 8.1 and later no warning at all is issued for the example > > program, even at -O0. > > The fix was to change it to be a valid constant expression .... Oh, okay. When I read Comment 2 I thought that a -Wpedantic warning was intended. If the intention was to have no warning ever then everything is fine.