Banderas para permitir advertencias completas y detalladas de g ++

122

A menudo, en C debajo gcc, comenzaré con el siguiente conjunto de indicadores de advertencia (ensamblados dolorosamente de múltiples fuentes):

-Wall -Wextra -Wformat-nonliteral -Wcast-align -Wpointer-arith -Wbad-function-cast \
-Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations -Winline -Wundef \
-Wnested-externs -Wcast-qual -Wshadow -Wwrite-strings -Wno-unused-parameter \
-Wfloat-equal -pedantic -ansi

Construiré (al menos mis versiones de depuración) con este conjunto de advertencias y arreglaré todo lo que pueda (generalmente todo), y luego solo eliminaré las banderas si no son relevantes o no se pueden arreglar (casi nunca es el caso). A veces, también agregaré -Werrorsi tengo que alejarme mientras compilo.

Solo estoy recogiendo C ++ (sí, tengo 15 años de retraso), y me gustaría comenzar con el pie derecho.

Mi pregunta es: ¿Alguien tiene un conjunto similar precompilado de indicadores de advertencia completos para C ++ en g++? (Sé que muchos de ellos serán iguales).

Sdaz MacSkibbons
fuente
69
Cuáles son las necesidades de gcc (ya que se decidió descaradamente mentira acerca -Wall) es un -Wbloody_everythingindicador :-)
paxdiablo
Puede marcar su pregunta como un tonto, pero también puede poner su última edición como respuesta, ya que realmente respondió su pregunta. Y me
encantaría votarlo
44
OP y @paxdiablo: GCC ha rechazado constantemente este tipo de cosas, pero está disponible en Clang a través de -Weverything. He leído que incluso los desarrolladores de Clang ++ están un poco preocupados por los usuarios que lo activan; aparentemente estaba destinado solo para uso de desarrollo interno. Sin embargo, esto no tiene sentido, porque encender -Weverythinges probablemente la mejor manera posible de descubrir advertencias potencialmente útiles que no conocía antes.
Kyle Strand
1
OP y @paxdiablo Ahora hay una manera de averiguar la lista completa de advertencias para una versión dada de GCC: github.com/barro/compiler-warnings
Kyle Strand
1
Posible duplicado de ¿Cómo activar (literalmente) TODAS las advertencias de GCC?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Respuestas:

138

Revisé y encontré el conjunto mínimo de inclusiones que deberían obtener el nivel máximo de advertencia. Luego eliminé de esa lista el conjunto de advertencias que siento que en realidad no indican que algo malo está sucediendo, o que tienen demasiados falsos positivos para ser utilizados en una compilación real. Comenté por qué cada uno de los que excluí fueron excluidos. Este es mi conjunto final de advertencias sugeridas:

-pedantic -Wall -Wextra -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wlogical-op -Wmissing-declarations -Wmissing-include-dirs -Wnoexcept -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-null-sentinel -Wstrict-overflow=5 -Wswitch-default -Wundef -Werror -Wno-unused

Advertencias cuestionables que están presentes:

  • Incluyo -Wno-unusedporque a menudo tengo variables que sé que usaré más adelante, pero aún no tengo la funcionalidad escrita. Eliminar las advertencias sobre eso me permite escribir en mi estilo preferido de diferir ocasionalmente la implementación de las cosas. Es útil apagarlo de vez en cuando para asegurarse de que nada se escape por las grietas.

  • -Wdisabled-optimizationparece una fuerte configuración de preferencia de usuario. Acabo de agregar este a mi compilación (solo para compilaciones optimizadas por razones obvias) y no apareció nada, por lo que no parece ser una advertencia especialmente comunicativa, al menos por la forma en que codifico. Lo incluyo (aunque el código que activa esta advertencia no es necesariamente incorrecto) porque creo en trabajar con mis herramientas en lugar de en contra de ellas. Si gcc me dice que no puede optimizar el código para la forma en que lo escribí, entonces debería considerar reescribirlo. Sospecho que el código que desencadena esta advertencia podría beneficiarse de ser más modular, sin embargo, aunque el código no es técnicamente incorrecto (probablemente), estilísticamente sí lo es.

  • -Wfloat-equaladvierte sobre comparaciones de igualdad seguras (en particular, comparación con un valor no calculado de -1). Un ejemplo en mi código donde uso esto es que tengo un vector de flotación. Paso por este vector, y hay algunos elementos que aún no puedo evaluar cuáles deberían ser, así que los configuré en -1.0f (dado que mi problema solo usa números positivos, -1 está fuera del dominio). Más tarde reviso y actualizo los valores de -1.0f. No se presta fácilmente a un método diferente de operación. Sospecho que la mayoría de las personas no tienen este problema, y ​​la comparación de un número exacto en coma flotante es probablemente un error, por lo que lo incluyo en la lista predeterminada.

  • -Wold-style-casttiene muchos falsos positivos en el código de la biblioteca que estoy usando. En particular, la familia htonl de funciones utilizadas en redes, así como una implementación de encriptación Rijndael (AES) que estoy usando tiene modelos antiguos de los que me advierte. Tengo la intención de reemplazar ambos, pero no estoy seguro de si hay algo más en mi código que se queje. Sin embargo, la mayoría de los usuarios probablemente deberían tener esto activado de manera predeterminada.

  • -Wsign-conversionfue difícil (y casi no figura en la lista). Activarlo en mi código generó una gran cantidad de advertencias (más de 100). Casi todos ellos eran inocentes. Sin embargo, he tenido cuidado de usar enteros con signo donde no estaba seguro, aunque para mi dominio del problema particular, generalmente obtendría un ligero aumento de la eficiencia usando valores sin signo debido a la gran cantidad de división de enteros que hago. Sacrifiqué esta eficiencia porque estaba preocupado por promover accidentalmente un entero con signo a un sin signo y luego dividirlo (lo que no es seguro, a diferencia de la suma, la resta y la multiplicación). Activar esta advertencia me permitió cambiar de manera segura la mayoría de mis variables a tipos sin signo y agregar algunos lanzamientos en otros lugares. Actualmente es un poco difícil de usar porque la advertencia no es tan inteligente. Por ejemplo, si lo hacesunsigned short + (integral constant expression), ese resultado se promueve implícitamente a int. Luego advierte sobre un posible problema de signos si asigna ese valor unsignedao unsigned short, aunque sea seguro. Esta es definitivamente la advertencia más opcional para casi todos los usuarios.

  • -Wsign-promo: ver -Wsign-conversion.

  • -Wswitch-defaultparece inútil (no siempre quiere un caso predeterminado si ha enumerado todas las posibilidades explícitamente). Sin embargo, activar esta advertencia puede hacer cumplir algo que probablemente sea una buena idea. Para los casos en los que desea ignorar explícitamente todo, excepto las posibilidades enumeradas (pero son posibles otros números), luego ingresedefault: break;para hacerlo explícito. Si enumera explícitamente todas las posibilidades, activar esta advertencia lo ayudará a asegurarse de poner algo como afirmar (falso) para asegurarse de que haya cubierto todas las opciones posibles. Le permite ser explícito en cuál es el dominio de su problema y cumplirlo mediante programación. Sin embargo, tendrá que tener cuidado al pegar la afirmación (falso) en todas partes. Es mejor que no hacer nada con el caso predeterminado, pero como es habitual con afirmar, no funcionará en las versiones de lanzamiento. En otras palabras, no puede confiar en él para validar los números que obtiene de, por ejemplo, una conexión de red o una base de datos sobre la que no tiene control absoluto. Las excepciones o regresar temprano son la mejor manera de manejar eso (¡pero aún así requieren que tenga un caso predeterminado!).

  • -WerrorEs importante para mí. Al compilar grandes cantidades de código en una compilación de subprocesos múltiples con múltiples objetivos, es fácil que pase una advertencia. Convertir las advertencias en errores garantiza que los note.

Luego hay un conjunto de advertencias que no están incluidas en la lista anterior porque no las encontré útiles. Estas son las advertencias y mis comentarios sobre por qué no los incluyo en la lista predeterminada:

Advertencias ausentes:

  • -Wabino es necesario porque no estoy combinando binarios de diferentes compiladores. Intenté compilarlo de todos modos, y no se activó, por lo que no parece innecesariamente detallado.

  • -Waggregate-returnNo es algo que considero un error. Por ejemplo, se dispara cuando se usa un bucle for basado en rango en un vector de clases. La optimización del valor de retorno debe tener en cuenta los efectos negativos de esto.

  • -Wconversionse activa en este código: short n = 0; n += 2;la conversión implícita a int provoca una advertencia cuando luego se convierte de nuevo a su tipo de destino.

  • -Weffc++incluye una advertencia si todos los miembros de datos no se inicializan en la lista de inicializadores. Intencionalmente no hago esto en muchos casos, por lo que el conjunto de advertencias está demasiado abarrotado para ser útil. Sin embargo, es útil encender de vez en cuando y buscar otras advertencias (como destructores no virtuales de clases base). Esto sería más útil como una colección de advertencias (como -Wall) en lugar de una sola advertencia por sí sola.

  • -Winlineestá ausente porque no uso la palabra clave en línea para fines de optimización, solo para definir funciones en línea en los encabezados. No me importa si el optimizador realmente lo alinea. Esta advertencia también se queja si no puede en línea una función declarada en un cuerpo de clase (como un destructor virtual vacío).

  • -Winvalid-pch falta porque no uso encabezados precompilados.

  • -Wmissing-format-attributeno se usa porque no uso extensiones gnu. Lo mismo para -Wsuggest-attributey muchos otros

  • Potencialmente notable por su ausencia es -Wno-long-long, que no necesito. Compilo con -std=c++0x( -std=c++11en GCC 4.7), que incluye long longtipos enteros. Aquellos atascados en C ++ 98 / C ++ 03 pueden considerar agregar esa exclusión de la lista de advertencia.

  • -Wnormalized=nfc ya es la opción predeterminada y parece ser la mejor.

  • -Wpaddedse activa ocasionalmente para optimizar el diseño de las clases, pero no se deja activado porque no todas las clases tienen elementos suficientes para eliminar el relleno al final. En teoría, podría obtener algunas variables adicionales para 'gratis', pero no vale la pena el esfuerzo adicional de mantener eso (si el tamaño de mi clase cambia, no es fácil eliminar esas variables previamente libres).

  • -Wstack-protector no se usa porque no uso -fstack-protector

  • -Wstrict-aliasing=3está activado por -Wally es el más preciso, pero parece que el nivel 1 y 2 dan más advertencias. En teoría, un nivel inferior es una advertencia 'más fuerte', pero a costa de más falsos positivos. Mi propio código de prueba compilado limpiamente en los 3 niveles.

  • -Wswitch-enumNo es el comportamiento que quiero. No quiero manejar cada declaración de cambio explícitamente. Sería útil si el lenguaje tuviera algún mecanismo para activar esto en las instrucciones de cambio especificadas (para garantizar que los cambios futuros a la enumeración se manejen en todos los lugares donde deben estar), pero es excesivo para una configuración de "todo o nada".

  • -Wunsafe-loop-optimizationscausa demasiadas advertencias espurias. Puede ser útil aplicar esto periódicamente y verificar manualmente los resultados. Como ejemplo, generó esta advertencia en mi código cuando recorrí todos los elementos en un vector para aplicarles un conjunto de funciones (usando el bucle for basado en rango). También es una advertencia para el constructor de una matriz const de const std :: string (donde esto no es un bucle en el código de usuario).

  • -Wzero-as-null-pointer-constanty -Wuseless-castson advertencias solo de GCC-4.7, que agregaré cuando haga la transición a GCC 4.7.

He presentado algunos informes de errores / solicitudes de mejora en gcc como resultado de algunas de estas investigaciones, por lo que espero poder agregar más advertencias de la lista "no incluir" a la lista "incluir" . Esta lista incluye todas las advertencias mencionadas en este hilo (además, creo que algunas más). Muchas de las advertencias no mencionadas explícitamente en esta publicación se incluyen como parte de otra advertencia que sí menciono. Si alguien nota advertencias que están excluidas de esta publicación por completo, avíseme.

editar: Parece que me había perdido varios (que ahora he agregado). En realidad, hay una segunda página en http://gcc.gnu.org que está bastante bien oculta. Opciones de advertencia generales y opciones de C ++ (desplácese hacia abajo para ver las advertencias)

David Stone
fuente
Recientemente envié una solicitud de mejora basada en mi investigación para esta respuesta: gcc.gnu.org/bugzilla/show_bug.cgi?id=53313 . Simplificaría dramáticamente la situación de advertencia al crear niveles de advertencia. En mi propuesta, mi conjunto sugerido de advertencias es aproximadamente -W4, con una propuesta adicional para crear -Winf, lo que significaría -Weverything-and-I-really-mean-it-this-time
David Stone
Solicitud de mejora que causaría que parte de -Wpadded se agregue a la lista recomendada: gcc.gnu.org/bugzilla/show_bug.cgi?id=53514
David Stone
Solicitud de mejora que haría que partes de -Weffc ++ se agreguen a la lista recomendada: gcc.gnu.org/bugzilla/show_bug.cgi?id=16166
David Stone
1
@Predelnik: es más complicado que eso. -Wswitch-enumadvierte si no maneja explícitamente cada valor de enumeración en un conmutador y defaultno cuenta como explícito. Por otro lado, -Wswitch-defaultle advierte si su conmutador no tiene un defaultcaso, incluso si ha cubierto explícitamente todos los valores posibles.
David Stone
2
Por cierto, úselo en -isystemlugar de -Isu "código de biblioteca anterior" para evitar todos esos falsos positivos
galois
39

Oh, todas mis búsquedas originales arrojaron el 99% de las publicaciones sobre cómo suprimir las advertencias (lo suficientemente aterrador), pero acabo de encontrar este comentario , que tiene este encantador conjunto de banderas (algunas menos relevantes):

Verificación cruzada con:

http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

-g -O -Wall -Weffc++ -pedantic  \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat=2 \
-Wformat-nonliteral -Wformat-security  \
-Wformat-y2k \
-Wimplicit  -Wimport  -Winit-self  -Winline \
-Winvalid-pch   \
-Wlong-long \
-Wmissing-field-initializers -Wmissing-format-attribute   \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked  -Wpadded -Wpointer-arith \
-Wredundant-decls \
-Wshadow -Wstack-protector \
-Wstrict-aliasing=2 -Wswitch-default \
-Wswitch-enum \
-Wunreachable-code -Wunused \
-Wunused-parameter \
-Wvariadic-macros \
-Wwrite-strings

Entonces, creo que es un buen punto de partida. No me di cuenta de que se trataba de un engañado, pero al menos estaba profundamente enterrado. :-)

Sdaz MacSkibbons
fuente
1
Tal vez, pero eso parece cambiar entre versiones, y probablemente por capricho de las manchas solares y RMS, por lo que ser demasiado explícito probablemente no hará daño. Es un buen punto de partida, de todos modos.
Sdaz MacSkibbons
3
De una muestra rápida de 4.5.2's c-opts.c / opts.c para 'case OPT_W', falta: desbordamiento estricto, undef, estricto nul sentinel, normalizado, multichar, declaración de función implícita, obsoleto, etiquetas endif, comentario s , macro incorporada redefinida, mayor que, mayor que eq, abi. Es una locura que no haya una opción de línea de comando para enumerarlos.
Tony Delroy
3
Creo que es más loco que -Wallno haga lo que uno esperaría. Pero gracias, ¡algunos de esos se ven muy útiles!
Sdaz MacSkibbons
1
Deshabilitar las advertencias tiene su lugar. Después de todo, son "advertencias". Otra situación es cuando habilita un indicador que habilita múltiples advertencias, pero desea ser selectivo al respecto.
Tamás Szelei
1
¿Cómo puedes usar -Waggregate-return? Esto me da una advertencia por cada uso debegin/end()
Flamefire
12

Algunos de ellos ya están incluidos en -Wallo -Wextra.

Una buena configuración base para C es:

-std=c99 -pedantic -Wall -Wextra -Wwrite-strings -Werror

y para C ++

-ansi -pedantic -Wall -Wextra -Weffc++

(omitiendo -WerrorC ++ ya que -Weffc++tiene algunas molestias)

Šimon Tóth
fuente
10
-Werror puede deshabilitarse para tipos específicos de advertencias, por ejemplo: -Werror -Weffc ++ -Wno-error = effc ++
Robert Hensing
2
ansi : en modo C, esto es equivalente a -std=c89. En modo C ++, es equivalente a -std=c++98. es decir, si está especificando alguna otra std, no useansi
Sean Breckenridge
2

Tratar

export CFLAGS="`gcc --help=warnings | grep '\-W' | awk '{print $1 \" \"}' |
sort | uniq` -pedantic -fdiagnostics-show-option -Werror"

Ese es un comienzo rápido y sucio que definitivamente necesitará algo de ajuste; por un lado, incluso si llama al compilador por el nombre apropiado para su idioma (por ejemplo, g++para C ++), recibirá advertencias que no se aplican a ese idioma (y el compilador levantará las manos y se negará a continuar hasta que eliminar la advertencia).

Otra cosa es que agregué -Werror, porque si no está arreglando las advertencias, ¿por qué le importa encenderlas? También puede eliminar las advertencias de la lista. (Por ejemplo, casi nunca lo uso -Waggregate-returncon C ++).

Algunas advertencias no harán nada sin otras opciones relacionadas con el rendimiento ( -Wstack-protector). -fdiagnostics-show-optiony el manual de GCC son tus amigos.

Por cierto, algunas advertencias son mutuamente excluyentes; en particular usando -Wtraditionaly -Wold-style-definitionjunto con -Werror, no se compilará.

Nathan Paul Simons
fuente
0

En mi Clion's CmakeLists.txt

cmake_minimum_required(VERSION 3.13)
project(cpp17)

set(CMAKE_CXX_STANDARD 17)

set(GCC_COVERAGE_COMPILE_FLAGS "-std=c++17 -Wall -Weffc++ -Wno-error=effc++ -pedantic \
 -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-newline-eof  \
-pedantic-errors -Wextra -Waggregate-return -Wcast-align \
-Wcast-qual -Wconversion \
-Wdisabled-optimization \
-Werror -Wfloat-equal -Wformat=2 \
-Wformat-nonliteral -Wformat-security  \
-Wformat-y2k \
-Wimplicit  -Wimport  -Winit-self  -Winline -Winvalid-pch   \
-Wlong-long \
-Wmissing-field-initializers -Wmissing-format-attribute   \
-Wmissing-include-dirs -Wmissing-noreturn \
-Wpacked  -Wpadded -Wpointer-arith \
-Wredundant-decls \
-Wshadow -Wstack-protector \
-Wstrict-aliasing=2 -Wswitch-default \
-Wswitch-enum \
-Wunreachable-code -Wunused \
-Wunused-parameter \
-Wvariadic-macros \
-Wwrite-strings")


set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" )

add_executable(cpp17 main.cpp)
snr
fuente