首页 > 解决方案 > 与在新表达式中解析类型 ID 相关的 gcc 发出错误

问题描述

这个节目

#include <cstddef>

int main()
{
    const std::size_t N1 = 2;
    const std::size_t N2 = 3;

    int ( **p )[N1] = new ( int ( *[N2] )[N1] );
}

使用编译器 C++ gcc HEAD 10.0.0 20190 进行编译。

编译器发出错误

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] );
      |                                               ^

但是,该程序使用 clang HEAD 10.0.0 编译。

指针类型 ID 规范是模棱两可的还是确实是 gcc 错误?

编辑:顺便说一句,如果要删除外括号,例如

int ( **p )[N1] = new int ( *[N2] )[N1];

然后 clang 也会发出一个引用 lambda 的错误

prog.cc:8:38: error: expected body of lambda expression
   int ( **p )[N1] = new int ( *[N2] )[N1];
                                     ^

标签: c++pointersgccc++17new-operator

解决方案


据我所知,这绝对是最新版本的 GCC 中的一个错误。据推测,GCC 正在尝试将( int ( *[N2] )[N1] )部分解析为new-placement,即带括号的表达式列表。Nowint (被解释为函数式转换等。

每个新表达式

new-expression :
    ::opt new new-placement opt new-type-id new-initializer opt
    ::opt new new-placement opt ( type-id ) new-initializer opt

关于new-placement( type-id 没有特殊的消歧规则,因此如果不能将其解释为expression-list),则应将其解释为type-id


EDIT部分是每个[expr.new]/4的语法错误:

注意:new-expression的new-type-id中的括号会产生令人惊讶的效果。[ 示例:

new int(*[10])();               // error

格式错误,因为绑定是

(new int) (*[10])();            // error

相反,new运算符的显式括号版本可用于创建复合类型的对象:

new (int (*[10])());

分配一个包含 10 个函数指针的数组(不带参数并返回int)。— 结束示例 ] — 结束注释 ]


推荐阅读