Ayrosa
Ayrosa

Reputation: 3513

Where in the Standard does it say that the declaration `auto f()() ->int;` is not allowed?

I know I'm being pedantic here, but I'm just trying to understand the C++ grammar production.

I will start with a simple-declaration.

simple-declaration:
    decl-specifier-seqopt   init-declarator-listopt

decl-specifier-seq:
    decl-specifier

decl-specifier:
    type-specifier

type-specifier:
    trailing-type-specifier

trailing-type-specifier:
    simple-type-specifier

simple-type-specifier:
     char
     int
     ...
     auto


Now, I'll look into the definition of a init-declarator-list.

init-declarator-list:
    init-declarator

init-declarator:
    declarator

declarator:
    noptr-declarator   parameters and qualifiers   trailing return type    (*2)

noptr-declarator:
    declarator-id   attribute-specifier-seqopt
    noptr-declarator   parameters and qualifiers    (*1)

parameters and qualifiers:
    (parameter-declaration-clause)   cv-qualifiersopt   ... (all optionals)

trailing-return-type:
    ->   trailing-type-specifier-seq

trailing-type-specifier-seq:
    trailing-type-specifier                See the definition of a traling-type-specifier above.


Replacing noptr-declarator by a declarator-id in (*1), using the previous definition of noptr-declaration, we arrive at the following definition of nonptr-declarator:

noptr-declaration:
    declarator-id   parameters and qualifiers

Now replacing noptr-declarator, parameters and qualifiers and trailing-return-type in (*2) by each definition given above, we obtain the following for declarator:

declarator:
    declarator-id   (parameter-declaration-clause)   (parameter-declaration-clause)   ->
                                    simple-type-specifier


With this last result we could say that the grammar allows the following declaration of a function f:

auto f()() -> int;  

which of course is not valid. But I couldn't find anything in the Standard saying, directly or indirectly, that this construction is ill-formed.

The error messages from GCC (f declared as function returning a function) and clang (auto return without trailing return type; deduced return types are a C++1y extensions) didn't help in this regard either.

Upvotes: 4

Views: 327

Answers (2)

Michael Karcher
Michael Karcher

Reputation: 4031

In fact, the gcc error message is quite helpful: The grammar does in fact allow auto f()() -> int, but this syntactically correct declaration is semantically invalid. It would describe a function returning a function returning int. See the answer of ecatmur for the standard quote disallowing that.

To understand the parse, work like this. f is what you want to declare. Parse to the right, you'll find an empty argument list, so f() is a valid expression, and the type of that expression gets declared. Parse again to the right, you'll find an argument list again, so the return type of f is a function taking zero arguments. Parse again to the right, and you will hit the end (the -> arrow), so parse to the left to find the result type, which is auto, and gets replaced by the type past the arrow.

Upvotes: 9

ecatmur
ecatmur

Reputation: 157364

[dcl.fct]/8:

[...] Functions shall not have a return type of type array or function, although they may have a return type of type pointer or reference to such things. [...]

Upvotes: 11

Related Questions