Bug 66618 - Failure to diagnose non-constant initializer for static object with -O1
Summary: Failure to diagnose non-constant initializer for static object with -O1
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.8.4
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2015-06-21 21:09 UTC by Keith Thompson
Modified: 2023-05-22 19:11 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2015-06-22 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Keith Thompson 2015-06-21 21:09:34 UTC
$ 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.
Comment 1 Marek Polacek 2015-06-22 12:58:41 UTC
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.
Comment 2 jsm-csl@polyomino.org.uk 2015-06-22 13:46:50 UTC
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).
Comment 3 Keith Thompson 2015-07-01 00:48:48 UTC
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.
Comment 4 Jakub Jelinek 2017-11-19 17:17:33 UTC
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
Comment 5 Jakub Jelinek 2017-12-01 08:41:50 UTC
Fixed for 8.1+.
Comment 6 Alex Henrie 2023-05-22 18:57:21 UTC
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.
Comment 7 Andrew Pinski 2023-05-22 19:04:13 UTC
(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 ....
Comment 8 Andrew Pinski 2023-05-22 19:04:29 UTC
(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.
Comment 9 Alex Henrie 2023-05-22 19:11:22 UTC
(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.