Clarify syntactic terms for array declarators

Jens Gustedt, INRIA and ICube, France

2025年02月16日

target

integration into IS ISO/IEC 9899:202y

document history

document number date comment
n3393 202411 Original proposal
n3414 202412 Motivate the two proposed normative changes
Use the term "number of elements"
Only refer to the different syntaxt rules as "forms"
Make it clearer that only one of the conditions for composite types is syntactic
n3495 202502 Grammar and change marks, discuss _Lengthof or similar

license

CC BY, see https://creativecommons.org/licenses/by/4.0

1 Motivation

The current wording of 6.7.7.3 is very confusing because it mixes up syntactic and semantic definitions in several places. In particular it introduces a term "size of an array" in the constraints section that is not properly defined; it is not clear what "specifies" means here. Later in the text even the case of a * token, which is just one other syntax derivation, is seemingly subsumed with that term. So is it a syntax element (the assignment expression or * token) or is it a semantic derivation (the value of that assignment expression, which does not exist for the * case)?

We propose to iron out these issues by changing the text to use already introduced terms and to make a clearer distinction of where the text talks about syntactic deduction and where it introduces semantic for that syntax.

2 Approach

We remove the confusing term "size of an array" by reverting its use to the one that appears in the syntax derivation, namely an (追記) assignment (追記ここまで) expression. Adding just this distinctive word in all places where the current text just talks about "expression", should make things clearer.

In particular when it comes to the definition of compatible types, the current text gives a definition that only applies sensibly to the syntactic constructs, and that lack a consistent lift to the semantics. So we change this definition of compatibility to refer to the syntax construct "array declarator" (which is the subject of the clause) and only then lift this definition to array types in a second step.

2.1 Normative changes

We propose two normative changes which are not meant to change existing practice but to repair the standard such it matches existing practice. If any of these normative changes is not wanted by WG14, it can easily be omitted.

2.1.1 Using integer constant expression instead of constant expression

The addition of the word (追記) integer (追記ここまで) in some places upgrading the term "constant expression" to "integer constant expression" (6.7.7.3 and J .2 item 72) is intended to be a normative change.

Discussion on the reflector has shown that the expressions here are meant to reflect a constraint at translation time and not a link time, and so we propose to rectify the text by this addition.

2.1.2 Completing incomplete array types

A change of semantics also occurs in 6.7.11 when changing the term "initializer list" to "initializer or braced initializer". This is doubly motivated

We also add "or by an initializer" in 6.2.5 p27, because without this the description is incomplete. The type of an identifier can be completed within the same definition, not only by additional declarations that have linkage that are provided later. Note that here adding "initializer" and not "braced initializer" is sufficient because that sentence is talking of declarations of identifiers. This addition does not change the normative contents of the text.

3 Suggested additions and changes to the wording.

New text is (追記) underlined green (追記ここまで), removed text is (削除) stroke-out red (削除ここまで).

3.1 In 6.2.5 (Types)

27 An array type of unknown (削除) size (削除ここまで) (追記) number of elements (追記ここまで) is an incomplete type. It is completed, for an identifier of that type, by specifying the size in a later declaration (with internal or external linkage) (追記) or by an initializer, see 6.7.11 (追記ここまで). A structure or union type of unknown content (as described in 6.7.3.4) is an incomplete type. It is completed, for all declarations of that type, by declaring the same structure or union tag with its defining content later in the same scope.

3.2 to 6.2.7, Compatible type and composite type

in p3, second bullet

  • If one type is an array of known constant size (追記) and N elements (追記ここまで), the composite type (削除) is an array of that size (削除ここまで) (追記) has N elements (追記ここまで).
  • Otherwise, if one type is a variable length array whose (削除) size is specified by an (削除ここまで) (追記) declarator has (追記ここまで) an (追記) assignment (追記ここまで) expression that is not evaluated, the behavior is undefined.
  • Otherwise, if one type is a variable length array (削除) whose size is specified (削除ここまで) (追記) with N elements (追記ここまで), the composite type is a variable length array (削除) of that size (削除ここまで) (追記) with N elements (追記ここまで).
  • Otherwise, if one type is a variable length array (削除) of unspecified size (削除ここまで) (追記) with an unspecified number of elements (追記ここまで), the composite type is a variable length array (削除) of unspecified size (削除ここまで) (追記) with an unspecified number of elements (追記ここまで).
  • Otherwise, both (追記) array (追記ここまで) types are (追記) incomplete (追記ここまで) (削除) arrays of unknown size (削除ここまで) and the composite type is an (追記) incomplete (追記ここまで) array (削除) of unknown size (削除ここまで) (追記) type (追記ここまで).

3.3 to 6.7.7.3, Array declarators

Constraints

1 In addition to optional type qualifiers and the keyword static, the [ and ] can delimit an (追記) assignment (追記ここまで) expression or (追記) a (追記ここまで) * (追記) token (追記ここまで). If they delimit an (追記) assignment (追記ここまで) expression (削除) (which specifies the size of an array), the expression (削除ここまで) (追記) it (追記ここまで) shall have an integer type. If the (追記) assignment (追記ここまで) expression is an (追記) integer (追記ここまで) constant expression, it shall have a value greater than zero. The element type shall not be an incomplete or function type. The optional type qualifiers and the keyword static shall appear only in a declaration of a function parameter with an array type, and then only in the outermost array type derivation.

2 ...

Semantics

3 ...

4 (削除) If the size is not present (削除ここまで) (追記) In the first form (追記ここまで), the array type (追記) has an unknown number of elements and (追記ここまで) is an incomplete type. (削除) If the size is * instead of being an expression (削除ここまで) (追記) In the fourth form (追記ここまで), the array type is a variable length array type (削除) of unspecified size (削除ここまで) (追記) with an unspecified number of elements (追記ここまで), which can only be used as part of the nested sequence of declarators or abstract declarators for a parameter declaration, not including (削除) anything inside an array size expression (削除ここまで) (追記) any array declarator of the second or third form (追記ここまで) in one of those declarators;161) such arrays are nonetheless complete types. (追記) Otherwise, if the assignment expression is evaluated its value is the number of elements of the array type (6.2.5); this value is subsequently also denoted by the terms size of an array or length of an array. (追記ここまで) If the (削除) size (削除ここまで) (追記) assignment (追記ここまで) expression is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; otherwise, the array type is a variable length array type. (Variable length arrays with automatic storage duration are a conditional feature that implementations may support; see 6.10.10.4.)

5 If the (削除) size is an (削除ここまで) (追記) assignment (追記ここまで) expression (削除) that (削除ここまで) is not an integer constant expression: if it occurs in a declaration at function prototype scope, it is treated as if it were replaced by (追記) a (追記ここまで) * (追記) token (追記ここまで); otherwise, each time it is evaluated it shall have a value greater than zero. The (削除) size (削除ここまで) (追記) number of elements (追記ここまで) of each instance of a variable length array type does not change during its lifetime. Where (削除) a size (削除ここまで) (追記) the (追記ここまで) (追記) assignment (追記ここまで) expression is part of the operand of a typeof or sizeof operator and changing the value of the (削除) size (削除ここまで) (追記) assignment (追記ここまで) expression would not affect the result of the operator, it is unspecified whether or not the (削除) size (削除ここまで) (追記) assignment (追記ここまで) expression is evaluated. Where (削除) a size (削除ここまで) (追記) an assignment (追記ここまで) expression is part of the operand of an alignof operator, that (追記) assignment (追記ここまで) expression is not evaluated.

6 For two array types to be compatible, both shall have compatible element types, and if (削除) both size specifiers are present, and are integer constant expressions, then both size specifiers shall have the same constant value (削除ここまで) (追記) for both the number of elements is specified, it shall be the same. (追記ここまで) (削除) If the two array types are used in a context which requires them to be compatible, the behavior is undefined if the two size specifiers evaluate to unequal values. (削除ここまで)

...

11 EXAMPLE 5 The following is invalid, because the use of [*] is inside an (削除) array size (削除ここまで) (追記) assignment (追記ここまで) expression (追記) of an array declarator (追記ここまで) rather than directly part of the nested sequence of abstract declarators for a parameter declaration:

void f(int (*)[sizeof(int (*)[*])]);

3.4 to 6.7.9, Type definitions

3 In a declaration whose storage-class specifier is typedef, each declarator defines an identifier to be a typedef name that denotes the type specified for the identifier in the way described in 6.7.7. Any (削除) array size (削除ここまで) (追記) assignment (追記ここまで) expressions associated with variable length array declarators and typeof operators are evaluated each time the declaration of the typedef name is reached in the order of execution. A typedef declaration does not introduce a new type, only a synonym for the type so specified. That is, in the following declarations: ...

3.5 to 6.7.11, Initialization

23 If an array of (削除) unknown size (削除ここまで) (追記) an incomplete array type (追記ここまで) is initialized, its (削除) size (削除ここまで) (追記) number of elements (追記ここまで) is determined by the largest indexed element with an explicit initializer. The array type is completed at the end of its initializer (削除) list (削除ここまで) (追記) (for array definitions) or braced initializer (for compound literals) (追記ここまで).

3.6 to 6.8.1

4 A full expression is an expression that is not part of another expression, nor part of a declarator or abstract declarator. There is also an implicit full expression in which (削除) the non-constant size expressions for a variably modified type are (削除ここまで) (追記) an assignment expression of an array declarator that is not an integer constant expression is (追記ここまで) evaluated; within that full expression, the evaluation of different (削除) size (削除ここまで) (追記) assignment (追記ここまで) expressions (追記) of array declarators (追記ここまで) are unsequenced with respect to one another. There is a sequence point between the evaluation of a full expression and the evaluation of the next full expression to be evaluated.

3.7 to 7.21.2, the unreachable macro

In p4 make the following change

Here, the static (削除) array size (削除ここまで) (追記) adorned assignment (追記ここまで) expression (追記) of the array declarator (追記ここまで) and the annotation of the control flow with unreachable indicates that the pointed-to parameter array argv will hold at least three elements, regardless of the circumstances.

3.8 to J .1

  1. Whether (削除) a size expression (削除ここまで) (追記) an assignment expression of an array declarator (追記ここまで) is evaluated when it is part of the operand of a sizeof operator and changing the value of the (削除) size (削除ここまで) (追記) assignment (追記ここまで) expression would not affect the result of the operator (6.7.7.3)

3.9 to J .2

  1. A program requires the formation of a composite type (削除) from a variable length array type whose size is specified by an (削除ここまで) (追記) from an array declarator with an assignment (追記ここまで) expression that is not evaluated (6.2.7).
  1. The (削除) size expression in an array declaration (削除ここまで) (追記) assignment expression of an array declarator (追記ここまで) is not (削除) a (削除ここまで) (追記) an integer (追記ここまで) constant expression and evaluates at program execution time to a nonpositive value (6.7.7.3).
  1. In a context requiring two array types to be compatible, they do not have compatible element types, or (削除) their size specifiers evaluate to unequal values (削除ここまで) (追記) their respective number of elements are specified but are not the same (追記ここまで) (6.7.7.3).

4 Interaction with other proposals

If n3499 is accepted concurrently, the additions of the word "assignment" above should instead read "reproducible". Note that n3498 also proposes changes to 6.7.7.3, but that these are independent of each other.

Another interaction is with the whole discussion if we should have a term for the "number of elements of an array" and what that term should be. If e.g we decide to stick to _Lengthof or lengthof, we could use "array length" throughout instead of "assignment expression" as proposed here. If we change the name of that operator to countof, use "array count", etc.

Aknowledments

Thanks to Jakub Łukasiewicz, Joseph Myers, Javier Múgica and Robert Seacord for review and discussions.

AltStyle によって変換されたページ (->オリジナル) /