Function call without decay

Jens Gustedt, INRIA and ICube, France

2025-05-28

target

integration into IS ISO/IEC 9899:202y

document history

document number date comment
n3557 202505 this document

1 Introduction

The choice that function designators decay to function pointer inside function call expressions seems to have been made to facilitate the description of function call operators and to ensure that the model corresponded to the low level jump instructions with a target label. The times that this model sufficiently describes modern compilation techniques are long past; inlining (with or without the inline keyword), specialization and link-time optimization regularly push this model to its limits.

Recently WG14 has accepted N3517, Array subscripting without decay, for C2y and this paper here attempts to change the text for function call expressions in the same spirit. Luckily, the implications for function calls are much less than for array subscripting, so we hope that we will easier get consensus.

Nevertheless we think that it is important to make that step, such that other changes that might come later during development of C2y can be integrated more easily. This concerns in particular

2 Approach

The current wording describes the constraints on the leading operand of a function call operator with

shall have type pointer to function returning void or returning a complete object type other than an array type

and then later wiggles around this description all over the text. Adding “function type” to this lengthy description in all places would make the text almost unreadable. Therefore we propose to do some housekeeping at the same time and to reorganize the text such that its intent becomes clearer.

No change of semantics is intended.

Unfortunately that housekeeping also implies certain reordering of paragraphs. We try to address this reorganization as readable as possible.

3 Wording changes

New text is underlined green, removed text is stroke-out red. Reorganization of the paragraphs is indicated in the running text, refers to new paragraph numbers, pX to current numbers.

3.1 Conversions

6.3.3.1 Lvalues, arrays, and function designators

p3 A function designator is an expression that has function type. Except when it is the operand of the sizeof operator,56) a typeof operator, or the unary & operator, or the leading operand of a function call operator, a function designator with type “function returning type” is converted to an expression that has type “pointer to function returning type”.

3.2 Expressions

6.5.3.3 Function calls

Move paragraph p3 up front, since it is purely descriptive.

Description

A postfix expression followed by parentheses () containing a possibly empty, comma-separated list of assignment expressions is a function call. The postfix expressionleading operand denotes the called function. The list of expressions specifiesother operands, if any, specify the arguments to the function call.

Constraints

Now come p1 and p2 combined together, including the new case that the function is just denoted by a function descriptor. Introducing a type FT for the specified function type alleviates the text.

The expression that denotes the called function91) leading operand shall have type pointer to function function type or be a pointer to such a function type. This function type FT shall be returning void or be returning a complete object type other than an array type.
p2
The number of arguments shall agree with the number of parameters of FT. Each argument shall have a type such that its value may be assigned to an object with the unqualified version of the type of its corresponding parameter.

91) Most often, this is the result of converting an identifier that is a function designator.

Semantics

Previously p7 and p5. These can be compacted by clearly refering to FT instead of beating around the bush.

If the called function is defined with a type that is not compatible with the type (of the expression) pointed to by the expression that denotes the called function FT, the behavior is undefined.
p5
If the expression that denotes the called function has type pointer to function FT is returning an a complete object type, the function call expression has the same type as that object type, and has the value determined as specified in 6.8.6.4. Otherwise, the function call has type void.

Previously p4 and p6 are combined and can be shortened, too.

An argument can be an expression of any complete object type. In preparing for the call to the function, the arguments are evaluated, and each parameter is assigned the value of the corresponding argument
p6 The arguments the resulting values are implicitly converted, as if by assignment, to the types of the corresponding parameters, taking the type of each parameter to be the unqualified version of its declared type.92) The ellipsis notation in a variadic function declarator (6.7.7.4) causes argument type conversion to stop after the last declared parameter, if present. The integer promotions are performed on each trailing argument, and trailing arguments that have type float are promoted to double. These are called the default argument promotions. No other conversions are performed implicitly.

92) A function can change the values of its parameters, but these changes cannot affect the values of the modify lvalues that are used as arguments. On the other hand, it is possible to pass a pointer to an object, and the function can then change the value of the object pointed to. A parameter declared to have array or function type is adjusted to have a pointer type as described in 6.7.7.4

Prefer to speak of operands. Also the same thing (execution of the called function) was addressed with two different terms within the same paragraph; chose one and stick to it.

There is a sequence point after the evaluations of all operands (the function designator and the actual arguments) but before the actual call execution of the called function. Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.93)

93) In other words, function executions do not interleave with each other.

Then terminate with p9 and p10 unchanged.

Recursive function calls shall be permitted, both directly and indirectly through any chain of other functions.

EXAMPLE …

3.3 Sequence points

C .1 Known Sequence Points

Update the first bullet point