模仿GCC的__builtin_unreachable?

时间:2011-05-17 13:52:41

标签: c++ gcc unreachable-code

我得到了关于交换机的完整批次警告,这些交换机仅部分覆盖了切换的枚举范围。因此,我希望所有这些开关都有一个“默认”,并在这种情况下放置__builtin_unreachable(GCC内置),以便编译器知道无法访问该情况。

然而,我才知道GCC4.3还不支持内置版。有没有什么好方法可以模仿这个功能?我考虑过取消引用空指针,但这可能有其他不良影响/警告等。你有更好的主意吗?

5 个答案:

答案 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)

嗯,类似的东西(因为__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

答案 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);