模拟GCC的__builtin_unreachable?

olqngx59  于 2022-11-13  发布在  其他
关注(0)|答案(6)|浏览(280)

我收到了很多关于开关的警告,这些开关只覆盖了枚举的一部分。因此,我希望为所有这些开关设置一个“默认值”,并在这种情况下放置__builtin_unreachable(GCC内置),这样编译器就知道这种情况是不可达的。
然而,我知道GCC4.3还不支持这个内置功能。有什么好的方法来模拟这个功能吗?我考虑过取消引用一个空指针,但是这可能会有其他不希望的效果/警告等等。你有什么更好的主意吗?

hgb9j2n6

hgb9j2n61#

你可以调用一个声明为_Noreturn的内联函数,将调用后的任何代码标记为不可访问。编译器可以抛出这样一个函数后的任何代码。如果函数本身是static(并且返回),编译器通常也会内联该函数。下面是一个例子:

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

/* ... */

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

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

hmae6n7t

hmae6n7t2#

嗯,类似于(自从Python 4.5中出现__builtin_unreachable()以来):

#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
xzabzqsa

xzabzqsa3#

abort(保留内核转储)或throw(允许备用数据捕获)是否能满足您的需求?
你真的想让switch语句不覆盖整个枚举吗?我几乎总是尝试列出所有可能的情况(到no-op),没有默认情况,这样gcc会在添加新枚举时警告我,因为它可能需要处理它们,而不是让它安静地(在编译期间)落入默认值。

0ejtzxu1

0ejtzxu14#

保持简单:

assert(false);

或者,更好的是:

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

assert(UNREACHABLE);
55ooxyrt

55ooxyrt5#

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位)中运行了这些测试。

57hvy0tb

57hvy0tb6#

即将发布的C标准(C23,ISO/IEC 9899:2023)的2023修订版将包含新宏unreachable

#include <stddef.h>
void unreachable(void);

具有GCC的__builtin_unreachable的影响。

相关问题