c++ gcc switch-statement warnings

c++ - GCC 7,-Animitaciones de fallos implícitas, y una forma portátil de eliminarlas?



switch-statement warnings (2)

Estamos detectando advertencias de GCC 7 para una caída implícita en una declaración de cambio. Anteriormente, los eliminamos en Clang (ese es el motivo del comentario que se ve a continuación):

g++ -DNDEBUG -g2 -O3 -std=c++17 -Wall -Wextra -fPIC -c authenc.cpp asn.cpp: In member function ‘void EncodedObjectFilter::Put(const byte*, size_t)’: asn.cpp:359:18: warning: this statement may fall through [-Wimplicit-fallthrough=] m_state = BODY; // fall through ^ asn.cpp:361:3: note: here case BODY: ^~~~

El manual de GCC indica que se debe usar __attribute__ ((fallthrough)) , pero no es portátil. El manual también dice "... también es posible agregar un comentario fallido para silenciar la advertencia" , pero solo ofrece FALLTHRU (¿es esta realmente la única opción?):

switch (cond) { case 1: bar (0); /* FALLTHRU */ default: … }

¿Existe una forma portátil de eliminar la caída mediante la advertencia para Clang y GCC? Si es así, entonces ¿qué es?


GCC espera que el marcador comente en su propia línea, como esto:

m_state = BODY; // fall through case BODY:

El marcador también tiene que venir justo antes de la etiqueta del case ; no puede haber un corsé de cierre intermedio.

fall through es uno de los marcadores reconocidos por GCC. No es sólo FALLTHRU . Para obtener una lista completa, consulte la documentación de la opción " -Wimplicit-fallthrough . También vea esta publicación en el blog de Red Hat Developer .

(Esto también debería ser compatible con Clang, aunque no puedo hacer que la línea troncal actual (r308163) emita una advertencia de conmutación directa para verificar esto).

Tenga en cuenta que suponer que la advertencia con comentarios de marcadores solo funciona si el compilador realmente ve el comentario. Si el preprocesador se ejecuta por separado, debe recibir instrucciones para conservar los comentarios, como -C con la opción -C de GCC ). Por ejemplo, para evitar advertencias falsas con ccache , debe especificar el indicador -C al compilar, o, con versiones recientes de ccache, usar la opción keep_comments_cpp .


C ++ 17 [[fallthrough]]

Ejemplo:

int main(int argc, char **argv) { switch (argc) { case 0: argc = 1; [[fallthrough]]; case 1: argc = 2; }; }

Compilar con:

g++ -std=c++17 -Wimplicit-fallthrough main.cpp

Si quitas el [[fallthrough]]; , GCC advierte:

main.cpp: In function ‘int main()’: main.cpp:5:15: warning: this statement may fall through [-Wimplicit-fallthrough=] argc = 1; ~~^~~ main.cpp:6:9: note: here case 1: ^~~~

También tenga en cuenta en el ejemplo que la advertencia solo ocurre si se cruzan dos casos: la declaración del último caso ( case 1 aquí) no genera advertencias aunque no tenga break .

Las siguientes construcciones tampoco generan la advertencia:

case 0: argc = 1; break; case 1: case 0: argc = 1; return 0; case 1: // Empty case synonyms are fine. case 0: case 1: // https://.com/a/45137452/895245 case 0: argc = 1; // fall through case 1: // GCC extension for pre C++17. case 0: argc = 1; __attribute__ ((fallthrough)); case 1: // GCC examines all braches. case 0: if (argv[0][0] == ''m'') { [[fallthrough]]; } else { return 0; } case 1: argc = 2;

Podemos ver en el último que GCC examina todas las ramas posibles y advierte si alguna de ellas no tiene [[fallthrough]]; o break o return .

Es posible que también desee verificar la disponibilidad de las funciones con macros como en este fragmento de código inspirado en GEM5 :

#if defined __has_cpp_attribute #if __has_cpp_attribute(fallthrough) #define MY_FALLTHROUGH [[fallthrough]] #else #define MY_FALLTHROUGH #endif #else #define MY_FALLTHROUGH #endif

Consulte también: https://en.cppreference.com/w/cpp/language/attributes/fallthrough

Probado en GCC 7.3.0, Ubuntu 16.04 .