模拟 GCC 的 __builtin_unreachable?

发布于 2024-11-07 22:41:43 字数 204 浏览 0 评论 0原文

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

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

I get a whole lot of warnings about switches that only partially covers the range of an enumeration switched over. Therefor, I would like to have a "default" for all those switches and put __builtin_unreachable (GCC builtin) in that case, so that the compiler know that case is not reachable.

However, I came to know that GCC4.3 does not support that builtin yet. Is there any good way to emulate that functionality? I thought about dereferencing a null pointer instead, but that may have other undesirable effects/warnings and such. Do you have any better idea?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

旧伤还要旧人安 2024-11-14 22:41:43

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

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

,其效果与 gcc 的 __builtin_unreachable 相同。

在较旧的 C 标准中,您可以调用声明为 _Noreturn 的内联函数,以将调用之后的任何内容标记为不可访问。编译器可以丢弃此类函数之后的任何代码。如果函数本身是静态的(并且确实返回),编译器通常也会内联该函数。下面是一个示例:

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

/* ... */

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

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

The upcoming 2023 revision of the C standard (C23, ISO/IEC 9899:2023) is going to have a new macro unreachable

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

with the effect of gcc's __builtin_unreachable.

On older C standards, you may be able to call an inline function declared _Noreturn to mark anything after that call as unreachable. The compiler is allowed to throw out any code after such a function. If the function itself is static (and does return), the compiler will usually also inline the function. Here is an example:

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

/* ... */

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

Notice that you invoke undefined behavior if a function marked _Noreturn indeed returns. Be sure that said function will never be called.

颜漓半夏 2024-11-14 22:41:43

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

Hmm, something like (since __builtin_unreachable() appeared in 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

陌上青苔 2024-11-14 22:41:43

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

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

Would abort (leaving a core dump) or throw (allowing for alternate data capture) accommodate your needs?

Do you really want to have switch statements that don't cover the full enumeration? I nearly always try to list all the possible cases (to no-op) with no default case so that gcc will warn me if new enumerations are added, as it may be required to handle them rather than letting it silently (during compile) fall into the default.

疯了 2024-11-14 22:41:43

保持简单:

assert(false);

或者,更好的是:

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

assert(UNREACHABLE);

keep it simple:

assert(false);

or, better yet:

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

assert(UNREACHABLE);
萌无敌 2024-11-14 22:41:43
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() 的开头,则编译器会为未实现的 生成链接器错误运算符=。我在 gcc 3.4.6(64 位)中运行了这些测试。

template<unsigned int LINE> class Unreachable_At_Line {}; 
#define __builtin_unreachable() throw Unreachable_At_Line<__LINE__>()

Edit:

Since you want to have unreachable code to be omitted by compiler, below is the simplest way.

#define __builtin_unreachable() { struct X {X& operator=(const X&); } x; x=x; }

Compiler optimizes away x = x; instruction especially when it's unreachable. Here is the usage:

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
}

If you put __builtin_unreachable() in the beginning of foo() then compiler generates a linker error for unimplemented operator =. I ran these tests in gcc 3.4.6 (64-bit).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文