Emulating GCC's __builtin_unreachable?

為{幸葍}努か 提交于 2019-12-03 08:27:58

问题


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?


回答1:


You can 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.




回答2:


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




回答3:


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.




回答4:


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).




回答5:


keep it simple:

assert(false);

or, better yet:

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

assert(UNREACHABLE);


来源:https://stackoverflow.com/questions/6031819/emulating-gccs-builtin-unreachable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!