Eu sei que a pergunta é sobre o GCC, mas para pessoas que procuram como fazer isso em outros e / ou vários compiladores ...
TL; DR
Você pode dar uma olhada no Hedley , que é um cabeçalho C / C ++ de domínio público que escrevi, que faz muitas dessas coisas para você. Vou colocar uma seção rápida sobre como usar o Hedley para tudo isso no final deste post.
Desativando o aviso
#pragma warning (disable: …)
possui equivalentes na maioria dos compiladores:
- MSVC:
#pragma warning(disable:4996)
- GCC:
#pragma GCC diagnostic ignored "-W…"
onde as reticências são o nome do aviso; por exemplo , #pragma GCC diagnostic ignored "-Wdeprecated-declarations
.
- clang:
#pragma clang diagnostic ignored "-W…"
. A sintaxe é basicamente a mesma que a do GCC, e muitos dos nomes de aviso são os mesmos (embora muitos não sejam).
- Compilador Intel C: use a sintaxe MSVC, mas lembre-se de que os números de aviso são totalmente diferentes. Exemplo:
#pragma warning(disable:1478 1786)
.
- IGP: Existe um
diag_suppress
pragma:#pragma diag_suppress 1215,1444
- TI: Existe uma
diag_suppress
pragma com a mesma sintaxe (mas com números de aviso diferentes!) Da IGP:pragma diag_suppress 1291,1718
- Oracle Developer Studio (suncc): existe um
error_messages
pragma. Irritantemente, os avisos são diferentes para os compiladores C e C ++. Ambos desabilitam basicamente os mesmos avisos:
- C:
#pragma error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)
- C ++:
#pragma error_messages(off,symdeprecated,symdeprecated2)
- IAR: também usa
diag_suppress
como IGP e TI, mas a sintaxe é diferente. Alguns dos números de aviso são os mesmos, mas eu outros divergimos:#pragma diag_suppress=Pe1444,Pe1215
- Pelles C: semelhante ao MSVC, embora novamente os números sejam diferentes
#pragma warn(disable:2241)
Para a maioria dos compiladores, geralmente é uma boa ideia verificar a versão do compilador antes de tentar desabilitá-la; caso contrário, você acabará acionando outro aviso. Por exemplo, o GCC 7 adicionou suporte ao -Wimplicit-fallthrough
aviso, portanto, se você se importa com o GCC antes do 7, deve fazer algo como
#if defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
Para clang e compiladores baseados em clang, como nas versões mais recentes do XL C / C ++ e armclang, você pode verificar se o compilador conhece um aviso específico usando a __has_warning()
macro.
#if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif
Claro que você também precisa verificar se a __has_warning()
macro existe:
#if defined(__has_warning)
# if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
# endif
#endif
Você pode ficar tentado a fazer algo como
#if !defined(__has_warning)
# define __has_warning(warning)
#endif
Então você pode usar __has_warning
um pouco mais facilmente. Clang até sugere algo semelhante para a __has_builtin()
macro em seu manual. Não faça isso . Outro código pode procurar __has_warning
e recorrer à verificação de versões do compilador, se não existir, e se você definir, __has_warning
quebrará o código. A maneira correta de fazer isso é criar uma macro no seu espaço para nome. Por exemplo:
#if defined(__has_warning)
# define MY_HAS_WARNING(warning) __has_warning(warning)
#else
# define MY_HAS_WARNING(warning) (0)
#endif
Então você pode fazer coisas como
#if MY_HAS_WARNING(warning)
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#elif defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
Empurrando e estourando
Muitos compiladores também oferecem suporte a uma maneira de enviar e enviar avisos para uma pilha. Por exemplo, isso desativará um aviso no GCC para uma linha de código e retornará ao estado anterior:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
call_deprecated_function();
#pragma GCC diagnostic pop
É claro que não há muito acordo entre os compiladores sobre a sintaxe:
- GCC 4.6+:
#pragma GCC diagnostic push
/#pragma GCC diagnostic pop
- clang:
#pragma clang diagnostic push
/#pragma diagnostic pop
- Intel 13+ (e provavelmente anterior):
#pragma warning(push)
/#pragma warning(pop)
- MSVC 15+ (VS 9.0 / 2008):
#pragma warning(push)
/#pragma warning(pop)
- BRAÇO 5.6+:
#pragma push
/#pragma pop
- TI 8.1+:
#pragma diag_push
/#pragma diag_pop
- Pelles C 2.90+ (e provavelmente anterior):
#pragma warning(push)
/#pragma warning(pop)
Se a memória serve, para algumas versões muito antigas do GCC (como 3.x, IIRC), os pragmas push / pop precisavam estar fora da função.
Escondendo os detalhes sangrentos
Para a maioria dos compiladores, é possível ocultar a lógica por trás das macros usando _Pragma
, introduzida no C99. Mesmo no modo não C99, a maioria dos compiladores suporta _Pragma
; a grande exceção é o MSVC, que possui sua própria __pragma
palavra-chave com uma sintaxe diferente. O padrão _Pragma
usa uma string, a versão da Microsoft não:
#if defined(_MSC_VER)
# define PRAGMA_FOO __pragma(foo)
#else
# define PRAGMA_FOO _Pragma("foo")
#endif
PRAGMA_FOO
É aproximadamente equivalente, uma vez pré-processado, a
#pragma foo
Isso nos permite criar macros para escrever código como
MY_DIAGNOSTIC_PUSH
MY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated_function();
MY_DIAGNOSTIC_POP
E esconda todas as verificações feias das versões nas definições de macro.
O caminho mais fácil: Hedley
Agora que você entende a mecânica de como fazer coisas assim de maneira portável, mantendo seu código limpo, entende o que um dos meus projetos, Hedley faz. Em vez de vasculhar toneladas de documentação e / ou instalar o maior número possível de compiladores para testar, basta incluir o Hedley (é um cabeçalho C / C ++ de domínio público) e pronto. Por exemplo:
#include "hedley.h"
HEDLEY_DIAGNOSTIC_PUSH
HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated();
HEDLEY_DIAGNOSTIC_POP
Desabilitará o aviso sobre a chamada de uma função obsoleta no GCC, clang, ICC, PGI, MSVC, TI, IAR, ODS, Pelles e possivelmente outras (provavelmente não me incomodarei em atualizar esta resposta ao atualizar o Hedley). E, nos compiladores que não são conhecidos por funcionar, as macros serão pré-processadas para nada, portanto, seu código continuará funcionando com qualquer compilador. É claro que esse HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
não é o único aviso que Hedley conhece, nem os avisos desabilitadores que Hedley pode fazer, mas espero que você entenda.