M.M M.M - 3 months ago 10
C++ Question

Is sizeof(int()) a legal expression?

This question is inspired by Is sizeof(void()) a legal expression? but with an important difference as explained below.

The expression in question is:

sizeof( int() )


In the C++ grammar there appears:


unary-expression:


  • sizeof
    unary-expression

  • sizeof (
    type-id
    )




however,
( int() )
can match both of these cases with different meanings:


  • As a unary-expression, it is a value-initialized
    int
    prvalue, surrounded in redundant parentheses

  • As a type-id, it is the type of a function with no parameters returning
    int
    .



In the semantic constraints for
sizeof
, i.e. C++14 [expr.sizeof]/1, it explains that the form
sizeof(
type-id
)
may not be applied to a function type.

However I'm not sure whether the violation of that semantic constraint implies that
sizeof( int() )
is correct and uses the
sizeof
unary-expression form; or whether there is some other rule that disambiguates the two cases at an earlier stage of grammar matching.

NB. For the other question
sizeof(void())
, neither interpretation is valid, so it could be argued that the compiler is correct to reject the expression with an error message indicating it matched the type-id form. However, gcc rejects
sizeof( int() )
with a message about type-id.

To be clear, my question is: "Is
sizeof( int() )
a legal expression?", particularly on the detail of how the grammar matching works when both of the above bulleted cases match.

Answer

No, sizeof( int() ) is ill-formed because int() is taken to be a type-id. Specifically, it's a function type, and sizeof cannot be applied to a function type.

[dcl.ambig.res]/2:

An ambiguity can arise from the similarity between a function-style cast and a type-id. The resolution is that any construct that could possibly be a type-id in its syntactic context shall be considered a type-id.

with this exact example given:

void foo(signed char a) {
    sizeof(int());                // type-id (ill-formed)
    sizeof(int(a));               // expression
    sizeof(int(unsigned(a)));     // type-id (ill-formed)