7

The following code can be compiled with gcc-13 and clang-16, but MSVC reports multiple errors

using foo_type = void ((((int, const char*))));   // (1)
// Compiler messages for line (1):
//    clang-16: ok.
//    gcc-13:   ok.
//    MSVC-v19: error C2062: type 'int' unexpected.


foo_type foo;

int main()
{
    foo(5, "Hello");
    return 0;
}

The question is: who's right? Does the Standard allow alias-declaration of a function type with multiple nested parentheses around argument list, like attempted in the example above?

Scheff's Cat
  • 19,528
  • 6
  • 28
  • 56
Igor G
  • 1,838
  • 6
  • 18

1 Answers1

5

Yes, that syntax is allowed and not specific to alias declarations. It applies to all declarators.

You can generally put as many parentheses around a declarator as you want. In the case of an abstract-declarator such as here, nothing changes, except that the declarator-id (i.e. the name) is omitted. An exception are declarators with a trailing-return-type.

For example, the following is also valid:

void (((foo(int, const char*))));

int main()
{
    foo(5, "Hello");
    return 0;
}

For the same reason you can also add parentheses around the * abstract-declarator in the function parameter:

using foo_type = void ((((int, const char(((*)))))));

Specifically for the tag, see the grammar production ( ptr-declarator ) for noptr-declarator in the non-abstract case and ( ptr-abstract-declarator ) for noptr-abstract-declarator in the abstract case.

TylerH
  • 20,799
  • 66
  • 75
  • 101
user17732522
  • 53,019
  • 2
  • 56
  • 105
  • I don't see how these productions permit extra parentheses around _parameters-and-qualifiers_. We have a single pair from **_parameters-and-qualifiers_ ⟶ `(` _parameter-declaration-clause_ `)` _cv-qualifier-seq_? …**, but no opportunity within _parameter-declaration-clause_ to introduce additional pairs. – Toby Speight Aug 15 '23 at 06:29
  • 3
    @TobySpeight _alias-declaration_ → `using` _identifier_ `=` _defining-type-id_ ; _defining-type-id_ → _defining-type-specifier-seq_ _abstract-declarator_ ; _defining-type-specifier-seq_ → … → `void` ; _abstract-declarator_ → _ptr-abstract-declarator_ → _noptr-abstract-declarator_ → `(` _ptr-abstract-declarator_ `)` → `(` _noptr-abstract-declarator_ `)` → `(` _parameters-and-qualifiers_ `)` – Language Lawyer Aug 15 '23 at 08:15
  • 2
    (Not) funny thing is that GCC accepts `using foo_type = auto ((((int, const char*) -> void)));` – Language Lawyer Aug 15 '23 at 08:27