我收到很多关于开关的警告,这些警告仅部分覆盖了切换的枚举范围。因此,我想为所有这些开关设置一个“默认值”,并__builtin_unreachable
在这种情况下放置(GCC 内置),以便编译器知道这种情况是不可达的。
但是,我知道 GCC4.3 还不支持该内置函数。有什么好方法可以模拟该功能吗?我考虑过取消引用空指针,但这可能会产生其他不良影响/警告等。你有更好的主意吗?
我收到很多关于开关的警告,这些警告仅部分覆盖了切换的枚举范围。因此,我想为所有这些开关设置一个“默认值”,并__builtin_unreachable
在这种情况下放置(GCC 内置),以便编译器知道这种情况是不可达的。
但是,我知道 GCC4.3 还不支持该内置函数。有什么好方法可以模拟该功能吗?我考虑过取消引用空指针,但这可能会产生其他不良影响/警告等。你有更好的主意吗?
您可以调用声明的内联函数_Noreturn
,以将该调用之后的任何内容标记为不可达。允许编译器在这样的函数之后抛出任何代码。如果函数本身是static
(并且确实返回),编译器通常也会内联函数。这是一个例子:
static _Noreturn void unreachable() {
return; /* intentional */
}
/* ... */
foo();
bar(); /* should better not return */
unreachable();
baz(); /* compiler will know this is not reachable */
请注意,如果标记的函数_Noreturn
确实返回,则调用未定义的行为。确保永远不会调用该函数。
嗯,类似(因为 __builtin_unreachable() 出现在 4.5 中):
#define GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
#if GCC_VERSION >= 40500
#define my_unreachable() __builtin_unreachable()
#else
#define my_unreachable() do { printf("Oh noes!!!111\n"); abort(); } while(0)
#endif
abort
(留下核心转储)或throw
(允许备用数据捕获)会满足您的需求吗?
您真的想要有不涵盖完整枚举的 switch 语句吗?我几乎总是尝试在没有默认情况的情况下列出所有可能的情况(到无操作),这样如果添加了新的枚举,gcc 会警告我,因为可能需要处理它们而不是让它静默(在编译期间)下降进入默认。
把事情简单化:
assert(false);
或者,更好的是:
#define UNREACHABLE (!"Unreachable code executed!")
assert(UNREACHABLE);
template<unsigned int LINE> class Unreachable_At_Line {};
#define __builtin_unreachable() throw Unreachable_At_Line<__LINE__>()
由于您希望编译器省略无法访问的代码,因此下面是最简单的方法。
#define __builtin_unreachable() { struct X {X& operator=(const X&); } x; x=x; }
编译器优化离开x = x;
指令,尤其是在它无法访问的时候。这是用法:
int foo (int i)
{
switch(i)
{
case 0: return 0;
case 1: return 1;
default: return -1;
}
__builtin_unreachable(); // never executed; so compiler optimizes away
}
如果您__builtin_unreachable()
在开头放置,则编译器会为 unimplementedfoo()
生成链接器错误operator =
。我在 gcc 3.4.6(64 位)中运行了这些测试。