3

I'm reading N1256 6.5.2.2 function call. Some parts were hard to understand to me. I googled with bold sentences or some keywords but couldn't find a straightforward answer to my question. So I ask mine.

At 6.5.2.2 p5(emphasize mine)

If the expression that denotes the called function has a type pointer to function returning an 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. If an attempt is made to modify the result of a function call or to access it after the next sequence point, the behavior is undefined.

Q1. What's the meaning of the bold sentence? Is there a way to modify the result of a function call or access it after the next sequence point?

A part of 6.5.2.2 p6(emphasize mine)

If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions. If the number of arguments does not equal the number of parameters, the behavior is undefined. If the function is defined with a type that includes a prototype, and either the prototype ends with an ellipsis (, ...) or the types of the arguments after promotion are not compatible with the types of the parameters, the behavior is undefined. If the function is defined with a type that does not include a prototype, and the types of the arguments after promotion are not compatible with those of the parameters after promotion, the behavior is undefined, except for the following cases: ...

At 6.7 p4, for the definition of compatible types.

All declarations in the same scope that refer to the same object or function shall specify compatible types.

Formal parameters are not an object, just a placeholder. Q2. Can arguments of a function call and a parameter be the same object? Q3. And why does the standard compare a promoted argument with a parameter? If there is a parameter to compare, promotion won't happen because default argument promotion happens only if the compiler doesn't know what data type callee expects.

Rohan Bari
  • 7,482
  • 3
  • 14
  • 34
op ol
  • 705
  • 4
  • 11
  • 1
    Possible duplicate for Q1: https://stackoverflow.com/questions/31128852/is-it-undefined-in-c11-to-modify-the-result-of-a-function-call-or-access-it-aft. Maybe Q2/Q3 should be in a separate question. – Nate Eldredge Mar 18 '21 at 04:19
  • 1
    Re “Formal parameters are not an object, just a placeholder”: It is not clear what you mean by that. C 2018 3.16 defines “parameter,” showing “formal parameter” as a synonym, as “object declared as part of a function declaration or definition that acquires a value on entry to the function, [or another definition for preprocessor macros],” directly contradicting your assertion that a formal parameter is not an object. A parameter is a separate object from the argument that was used to initialize it. – Eric Postpischil Mar 18 '21 at 11:48

1 Answers1

1

(Replacing previous answer)

For Q3, this seems to be about the case where the expression denoting the called function does not include a prototype, but the function definition does. In that case the arguments will be subject to promotion.

void foo1(short s) { // defined with a prototype
    // ...
}

void foo2(int i) { // defined with a prototype
   // ...
}

void bar(void) {
    void (*ptr)(); // no prototype
    char c = 'x';
    short s = 8;
    int i = 1234;
    long l = 12345678;

    ptr = foo1;
    ptr(c); // UB; char promoted to int which is not compatible with short
    ptr(s); // Also UB! short promoted to int which is not compatible with short
    ptr(i); // likewise UB
    // AFAICT there is no way to call foo1 through ptr without UB

    ptr = foo2;
    ptr(c); // OK; char promoted to int which is compatible with int
    ptr(s); // likewise OK
    ptr(i); // likewise OK
    ptr(l); // UB; long is not compatible with int.
}
Nate Eldredge
  • 48,811
  • 6
  • 54
  • 82
  • Does `foo()` have prototype? I think the standard assumes situation that there is a prototype. And do you think 'compatible' is the same as one type can be represented by another(compatible) type? That is, the word should be interpreted literally and not the definition of the standard? – op ol Mar 18 '21 at 05:11
  • Updated answer. I do mean "compatible" in the sense of the standard. – Nate Eldredge Mar 18 '21 at 05:24
  • I might misunderstand the meaning of 'compatible'. The type in question is not an array type, pointer type, structure, union, enumeration, function, or qualified type. Then two type are compatible when they are the same. Promoted argument of the function call ptr(); would never be the same as short because integer promotion makes a promoted type at least int precision. Then `ptr(c)`, `ptr(i)` and `ptr(l)` are all UB, I think. Your answer is, however, exactly describe the standard's illustration. – op ol Mar 18 '21 at 05:44
  • @opol: Yes, now I think I understand your point. Edited to try once more. – Nate Eldredge Mar 18 '21 at 05:56