两个月前,我报告了一个clang++错误,它是当使用z编译时,下面的C++程序将4294967295设置为clang++ -O2 -fno-strict-enums

enum e { e1, e2 } e;

long long x, y, z;

char *p;

void f(void) {
    e = (enum e) 4294967295;
    x = (long long) e;
    y = e > e1;
    z = &p[e] - p;
}
由于该程序未定义,我的错误报告被关闭为无效。我的感觉是使用选项-fno-strict-enums对其进行了定义。
据我所知,Clang没有值得称呼的文档,因为它的目的是在接受的选项及其含义方面与GCC兼容。我阅读了GCC关于-fno-strict-enums选项的文档,说该程序应将z的值设置为-1:

请注意,仅记录了-fstrict-enums选项,但似乎很清楚-fno-strict-enums禁用了-fstrict-enums启用的编译器行为。我无法针对GCC的文档提出错误,因为生成的二进制文件将z设置为-1(我理解-fno-strict-enums强制执行的工作)正是g++ -O2 -fno-strict-enums所做的事情。
谁能告诉我-fno-strict-enums在Clang中的作用是什么(如果我误解了它在GCC中的作用,那么在GCC中),以及该选项的值是否对Clang的任何地方都有效?
作为引用,我的错误报告是here,而显示我的意思的编译器资源管理器链接是here。用作引用的版本是针对I32LP64体系结构的Clang 10.0.1和GCC 10.2。

最佳答案

-fno-strict-enums的作用是取消-fstrict-enums。也就是说,不允许编译器使用枚举类型的值只能是枚举值之一的假设进行优化。我想强调,选择一词是“允许的”,而不是“必需的”。可能很难看到不再允许一开始没有做的事情的影响。不过,我想我已经找到了一个可以看到这一点的例子。
首先,我想在问题中阐明“枚举的值”。枚举e具有两个枚举器,其值分别为01。表示这些值所需的最少位数是1。因此,枚举的值都是可以用1位表示的所有值。在这种情况下,这恰好与枚举器的值一致,但在其他示例中不能保证。
接下来,让我们从问题的代码中删除一行。

enum e { e1, e2 } e;

long long x, y, z;

char *p;

void f(void) {
    //e = (enum e) 4294967295;
    x = (long long) e;
    y = e > e1;
    z = &p[e] - p;
}
我删除的行会干扰strict-enum标志。当编译器确切知道e的值是时,该标志允许编译器做出不必要的假设。编译器可以合理地选择不假定e仅可容纳01,这很明显是它只是被赋予了一个不同的值。 (此干扰不取决于4294967295对于32位有符号整数而言太大,而仅取决于4294967295作为编译时值。作为另一个示例,将(enum e) 2分配给e也会导致这种干扰。)
专注于分配y = e > e1。如果-fno-strict-enums有效,唯一可用的优化是将e1替换为0。但是,如果我们可以假定e只能是01(枚举的值,恰好也是枚举数的值),则可以使用另一种优化方法。
如果e0,则以下各项具有相同的值:
  • (long long) (e > e1)
  • (long long) (0 > 0)
  • (long long) false
  • (long long) e

  • 如果e1,则以下各项具有相同的值:
  • (long long) (e > e1)
  • (long long) (1 > 0)
  • (long long) true
  • (long long) e

  • 无论哪种情况,我们都可以跳过比较,只需将e转换为long long即可。这反射(reflect)在clang 10为y = e > e1行生成的程序集中。
    -fstrict-enums
    movq    %rax, y(%rip)
    
    -fno-strict-enums
    xorl    %ecx, %ecx
    testl   %eax, %eax
    setg    %cl
    movq    %rcx, y(%rip)
    
    -fstrict-enums进行了优化,-fno-strict-enums不允许这样做。

    关于c++ - clang++的-fno-strict-enums选项有什么作用?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/64728842/

    10-11 19:03