Sinalizadores para ativar avisos detalhados e detalhados do g ++


122

Freqüentemente, em C abaixo gcc, começarei com o seguinte conjunto de sinalizadores de aviso (dolorosamente reunidos de várias fontes):

-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

Eu construirei (pelo menos minhas versões de depuração) com esse conjunto de avisos e corrigirei tudo o que for possível (geralmente tudo) e removerei os sinalizadores apenas se não forem relevantes ou não corrigíveis (quase nunca é o caso). Às vezes, também adicionarei -Werrorse precisar me afastar durante a compilação.

Estou apenas aprendendo C ++ (sim, tenho 15 anos de atraso) e gostaria de começar com o pé direito.

Minha pergunta é: Alguém tem um conjunto semelhante pré-compilado de sinalizadores de aviso completos para C ++ em g++? (Eu sei que muitos deles serão os mesmos.)


69
Que necessidades do CCG (uma vez que está decidido descaradamente mentira sobre -Wall) é uma -Wbloody_everythingbandeira :-)
paxdiablo

Você pode marcar sua pergunta como burra, mas também pode colocar sua última edição como resposta, uma vez que realmente respondeu sua pergunta. E eu ficaria feliz em votá-lo em seguida :) :)
ereOn

4
OP e @paxdiablo: o GCC rejeitou consistentemente esse tipo de coisa, mas está disponível no Clang via -Weverything. Eu li que mesmo os desenvolvedores do Clang ++ estão um pouco preocupados com os usuários ativando-o; aparentemente, ele foi projetado apenas para uso em desenvolvimento interno. Porém, isso não faz sentido, porque ativar -Weverythingé provavelmente a melhor maneira possível de descobrir avisos potencialmente úteis que você não conhecia antes.
Kyle Strand

1
OP e @paxdiablo Há agora uma maneira de descobrir a lista completa das advertências para uma determinada versão do GCC: github.com/barro/compiler-warnings
Kyle Strand

Respostas:


138

Examinei e encontrei o conjunto mínimo de inclusões que deveria receber o nível máximo de aviso. Em seguida, removi dessa lista o conjunto de avisos que, na verdade, não indicam que algo de ruim está acontecendo, ou então há muitos falsos positivos para serem usados ​​em uma compilação real. Comentei por que todos os que excluí foram excluídos. Este é o meu conjunto final de avisos sugeridos:

-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

Avisos questionáveis ​​presentes:

  • Incluo -Wno-unusedporque geralmente tenho variáveis ​​que sei que usarei mais tarde, mas ainda não tenho a funcionalidade escrita. A remoção de avisos sobre isso me permite escrever no meu estilo preferido de adiar ocasionalmente a implementação das coisas. É útil desativá-lo de vez em quando para garantir que nada escorregue pelas rachaduras.

  • -Wdisabled-optimizationparece uma forte configuração de preferência do usuário. Acabei de adicionar este à minha compilação (apenas para compilações otimizadas por razões óbvias) e ele não apareceu nada, por isso não parece ser um aviso especialmente falador, pelo menos pela maneira como codifico. Eu o incluo (mesmo que o código que aciona esse aviso não esteja necessariamente errado) porque acredito em trabalhar com minhas ferramentas em vez de contra elas. Se o gcc está me dizendo que não pode otimizar o código da maneira como o escrevi, então devo reescrevê-lo. Suspeito que o código que aciona esse aviso possa se beneficiar de ser mais modular, independentemente, portanto, embora o código não esteja tecnicamente errado (provavelmente), estilisticamente é provável.

  • -Wfloat-equalalerta para comparações de igualdade seguras (em particular, comparação com um valor não calculado de -1). Um exemplo no meu código em que eu uso isso é que eu tenho um vetor de float. Eu passo por esse vetor e há alguns elementos que ainda não posso avaliar o que deveriam ser, então os defino como -1.0f (já que meu problema usa apenas números positivos, -1 está fora do domínio). Mais tarde, passo a atualizar os valores -1.0f. Não se presta facilmente a um método de operação diferente. Eu suspeito que a maioria das pessoas não tenha esse problema, e a comparação de um número exato em ponto flutuante provavelmente é um erro, por isso estou incluindo-o na lista padrão.

  • -Wold-style-casttem muitos falsos positivos no código da biblioteca que estou usando. Em particular, a família de funções htonl usada nas redes, bem como a implementação de criptografia Rijndael (AES) que estou usando, tem moldes no estilo antigo que me alertam. Pretendo substituir os dois, mas não tenho certeza se há mais alguma coisa no meu código sobre a qual ele reclamará. A maioria dos usuários provavelmente deve ter isso por padrão, no entanto.

  • -Wsign-conversionfoi difícil (e quase não entrou na lista). Ativá-lo no meu código gerou uma enorme quantidade de avisos (mais de 100). Quase todos eles eram inocentes. No entanto, tomei o cuidado de usar números inteiros assinados sempre que não tivesse certeza, embora, para meu domínio de problema específico, normalmente recebesse um ligeiro aumento de eficiência usando valores não assinados devido à grande quantidade de divisão de números inteiros que faço. Eu sacrifiquei essa eficiência porque estava preocupado em promover acidentalmente um número inteiro assinado para um não assinado e depois dividi-lo (o que não é seguro, ao contrário da adição, subtração e multiplicação). Ativar esse aviso me permitiu alterar com segurança a maioria das minhas variáveis ​​para tipos não assinados e adicionar algumas transmissões em outros lugares. Atualmente, é um pouco difícil de usar, porque o aviso não é tão inteligente. Por exemplo, se você fizerunsigned short + (integral constant expression), esse resultado é implicitamente promovido para int. Em seguida, ele avisa sobre um possível problema de sinal se você atribuir esse valor a unsignedou unsigned short, mesmo que seja seguro. Esse é definitivamente o aviso mais opcional para quase todos os usuários.

  • -Wsign-promo: veja -Wsign-conversion.

  • -Wswitch-defaultparece inútil (você nem sempre quer um caso padrão se tiver enumerado explicitamente todas as possibilidades). No entanto, ativar esse aviso pode aplicar algo que provavelmente é uma boa ideia. Nos casos em que você deseja explicitamente ignorar tudo, exceto as possibilidades listadas (mas outros números são possíveis), insiradefault: break;para torná-lo explícito. Se você enumerar explicitamente todas as possibilidades, ativar esse aviso ajudará a garantir algo como assert (false) para garantir que você realmente cobriu todas as opções possíveis. Ele permite que você seja explícito em qual é o domínio do seu problema e o imponha programaticamente. No entanto, você terá que ter cuidado em apenas afirmar (false) em qualquer lugar. É melhor do que não fazer nada com o caso padrão, mas, como de costume com assert, ele não funcionará nas versões do release. Em outras palavras, você não pode confiar nele para validar os números obtidos de, digamos, uma conexão de rede ou um banco de dados sobre o qual você não tem controle absoluto. Exceções ou retorno antecipado são a melhor maneira de lidar com isso (mas ainda exigem que você tenha um caso padrão!).

  • -Werroré importante para mim. Ao compilar grandes quantidades de código em uma compilação multithread com vários destinos, é fácil passar um aviso. Transformar avisos em erros garante que eu os observe.

Depois, há um conjunto de avisos que não estão incluídos na lista acima porque eu não achei que fossem úteis. Estes são os avisos e meus comentários sobre por que não os incluo na lista padrão:

Avisos ausentes:

  • -Wabinão é necessário porque não estou combinando binários de diferentes compiladores. Tentei compilar com ele de qualquer maneira, e não foi acionado, por isso não parece desnecessariamente detalhado.

  • -Waggregate-returnnão é algo que eu considere um erro. Por exemplo, ele é acionado ao usar um loop for baseado em intervalo em um vetor de classes. A otimização do valor de retorno deve cuidar de quaisquer efeitos negativos disso.

  • -Wconversionaciona esse código: short n = 0; n += 2;a conversão implícita em int causa um aviso quando é convertida novamente em seu tipo de destino.

  • -Weffc++inclui um aviso se todos os membros dos dados não forem inicializados na lista de inicializadores. Intencionalmente não faço isso em muitos casos, portanto o conjunto de avisos é muito confuso para ser útil. É útil ativar de vez em quando e procurar outros avisos (como destruidores não virtuais de classes base). Isso seria mais útil como uma coleção de avisos (como -Wall) em vez de um único aviso por si só.

  • -Winlineestá ausente porque eu não uso a palavra-chave inline para fins de otimização, apenas para definir funções inline nos cabeçalhos. Não me importo se o otimizador realmente o alinha. Esse aviso também se queixa se não conseguir incorporar uma função declarada em um corpo de classe (como um destruidor virtual vazio).

  • -Winvalid-pch está ausente porque eu não uso cabeçalhos pré-compilados.

  • -Wmissing-format-attributenão é usado porque eu não uso extensões gnu. Mesmo para -Wsuggest-attributee vários outros

  • Potencialmente notável por sua ausência é -Wno-long-long, da qual eu não preciso. Eu compilo com -std=c++0x( -std=c++11no GCC 4.7), que inclui long longtipos inteiros. Os que estão presos no C ++ 98 / C ++ 03 podem considerar adicionar essa exclusão da lista de avisos.

  • -Wnormalized=nfc já é a opção padrão e parece ser a melhor.

  • -Wpaddedé ativado ocasionalmente para otimizar o layout das classes, mas não é ativado porque nem todas as classes têm elementos suficientes para remover o preenchimento no final. Em teoria, eu poderia obter algumas variáveis ​​extras para 'free', mas não vale a pena o esforço extra de manter isso (se o tamanho da minha classe mudar, não é fácil remover essas variáveis ​​anteriormente livres).

  • -Wstack-protector não é usado porque eu não uso -fstack-protector

  • -Wstrict-aliasing=3está ativado -Walle é o mais preciso, mas parece que os níveis 1 e 2 dão mais avisos. Em teoria, um nível mais baixo é um aviso "mais forte", mas custa mais falsos positivos. Meu próprio código de teste compilado de forma limpa em todos os três níveis.

  • -Wswitch-enumNão é um comportamento que eu quero. Não quero lidar com todas as instruções de switch explicitamente. Seria útil se o idioma tivesse algum mecanismo para ativar isso em instruções de chave especificadas (para garantir que futuras alterações na enum sejam tratadas em todos os lugares que elas precisam estar), mas é um exagero para uma configuração de "tudo ou nada".

  • -Wunsafe-loop-optimizationscausa muitos avisos espúrios. Pode ser útil aplicar este periodicamente e verificar manualmente os resultados. Como exemplo, ele gerou esse aviso no meu código quando fiz um loop sobre todos os elementos em um vetor para aplicar um conjunto de funções a eles (usando o loop for baseado em intervalo). Também é um aviso para o construtor de uma matriz const de const std :: string (onde não há loop no código do usuário).

  • -Wzero-as-null-pointer-constante -Wuseless-castsão apenas avisos do GCC-4.7, que adicionarei quando passar para o GCC 4.7.

Arquivei alguns relatórios de bugs / solicitações de aprimoramento no gcc como resultado de algumas dessas pesquisas. Espero que, eventualmente, eu possa adicionar mais avisos da lista "não incluir" na lista "incluir" . Esta lista inclui todos os avisos mencionados neste tópico (além de alguns extras). Muitos dos avisos não mencionados explicitamente nesta postagem estão incluídos como parte de outro aviso que menciono. Se alguém perceber completamente quaisquer avisos excluídos desta postagem, entre em contato.

edit: Parece que eu perdi vários (que eu adicionei agora). Na verdade, existe uma segunda página em http://gcc.gnu.org que está muito bem oculta. Opções gerais de aviso e opções C ++ (role para baixo até o final para obter avisos)


Recentemente, enviei uma solicitação de aprimoramento com base em minha pesquisa para esta resposta: gcc.gnu.org/bugzilla/show_bug.cgi?id=53313 . Simplificaria drasticamente a situação de aviso, criando níveis de aviso. Na minha proposta, meu conjunto sugerido de avisos é de aproximadamente -W4, com uma proposta adicional para criar -Winf, o que significaria -Weverything-and-I-realmente-média-it-este-tempo
David Stone

Solicitação de aprimoramento que faria com que parte de -Wpadded fosse adicionada à lista recomendada: gcc.gnu.org/bugzilla/show_bug.cgi?id=53514
David Stone

Solicitação de aprimoramento que faria com que partes do -Weffc ++ fossem adicionadas à lista recomendada: gcc.gnu.org/bugzilla/show_bug.cgi?id=16166
David Stone

1
@Predelnik: É mais complicado que isso. -Wswitch-enumavisa se você não manipula explicitamente todos os valores de enumeração em uma opção e defaultnão conta como explícito. Por outro lado, -Wswitch-defaultavisa se o seu switch não possui um defaultcaso, mesmo que você tenha explicitamente coberto todos os valores possíveis.
David Stone

2
BTW - utilização -isystem, em vez de -Ino seu "código da biblioteca de idade" para evitar todos esses falsos positivos
galois

39

Ah, todas as minhas pesquisas originais exibiram 99% das postagens sobre como suprimir avisos (assustadoramente), mas acabei de passar por esse comentário , que tem esse adorável conjunto de sinalizadores (alguns menos relevantes):

Cruzado com:

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

Então, acho que esse é um bom ponto de partida. Não percebeu que aquilo era um engodo, mas pelo menos estava profundamente enterrado. :-)


1
Talvez, mas isso pareça mudar entre as versões, e provavelmente por capricho das manchas solares e do RMS, portanto, ser excessivamente explícito provavelmente não vai doer. É um bom ponto de partida, de qualquer maneira.
Sdaz MacSkibbons

3
De um grep rápido de c-opts.c / opts.c do 4.5.2 para 'case OPT_W', você está ausente: overflow estrito, undef, sentinela estrita nul, normalizado, multichar, declaração de função implícita, rótulos obsoletos, endif, comentários s , macro incorporada redefinida, maior que, maior que eq, abi. É uma loucura que não haja uma opção de linha de comando para listá-los.
Tony Delroy

3
Eu acho que é mais louco que -Wallnão faça o que seria de esperar. Mas obrigado, alguns deles parecem muito úteis!
Sdaz MacSkibbons

1
Desativar avisos tem seu lugar. Afinal, eles são "avisos". Outra situação é quando você ativa um sinalizador que ativa vários avisos, mas deseja ser seletivo.
Tamás Szelei 25/03

1
Como você é capaz de usar -Waggregate-return? Isso me dá um aviso para cada uso debegin/end()
Flamefire

12

Alguns deles já estão incluídos no -Wallou -Wextra.

Uma boa configuração básica para C é:

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

e para C ++

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

(pulando -Werrorpara C ++, pois -Weffc++tem alguns aborrecimentos)


10
-Werror pode ser desativado para tipos específicos de avisos, por exemplo: -Werror -Weffc ++ -Wno-error = EFFC ++
Robert Hensing

2
ansi : No modo C, isso é equivalente a -std=c89. No modo C ++, é equivalente a -std=c++98. ou seja, se você está especificando algum outro std, o uso não façaansi
Sean Breckenridge

2

Experimentar

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

É um começo rápido e sujo, que definitivamente precisará de alguns ajustes; por um lado, mesmo se você chamar o compilador pelo nome apropriado para o seu idioma (por exemplo, g++para C ++), você receberá avisos que não se aplicam a esse idioma (e o compilador levantará as mãos e se recusará a continuar até que você remova o aviso).

Outra coisa é que eu adicionei -Werror, porque se você não está corrigindo os avisos, por que se importa em ativá-los? Você também pode retirar avisos da lista. (Por exemplo, quase nunca uso -Waggregate-returncom C ++.)

Alguns avisos não farão nada sem outras opções relacionadas ao desempenho ( -Wstack-protector). -fdiagnostics-show-optione o manual do GCC são seus amigos.

A propósito, alguns avisos são mutuamente exclusivos; em particular, usando -Wtraditionale -Wold-style-definitionjunto com -Werror, não será compilado.


0

Em CmakeLists.txt do meu Clion

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)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.