为什么gcc会警告decltype(main())而不是clang?

a59*_*640 11 c++ gcc clang c++11

请使用以下代码:

int main()
{
    decltype(main()) x = 0;
    return x;
}
Run Code Online (Sandbox Code Playgroud)

gcc抱怨:

main.cpp: In function 'int main()':
main.cpp:8:19: warning: ISO C++ forbids taking address of function '::main' [-Wpedantic]
     decltype(main()) x = 0;
                   ^
main.cpp:8:19: warning: ISO C++ forbids taking address of function '::main' [-Wpedantic]
Run Code Online (Sandbox Code Playgroud)

但没有铿锵 那么怎么decltype(main())会引发这个错误呢?怎么decltype拿主要的地址?

Bri*_*ian 11

在这种情况下,GCC的诊断可能没有正确措辞,因为decltype不需要知道地址main; 它只需要知道它的类型.但是,警告基于以下标准(§3.6.1/ 3):

该功能main不得在程序中使用.

我想GCC将此解释为意味着你甚至无法在未经评估的表达中使用它.

Clang(版本3.4无论如何)似乎根本没有实现这个规则,即使我打开了我能想到的所有标志,即使是main递归调用本身.这就是为什么它不会给你一个警告.

  • 我不认为这是clang中的错误,编译器不需要诊断用户做的每一个愚蠢的事情,并且通过我读取一个调用`main`的程序具有未定义的行为. (2认同)

Sha*_*our 10

这个主题最近在线程中的未定义行为研究组讨论列表中实际出现了什么"函数main不能在程序中使用"是什么意思?.它不会马上出现,但这里是它在线程中以下面的语句开始的地方:

我不认为decltype(main())是odr-use或sizeof(decltype(main)).

一组非常简短的响应如下所示:

没错,我只是看不出那些实用性.在后一种情况下,您可能意味着sizeof(decltype(&main)).

我认为最常见的非ODR使用主要是在前向声明之后定义它,现在Steven Clamage澄清说应该是格式错误.更广泛的"使用"定义是名称查找的结果而不参考ODR现在看起来是正确的.

和:

C++ 98提到'use'有一个交叉引用3.2 [basic.def.odr].C++ 11不再具有交叉引用,并且没有更改为"odr-use",所以我希望它意味着任何用途.

所以似乎3.6.1 主要功能部分的解释说:

函数main不得在程序中使用.[...]

即使在未评估的上下文中也意味着任何用途,因此gcc在这里产生错误是正确的,尽管消息本身似乎没有意义.

更新

值得注意的是,原始提案:修复缺陷报告1109的N3154将改为3.6.1:

函数main不应在程序中使用odr-used(3.2)....

这将允许这个decltype例子,但在被接受时进行了修改,我们可以看到新的提案:N3214改为我们今天所拥有的:

函数main不得在程序中使用

这将强烈表明UB邮件列表中的任何使用形式错误的观点main确实是正确的.