简体   繁体   中英

Emulating GCC's __builtin_unreachable?

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?

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.

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

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.

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

keep it simple:

assert(false);

or, better yet:

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

assert(UNREACHABLE);

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM