¿Cómo activar (literalmente) TODAS las advertencias de GCC?

194

Me gustaría habilitar, literalmente, TODAS las advertencias que tiene GCC. (Pensarías que sería fácil ...)

  • Pensarías que -Wallpodría hacer el truco, ¡pero no! Aún lo necesito -Wextra.

  • Pensarías que -Wextrapodría hacer el truco, ¡pero no! Esto no habilita todas las advertencias enumeradas aquí (por ejemplo -Wshadow). Y todavía no tengo idea si esta lista es completa.

¿Cómo le digo a GCC que habilite (no if's, and's, or but's!) Todas las advertencias que tiene?

usuario541686
fuente
27
@Arafangion: No entiendo qué es "incierto" sobre la pregunta, sí, me gustaría activar todas las advertencias que son aplicables a mi código, no importa cuán pedante sea. En cuanto a la razón, es muy simple: he encontrado que algunas de las advertencias que no están activadas por -Wall o -Wextra son útiles, por lo que quiero probar el resto para ver si puedo mejorar mi código. Es tan simple como eso.
user541686
12
@JoachimPileborg: "¿De qué quieres que avise el compilador?" ¿Posibles errores y / o mal estilo? Quiero decir, si supiera todas las advertencias exactas, las habría activado manualmente, sin necesidad de plantear la pregunta. Si la respuesta es "tienes que mirar el código fuente para encontrarlos", ¡entonces publícalo como la respuesta!
user541686
56
Clang 3.1 ofrece -Weverything.
Alexandre Hamez
55
@Arafangion Bueno, la pregunta está etiquetada como C ++, así que ... :)
Algún tipo de programador el
55
@JoachimPileborg Y ahora hay (finalmente) una forma automatizada de extraer las advertencias de la fuente: github.com/barro/compiler-warnings
Kyle Strand

Respuestas:

129

No puedes

El manual para GCC 4.4.0 solo es completo para esa versión, pero enumera todas las advertencias posibles para 4.4.0. Sin embargo, no están todos en la página a la que se vincula, por ejemplo, algunas opciones específicas del idioma están en las páginas para las opciones de C ++ u Obj-C. Para encontrarlos todos, es mejor mirar el Resumen de opciones

Activar todo incluiría lo -Wdouble-promotionque solo es relevante en las CPU con una unidad de punto flotante de precisión simple de 32 bits que se implementa floaten hardware, pero emula doubleen software. Hacer cálculos como doubleusaría la emulación de software y sería más lento. Eso es relevante para algunas CPU integradas, pero es completamente irrelevante para las CPU de escritorio modernas con soporte de hardware para punto flotante de 64 bits.

Otra advertencia que generalmente no es útil es -Wtraditional, ¡que advierte sobre un código perfectamente bien formado que tiene un significado diferente (o no funciona) en las "string " "concatenation"definiciones de funciones tradicionales de C, por ejemplo , o ISO C! ¿Realmente te importa la compatibilidad con compiladores de 30 años? ¿De verdad quieres una advertencia para escribir int inc(int i) { return i+1; }?

Creo que -Weffc++es demasiado ruidoso para ser útil, se basa en la primera edición obsoleta de Effective C ++ y advierte sobre construcciones que son C ++ perfectamente válidas (y para las cuales las pautas cambiaron en ediciones posteriores del libro). No quiero ser advirtió que no he inicializado un std::stringmiembro en mi constructor; tiene un constructor predeterminado que hace exactamente lo que quiero, ¿por qué debería escribir m_str()para llamarlo? Las -Weffc++advertencias que serían útiles son demasiado difíciles para que el compilador las detecte con precisión (dando falsos negativos), y las que no son útiles, como la inicialización explícita de todos los miembros, solo producen demasiado ruido, dando falsos positivos.

Luc Danton proporcionó un gran ejemplo de advertencias inútiles -Waggregate-returnque casi nunca tienen sentido para el código C ++.

es decir, realmente no quieres todas las advertencias, solo piensas que sí.

Revise el manual, lea sobre ellos, decida qué desea habilitar, pruébelos. Leer el manual de su compilador es un Good Thing TM de todos modos, tomar un atajo y habilitar advertencias que no entiende no es una muy buena idea, especialmente si es para evitar tener que usar RTFM.

Cualquiera que simplemente encienda todo probablemente lo esté haciendo porque no tiene idea porque o un jefe de pelo puntiagudo dijo "no hay advertencias".

Algunas advertencias son importantes y otras no. Tienes que discriminar o arruinas tu programa. Consideremos, por ejemplo, -Wdouble-promotion. Si está trabajando en un sistema integrado, es posible que desee esto; Si está trabajando en un sistema de escritorio, probablemente no. Qué y desea -Wtraditional? Lo dudo.

Editar: Consulte también -Wall-all para habilitar todas las advertencias que se cierra como WONTFIX.

Edición 2: en respuesta a la queja de DevSolar sobre que los makefiles necesitan usar diferentes advertencias dependiendo de la versión del compilador, si -Wall -Wextrano es adecuado, entonces no es difícil usar CFLAGS específicos del compilador y de la versión:

compiler_name := $(notdir $(CC))
ifeq ($(compiler_name),gcc)
compiler_version := $(basename $(shell $(CC) -dumpversion))
endif
ifeq ($(compile_name),clang)
compiler_version := $(shell $(CC) --version | awk 'NR==1{print $$3}')
endif
# ...
wflags.gcc.base := -Wall -Wextra
wflags.gcc.4.7 := -Wzero-as-null-pointer-constant
wflags.gcc.4.8 := $(wflags.gcc.4.7)
wflags.clang.base := -Wall -Wextra
wflags.clang.3.2 := -Weverything
CFLAGS += $(wflags.$(compiler_name).base) $(wflags.$(compiler_name).$(compiler_version))
Jonathan Wakely
fuente
38
"Repase el manual, lea sobre ellos, decida qué desea habilitar, pruébelos". El problema aquí son los pasos que omitió: "Vuelva a visitar el manual para todas y cada una de las versiones del compilador y adapte su lista de advertencias porque están cambiando. Haga que sus Makefiles verifiquen la versión exacta del compilador y utilicen una lista diferente de advertencias". para cada uno de ellos ". Tenemos niveles de optimizaciones mantenidos por el mantenedor; ¿Por qué no podrían molestarse en proporcionar el mismo servicio para las advertencias?
DevSolar
17
@ JonathanWakely: Tengo mis proyectos, y GCC no está entre ellos. Señalo una debilidad en su producto. O lo arreglan o aceptan la culpa por no hacerlo, pero no depende de mí arreglarlo por ellos, maldita sea OSS.
DevSolar
14
@ JonathanWakely: "Si quieres algo, pídelo, no te quejes ". - No estoy obligado a participar en el proyecto GCC para criticarlo, especialmente si el # 31573 ya se ha marcado como WONTFIX. Eso coloca a este sujeto del "preguntar sobre eso" en el estadio de béisbol "perra sobre eso".
DevSolar
61
-Weverythinges la mejor solución, creo, que la estrategia gcc de no dar esa opción. Uso esa bandera con clang porque mi filosofía es que quiero todas las advertencias por defecto (porque alguien pensó que era lo suficientemente útil para agregar al compilador), y si no me gusta, apago esa advertencia específicamente. El punto es que no sabes acerca de las advertencias que no se disparan, pero sí sabes sobre las advertencias que no quieres que se disparen, y se apagan fácilmente.
David Stone
17
@ JonathanWakely Sí, pero son insignificantes. La forma más fácil de ver qué advertencias pueden ser relevantes para su código es ver qué advertencias activa su código; en ese punto, puede ver un ejemplo relevante de la vida real del código potencialmente peligroso antes de decidir si deshabilita o no la advertencia. Esto se puede hacer fácilmente con la -Weverythingopción de Clang , pero es imposible hacerlo con GCC.
Kyle Strand
71

Estoy de acuerdo con las respuestas anteriores de que probablemente no sea beneficioso habilitar literalmente todas las advertencias, sin embargo, el CCG proporciona una forma razonablemente conveniente de lograr esto. El comando

gcc -Q --help=warning

proporciona una lista de todas las opciones de advertencia compatibles con información sobre si están activas. Por cierto, esto puede usarse para averiguar qué opciones están (no) habilitadas, por ejemplo, -Wally-Wextra

gcc -Wall -Wextra -Q --help=warning

Para habilitar todas las advertencias, puede usar algunas expresiones regulares para extraer los parámetros de la línea de comandos

gcc -Q --help=warning | sed -e 's/^\s*\(\-\S*\)\s*\[\w*\]/\1 /gp;d' | tr -d '\n'

Para mi GCC actual esto da:

-Wabi -Wabi-tag -Waddress -Waggregate-return -Waggressive-loop-optim optimizaciones -Waliasing -Walign-commons -Wampersand -Warray-limits -Warray-temporarios -Wassign-intercept -Wattributes -Wbad-function-cast -Wbool-compare -Wbuiltin-macro-redefined -Wc ++ - compat -Wc ++ 0x-compat -Wc ++ 14-compat -Wc-binding-type -Wc90-c99-compat -Wc99-c11-compat -Wcast-align -Wcast-qual -Wchar-subíndices -Wcharacter-truncamiento -Wchkp -Wclobbered -Wcomment -Wcompare-reals -Wcondicionalmente compatible -Wconversion -Wconversion-extra -Wconversion-null -Wcoverage-incompatch -Wcpp -Wctor-dtor-privacy -Wdate-time -Wdeclaration -después-declaración -Wdelete-incomplete -Wdelete-non-virtual-dtor -Wdeprecated -Wdeprecated-declaraciones -Wdesignated-init -Wdisabled-optimization -Wdiscarded-array-qualifiers -Wdiscarded-qualifiers -Wdiv-by-zero -Wdouble-promotion -Weffc ++ -Cuerpo húmedo-Wendif-etiquetas -Wenum-compare -Wextra -Wfloat-equal -Wformat-contiene-nul -Wformat-extra-args -Wformat-nonliteral -Wformat-security -Wformat-signatureness -Wformat-y2k -Wformat-zero-length -Wfree -no-objeto-eliminación -Wfunction-elimination -Wignored-qualifiers -Wimplicit -Wimplicit-function-declaración -Wimplicit-int -Wimplicit-interface -Wimplicit-procedure -Wincompatible-puntero-tipos -Winherited-variadic-ctor -Winit-self -Winline -Wint-conversion -Wint-to-pointer-cast -Wintrinsic-shadow -Wintrinsics-std -Winvalid-memory-model -Winvalid-offsetof -Winvalid-pch -Wjump-misses-init -Wline-truncation -Wliteral-suffix -Wlogical -no-paréntesis -Wlogical-op -Wlong-long -Wmain -Wmaybe-noinialized -Wmemset-transposed-args -Wmissing-braces -Wmissing-declaraciones -Wmissing-field-initializers -Wmissing-include-dirs -Wmissing-parameter-type-type -Presentación-prototipos-Wmultichar -Wnarrowing -Wnested-externs -Wnoexcept -Wnon-template-friend -Wnon-virtual-dtor -Wnonnull -Wodr -Wold-style-cast -Wold-style-declaración -Wold-style-definition -Wopenmp-simd -Woverflow -Woverlength-strings -Woverloaded-virtual -Woverride-init -Wpacked -Wpacked-bitfield-compat -Wpadded -Wparentheses -Wpedantic -Wpmf-converssions -Wpointer-arith -Wpointer-sign -Wpointer-to-int-cast -Wpragmas -Wproperty -assign-default -Wprotocol -Wreal-q-constant -Wrealloc-lhs -Wrealloc-lhs-all -Wredundant-decls -Wreorder -Wreturn-local-addr -Wreturn-type -Wselector -Wsequence-point -Wshadow -Wshadow-ivar -Wshift-count-negative -Wshift-count-overflow -Wsign-compare -Wsign-promo -Wsized-deallocation -Wsizeof-array-argumento -Wsizeof-pointer-memaccess -Wstack-protector -Wstrict-null-sentinel -Wstrict-prototypes -Wstrict-selector-match-Wsuggest-attribute = const -Wsuggest-attribute = format -Wsuggest-attribute = noreturn -Wsuggest-attribute = pure -Wsuggest-final-method -Wsuggest-final-types -Wsuggest-override -Wsurprising -Wswitch -Wswitch-bool -Wswitch -default -Wswitch-enum -Wsync-nand -Wsynth -Wsystem-headers -Wtabs -Wtarget -etime -Wtraditional -Wtraditional-conversion -Wtrampolines -Wtrigraphs -Wtype-limits -Wundeclared-selector -Wundef -Wunderflow -Wuninitialized -mas -unk -Optimaciones de bucle seguro -Wunsuffixed-float-constantes -Wunused -Wunused-but-set-parameter -Wunused-but-set-variable -Wunused-dummy-argumento -Wunused-function -Wunused-label -Wunused-local-typedefs - Macros sin uso - Parámetros sin uso - Resultado sin uso - Valor sin uso - Variable sin uso - Uso sin solo - Sin uso de fundido - Wvarargs - Macros variables - Diseño de operación de vectores - Movimiento virtual-Wvla -Wvolatile-register-var -Wwrite-strings -Wzero-as-null-pointer-constant -Wzerotrip -frequire-return-instrucción

Esto ahora se puede usar para llamar al GCC, es decir

gcc $(gcc -Q --help=warning | sed -e 's/^\s*\(\-\S*\)\s*\[\w*\]/\1 /gp;d' | tr -d '\n')

Sin embargo, tenga en cuenta que esto genera advertencias debido a que algunas opciones de advertencia solo están disponibles para ciertos idiomas (p C++. Ej .). Esto podría evitarse utilizando más expresiones regulares para incluir solo las opciones permitidas para el idioma actual o agregando un apropiado -Wno-whateveral final de la llamada.

Haatschii
fuente
10
Me temo que no es práctico. Gcc me ha mostrado advertencias de std lib.
Valentin Heinitz
13
@ValentinHeinitz Como dije, no creo que sea beneficioso habilitar literalmente todas las advertencias, pero esto fue lo que solicitó OP. Sin embargo, creo que al eliminar explícitamente algunas advertencias problemáticas que ya se mencionaron en otras respuestas (por ejemplo, al agregar el respectivo -Wno-lo que sea al final de la llamada), esto puede ser útil.
Haatschii
66
@ValentinHeinitz Puede evitar que gcc emita advertencias para los encabezados del sistema / std / de terceros utilizando en -isystemlugar de -Ilos directorios relevantes.
Kyle Strand
44
Esta debería ser la respuesta aceptada, ya que en realidad responde directamente a la pregunta.
TFuto
16

Es simplemente imposible programar con todas las advertencias habilitadas (a menos que las ignore, pero entonces, ¿por qué molestarse?). Por ejemplo, supongamos que usted usa siguiente conjunto de banderas: -Wstrict-prototypes -Wtraditional.

Incluso con dos advertencias habilitadas, el siguiente programa se quejaría.

/tmp $ cat main.c 
int main(int argc, char **argv) {
    return 0;
}
/tmp $ gcc -Wstrict-prototypes -Wtraditional main.c 
main.c: In function main’:
main.c:1:5: warning: traditional C rejects ISO C style function definitions [-Wtraditional]
 int main(int argc, char **argv) {
     ^

Puedes pensar "bueno, voy a usar prototipos de estilo antiguo entonces". No, esto no funcionará.

/tmp $ cat main.c 
int main(argc, argv)
    int argc;
    char **argv;
{
    return 0;
}
/tmp $ gcc -Wstrict-prototypes -Wtraditional main.c 
main.c:1:5: warning: function declaration isnt a prototype [-Wstrict-prototypes]
 int main(argc, argv)
     ^

Y no, no especificar ningún prototipo también está mal, ya que el compilador también se quejará.

/tmp $ cat main.c 
int main() {
    return 0;
}
/tmp $ gcc -Wstrict-prototypes -Wtraditional main.c 
main.c:1:5: warning: function declaration isnt a prototype [-Wstrict-prototypes]
 int main() {
     ^

Si define alguna función dentro de su programa, no puede usar todos los indicadores, porque el compilador se quejará de cualquier definición de función imaginable.

Para C ++, esto es posible (el -Wtraditionalindicador no existe), y se pueden compilar programas muy simples. Para habilitar todas las advertencias, use la siguiente lista de advertencias (probablemente algunas advertencias están duplicadas, porque no me molesté en filtrar las advertencias habilitadas por -Wall).

-Wabi -Wctor-dtor-privacy -Wnon-virtual-dtor -Wreorder -Weffc++ -Wstrict-null-sentinel -Wno-non-template-friend -Wold-style-cast -Woverloaded-virtual -Wno-pmf-conversions -Wsign-promo -Wextra -Wall -Waddress -Waggregate-return -Warray-bounds -Wno-attributes -Wno-builtin-macro-redefined -Wc++0x-compat -Wcast-align -Wcast-qual -Wchar-subscripts -Wclobbered -Wcomment -Wconversion -Wcoverage-mismatch -Wno-deprecated -Wno-deprecated-declarations -Wdisabled-optimization -Wno-div-by-zero -Wempty-body -Wenum-compare -Wno-endif-labels -Wfatal-errors -Wfloat-equal -Wformat -Wformat=2 -Wno-format-contains-nul -Wno-format-extra-args -Wformat-nonliteral -Wformat-security -Wformat-y2k -Wignored-qualifiers -Winit-self -Winline -Wno-int-to-pointer-cast -Wno-invalid-offsetof -Winvalid-pch -Wunsafe-loop-optimizations -Wlogical-op -Wlong-long -Wmain -Wmissing-braces -Wmissing-field-initializers -Wmissing-format-attribute -Wmissing-include-dirs -Wmissing-noreturn -Wno-mudflap -Wno-multichar -Wnonnull -Wno-overflow -Woverlength-strings -Wpacked -Wpacked-bitfield-compat -Wpadded -Wparentheses -Wpointer-arith -Wredundant-decls -Wreturn-type -Wsequence-point -Wshadow -Wsign-compare -Wsign-conversion -Wstack-protector -Wstrict-aliasing=1 -Wstrict-overflow=5 -Wswitch -Wswitch-default -Wswitch-enum -Wsync-nand -Wsystem-headers -Wtrigraphs -Wtype-limits -Wundef -Wuninitialized -Wunknown-pragmas -Wno-pragmas -Wunreachable-code -Wunused -Wunused-function -Wunused-label -Wunused-parameter -Wunused-value -Wunused-variable -Wvariadic-macros -Wvla -Wvolatile-register-var -Wwrite-strings
Konrad Borowski
fuente
13
Nunca me molesté en verificar esto hasta ahora, pero en realidad, no es imposible ... intenteint main(int, char **); int main(argc, argv) int argc; char **argv; { (void)argc; (void)argv; return 0; }
user541686
2
Incluso con este programa trivial todavía puedo obtener "advertencia: el uso de la pila es de 16 bytes [-Wstack-use =]" ;-)
Marc Glisse
7

Alguien ha creado un conjunto de herramientas para determinar el conjunto completo de advertencias para una versión dada de GCC o Clang.

Para GCC, copiar de la lista completa de advertencias proporcionadas por esta herramienta para su versión del compilador parece ser la única forma de garantizar que todas las advertencias estén activadas, ya que (a diferencia de Clang) GCC no proporciona -Weverything.

La herramienta parece analizar el c.optarchivo real en el código fuente de GCC, por lo que sus resultados deben ser definitivos.

El repositorio también contiene archivos de texto con las listas de advertencia generadas para la mayoría de las versiones de GCC y Clang (actualmente Clang 3.2 a 3.7 y GCC 3.4 a 5.3).

https://github.com/barro/compiler-warnings

Kyle Strand
fuente
Esta es la respuesta. Use la lista de "nivel superior" y agregue todos los argumentos que están en el nivel superior (no sangrado / anidado). github.com/Barro/compiler-warnings/blob/master/gcc/…
Jetski S-type
6

Gcc 4.3+ ahora tiene -Q --help = advertencias, incluso puede especificar --help = advertencias, C para imprimir las advertencias relacionadas con C.

Acabo de escribir un módulo m4 para aprovechar esto (también es compatible con clang's -Weverything), vea wget_manywarnings.m4

Cómo usarlo es bastante simple, básicamente el módulo activa cada indicador de advertencia. Y elimina las advertencias según sea necesario; algunas son realmente muy detalladas. Ejemplo: configure.ac

Si no usa las herramientas automáticas, encontrará el código para activar todas las advertencias deshabilitadas en el módulo m4, que básicamente es la llamada gcc canalizada a través de awk:

flags="-Wall -Wextra -Wformat=2 "$(gcc -Wall -Wextra -Wformat=2 -Q --help=warning,C|awk '{ if (($2 == "[disabled]" || $2 == "") && $1!~/=/ && $1~/^-W/&& $1!="-Wall") print $1 }'

Rockdaboot
fuente
3

De esta página :

Tenga en cuenta que algunos indicadores de advertencia no están implícitos en -Wall. Algunos de ellos advierten sobre construcciones que los usuarios generalmente no consideran cuestionables, pero que ocasionalmente es posible que desee verificar; otros advierten sobre construcciones que son necesarias o difíciles de evitar en algunos casos, y no existe una manera simple de modificar el código para suprimir la advertencia. Algunos de ellos están habilitados por, -Wextrapero muchos de ellos deben habilitarse individualmente.

Supongo que la pregunta es ¿ cuáles ? Tal vez podría grep esa página para todas las líneas que comienzan con -W, y obtener una lista completa de las banderas de advertencia. Luego compare aquellos con las listas debajo -Wally -Wextra. También lo hay -Wpedantic, aunque obviamente quieres ser aún más pedante =)

arrozal
fuente
"Y todavía no tengo idea de si esta lista es completa" ... sí, ciertamente puedo abarcar esa página, pero la pregunta es, ¿es completa?
user541686
1
No lo sé ... Puede que tenga que pasar por el código fuente de GCC. ¿Estás tratando de hacer que tu vida como programador sea extremadamente difícil, o hay una buena razón por la que quieres ver cada advertencia concebible? =)
arroz
2
Me gustaría ver el diagnóstico de GCC de mi código. Me parece realmente útil. Pero obviamente, si ya supiera todas las advertencias y cuáles son útiles (y cuáles no), entonces no habría nada que preguntar. No hay una forma real de saberlo a menos que lo pruebe (y, por ejemplo, encontré que el sombreado es útil, por lo que no es que sean inútiles solo porque están apagados).
user541686
3

Y todavía no tengo idea si esta lista es completa.

Probablemente lo sea, pero la única lista que es 100% completa es la fuente real del compilador. Sin embargo, ¡GCC es grande ! Y no sé si todos los parámetros de la línea de comandos se recopilan en un solo lugar o se distribuyen en varios archivos de origen. También tenga en cuenta que algunas advertencias son para el preprocesador, algunas para el compilador real y otras para el vinculador (que es un programa completamente separado y que se encuentra en el paquete binutils), por lo que es muy probable que estén dispersas.

Algún tipo programador
fuente
3
Me conecté a la página Resumen de opciones en mi respuesta, que agrupa todas las opciones en una sola página. Las políticas de revisión de código de GCC no permiten nuevas opciones sin documentación, por lo que los documentos deben ser completos.
Jonathan Wakely