Description
The following code doesn't compile for all major compilers, but receives no warnings from -Wall -Wpedantic -Wextra
:
const float x = 0;
const float y = x;
This code isn't portable, even with the C23 relaxations. GCC and clang allow it, but MSVC rejects it. It is technically legal C, but the portability issues at least deserve a warning.
Relevant Wording
More latitude is permitted for constant expressions in initializers. Such a constant expression shall
be, or evaluate to, one of the following:
- a named constant,
- a compound literal constant,
- 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
For the initialization of y
, obviously only the first and third bullets can apply. Arithmetic constant expressions are built on top of named constants, so the only question is whether x
is a named constant.
An identifier that is:
- an enumeration constant,
- a predefined constant, or
- declared with storage-class specifier
constexpr
and has an object type,is a named constant, as is [...]
x
is not a named constant, because it is not constexpr
. However, this code is not ill-formed, merely implementation-defined:
An implementation may accept other forms of constant expressions; however, they are not an integer constant expression.
- 6.6 Constant expressions p14
Suggested Solution
Clang should issue a warning, along the lines of:
initialization of 'y' relies on implementation-defined constant expressions [-Wnon-portable-constexpr]