C++ 模拟GCC';s_uuu内置的无法访问?

C++ 模拟GCC';s_uuu内置的无法访问?,c++,gcc,unreachable-code,C++,Gcc,Unreachable Code,我收到了很多关于交换机的警告,这些警告只部分覆盖了所切换枚举的范围。因此,我希望所有这些开关都有一个“默认值”,并在这种情况下放置\uuuuuu builtin\u unreachable(GCC builtin),以便编译器知道这种情况是不可访问的 然而,我知道GCC4.3还不支持该内置程序。有没有什么好的方法来模拟这种功能?我考虑取消对空指针的引用,但这可能会产生其他不良影响/警告等。你有更好的主意吗 嗯,有点像(因为在4.5中出现了uu builtin_unreachable()): ab

我收到了很多关于交换机的警告,这些警告只部分覆盖了所切换枚举的范围。因此,我希望所有这些开关都有一个“默认值”,并在这种情况下放置
\uuuuuu builtin\u unreachable
(GCC builtin),以便编译器知道这种情况是不可访问的

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

嗯,有点像(因为在4.5中出现了uu builtin_unreachable()):

abort
(保留核心转储)或
throw
(允许替代数据捕获)是否符合您的需要

是否确实希望switch语句不包含完整的枚举?我几乎总是尝试列出所有可能的情况(无操作),没有默认情况,这样gcc会在添加新枚举时警告我,因为可能需要处理它们,而不是让它(在编译过程中)陷入默认状态

template<unsigned int LINE> class Unreachable_At_Line {}; 
#define __builtin_unreachable() throw Unreachable_At_Line<__LINE__>()
编译器优化了
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
}
如果在
foo()
的开头放置
\uuuuu内置的不可访问()
,则编译器会为未实现的
运算符=
生成一个链接器错误。我在gcc 3.4.6(64位)中运行了这些测试

assert(false);
或者,更好的是:

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

assert(UNREACHABLE);

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

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

/* ... */

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

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

行将始终扩展到定义了“builtin\u unreachable()未使用”的行这与@janneb的解决方案有相同的问题。编译器必须发出抛出命令。@Johannes,你能检查编辑过的答案吗?在这里,编译器要么给出错误,要么优化无法访问的部分。因此,没有实时并发症。
if(x)y();否则我的_将无法到达()不适用于您的定义,但这仍然假设代码是可访问的。编译器不允许优化printf和中止,因此它必须发出该代码。我想特别告诉编译器宏所在的位置是不可访问的,这样它就忽略了codegen或其后所有控制流点的警告。@litb:实际上,您是在问“我的编译器不允许我将代码指定为不可访问的,我如何告诉我的编译器代码是不可访问的”。真的不能计算。无论如何,至少在我的系统上,abort()是用属性((noreturn))标记的,因此编译器应该能够删除该调用下面的任何代码。我想你仍然会收到警告。@janneb不,我正在寻找一种方法来实现类似于
\uuuuu内置\uu无法访问的
。对“abort”的调用无法做到这一点,因为它定义了行为,所以编译器仍然必须将对“abort”的调用放在那个位置:(@nos)它会影响性能。这个位置已经证明是一个瓶颈,所以我需要避免编译器发出任何无用的分支和样板文件,因为它认为某些代码是可以访问的(如果逻辑证明无法访问它,可能是基于更高级别的逻辑,通过静态分析代码是看不见的)。太简单了。编译器仍然会将断言之后的任何内容视为可访问的,这可能会导致不必要的警告。你确定吗?POSIX说assert()是一个宏,编译器应该能够静态地看到false永远不会计算为true,因此将assert(false)最终转换为对abort()的调用。@CAFxX只有在未定义
NDEBUG
时,这才是真的。断言在非调试构建中意味着没有操作。
开关((int)myenum)/*静默警告*/
^^它通过说“标记为noreturn的函数返回”发出警告。@Johannes Schaub这是对的。gcc会警告您,但会接受代码。只要您的代码从未真正达到不可访问的程度(),您的代码不应表现出未定义的行为。这是“无法访问”演变为“无法访问”的正确基础。禁用特定警告,因为它是有意返回的。除了返回之外,可能还有其他一些技巧,但“无法访问”等同于“无法访问”。与@fuzzxl相比,您不应该这样做吗调用abort()而不是return。它不仅不会导致未定义的行为,而且是正确的,因为abort函数是用_Noreturn函数说明符定义的。@2501
\u内置的u unreachable()的思想
是给编译器一个提示,提示它不能自行干预。通过插入对
中止()
\u builtin\u unreachable()
的调用无法达到此目标。
是关于优化,而不是关于安全。
#define UNREACHABLE (!"Unreachable code executed!")

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

/* ... */

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