2022-06-14
org: | ISO/IEC JCT1/SC22/WG14 | document: | N3010 | |
target: | IS 9899:2023 | version: | 2 | |
date: | 2022-06-14 | 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.
Recently, this ambiguity has also led some uncertainty in the clang/LLVM community and from there to a lengthy discussion on the WG14 reflector and social media.
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; the answers to the first two questions, the first three possible modification of the text, and the optional syntax addition should have no normative impact. Only one, separated, normative change is suggested. A lot of polls are taken separately; of most importance for the resultion of questioning from the field are the first two.
Changes are proposed against the wording in C23 draft n2912. 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 and p 6, and move text into a footnote
5 A parenthesized expression is a primary expression. Its type
and, value and semantics are identical to those of the unparenthesized expression.It is an lvalue, a function designator, or a void expression if the unparenthesized expression is, respectively, an lvalue, a function designator, or a void expression.
6 A generic selection is a primary expression. Its type
and, value and semantics depend on the selected generic association, as detailed in the following subclause.
Add a new paragraph p7
7 A parenthesized expression or a generic selection are said to be derived from the unparenthesized expression or from the selected generic association, respectively. FNT1)
FNT1) Such a primary expression 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 expression from which it is derived 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 and move text into a footnote
4 The type
and, value and semantics of a generic selection are identical to those of its result expression.It is an lvalue, a function designator, or a void expression if its result expression is, respectively, an lvalue, a function designator, or a void expression.
Emphasize that all constants may also appear inside primary expressions. Also make it clear that only evaluated parts account for the property.
6 An integer constant expression130) shall have integer type and shall only have evaluated operands that are integer constants, enumeration constants, character constants, predefined constants, or other primary expressions that are derived from these, or
sizeof
expressions whose results are integer constants,alignof
expressions, and floating constants (or derived primary expressions) that are the immediate operands of casts. Cast operators in an integer constant expression that are evaluated shall only convert arithmetic types to integer types, except as part of an operand to the typeof operators,.sizeof
operator, oralignof
operator
7 More latitude is permitted for constant expressions in initializers. Such a constant expression shall be, or evaluate to, one of the following:
or a primary expression that is derived from these.
- 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
.,
8 An arithmetic constant expression shall have arithmetic type and shall only have evaluated operands that are integer constants, floating constants, enumeration constants, character constants, predefined constants,or other primary expressions that are derived from these, or
sizeof
expressions whose results are integer constants, andalignof
expressions. Cast operators in an arithmetic constant expression that are evaluated shall only convert arithmetic types to arithmetic types, except as part of an operand to the typeof operators, sizeof operator, or alignof operator.
9 An address constant is a null pointer, a pointer to an lvalue designating an object of static storage duration, or a pointer to a function designator; it shall be created explicitly using the unary
&
operator or the cast of an integer constantcast(or derived primary expression) to pointer type, or implicitly by the use of an expression of array or function type. The array-subscript[]
and member-access.
and->
operators, the address&
and indirection*
unary operators, and pointer casts may be used in the creation of an address constant, but the value of an object shall not be accessed by use of these operators.
Currently, terms are introduced in clause 6.6 that are then implicitly used in syntax derivations. A common pattern is for example to have “constant-expression” in a syntax rule and then to have a constraint that the particular constant expression must be an integer constant expression. We think that this would be easier to read (and less verbose at the same time) if we introduce the terms directly as syntax terms and then use these syntax terms consequently in the sequel.
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.
Is there an intended semantic difference between the use of an expression
expr
and its parametrized version(expr)
?Is there an intended semantic difference between the use of the result expression of a generic selection and the generic selection itself?
Does WG14 want to integrate the changes for the Sematics clause of primary expressions, 3.1 of N3010, into C23?
Does WG14 want to integrate the changes for generic expressions, 3.2 of N3010, into C23?
Does WG14 want to integrate the changes for primary expressions in constant expressions, 3.3 of N3010, into C23?
Does WG14 want to integrate the syntax additions for constant expression, 4.1 to 4.9 of N3010, into C23?
Does WG14 want to integrate the syntax additions for constant expression, 4.1 to 4.9 of N3010, into a future version of C?
Does WG14 want to integrate the change for
static_assert
, 5 of N3010, into C23?Does WG14 want to integrate the change for
static_assert
, 5 of N3010, into a future version of C?