Search code examples
clanguage-lawyerlvaluefunction-call

Why isn't function call an lvalue


This should be pretty obvious, but I could not any normative reference in the Standard explicitly that function call is (not) an lvalue. There is somewhat related question, but it's about C++ and no references is provided.

Looking through 6.5.2.2(p5) Function calls the only I could find is

If the expression that denotes the called function has 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

6.3.2.1(p1) states that

An lvalue is an expression (with an object type other thanvoid) that potentiallydesignates an object

So I tried to find if a function call designates an object. It is not specified in the Standard if the function call result has storage duration and lifetime. Since any object has storage duration and lifetime I concluded that any function call expression does not designate an object an hence not an lvalue.

But this seems confusing and complicated. In particular I found an example 6.5.2.3(p7):

EXAMPLE 1 If f is a function returning a structure or union, and x is a member of that structure or union, f().x is a valid postfix expression but is not an lvalue.

Judging by this example if f() would be an lvalue f().x would also be an lvalue. But examples are informative which made me confused.


Solution

  • It's not an lvalue because its described as a "value" in the paragraph you quoted. The standard explicitly mentions when an expression has the property of being an lvalue. For instance:

    6.5.3.2 Address and indirection operators (emphasis mine)

    4 The unary * operator denotes indirection. If the operand points to a function, the result is a function designator; if it points to an object, the result is an lvalue designating the object. If the operand has type ''pointer to type'', the result has type ''type''. If an invalid value has been assigned to the pointer, the behavior of the unary * operator is undefined.

    As for accessing a union or member. The standard doesn't require the postfix expression in expr.id to be an lvalue. On the contrary. The whole member access has the same value category as the postfix expression:

    6.5.2.3 Structure and union members (emphasis mine)

    3 A postfix expression followed by the . operator and an identifier designates a member of a structure or union object. The value is that of the named member, and is an lvalue if the first expression is an lvalue. If the first expression has qualified type, the result has the so-qualified version of the type of the designated member.

    So in the example you quoted, f().x is a value, and not an lvalue, because f() itself is not an lvalue.