¿Cómo puedo activar (literalmente) TODAS las advertencias de GCC?
Me gustaría habilitar, literalmente, todas las advertencias que tiene GCC. (Pensarías que sería fácil...)
Se podría pensar que Wall podría funcionar, ¡pero no! Aún necesitas -Wextra .
Pensarías
-Wextra
que podría funcionar, ¡pero no! No todas las advertencias enumeradas aquí (por ejemplo, -Wshadow ) están habilitadas por esto. Y todavía no tengo idea de si esta lista es completa.
¿Cómo le digo a GCC que habilite (¡sin si, y o pero!) todas las advertencias que tiene?
No puedes.
El manual de GCC 4.4.0 sólo 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 enlaza. Por ejemplo, algunas opciones específicas del idioma se encuentran en las páginas de opciones de C++ u opciones de Objective-C. Para encontrarlos todos, es mejor que consultes el Resumen de opciones .
Activar todo incluiría -Wdouble-promotion
lo que solo es relevante en CPU con una unidad de punto flotante de precisión simple de 32 bits que se implementa float
en hardware, pero emula double
en software. Hacer cálculos como double
utilizaría la emulación del software y sería más lento. Esto es relevante para algunas CPU integradas, pero completamente irrelevante para las CPU de escritorio modernas con soporte de hardware para punto flotante de 64 bits.
Otra advertencia que no suele ser útil es -Wtraditional
, que advierte sobre código perfectamente bien formado que tiene un significado diferente (o no funciona) en C tradicional, por ejemplo, "string " "concatenation"
o definiciones de funciones ISO C. ¿Realmente te importa la compatibilidad con compiladores de hace 30 años? ¿ Realmente quieres una advertencia por escribir int inc(int i) { return i+1; }
?
Creo -Weffc++
que es demasiado ruidoso para ser útil. Se basa en la primera edición obsoleta de Effective C++ y advierte sobre construcciones que son perfectamente válidas en C++ (y para las cuales las pautas cambiaron en ediciones posteriores del libro). No quiero que me adviertan que no he inicializado un std::string
miembro 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 de detectar con precisión para el compilador (dando falsos negativos), y las que no son útiles, como la inicialización explícita de todos los miembros, simplemente producen demasiado ruido y dan falsos positivos.
Luc Danton proporcionó un gran ejemplo de advertencias inútiles -Waggregate-return
que casi con seguridad nunca tienen sentido para el código C++.
Es decir, realmente no quieres todas las advertencias; simplemente crees que sí.
Lea el manual, lea sobre ellos, decida cuál desea habilitar y pruébelos. Leer el manual de su compilador es algo bueno de todos modos, tomar un atajo y habilitar advertencias que no comprende no es una muy buena idea, especialmente si es para evitar tener que usar RTFM .
Cualquiera que simplemente active todo probablemente lo haga porque no tiene ni idea o porque un jefe de pelo puntiagudo dijo "sin advertencias".
Algunas advertencias son importantes y otras no. Tienes que ser exigente o arruinarás 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 lo haga. Y tu quieres -Wtraditional
? Lo dudo .
Consulte también -Wall-all para habilitar todas las advertencias que están cerradas como WONTFIX .
En respuesta a la queja de DevSolar acerca de que los archivos MAKE necesitan usar diferentes advertencias dependiendo de la versión del compilador, si -Wall -Wextra
no 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))
Estoy de acuerdo con las respuestas anteriores en que probablemente no sea beneficioso habilitar literalmente todas las advertencias; sin embargo, GCC proporciona una forma razonablemente conveniente de lograrlo. El comando
gcc -Q --help=warning
proporciona una lista de todas las opciones de advertencia admitidas con información sobre si están activas. Por cierto, esto se puede utilizar para averiguar qué opciones están (no) habilitadas por, por ejemplo, -Wall
y-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 comando.
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-optimizaciones -Waliasing -Walign-commons -Wampersand -Warray-bounds -Warray-temporaries -Wassign-intercept -Wattributes -Wbad-function-cast -Wbool-compare -Wbuiltin-macro-redefinido -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-truncation -Wchkp -Wclobbered -Wcomment -Wcompare-reals -Wconditionally-supported -Wconversion -Wconversion-extra -Wconversion-null -Wcoverage-mismatch -Wcpp -Wctor-dtor-privacy -Wdate-time -Wdeclaration -post-declaración -Wdelete-incompleto -Wdelete-non-virtual-dtor -Wdeprecated -Wdeprecated-declarations -Wdesignated-init -Wdisabled-optimization -Wdiscarded-array-qualifiers -Wdiscarded-qualifiers -Wdiv-by-zero -Wdouble-promotion -Weffc++ -Wempty-body -Wendif-labels -Wenum-compare -Wextra -Wfloat-equal -Wformat-contains-nul -Wformat-extra-args -Wformat-nonliteral -Wformat-security -Wformat-signness -Wformat-y2k -Wformat -longitud-cero -Wfree-non-heap-object -Wfunction-elimination -Wimplicit-qualifiers -Wimplicit -Wimplicit-function-declaration -Wimplicit-int -Wimplicit-interface -Wimplicit-procedure -Wincompatible-pointer-types -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-truncamiento -Wliteral-suffix -Wlogic-not-paréntesis -Wlogic-op -Wlong-long -Wmain -Wmaybe-uninitialized -Wmemset-args-transposed -Wmissing-braces -Wmissing-declarations -Wmissing-field-initializers -Wmissing-include-dirs -Wmissing-parameter-type -Wmissing-prototypes -Wmultichar -Wnarrowing -Wnested-externs -Wnoexcept -Wnon-template-friend -Wnon-virtual-dtor -Wnonnull -Wodr -Wold-style-cast -Wold-style-declaration -Wold -definición de estilo -Wopenmp-simd -Woverflow -Woverlength-strings -Woverloaded-virtual -Woverride-init -Wpacked -Wpacked-bitfield-compat -Wpadded -Wparentheses -Wpedantic -Wpmf-conversions -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-argument -Wsizeof-pointer-memaccess -Wstack-protector -Wstrict-null-sentinel -Wstrict-prototipos -Wstrict-selector-match -Wsuggest-attribute=const -Wsuggest-attribute=formato -Wsuggest-attribute=noreturn -Wsuggest-attribute=puro -Wsuggest-final-methods -Wsuggest-final -types -Wsuggest-override -Wsurprising -Wswitch -Wswitch-bool -Wswitch-default -Wswitch-enum -Wsync-nand -Wsynth -Wsystem-headers -Wtabs -Wtarget-lifetime -Wtraditional -Wtraditional-conversion -Wtrampolines -Wtrigraphs -Wtype -limites -Wundeclared-selector -Wundef -Wunderflow -Wuninitialized -Wunknown-pragmas-Optimizaciones-de-bucle-Wunsafe -Constantes-flotantes-Wunsuffixed -Wunused -Wunused-pero-establece-parámetro -Wunused-pero-establece-variable -Wunused-dummy-argument -Wunused-function -Wunused-label -Wunused-local-typedefs -Wunused-macros -Wunused-parámetro -Wunused-resultado -Wunused-valor -Wunused-variable -Wuse-sin-solo -Wuseless-cast -Wvarargs -Wvariadic-macros -Wvector-operación-rendimiento -Wvirtual-move-assign -Wvla -Wvolatile-register-var -Wwrite-strings -Wzero-as-null-pointer-constant -Wzerotrip -frequire-return-statement
Esto ahora se puede utilizar 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 (por ejemplo, C++
). Estos podrían evitarse usando más expresiones regulares para incluir solo las opciones permitidas para el idioma actual o agregando una apropiada -Wno-whatever
al final de la llamada.
Es simplemente imposible programar con todas las advertencias habilitadas (a menos que vaya a ignorarlas, pero entonces, ¿para qué molestarse?). Por ejemplo, supongamos que utiliza el siguiente conjunto de indicadores: -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) {
^
Quizás pienses "bueno, entonces voy a usar prototipos de estilo antiguo". 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 isn’t a prototype [-Wstrict-prototypes]
int main(argc, argv)
^
Y no, no especificar ningún prototipo también es incorrecto, 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 isn’t 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 (la -Wtraditional
bandera no existe) y se pueden compilar programas muy simples. Para habilitar todas las advertencias, utilice 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