Como ativar (literalmente) TODOS os avisos do GCC?

194

Gostaria de ativar - literalmente - TODOS os avisos que o GCC possui. (Você pensaria que seria fácil ...)

  • Você pensaria que -Wallpoderia fazer o truque, mas não! Ainda precisa -Wextra.

  • Você pensaria que -Wextrapoderia fazer o truque, mas não! Nem todos os avisos listados aqui (por exemplo -Wshadow) são ativados por isso. E ainda não tenho ideia se esta lista é abrangente.

Como eu digo ao GCC para ativar (sem if's, e's ou but's!) Todos os avisos que possui?

user541686
fonte
27
@Arafangion: Eu não entendo o que não é "claro" sobre a pergunta - sim, eu gostaria de ativar todos os avisos aplicáveis ​​ao meu código, por mais pedante que seja. Por esse motivo, é muito simples: achei alguns dos avisos que não são ativados por -Wall ou -Wextra úteis e, por isso, quero tentar o resto para ver se posso melhorar meu código. É simples assim.
user541686
12
@JoachimPileborg: "Sobre o que você deseja que o compilador avise?" Erros potenciais e / ou estilo ruim? Quero dizer, se eu soubesse todos os avisos exatos, eu os teria ativado manualmente, sem necessidade de fazer a pergunta. Se a resposta for realmente "você precisa procurar o código-fonte para encontrar todos eles", publique-o como resposta!
user541686
56
clang 3.1 oferece -Weverything.
Alexandre Hamez 30/07/2012
5
@Arafangion Bem, a questão é marcado C ++ assim ... :)
Um cara programador
5
@JoachimPileborg E agora não é (finalmente) uma forma automatizada para extrair os avisos da fonte: github.com/barro/compiler-warnings
Kyle Strand

Respostas:

129

Você não pode.

O manual do GCC 4.4.0 é abrangente apenas para essa versão, mas lista todos os avisos possíveis para o 4.4.0. Eles não estão todos na página para a qual você vincula, por exemplo, algumas opções específicas do idioma estão nas páginas de opções C ++ ou Obj-C. Para encontrá-los todos, é melhor consultar o Resumo das opções

Ligar tudo incluiria o -Wdouble-promotionque é relevante apenas em CPUs com uma unidade de ponto flutuante de precisão única de 32 bits que implementa floatem hardware, mas simula doubleem software. Fazendo cálculos como doubleusaria a emulação de software e seria mais lento. Isso é relevante para algumas CPUs incorporadas, mas completamente irrelevante para as modernas CPUs de desktop com suporte de hardware para ponto flutuante de 64 bits.

Outro aviso que geralmente não é útil é -Wtraditional, que alerta sobre códigos perfeitamente formados que têm um significado diferente (ou não funciona) nas "string " "concatenation"definições tradicionais de C, por exemplo , ou ISO C! Você realmente se importa com a compatibilidade com compiladores de 30 anos? Você realmente quer um aviso para escrever int inc(int i) { return i+1; }?

Eu acho que -Weffc++é muito barulhento para ser útil, é baseado na primeira edição desatualizada do Effective C ++ e alerta sobre construções perfeitamente válidas em C ++ (e para as quais as diretrizes foram alteradas nas edições posteriores do livro.) Eu não quero ser avisei que não inicializei um std::stringmembro no meu construtor; ele tem um construtor padrão que faz exatamente o que eu quero, por que devo escrever m_str()para chamá-lo? Os -Weffc++avisos que seriam úteis são muito difíceis para o compilador detectar com precisão (dando falsos negativos) e os que não são úteis, como inicializar explicitamente todos os membros, apenas produzem muito ruído, dando falsos positivos.

Luc Danton forneceu um ótimo exemplo de avisos inúteis, dos -Waggregate-returnquais quase certamente nunca faz sentido para o código C ++.

ou seja, você realmente não deseja todos os avisos, apenas pensa que deseja.

Leia o manual, leia sobre eles, decida qual você deseja ativar e tente. Ler o manual do seu compilador é uma Good Thing TM de qualquer maneira, tomar um atalho e ativar avisos que você não entende não é uma boa idéia, especialmente se for para evitar ter que usar o RTFM.

Quem simplesmente liga tudo provavelmente está fazendo isso porque não tem noção, porque ou um chefe de cabelos pontudos disse "sem avisos".

Alguns avisos são importantes e outros não. Você tem que ser discriminador ou estragar seu programa. Considere, por exemplo -Wdouble-promotion,. Se você estiver trabalhando em um sistema incorporado, poderá querer isso; se você estiver trabalhando em um sistema desktop, provavelmente não. E você quer -Wtraditional? Eu duvido.

Editar: Consulte também -Wall-all para ativar todos os avisos fechados como WONTFIX.

Edit 2: em resposta à reclamação do DevSolar sobre makefiles que precisam usar avisos diferentes dependendo da versão do compilador, se -Wall -Wextranão for adequado, não será difícil usar CFLAGS específicos do compilador e da versão:

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
fonte
38
"Leia o manual, leia sobre eles, decida qual você deseja habilitar, experimente." O problema aqui são as etapas que você deixou de fora: "Visite novamente o manual de todas as versões do compilador e adapte sua lista de avisos porque eles estão mudando. Faça com que seus Makefiles verifique a versão exata do compilador e use uma lista diferente de avisos. para cada um deles ". Temos níveis de otimizações mantidos pelo mantenedor; por que eles não se preocuparam em fornecer o mesmo serviço para avisos?
DevSolar
17
@ JonathanWakely: Eu tenho meus projetos e o GCC não está entre eles. Aponto para uma fraqueza no produto deles. Ou eles consertam ou aceitam a culpa por não fazer isso, mas não cabe a mim consertar isso para eles, OSS seja condenado.
DevSolar 30/07/12
14
@ JonathanWakely: "Se você quer algo, peça, não se preocupe com isso". - Não sou obrigado a participar do projeto do GCC para criticá-lo, principalmente se o # 31573 já tiver sido marcado como WONTFIX. Isso coloca esse assunto do "pergunte sobre isso" no estádio "cadela sobre isso".
DevSolar
61
-Weverythingé a melhor solução, eu acho, do que a estratégia do gcc de não dar essa opção. Eu uso esse sinalizador com clang porque minha filosofia é que eu quero todos os avisos por padrão (porque alguém achou útil o suficiente para adicionar ao compilador) e, se eu não gostar, desativo esse aviso especificamente. O ponto é que você não sabe sobre avisos que não são acionados, mas sabe sobre avisos que não deseja que sejam acionados e eles são facilmente desativados.
David Stone
17
@ JonathanWakely Sim, mas eles são insignificantes. A maneira mais fácil de ver quais avisos podem ser relevantes para o seu código é ver quais avisos são acionados pelo seu código; nesse ponto, você pode ver um exemplo relevante e real do código potencialmente perigoso antes de decidir se desativa ou não o aviso. Isso pode ser feito facilmente com a -Weverythingopção de Clang , mas é impossível fazer com o GCC.
Kyle Strand
71

Concordo com as respostas anteriores de que provavelmente não é benéfico ativar literalmente todos os avisos, no entanto, o GCC fornece uma maneira razoavelmente conveniente de conseguir isso. O comando

gcc -Q --help=warning

fornece uma lista de todas as opções de aviso suportadas com informações sobre se elas estão ativas. A propósito, isso pode ser usado para descobrir quais opções (não) estão ativadas, por exemplo, -Walle-Wextra

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

Para habilitar todos os avisos, você pode usar algum regex para extrair os parâmetros da linha de comando

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

Para o meu GCC atual, isso fornece:

-Wabi -Wabi-tag -Waddress -Waggregate-return -Waggressive-loop-optimizations -Waliasing -Walign-commons -Wampersand -Warray-bounds -Warray-temporaries -Wassign-intercept -Wattributes -Wbad-function-cast -Wbool-compare -Wbuiltin-macro-redefiniu -Wc ++ - compat -Wc ++ 0x-compat -Wc ++ 14-compat -Wc-tipo de ligação -Wc90-c99-compat -Wc99-c11-compat -Wcast-align -Wcast-qual -Wchar-subscripts -Wcharacter-truncation -Wchkp -Wclobbered -Wcomment -Wcompare-reals -Wconditionally-supported -Wconversion -Wconversion-extra -Wconversion-null -Wcoverage-mismatch -Wcpp -Wctor-dtor-privacy -Wdate-time -Wdeclaration -after-statement -Wdelete-incompleto -Wdelete-não-virtual-dtor -Wdeprecated -Wdeprecated-declarações -Wdesignated-init -Wdisabled-optimization -Wdiscarded-array-qualifiers -Wdiscarded-qualifiers -Wdiv-by-zero -Wdouble-promotion - Weffc ++ - Corpo vazio-Wendif-labels -Wenum-compare -Wextra -Wfloat-equal -Formato-contém-nul -Formato-extra-args -Formato-não-literais -Formato-segurança -Formato-sinalidade -Formato-y2k -Formato-zero-comprimento -Wfree -nonheap-object -Wfunction-eliminação -Wignored-qualifiers -Wimplicit -Wimplicit-function-declaração -Wimplicit-int -Wimplicit-interface -Wimplicit-procedure -Wincompatible-ponteiro-types -Winherited-variadic-ctor -Winit-self -Winline -Wint-conversion -Wint-to-pointer-cast -Wintrinsic-shadow -Wintrinsics-std -Winvalid-memory-model -Winvalid-offsetof -Winvalid-pch -Jump-misses-init -Wline-truncation -Wlitereral-suffix -Wlogical -not-parentheses -Wlogical-op -Wlong-long -Wmain -Wmaybe-uninitialized -Wmemset-transposed-args -Wmissing-braces -Wmissing-declarações -Wmissing-field-initializers -Wmissing-include-dirs -Wmissing-parameter-type -Protótipos de falta-Wmultichar -Wnarrowing -Wnested-externs -Wnoexcept -Wnon-template-friend -Wnon-virtual-dtor -Wnonnull -Wodr -Woldr estilo de elenco -Wolden-estilo-declaração -Wold-estilo-definição -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-ponteiro-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-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-limits -Wundeclared-selector -Wundef -Wunderin -Wuninitialized -Wunsafe-loop-optimizations -Wunsuffixed-float-constantes -Wunused -Wunused-but-set-parameter -Wunused-but-set-variable -Wunused-dummy-argument -Wunused-function -Wunused-label -Wunused-label -Wunused-local-typedefs -Wunused-macros -Wunused-result -Wunused-result -Wunused-variable -Wunused-variável -Wuse-sem-apenas -Wuseless-cast -Wvarargs -Wvariadic-macros -Vector-operation-performance -Wvirtual-move-assign-Wvla -Wvolatile-register-var -Wwrite-strings -Wzero-como-null-ponteiro-constante -Wzerotrip -frequire-return-statement

Agora isso pode ser usado para chamar o GCC, ou seja,

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

Observe, no entanto, que isso resulta em avisos devido a algumas opções de aviso estarem disponíveis apenas para determinados idiomas (por exemplo C++). Isso pode ser evitado usando um pouco mais de regex para incluir apenas as opções permitidas para o idioma atual ou adicionando um apropriado -Wno-whateverno final da chamada.

Haatschii
fonte
10
Receio que não seja prático. O Gcc me mostrou avisos do std lib.
Valentin Heinitz 5/09/16
13
@ValentinHeinitz Como eu disse, não acho que seja benéfico habilitar literalmente todos os avisos, mas foi o que o OP pediu. No entanto, acho que removendo explicitamente alguns avisos problemáticos já mencionados em outras respostas (por exemplo, adicionando -Wno-qualquer que seja no final da chamada), isso pode ser útil.
precisa saber é o seguinte
6
@ValentinHeinitz Você pode impedir que o gcc emita avisos para cabeçalhos de sistema / std / terceiros usando em -isystemvez de -Inos diretórios relevantes.
Kyle Strand
4
Essa deve ser a resposta aceita, já que isso realmente responde diretamente à pergunta.
TFuto 02/09
16

É simplesmente impossível programar com todos os avisos ativados (a menos que você os ignore, mas por que se preocupar?). Por exemplo, vamos supor que você use o seguinte conjunto de sinalizadores: -Wstrict-prototypes -Wtraditional.

Mesmo com dois avisos ativados, o programa a seguir reclamaria.

/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) {
     ^

Você pode pensar "bem, eu vou usar protótipos de estilo antigo então". Não, isso não vai 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)
     ^

E não, não especificar nenhum protótipo também está errado, pois o compilador também reclamará.

/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() {
     ^

Se você definir alguma função dentro do seu programa, não poderá usar todos os sinalizadores, porque o compilador reclamará de qualquer definição de função imaginável.

Para C ++, isso é possível (o -Wtraditionalsinalizador não existe) e programas muito simples podem ser compilados. Para habilitar todos os avisos, use a seguinte lista de avisos (provavelmente alguns avisos foram duplicados, porque eu não me preocupei em filtrar os avisos ativados 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
fonte
13
Eu nunca me preocupei em verificar isso até agora, mas, na verdade, não é impossível ... tente #int main(int, char **); int main(argc, argv) int argc; char **argv; { (void)argc; (void)argv; return 0; }
user541686
2
Mesmo com este programa trivial eu ainda pode obter "aviso: uso da pilha é de 16 bytes [-Wstack-usage =]" ;-)
Marc Glisse
7

Alguém criou um conjunto de ferramentas para determinar o conjunto completo de avisos para uma determinada versão do GCC ou Clang.

Para o GCC, copiar da lista completa de avisos fornecidos por esta ferramenta para a sua versão do compilador parece ser a única maneira de garantir que todos os avisos sejam ativados, pois (ao contrário do Clang) o GCC não fornece -Weverything.

A ferramenta parece analisar o c.optarquivo real no código-fonte do GCC, portanto, seus resultados devem ser definitivos.

O repositório também contém arquivos de texto com as listas de aviso geradas para a maioria das versões GCC e Clang (atualmente Clang 3.2 a 3.7 e GCC 3.4 a 5.3).

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

Kyle Strand
fonte
Essa é a resposta. Use a lista "nível superior" e adicione todos os argumentos que estão no nível superior (não recuado / aninhado). github.com/Barro/compiler-warnings/blob/master/gcc/…
Jetski S-type
6

O Gcc 4.3+ agora possui -Q --help = avisos, você pode até especificar --help = warnings, C para imprimir apenas os avisos relacionados ao C.

Acabei de escrever um módulo m4 para tirar proveito disso (também suporta -Weverything do clang), consulte wget_manywarnings.m4

Como usá-lo é bastante simples, basicamente o módulo ativa cada sinalizador de aviso. E você remove os avisos conforme necessário - alguns são realmente muito detalhados. Exemplo: configure.ac

Se você não usar autotools, encontrará o código para ativar todos os avisos desabilitados no módulo m4, que basicamente é a chamada do gcc transmitida pelo 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
fonte
3

A partir desta página :

Observe que alguns sinalizadores de aviso não estão implícitos -Wall. Alguns deles alertam sobre construções que os usuários geralmente não consideram questionáveis, mas que ocasionalmente você pode procurar; outros alertam sobre construções necessárias ou difíceis de evitar em alguns casos, e não há uma maneira simples de modificar o código para suprimir o aviso. Alguns deles são ativados por, -Wextramas muitos devem ser ativados individualmente.

Eu acho que a pergunta é quais ? Talvez você possa cumprimentar essa página para todas as linhas que começam com -W e obter uma lista completa de sinalizadores de aviso. Em seguida, compare-os com as listas em -Walle -Wextra. Há também -Wpedantic, embora você obviamente esteja querendo ser ainda mais pedante ainda =)

arroz
fonte
"E ainda não tenho idéia se essa lista é abrangente" ... sim, certamente posso cumprimentar essa página, mas a questão é: é abrangente?
user541686
1
Não sei ... Você pode precisar ler o código-fonte do GCC. Você está tentando tornar sua vida como programador extremamente difícil ou há uma boa razão para querer ver todos os avisos possíveis? =)
paddy
2
Gostaria de ver o diagnóstico do meu código pelo GCC - acho que é realmente útil. Mas, obviamente, se eu já soubesse de todos os avisos e quais são úteis (e quais não são), não haveria nada a perguntar. Não existe uma maneira real de eu contar, a menos que eu as experimente (e, por exemplo, achei a sombra útil, portanto não é inútil apenas porque estão desligadas).
user541686
3

E ainda não tenho ideia se esta lista é abrangente.

Provavelmente é, mas a única lista 100% abrangente é a fonte real do compilador. No entanto, o GCC é grande ! E não sei se todos os parâmetros da linha de comando são coletados em um único local ou espalhados por vários arquivos de origem. Observe também que alguns avisos são para o pré-processador, outros para o compilador real e outros para o vinculador (que é um programa completamente separado e encontrado no pacote binutils), portanto eles provavelmente estão espalhados.

Algum cara programador
fonte
3
Vinculei à página Resumo das opções na minha resposta, que agrupa todas as opções em uma página. As políticas de revisão de código do GCC não permitem novas opções sem documentação; portanto, os documentos devem ser abrangentes.
Jonathan Wakely