Sé que la pregunta es sobre GCC, pero para las personas que buscan cómo hacer esto en otros y / o compiladores múltiples ...
TL; DR
Es posible que desee echar un vistazo a Hedley , que es un encabezado C / C ++ de dominio público que escribí y que hace muchas de estas cosas por usted. Pondré una sección rápida sobre cómo usar Hedley para todo esto al final de esta publicación.
Deshabilitar la advertencia
#pragma warning (disable: …)
tiene equivalentes en la mayoría de los compiladores:
- MSVC:
#pragma warning(disable:4996)
- CCG:
#pragma GCC diagnostic ignored "-W…"
donde la elipsis es el nombre de la advertencia; por ejemplo , #pragma GCC diagnostic ignored "-Wdeprecated-declarations
.
- tañido:
#pragma clang diagnostic ignored "-W…"
. La sintaxis es básicamente la misma que la de GCC y muchos de los nombres de advertencia son los mismos (aunque muchos no lo son).
- Compilador Intel C: use la sintaxis MSVC, pero tenga en cuenta que los números de advertencia son totalmente diferentes. Ejemplo:
#pragma warning(disable:1478 1786)
.
- PGI: Hay un
diag_suppress
pragma:#pragma diag_suppress 1215,1444
- TI: Hay un
diag_suppress
pragma con la misma sintaxis (¡pero diferentes números de advertencia!) Que PGI:pragma diag_suppress 1291,1718
- Oracle Developer Studio (suncc): hay un
error_messages
pragma. Molesto, las advertencias son diferentes para los compiladores C y C ++. Ambos deshabilitan básicamente las mismas advertencias:
- C:
#pragma error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)
- C ++:
#pragma error_messages(off,symdeprecated,symdeprecated2)
- IAR: también se usa
diag_suppress
como PGI y TI, pero la sintaxis es diferente. Algunos de los números de advertencia son los mismos, pero otros han divergido:#pragma diag_suppress=Pe1444,Pe1215
- Pelles C: similar a MSVC, aunque nuevamente los números son diferentes
#pragma warn(disable:2241)
Para la mayoría de los compiladores, a menudo es una buena idea verificar la versión del compilador antes de intentar deshabilitarla, de lo contrario, terminará activando otra advertencia. Por ejemplo, GCC 7 agregó soporte para la -Wimplicit-fallthrough
advertencia, así que si te importa GCC antes de 7 deberías hacer algo como
#if defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
Para clang y compiladores basados en clang, como las versiones más nuevas de XL C / C ++ y armclang, puede verificar si el compilador conoce una advertencia particular utilizando la __has_warning()
macro.
#if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif
Por supuesto, también debe verificar si __has_warning()
existe la macro:
#if defined(__has_warning)
# if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
# endif
#endif
Puede sentirse tentado a hacer algo como
#if !defined(__has_warning)
# define __has_warning(warning)
#endif
Para que pueda usar __has_warning
un poco más fácilmente. Clang incluso sugiere algo similar para la __has_builtin()
macro en su manual. No hagas esto . Otro código puede verificar __has_warning
y recurrir a verificar las versiones del compilador si no existe, y si usted define __has_warning
, romperá su código. La forma correcta de hacer esto es crear una macro en su espacio de nombres. Por ejemplo:
#if defined(__has_warning)
# define MY_HAS_WARNING(warning) __has_warning(warning)
#else
# define MY_HAS_WARNING(warning) (0)
#endif
Entonces puedes hacer cosas como
#if MY_HAS_WARNING(warning)
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#elif defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
Empujando y haciendo estallar
Muchos compiladores también admiten una forma de enviar y desplegar advertencias en una pila. Por ejemplo, esto deshabilitará una advertencia en GCC para una línea de código, luego la devolverá a su estado anterior:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
call_deprecated_function();
#pragma GCC diagnostic pop
Por supuesto, no hay mucho acuerdo entre los compiladores sobre la sintaxis:
- GCC 4.6+:
#pragma GCC diagnostic push
/#pragma GCC diagnostic pop
- Clang:
#pragma clang diagnostic push
/#pragma diagnostic pop
- Intel 13+ (y probablemente anterior):
#pragma warning(push)
/#pragma warning(pop)
- MSVC 15+ (VS 9.0 / 2008):
#pragma warning(push)
/#pragma warning(pop)
- BRAZO 5.6+:
#pragma push
/#pragma pop
- TI 8.1+:
#pragma diag_push
/#pragma diag_pop
- Pelles C 2.90+ (y probablemente antes):
#pragma warning(push)
/#pragma warning(pop)
Si la memoria funciona, para algunas versiones muy antiguas de GCC (como 3.x, IIRC), los pragmas push / pop tenían que estar fuera de la función.
Ocultando los detalles sangrientos
Para la mayoría de los compiladores es posible ocultar la lógica detrás del uso de macros _Pragma
, que se introdujo en C99. Incluso en modo no C99, la mayoría de los compiladores son compatibles _Pragma
; La gran excepción es MSVC, que tiene su propia __pragma
palabra clave con una sintaxis diferente. El estándar _Pragma
toma una cadena, la versión de Microsoft no:
#if defined(_MSC_VER)
# define PRAGMA_FOO __pragma(foo)
#else
# define PRAGMA_FOO _Pragma("foo")
#endif
PRAGMA_FOO
Es aproximadamente equivalente, una vez preprocesado, a
#pragma foo
Esto nos permite crear macros para que podamos escribir código como
MY_DIAGNOSTIC_PUSH
MY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated_function();
MY_DIAGNOSTIC_POP
Y esconda todas las verificaciones de versiones feas en las definiciones de macro.
La manera fácil: Hedley
Ahora que comprende la mecánica de cómo hacer cosas como esta de forma portátil mientras mantiene limpio su código, comprende lo que hace uno de mis proyectos, Hedley . En lugar de buscar toneladas de documentación y / o instalar tantas versiones de tantos compiladores como pueda probar, puede incluir Hedley (es un encabezado C / C ++ de dominio público único) y listo. Por ejemplo:
#include "hedley.h"
HEDLEY_DIAGNOSTIC_PUSH
HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated();
HEDLEY_DIAGNOSTIC_POP
Deshabilitará la advertencia acerca de llamar a una función obsoleta en GCC, clang, ICC, PGI, MSVC, TI, IAR, ODS, Pelles y posiblemente otras (probablemente no me moleste en actualizar esta respuesta mientras actualizo Hedley). Y, en los compiladores que no se sabe que funcionan, las macros se procesarán previamente a cero, por lo que su código seguirá funcionando con cualquier compilador. Por supuesto, HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
no es la única advertencia que Hedley conoce, ni las advertencias de desactivación son todo lo que Hedley puede hacer, pero espero que entiendas la idea.