GCC 的 -Wmaybe-uninitialized 是否为基于枚举的 switch 语句生成带有 -O1 的虚假警告?
Is GCC's -Wmaybe-uninitialized generating a spurious warning with -O1 for a switch statement based on an enum?
我有一段如下形式的代码:
typedef enum {A=1,B} EnumType;
int foo (EnumType x)
{
int r;
switch (x) {
case A:
r = 1;
break;
case B:
r = 2;
break;
/*
default:
r = -1;
break;
*/
}
return r;
}
我使用 GCC 6.3.0 编译并收到警告:
$ gcc --version
gcc (MacPorts gcc6 6.3.0_2) 6.3.0
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gcc -c -Wall -O1 test.c
test.c: In function 'foo':
test.c:20:10: warning: 'r' may be used uninitialized in this function [-Wmaybe-uninitialized]
return r;
^
代码对我来说似乎是安全的,确实有一些关于 GCC producing false positives with this warning 的讨论。
这是虚假警告吗?
更多相关信息:
- 添加注释掉的
default:
块解决警告
-O0
不出现警告
这个警告是完全正确的,因为 enum
类型不会将可能的值限制为在此 enum
中定义的成员——它可以保存 any 基础整数类型的值。因此,如果您的开关中没有 default
分支,您确实可以使用未初始化的 r
和您显示的代码。
我可以使用问题中显示的确切代码重现 gcc
和 -O0
缺少的警告,所以在我看来这就像 gcc
中的错误。无论优化级别如何,都应发出警告。
很容易弄清楚:在某些可能的程序路径中,r 将在未初始化的情况下返回。所以你得到了警告。枚举只是 int 所以你有很多可能的情况。
运行时不根据值检查枚举。
关于问题的第二部分。这是故意的,因为任何级别的优化都可以(在这种情况下,如果枚举类型的值是非法的,将删除代码——编译器假定没有其他可能的值)
这个案例最有意思:
https://godbolt.org/g/TDUhN7
您可能认为您检查了非法值。但是编译器已经删除了代码:)
顺便说一句 - 有趣的是为什么我的回答被否决了
我有一段如下形式的代码:
typedef enum {A=1,B} EnumType;
int foo (EnumType x)
{
int r;
switch (x) {
case A:
r = 1;
break;
case B:
r = 2;
break;
/*
default:
r = -1;
break;
*/
}
return r;
}
我使用 GCC 6.3.0 编译并收到警告:
$ gcc --version
gcc (MacPorts gcc6 6.3.0_2) 6.3.0
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$ gcc -c -Wall -O1 test.c
test.c: In function 'foo':
test.c:20:10: warning: 'r' may be used uninitialized in this function [-Wmaybe-uninitialized]
return r;
^
代码对我来说似乎是安全的,确实有一些关于 GCC producing false positives with this warning 的讨论。
这是虚假警告吗?
更多相关信息:
- 添加注释掉的
default:
块解决警告 -O0
不出现警告
这个警告是完全正确的,因为 enum
类型不会将可能的值限制为在此 enum
中定义的成员——它可以保存 any 基础整数类型的值。因此,如果您的开关中没有 default
分支,您确实可以使用未初始化的 r
和您显示的代码。
我可以使用问题中显示的确切代码重现 gcc
和 -O0
缺少的警告,所以在我看来这就像 gcc
中的错误。无论优化级别如何,都应发出警告。
很容易弄清楚:在某些可能的程序路径中,r 将在未初始化的情况下返回。所以你得到了警告。枚举只是 int 所以你有很多可能的情况。
运行时不根据值检查枚举。
关于问题的第二部分。这是故意的,因为任何级别的优化都可以(在这种情况下,如果枚举类型的值是非法的,将删除代码——编译器假定没有其他可能的值)
这个案例最有意思: https://godbolt.org/g/TDUhN7
您可能认为您检查了非法值。但是编译器已经删除了代码:)
顺便说一句 - 有趣的是为什么我的回答被否决了