Pas*_*uoq 7 c++ enums compiler-flags clang++
两个月前,我报作为一个clang++错误,那下面套C ++程序z,以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;
}
Run Code Online (Sandbox Code Playgroud)
由于程序未定义,我的错误报告因无效而关闭。我的感觉是使用该选项-fno-strict-enums使其定义。
据我所知,Clang 没有名副其实的文档,因为它的目标是在它接受的选项及其含义方面与 GCC 兼容。我读了 GCC 的选项文档-fno-strict-enums说程序应该将值设置z为-1:
-fstrict-枚举
允许编译器使用以下假设进行优化:枚举类型的值只能是枚举值之一(如 C++ 标准中所定义;基本上,可以用最少位数表示的值来表示所有枚举器)。如果程序使用强制转换将任意整数值转换为枚举类型,则此假设可能无效。
请注意,仅记录了该选项-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 的任何地方都有任何影响?
作为参考,我的错误报告在这里和 Compiler Explorer 链接显示了我的意思在这里。用作参考的版本是针对 I32LP64 架构的 Clang 10.0.1 和 GCC 10.2。
的作用-fno-strict-enums是取消-fstrict-enums。也就是说,编译器不允许使用枚举类型的值只能是枚举值之一的假设进行优化。我想强调的是,这个词的选择是“允许”,而不是“要求”。很难看出不再允许那些一开始就没有做的事情所产生的影响。不过,我想我已经找到了一个可以看出这一点的例子。
首先,我想在问题的背景下澄清“枚举的值”。该枚举e有两个枚举器,其值为0和1。表示这些值所需的最小位数是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;
}
Run Code Online (Sandbox Code Playgroud)
我删除的线干扰了旗帜strict-enum。当编译器确切知道 的值是什么e时,该标志允许编译器做出不必要的假设。编译器可以合理地选择不假设e只能保存0,或者1当很明显它只是被赋予不同的值时。(这种干扰并不依赖于4294967295对于 32 位有符号整数来说太大,而仅仅依赖于4294967295编译时值。再举一个例子,分配(enum e) 2toe也会导致这种干扰。)
专注于作业y = e > e1。如果-fno-strict-enums有效,唯一可用的优化就是替换e1为0。但是,如果我们可以假设e只能是0或1(枚举的值,恰好也是枚举器的值),则可以使用另一种优化。
如果e是0,则以下各项具有相同的值:
(long long) (e > e1)(long long) (0 > 0)(long long) false(long long) e如果e是1,则以下各项具有相同的值:
(long long) (e > e1)(long long) (1 > 0)(long long) true(long long) e无论哪种情况,我们都可以跳过比较并简单地转换e为long long. 这反映在 clang 10 为该行生成的程序集中y = e > e1。
和-fstrict-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;
}
Run Code Online (Sandbox Code Playgroud)
和-fno-strict-enums
movq %rax, y(%rip)
Run Code Online (Sandbox Code Playgroud)
-fstrict-enums已进行了不允许的优化-fno-strict-enums。