¿Emulando __builtin_unreachable de GCC?

Recibo muchas advertencias sobre los conmutadores que solo cubren parcialmente el rango de una enumeración cambiada. Por lo tanto, me gustaría tener un “valor predeterminado” para todos esos conmutadores y poner __builtin_unreachable (GCC builtin) en ese caso, para que el comstackdor sepa que el caso no es accesible.

Sin embargo, llegué a saber que GCC4.3 aún no es compatible con esa función incorporada. ¿Hay alguna buena manera de emular esa funcionalidad? Pensé en desreferenciar un puntero nulo en su lugar, pero eso puede tener otros efectos / advertencias no deseados y demás. ¿Tienes alguna idea mejor?

Hmm, algo como (ya que __builtin_unreachable () apareció en 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
#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 

Puede llamar a una función en línea declarada _Noreturn para marcar cualquier cosa después de esa llamada como inaccesible. El comstackdor tiene permitido tirar cualquier código después de dicha función. Si la función en sí es static (y regresa), el comstackdor usualmente también integrará la función. Aquí hay un ejemplo:

 static _Noreturn void unreachable() { return; /* intentional */ } /* ... */ foo(); bar(); /* should better not return */ unreachable(); baz(); /* compiler will know this is not reachable */ 

Observe que invoca un comportamiento indefinido si una función marcada con _Noreturn devuelve. Asegúrese de que dicha función nunca será llamada.

¿ abort (dejando un volcado de memoria) o throw (permitiendo una captura de datos alternativa) se adaptaría a sus necesidades?

¿Realmente desea tener declaraciones de cambio que no cubran la enumeración completa? Casi siempre trato de enumerar todos los casos posibles (no operativo) sin un caso predeterminado para que gcc me avise si se agregan nuevas enumeraciones, ya que puede ser necesario manejarlas en lugar de dejarlas en silencio (durante la comstackción) en el valor predeterminado.

 template class Unreachable_At_Line {}; #define __builtin_unreachable() throw Unreachable_At_Line<__line__>() 

Editar :

Dado que desea que el comstackdor omita el código inalcanzable, a continuación se muestra la forma más sencilla.

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

El comstackdor optimiza lejos x = x; Instrucción especialmente cuando es inalcanzable. Aquí está el uso:

 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 } 

Si coloca __builtin_unreachable() al comienzo de foo() , el comstackdor genera un error de vinculador para el operator = no implementado operator = . Ejecuté estas pruebas en gcc 3.4.6 (64 bits).

mantenlo simple:

 assert(false); 

o mejor aún:

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