我得到了关于交换机的完整批次警告,这些交换机仅部分覆盖了切换的枚举范围。因此,我希望所有这些开关都有一个“默认”,并在这种情况下放置__builtin_unreachable
(GCC内置),以便编译器知道无法访问该情况。
然而,我才知道GCC4.3还不支持内置版。有没有什么好方法可以模仿这个功能?我考虑过取消引用空指针,但这可能有其他不良影响/警告等。你有更好的主意吗?
答案 0 :(得分:8)
您可以调用声明为_Noreturn
的内联函数,将该调用后的任何内容标记为无法访问。允许编译器在这样的函数之后抛出任何代码。如果函数本身是static
(并且确实返回),则编译器通常也会内联函数。这是一个例子:
static _Noreturn void unreachable() {
return; /* intentional */
}
/* ... */
foo();
bar(); /* should better not return */
unreachable();
baz(); /* compiler will know this is not reachable */
请注意,如果标记为_Noreturn
的函数确实返回,则调用未定义的行为。确保永远不会调用所述函数。
答案 1 :(得分:7)
#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
答案 2 :(得分:3)
abort
(留下核心转储)或throw
(允许备用数据捕获)会满足您的需求吗?
你真的想拥有不涵盖完整枚举的switch语句吗?我几乎总是尝试列出所有可能的情况(没有操作)没有默认情况,这样gcc会警告我是否添加了新的枚举,因为它可能需要处理它们而不是让它静默(在编译期间)掉落进入默认值。
答案 3 :(得分:3)
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()
放在foo()
的开头,则编译器会为未实现的operator =
生成链接器错误。我在gcc 3.4.6(64位)中运行了这些测试。
答案 4 :(得分:2)
保持简单:
assert(false);
或者,更好的是:
#define UNREACHABLE (!"Unreachable code executed!")
assert(UNREACHABLE);