模仿海湾合作委员会__builtin_unreachable?

Emulating GCC's __builtin_unreachable?

本文关键字:builtin unreachable 委员会 仿海      更新时间:2023-10-16

我收到了很多关于开关的警告,这些开关只部分覆盖了切换的枚举范围。因此,我希望为所有这些开关提供一个"默认值",并将__builtin_unreachable(GCC 内置)放在该情况下,以便编译器知道该情况不可访问。

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

即将

发布的 C 标准(C23、ISO/IEC 9899:2023)的 2023 年修订版将有一个新的宏观unreachable

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

在海湾合作委员会__builtin_unreachable的影响下.

在较旧的 C 标准上,您可以调用声明为 _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!!!111n"); 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()放在foo()的开头,则编译器会为未实现的operator =生成链接器错误。我在 gcc 3.4.6(64 位)中运行了这些测试。