2022-04-24
org: | ISO/IEC JCT1/SC22/WG14 | document: | N2980 | |
target: | IS 9899:2023 | version: | 1 | |
date: | 2022-04-24 | license: | CC BY |
When preparing the recent proposals for changes to constant expressions (keywords false
and true
, constexpr
and nullptr
) it came to me that the text on primary expressions is not completely clear concerning the specialized properties of expressions that the standard knows about. The general idea is that these propagate well through primary expressions, but the current text only mentions lvalues, function designators and void expressions explicitly.
There are more properties that give special status to expressions, namely being a constant expression, an integer constant expression, an arithmetic constant expression, an address constant, or a null pointer constant. I don’t think that anybody gets these wrong, but nevertheless it might be worth to add words to the text that make this explicit.
Besides constant expression, these special properties are not defined as syntax terms but only as derived terms. In particular, all appearances (except one) in the syntax of the term constant-expression then have explicit constraints that these in fact are integer constant expressions. It appeared to me that the understanding of the text could be much easier if that property would immediately follow from the syntax.
This is intended for clarification. Only one, separated, normative change is implied. For the latter a separate poll is taken.
Changes are proposed against the wording in C23 draft n2731 with the changes for keywords added. Some of the other recent proposal may textually interact or even conflict with the proposal, here, but these should be resolvable by editorial decisions, only.
change p5
5 A parenthesized expression is a primary expression. Its type and value are identical to those of the unparenthesized expression. It is a constant expression, an integer constant expression, an arithmetic constant expression, an address constant, a null pointer constant, an lvalue, a function designator, or a void expression if the unparenthesized expression is, respectively, a constant expression, an integer constant expression, an arithmetic constant expression, an address constant, a null pointer constant, an lvalue, a function designator, or a void expression.
change p4
4 The type and value of a generic selection are identical to those of its result expression. It is a constant expression, an integer constant expression, an arithmetic constant expression, an address constant, a null pointer constant, an lvalue, a function designator, or a void expression if its result expression is, respectively, a constant expression, an integer constant expression, an arithmetic constant expression, an address constant, a null pointer constant, an lvalue, a function designator, or a void expression.
Syntax
1 constant-expression:
conditional-expression
integer-constant-expression:
constant-expression
arithmetic-constant-expression:
constant-expression
address-constant:
constant-expression
null-pointer-constant:
constant-expression
Description
2 A constant expression can be evaluated during translation rather than runtime, and accordingly may be used in any place that a constant may be. Null pointer constants have been described in 6.3.2.3.
member-declarator:
declarator
declaratoropt : integer-constant-expression
enumerator:
enumeration-constant attribute-specifier-sequenceopt
enumeration-constant attribute-specifier-sequenceopt = integer-constant-expression
Constraints
2 The integer constant expression that defines the value of an enumeration constant shall
be an integer constant expression that hashave a value representable as anint
.
Syntax
1 alignment-specifier:
_Alignas
(
type-name)
_Alignas
(
integer-constant-expression)
Constraints
2 An alignment specifier shall appear only in the declaration specifiers of a declaration, or in the specifier-qualifier list of a member declaration, or in the type name of a compound literal. An alignment specifier shall not be used in conjunction with either of the storage-class specifiers typedef or register, nor in a declaration of a function or bit-field.
3 The integer constant expression shall
be an integer constant expression. It shallevaluate to a valid fundamental alignment, or to a valid extended alignment supported by the implementation for an object of the storage duration (if any) being declared, or to zero.
in p1 modify
designator:
[
integer-constant-expression]
.
identifier
modify p6
6 If a designator has the form
[
integer-constant-expression]
then the current object (defined below) shall have array type
and the expression shall be an integer constant expression. If the array is of unknown size, any nonnegative value is valid.
Syntax
1 label:
attribute-specifier-sequenceopt identifier
:
attribute-specifier-sequenceopt
case
integer-constant-expression:
attribute-specifier-sequenceopt
default
:
labeled-statement:
label statement
switch
statement (6.8.4.2)change p3
3
The expression of each case label shall be an integer constant expression and nNo two of thecase
integer constant expressions in the sameswitch
statement shall have the same value after conversion. There may be at most onedefault
label in aswitch
statement. (Any enclosedswitch
statement may have adefault
label orcase
integer constant expressions with values that duplicatecase
integer constant expressions in the enclosingswitch
statement.)
change p5
5 The integer promotions are performed on the controlling expression. The integer constant expression in each
case
label is converted to the promoted type of the controlling expression. If a converted value matches that of the promoted controlling expression, control jumps to the statement following the matchedcase
label. Otherwise, if there is adefault
label, control jumps to the statement following thedefault
label. If no convertedcase
constant expression matches and there is nodefault
label, no part of theswitch
body is executed.
change in p1
if-group:
#
if
integer-constant-expression new-line groupopt
#
ifdef
identifier new-line groupopt
#
ifndef
identifier new-line groupopt
elif-groups:
elif-group
elif-groups elif-group
elif-group:
#
elif
integer-constant-expression new-line groupopt
#
elifdef
identifier new-line groupopt
#
elifndef
identifier new-line groupopt
change p6
6 Preprocessing directives of the forms
#
if
integer-constant-expression new-line groupopt
#
elif
integer-constant-expression new-line groupopt
check whether the controlling integer constant expression evaluates to nonzero.
and change the term
controlling integer constant expression
where it occurs.
For static assertions the situation is a bit different because the requirement to be an integer constant expression is not formulated as a constraint; if the expression is not an integer constant expression the behavior is undefined.
This a divergence with C++, which allows all constant expressions that are convertible to bool
. If WG14 would aggree to this change, this would be a normative change, although this would only affect existing implementations, not existing code.
On the other hand, it would reduce the number of cases for which C and C++ are different. This would a win, since this is a feature that C copied from C++.
Syntax
1 static_assert-declaration:
static_assert
(
constant-expression , string-literal)
;
static_assert
(
constant-expression)
;
Constraints
2 The constant expression shall compare unequal to
0
.
Semantics
3
The constant expression shall be an integer constant expression.If the value of the constant expression compares unequal to0
, the declaration has no effect. Otherwise, the constraint is violated and the implementation shall produce a diagnostic message which should include the text of the string literal, if present.
Does WG14 want to integrate the changes for primary expressions, 3.1 and 3.2 of N2980, into C23?
Does WG14 want to integrate the changes for constant expression, 3.3 to 3.11 of N2980, into C23?
Does WG14 want to integrate the change for
static_assert
, 3.12 of N2980, into C23?