26

我收到很多关于开关的警告,这些警告仅部分覆盖了切换的枚举范围。因此,我想为所有这些开关设置一个“默认值”,并__builtin_unreachable在这种情况下放置(GCC 内置),以便编译器知道这种情况是不可达的。

但是,我知道 GCC4.3 还不支持该内置函数。有什么好方法可以模拟该功能吗?我考虑过取消引用空指针,但这可能会产生其他不良影响/警告等。你有更好的主意吗?

4

5 回答 5

12

您可以调用声明的内联函数_Noreturn,以将该调用之后的任何内容标记为不可达。允许编译器在这样的函数之后抛出任何代码。如果函数本身是static(并且确实返回),编译器通常也会内联函数。这是一个例子:

static _Noreturn void unreachable() {
    return; /* intentional */
}

/* ... */

foo();
bar(); /* should better not return */
unreachable();
baz(); /* compiler will know this is not reachable */

请注意,如果标记的函数_Noreturn确实返回,则调用未定义的行为。确保永远不会调用该函数。

于 2014-03-15T16:54:06.403 回答
8

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

于 2011-05-17T14:15:20.783 回答
4

abort(留下核心转储)或throw(允许备用数据捕获)会满足您的需求吗?

您真的想要有不涵盖完整枚举的 switch 语句吗?我几乎总是尝试在没有默认情况的情况下列出所有可能的情况(到无操作),这样如果添加了新的枚举,gcc 会警告我,因为可能需要处理它们而不是让它静默(在编译期间)下降进入默认。

于 2011-05-17T14:15:33.840 回答
3

把事情简单化:

assert(false);

或者,更好的是:

#define UNREACHABLE (!"Unreachable code executed!")

assert(UNREACHABLE);
于 2011-05-17T14:19:03.860 回答
2
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 位)中运行了这些测试。

于 2011-05-17T14:18:23.430 回答