[Bug c/69960] "initializer element is not constant"
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"
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"
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"
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"
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"
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"
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"
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"
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"
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"
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"
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"
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"
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"
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"
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"
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"
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"
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"
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"
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"
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"
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"
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"
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"
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