2

给定以下完整程序:

#include <functional>

struct jobbie
{
    std::function<void()> a;
};

void do_jobbie(jobbie j = {})
{
    if (j.a) 
        j.a();
}

int main()
{
    do_jobbie();
    return 0;
}

在 gcc (Ubuntu 4.8.1-2ubuntu1~12.04) 4.8.1 上编译这个:boom!

richard@DEV1:~/tmp$ g++ -std=c++11 bug.cpp
bug.cpp: In function ‘int main()’:
bug.cpp:16:13: internal compiler error: in create_tmp_var, at gimplify.c:479
  do_jobbie();
             ^
Please submit a full bug report,
with preprocessed source if appropriate.
See <file:///usr/share/doc/gcc-4.8/README.Bugs> for instructions.
Preprocessed source stored into /tmp/ccWGpb7M.out file, please attach this to your bugreport.

然而,clang [Apple LLVM 版本 5.1 (clang-503.0.40) (基于 LLVM 3.4svn)] 对此很满意。

$ clang++ -std=c++11 bug.cpp

在我看来,clang 正确地推断出 j 默认为默认构造的jobbie对象,而 gcc (显然)正在爆炸。

将第 8 行替换为void do_jobbie(jobbie j = jobbie {})修复 gcc 上的问题。

问题 - 以下哪些是正确的:

  1. clang 是正确的,gcc 是错误的(忽略编译器爆炸)
  2. clang 超出了标准,它不应该真正编译
  3. 标准没有说清楚?
4

2 回答 2

4

内部编译器错误始终是编译器错误。编译器应该能够处理任何东西而不会像那样崩溃。

clang 在崩溃时有类似的处理,生成报告错误的数据并将用户指向 clang 的错误报告网页。

我看不出这段代码有什么棘手的地方。对我来说,它应该编译和运行似乎很简单。

于 2014-08-02T16:21:19.933 回答
2

这表明它应该工作:

默认参数具有与参数类型变量声明中的初始化程序相同的语义约束,使用复制初始化语义。

(8.3.6,来自草案 n3936 的措辞)

于 2014-08-02T17:03:14.147 回答