[Bug c/69960] "initializer element is not constant"

2023-02-23 Thread daniel.lundin.mail at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

--- Comment #25 from Daniel Lundin  ---
(In reply to jos...@codesourcery.com from comment #24)
> On Thu, 23 Feb 2023, daniel.lundin.mail at gmail dot com via Gcc-bugs wrote:
> 

Regardless of how one chose to read that part of the standard, fact remains
that this part of the standard has not changed since C89 but still gcc behaves
wildly different depending on version. This makes it impossible to port
strictly conforming programs between different gcc versions, because then
you'll either get a diagnostic that you (arguably) shouldn't be getting, or you
will not get a diagnostic where you (arguably) should be expecting one. 

This makes gcc a hazard in my case. My choices are to forbid newer versions or
to port to a different compiler. In case -pedantic would still result in a
diagnostic past version 8 then that would make gcc behave consistently across
versions and that would solve the problem. As was already mentioned previously
in this thread, before this change was implemented with that remark ignored.

Additionally there is bug #2 where (uint32_t)_pointer does not give a
diagnostic in case the pointer is 32 bit, which is non-conforming behavior for
constant expressions. I should perhaps open a separate bug report about that
since I'm not sure if it's related to this one.

[Bug c/69960] "initializer element is not constant"

2023-02-23 Thread joseph at codesourcery dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

--- Comment #24 from joseph at codesourcery dot com  ---
On Thu, 23 Feb 2023, daniel.lundin.mail at gmail dot com via Gcc-bugs wrote:

> In this code 
> 
> static const int y = 1;
> static int x = y;
> 
> y is not an integer constant expression, nor is it an integer constant in the
> meaning that ISO 9899 defines it.

Correct, but irrelevant, since nothing in that code example is required by 
the standard to be an integer constant expression.

> Therefore an initializer was given which is
> not a constant expression.

No, it's an "other form of constant expression" accepted by GCC.

> "an implementation may accept other forms of constant expressions" does not
> mean that an implementation can throw out any constraints it pleases out the
> window.

Correct.  The Constraints on constant expressions say "Constant 
expressions shall not contain assignment, increment, decrement, 
function-call, or comma operators, except when they are contained within a 
subexpression that is not evaluated." and "Each constant expression shall 
evaluate to a constant that is in the range of representable values for 
its type.".  The initializer is entirely consistent with those 
Constraints, so it is within the bounds of what an implementation may 
accept as an "other form of constant expression".  Whereas it wouldn't be 
valid for an implementation to accept f() as a constant expression 
(contains a function call), for example.

Note also that only violations of Syntax and Constraints require 
diagnostics (and thus -pedantic doesn't claim to ensure diagnostics for 
code that's not strictly conforming for some other reason than violating 
Syntax or Constraints).

[Bug c/69960] "initializer element is not constant"

2023-02-22 Thread daniel.lundin.mail at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

--- Comment #23 from Daniel Lundin  ---
(In reply to jos...@codesourcery.com from comment #21)
> On Wed, 22 Feb 2023, daniel.lundin.mail at gmail dot com via Gcc-bugs wrote:
> 
> > First of all, it is questionable if gcc is still conforming after the change
> > discussed here and implemented as per gcc 8.0. Yes "an implementation may
> > accept other forms of constant expressions" but that doesn't mean that a
> > compiler is allowed to ignore the constraints in C17 6.7.9/4 nor the 
> > definition
> > of an integer constant expression. So this ought to explicitly be a compiler
> > extension and we ought to have a way to reliably compile strictly conforming
> > programs with gcc without constraint violations silently getting ignored. 
> 
> "integer constant expression" does not mean the same thing as "constant 
> expression of integer type".  

Yes, who said otherwise? Rather, this is the problem. Please check out the link
I gave for the full reasoning including quotes.
https://stackoverflow.com/questions/68252570/why-are-const-qualified-variables-accepted-as-initializers-on-gcc

Specifically (C17 6.6):

"An integer constant expression shall have integer type and shall only have
operands that are integer constants, enumeration constants, character
constants, sizeof expressions whose results are integer constants, _Alignof
expressions, and floating constants that are the immediate operands of casts."

In this code 

static const int y = 1;
static int x = y;

y is not an integer constant expression, nor is it an integer constant in the
meaning that ISO 9899 defines it. Therefore an initializer was given which is
not a constant expression. Therefore this is a constraint violation of C17
6.7.9/4 and a diagnostic must be issued. Therefore gcc is not conforming
because of the "bug fix" carried out above.

"an implementation may accept other forms of constant expressions" does not
mean that an implementation can throw out any constraints it pleases out the
window. Also the text "however, they are not an integer constant expression"
added in C23 must have been added for a reason, such as misbehaving compilers.

[Bug c/69960] "initializer element is not constant"

2023-02-22 Thread joseph at codesourcery dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

--- Comment #22 from joseph at codesourcery dot com  ---
I do however expect there may be cases in GCC 13 where constexpr 
initializers of floating type are accepted that do not meet the definition 
of arithmetic constant expressions, since GCC is generally a lot more 
careful about ensuring things are integer constant expressions when 
required than it is about doing the same for arithmetic constant 
expressions (before C2x there weren't any cases that allowed arithmetic 
constant expressions without also allowing other kinds of constant 
expressions permitted in initializers).

[Bug c/69960] "initializer element is not constant"

2023-02-22 Thread joseph at codesourcery dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

--- Comment #21 from joseph at codesourcery dot com  ---
On Wed, 22 Feb 2023, daniel.lundin.mail at gmail dot com via Gcc-bugs wrote:

> First of all, it is questionable if gcc is still conforming after the change
> discussed here and implemented as per gcc 8.0. Yes "an implementation may
> accept other forms of constant expressions" but that doesn't mean that a
> compiler is allowed to ignore the constraints in C17 6.7.9/4 nor the 
> definition
> of an integer constant expression. So this ought to explicitly be a compiler
> extension and we ought to have a way to reliably compile strictly conforming
> programs with gcc without constraint violations silently getting ignored. 

"integer constant expression" does not mean the same thing as "constant 
expression of integer type".  If you use this expression in a context 
requiring an integer constant expression (case label, bit-field width, 
array designator in initializer, enum value, array size at file scope, 
constexpr initializer for object of integer type, etc.), it's properly 
rejected as required; in contexts where both integer constant expressions 
and other expressions are valid but with different semantics (e.g. 
determining whether something is a null pointer constant, determining 
whether an array is a VLA in a context where both VLA and non-VLA arrays 
are valid), again it's treated as non-constant.

[Bug c/69960] "initializer element is not constant"

2023-02-22 Thread daniel.lundin.mail at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

--- Comment #20 from Daniel Lundin  ---
Further info about the "ARM32 port bug". 

In case you write code like `(uint32_t)_pointer` and the port happens
to use 32 bit pointers, the non-conforming cast is let through. 

In case you cast to an integer type of different size in relation to the
pointer size (non-portable cast), you first get a warning about that: "warning:
cast from pointer to integer of different size [-Wpointer-to-int-cast]",
followed by the diagnostic "error: initializer element is not computable at
load time".

https://godbolt.org/z/xjYvd41qe

Correct compiler behavior here is to always give a diagnostic for
(uint32_t)_handler not being an acceptable arithmetic constant
expression. 

If that's the same "implementation may accept other forms of constant
expressions"  bug as originally discussed here or a different bug, I don't
know.

[Bug c/69960] "initializer element is not constant"

2023-02-22 Thread daniel.lundin.mail at gmail dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

Daniel Lundin  changed:

   What|Removed |Added

 CC||daniel.lundin.mail at gmail 
dot co
   ||m

--- Comment #19 from Daniel Lundin  ---
This ought to be discussed again. "clang allows it" is not an argument. 

First of all, it is questionable if gcc is still conforming after the change
discussed here and implemented as per gcc 8.0. Yes "an implementation may
accept other forms of constant expressions" but that doesn't mean that a
compiler is allowed to ignore the constraints in C17 6.7.9/4 nor the definition
of an integer constant expression. So this ought to explicitly be a compiler
extension and we ought to have a way to reliably compile strictly conforming
programs with gcc without constraint violations silently getting ignored. 

So if this feature is desired as an extension (I'm sure it is), then the old
diagnostic message should still be there when compiling as -std=c17 -pedantic.
See detailed discussion and relevant ISO 9899 quotes here:
https://stackoverflow.com/questions/68252570/why-are-const-qualified-variables-accepted-as-initializers-on-gcc

On top of that mess, I just found out that gcc behaves inconsistently in
regards of constant expressions between compiler ports. All gcc ports reject an
initializer such as (uint32_t)_pointer as they ought, except gcc for
ARM32 which silently allows this even under strict mode. This as per
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108875 which I think is NOT a bug,
since the definition of an arithmetic constant expression (6.6) always had
"Cast operators in an arithmetic constant expression shall only convert
arithmetic types to arithmetic types". A function/object pointer is not an
arithmetic type. A normative "shall" was violated. A conforming compiler must
issue a diagnostic. 

If the C standard by design blocks meaningful use of some constant expressions
inside initializer lists (I would agree that it does, the linked bug report
above is a very valid use-case in embedded systems), then gcc has the option to
make an extension and only warn in -pedantic mode. Bug again, this route was
not taken there either. Standard compliance was just silently abandoned in the
ARM32 port.

Therefore the current state of affairs is: gcc <8.0 (IMO compliant) behaves
differently from gcc >=8.0 which in turn behaves differently from gcc ARM32 any
version. Three different gcc behaviors for a language feature which has NOT
changed at all between C90 to C17.

All of this has to be revisited for the C23 constexpr/"named constants" 
implementation, so it would be great if we at the same time can separate
non-standard extensions from -pedantic mode. Notably C23 does not allow casts
from non-arithemtic types inside arithmetic constant expressions either.

Also note that C23 changed the wording slightly from C17: "An implementation
may accept other forms of constant expressions; however, they are not an
integer constant expression." I don't know why but likely because of some
implemented DR.

[Bug c/69960] "initializer element is not constant"

2021-09-27 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

Andrew Pinski  changed:

   What|Removed |Added

   Target Milestone|--- |8.0

[Bug c/69960] "initializer element is not constant"

2017-12-01 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

Jakub Jelinek  changed:

   What|Removed |Added

 Status|NEW |RESOLVED
 Resolution|--- |FIXED

--- Comment #18 from Jakub Jelinek  ---
Fixed for 8.1+.

[Bug c/69960] "initializer element is not constant"

2017-11-19 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

--- Comment #17 from Jakub Jelinek  ---
Author: jakub
Date: Sun Nov 19 17:17:01 2017
New Revision: 254930

URL: https://gcc.gnu.org/viewcvs?rev=254930=gcc=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

[Bug c/69960] "initializer element is not constant"

2017-10-24 Thread mpolacek at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

Marek Polacek  changed:

   What|Removed |Added

 CC||drikosev at gmail dot com

--- Comment #16 from Marek Polacek  ---
*** Bug 82695 has been marked as a duplicate of this bug. ***

[Bug c/69960] "initializer element is not constant"

2017-05-11 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

--- Comment #15 from Jakub Jelinek  ---
(In reply to Jakub Jelinek from comment #14)
> C++ FE's constexpr.c has bool lval argument to many recursive functions, so
> it can differentiate between cases where you don't want to fold "str"[0] to
> 's' and cases where you can do that.  It is among other cases set when
> processing ADDR_EXPR's operand.  But c_fully_fold_internal doesn't have
> anything like that, so that would need to be introduced there.

>From the related PR66618, it seems that if we had such an argument properly
propagated, we could as well use decl_constant_value_for_optimization during
c_fully_fold_internal (if not pedantic?) centrally for VAR_DECLs, rather then
just using it on selected operands where we basically know for sure we don't
need an lvalue.

Without such changes, a hack could be to add the ARRAY_REF of STRING_CST with
constant index folding into decl_constant_value_for_optimization.

[Bug c/69960] "initializer element is not constant"

2017-05-11 Thread jakub at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

Jakub Jelinek  changed:

   What|Removed |Added

 CC||jakub at gcc dot gnu.org

--- Comment #14 from Jakub Jelinek  ---
C++ FE's constexpr.c has bool lval argument to many recursive functions, so it
can differentiate between cases where you don't want to fold "str"[0] to 's'
and cases where you can do that.  It is among other cases set when processing
ADDR_EXPR's operand.  But c_fully_fold_internal doesn't have anything like
that, so that would need to be introduced there.

[Bug c/69960] "initializer element is not constant"

2016-04-15 Thread bernds at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

--- Comment #13 from Bernd Schmidt  ---
I actually tried this a few weeks ago, it's slightly less trivial than it seems
since you don't want to fold away the inside of &("fish"[0]).

[Bug c/69960] "initializer element is not constant"

2016-04-15 Thread msebor at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

Martin Sebor  changed:

   What|Removed |Added

 CC||devel at fresse dot org

--- Comment #12 from Martin Sebor  ---
*** Bug 54823 has been marked as a duplicate of this bug. ***

[Bug c/69960] "initializer element is not constant"

2016-04-15 Thread msebor at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

Martin Sebor  changed:

   What|Removed |Added

 Status|UNCONFIRMED |NEW
   Last reconfirmed||2016-04-15
 Ever confirmed|0   |1
   Severity|normal  |enhancement

--- Comment #11 from Martin Sebor  ---
Seems like there is agreement that this would be a useful enhancement so I'll
mark this enhancement request as accepted by changing its Status to New (and
its Severity to Enhancement).

[Bug c/69960] "initializer element is not constant"

2016-03-02 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

--- Comment #10 from Jonathan Wakely  ---
Martin said almost exactly what I was going to say :-)

Compilers are allowed to accept this, as Clang does, but they are not required
to.

[Bug c/69960] "initializer element is not constant"

2016-03-02 Thread msebor at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

Martin Sebor  changed:

   What|Removed |Added

 CC||msebor at gcc dot gnu.org

--- Comment #9 from Martin Sebor  ---
I also agree that accepting it would be a useful extension (perhaps when
diagnosed in pedantic mode to aid portability since other compilers reject it).

As to where C11 rules it out, I believe it's in 6.6 which says that "constant
expressions in initializers ... shall be, or evaluate to, one of the following:

-- an /arithmetic constant expression/,
-- a null pointer constant,
-- an address constant, or
-- an address constant for a complete object type plus or minus an integer
constant expression."

An /arithmetic constant expression/ shall have arithmetic type and shall only
have operands that are integer constants, floating constants, enumeration
constants, character constants, sizeof expressions whose results are integer
constants, and _Alignof expressions.

"f"[0] is none of the above expressions.

C also says that "An implementation may accept other forms of constant
expressions" so accepting it wouldn't be out of line with the requirements.

[Bug c/69960] "initializer element is not constant"

2016-03-02 Thread mpolacek at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

--- Comment #8 from Marek Polacek  ---
I don't think it is forbidden.  The C standard allows some latitude for
constant expressions in initializers, so I think we could accept code as in
Comment 5, i.e. evaluate it to an arithmetic constant expression.

[Bug c/69960] "initializer element is not constant"

2016-03-02 Thread bernds at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

Bernd Schmidt  changed:

   What|Removed |Added

 CC||redi at gcc dot gnu.org

--- Comment #7 from Bernd Schmidt  ---
Cc'ing Jonathan in the hope he can answer the question.

[Bug c/69960] "initializer element is not constant"

2016-03-02 Thread bernds at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

Bernd Schmidt  changed:

   What|Removed |Added

 CC||bernds at gcc dot gnu.org

--- Comment #6 from Bernd Schmidt  ---
I'm also curious why this wouldn't be considered constant. I only have an old
draft C standard, but I see no language forbidding this, and it can be
evaluated at compile-time.

We even have a fold_read_from_constant_string, but for whatever reason it's not
called when folding an ARRAY_REF.

[Bug c/69960] "initializer element is not constant"

2016-03-01 Thread mpolacek at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

--- Comment #5 from Marek Polacek  ---
This is basically about
  char t = "f"[0];
at the file scope.  clang probably started to accept this in 3.8 or in 3.9.

[Bug c/69960] "initializer element is not constant"

2016-02-25 Thread felix-gcc at fefe dot de
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

--- Comment #4 from felix-gcc at fefe dot de ---
So which part of it is not constant, you would say?

It all looks constant to me. It only operates on constants.
If 3+4 is constant, why should this not be constant?

[Bug c/69960] "initializer element is not constant"

2016-02-25 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

--- Comment #3 from Jonathan Wakely  ---
The C standard says it's not a constant, but clang accepts it as an extension.
That doesn't make it valid C though.

[Bug c/69960] "initializer element is not constant"

2016-02-25 Thread felix-gcc at fefe dot de
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

--- Comment #2 from felix-gcc at fefe dot de ---
uh, yes in C.

$ cat test.c
#define TOLOWER(x) (x&~0x20)
#define Word(s) \
  s[1] ? s[2] ? s[3] ? \
(TOLOWER(s[0]) << 24) + (TOLOWER(s[1]) << 16) + (TOLOWER(s[2]) << 8) +
TOLOWER(s[3]) : \
(TOLOWER(s[0]) << 16) + (TOLOWER(s[1]) << 8) + TOLOWER(s[2]) : \
(TOLOWER(s[0]) << 8) + TOLOWER(s[1]) : \
TOLOWER(s[0])

const unsigned int _the = Word("the");
$ clang -c test.c
$ clang --version
clang version 3.9.0 (trunk 261746)

[Bug c/69960] "initializer element is not constant"

2016-02-25 Thread mpolacek at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69960

Marek Polacek  changed:

   What|Removed |Added

 CC||mpolacek at gcc dot gnu.org

--- Comment #1 from Marek Polacek  ---
(In reply to felix-gcc from comment #0)
> How is this not constant? clang thinks it is constant.

Not in C:

$ clang q.c -c
q.c:9:27: error: initializer element is not a compile-time constant