优化 ARM Apple Clang 中关于将双精度型隐式转换为字节的错误

pra*_*pin 0 c++ clang++

我在我们的 C++ iOS 应用程序中发现了一个严重的错误,我怀疑这是由基于 ARM 的 Apple Clang 上的编译器错误引起的。

我能够在 Mac M1 机器上的 MRE 中重现该错误。

#include <cstdio>

int main(int argc, const char** argv)
{
    int total = 0;
    for(double a=1000; a<10000; a*=1.1)
    {
        unsigned char d = a / 0.1;
        total += d;
    }
    printf("Total: %d\n", total);
}
Run Code Online (Sandbox Code Playgroud)

在没有优化的情况下编译,测试程序总是产生相同的输出:

% ./a.out            
Total: 3237
% ./a.out
Total: 3237
% ./a.out
Total: 3237
Run Code Online (Sandbox Code Playgroud)

然而,当进行优化编译时,结果数字似乎是随机的:

% clang -O3 test.cpp 
% ./a.out            
Total: 74841976
% ./a.out
Total: 71057272
% ./a.out
Total: 69828472
Run Code Online (Sandbox Code Playgroud)

Apple Clang 版本为 13.0:

% clang --version
Apple clang version 13.0.0 (clang-1300.0.29.30)
Target: arm64-apple-darwin21.3.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Run Code Online (Sandbox Code Playgroud)

我相信该程序没有未定义的行为。所以我的问题是:

  • 这真的是编译器错误吗?
  • 原始(非苹果)Clang 上的行为也是错误的吗?
  • 我应该填写错误报告吗?

Nat*_*ica 5

您的代码确实有未定义的行为。当你这样做时

unsigned char d = a / 0.1;
Run Code Online (Sandbox Code Playgroud)

您正在进行浮点到整数的转换,这意味着[conv.fpint]/1适用并且它指出:

浮点类型的纯右值可以转换为整数类型的纯右值。转换截断;也就是说,小数部分被丢弃。如果截断值无法在目标类型中表示,则行为未定义。

强调我的

因此,一旦a / 0.1超过 an 的最大值,unsigned char您就会出现未定义的行为。