Desativar seletivamente os avisos do GCC para apenas parte de uma unidade de tradução?

85

Qual é o GCC mais próximo equivalente a este código de pré-processador MSVC?

#pragma warning( push )                    // Save the current warning state.
#pragma warning( disable : 4723 )          // C4723: potential divide by 0
// Code which would generate warning 4723.
#pragma warning( pop )                     // Restore warnings to previous state.

Temos código em cabeçalhos comumente incluídos, os quais não queremos gerar um aviso específico. No entanto, queremos que os arquivos que incluem esses cabeçalhos continuem a gerar esse aviso (se o projeto tiver esse aviso habilitado).

Jon-Eric
fonte
Se os cabeçalhos estiverem instalados em / usr / include ou o que for, o gcc não gera avisos para eles por padrão.
Spudd86 de

Respostas:

95

Isso é possível no GCC desde a versão 4.6 ou por volta de junho de 2010 no tronco.

Aqui está um exemplo:

#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wuninitialized"
    foo(a);         /* error is given for this one */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wuninitialized"
    foo(b);         /* no diagnostic for this one */
#pragma GCC diagnostic pop
    foo(c);         /* error is given for this one */
#pragma GCC diagnostic pop
    foo(d);         /* depends on command line options */
Matt Joiner
fonte
8
A funcionalidade push e pop foi adicionada ao gcc 4.6 ( gcc.gnu.org/onlinedocs/gcc-4.6.0/gcc/Diagnostic-Pragmas.html ).
Dave Johansen
Provavelmente, você vai querer empurrar duas vezes se for estourar duas vezes.
Dan de
2
@Dan: Leia o manual e comente. Observe a origem do exemplo.
Matt Joiner
Para sua informação, para versões mais antigas como 4.4.7, você ainda pode usar o, #pragma GCC diagnostic [error|warning|ignored]mas o popnão é implementado / suportado.
Trevor Boyd Smith,
36

A coisa mais próxima é o pragma diagnóstico GCC , #pragma GCC diagnostic [warning|error|ignored] "-Wwhatever". Não está muito perto do que você deseja e consulte o link para obter detalhes e advertências.

caos
fonte
1
Você sabe qual pode ser a razão para não adicionar esse recurso? (Não consegui encontrar.) Acho o aviso push-disable-pop útil.
1
Eu realmente não imagino que "não adicionar recursos" ao gcc tende a ter tanto fundamento quanto a ausência de alguém submetendo um patch de trabalho.
caos de
14
Não é que ninguém esteja disposto a fazer o trabalho para esse tipo de controle de aviso de baixa granularidade no gcc, ou enviar o código - eu conheço uma grande empresa do Vale do Silício que já fez isso e outra que teria o prazer de pagar alguém para fazer isso e colocar o código no fluxo. Em vez disso, por meio de uma discussão com um cara que (como um dos mantenedores do gdb) está conectado a essas coisas, os mantenedores do gcc têm uma filosofia: "Se houver um aviso, é um bug e você precisa corrigi-lo." Então (imo) é um argumento religioso, e eles controlam o código para vencer.
Bob Murphy
Para adicionar ao comentário de Bob, os desenvolvedores do GCC têm um histórico de não gostar da #pragmadiretiva, portanto, qualquer coisa que seja específica do GCC provavelmente será implementada como um __attribute__((foo)).
Tom
10
new gcc (> = 4.4) tem #pragma GCC push_optionspara que você possa mexer com mais do que apenas diagnósticos ... gcc.gnu.org/onlinedocs/gcc/…
Spudd86 de
33

Eu fiz algo semelhante. Para código de terceiros, eu não queria ver nenhum aviso. Então, em vez de especificar -I/path/to/libfoo/include, usei -isystem /path/to/libfoo/include. Isso faz com que o compilador trate esses arquivos de cabeçalho como "cabeçalhos do sistema" para fins de avisos e, desde que você não os habilite -Wsystem-headers, estará seguro. Ainda vi alguns avisos vazarem de lá, mas eliminam a maior parte do lixo.

Observe que isso ajuda se você puder isolar o código ofensivo por diretório de inclusão. Se for apenas um subconjunto do seu próprio projeto, ou misturado com outro código, você está sem sorte.

Tom
fonte
1
Ótima dica. Se estiver usando LLVM, adicione o sinalizador -isystem em "Outros Sinalizadores C" na seção "Compilador Apple LLVM - Linguagem".
Nestor
@Tom Obrigado por compartilhar. Não consigo entender onde usar sua solução. Você pode falar um pouco mais?
Lorenzo B
1

Esta é uma expansão da resposta de Matt Joiner .

Se você não deseja gerar pragmas em todo o seu código, pode usar o operador _Pragma :

#ifdef __GNUC__
#  define DIAGNOSTIC_ERROR(w) _Pragma("GCC diagnostic error \"" w "\"")
#  define DIAGNOSTIC_IGNORE(w) _Pragma("GCC diagnostic ignore \"" w "\"")
#  define DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
#  define DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
#endif
// (...)

DIAGNOSTIC_ERROR("-Wuninitialized")
foo(a); // Error

DIAGNOSTIC_PUSH
DIAGNOSTIC_IGNORE("-Wuninitialized")
foo(a); // No error

DIAGNOSTIC_POP
foo(a); // Error
Cássio Renan
fonte