This program
#include <cstddef>
int main()
{
const std::size_t N1 = 2;
const std::size_t N2 = 3;
int ( **p )[N1] = new ( int ( *[N2] )[N1] );
}
does not compile using the compiler C++ gcc HEAD 10.0.0 20190.
The compiler issues error
prog.cc: In lambda function:
prog.cc:8:40: error: expected '{' before ')' token
8 | int ( **p )[N1] = new ( int ( *[N2] )[N1] );
| ^
prog.cc: In function 'int main()':
prog.cc:8:34: error: no match for 'operator*' (operand type is 'main()::<lambda()>')
8 | int ( **p )[N1] = new ( int ( *[N2] )[N1] );
prog.cc:8:47: error: expected type-specifier before ';' token
8 | int ( **p )[N1] = new ( int ( *[N2] )[N1] );
| ^
However the program compiles using clang HEAD 10.0.0.
Is the pointer type-id specification ambiguous or is it indeed a gcc bug?
EDIT: By the way if to remove the outer parentheses like
int ( **p )[N1] = new int ( *[N2] )[N1];
then clang also issues an error referencing a lambda
prog.cc:8:38: error: expected body of lambda expression
int ( **p )[N1] = new int ( *[N2] )[N1];
^
As far as I can tell, this is definitely a bug in the newest versions of GCC. Presumably, GCC is attempting to parse the ( int ( *[N2] )[N1] )
part as a new-placement, i.e., a parenthesized expression list. Now int (
is interpreted as a function-style cast, etc.
Per new-expression:
new-expression:
::
optnew
new-placementopt new-type-id new-initializeropt
::
optnew
new-placementopt(
type-id)
new-initializeropt
There is no special disambiguation rule regarding new-placement vs (
type-id )
, so the thing should be interpreted as a type-id if it cannot be interpreted as an expression-list.
The EDIT part is a syntax error per [expr.new]/4:
[ Note: Parentheses in a new-type-id of a new-expression can have surprising effects. [ Example:
new int(*[10])(); // error
is ill-formed because the binding is
(new int) (*[10])(); // error
Instead, the explicitly parenthesized version of the new
operator can be used to create objects of compound types:
new (int (*[10])());
allocates an array of 10 pointers to functions (taking no argument and returning int
).
— end example ]
— end note ]