¿Deshabilitar selectivamente las advertencias de GCC solo para una parte de una unidad de traducción?

85

¿Cuál es el equivalente GCC más cercano a este código de preprocesador 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.

Tenemos código en encabezados comúnmente incluidos que no queremos generar una advertencia específica. Sin embargo, queremos que los archivos que incluyen esos encabezados continúen generando esa advertencia (si el proyecto tiene esa advertencia habilitada).

Jon-Eric
fuente
Si los encabezados están instalados en / usr / include o lo que sea, gcc no genera advertencias para ellos de forma predeterminada.
Spudd86

Respuestas:

95

Esto es posible en GCC desde la versión 4.6, o alrededor de junio de 2010 en el tronco.

He aquí un ejemplo:

#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
fuente
8
La funcionalidad push y pop se agregó en gcc 4.6 ( gcc.gnu.org/onlinedocs/gcc-4.6.0/gcc/Diagnostic-Pragmas.html ).
Dave Johansen
Probablemente quieras presionar dos veces si vas a hacer estallar dos veces.
Dan
2
@Dan: Lea el manual y comente. Tenga en cuenta el origen del ejemplo.
Matt Joiner
Para su información, para versiones anteriores como 4.4.7 aún puede usar #pragma GCC diagnostic [error|warning|ignored]pero popno está implementado / es compatible.
Trevor Boyd Smith
36

Lo más parecido es el pragma de diagnóstico GCC , #pragma GCC diagnostic [warning|error|ignored] "-Wwhatever". No está muy cerca de lo que desea, y consulte el enlace para obtener detalles y advertencias.

caos
fuente
1
¿Sabe cuál y dónde podría estar la justificación para no agregar esta función? (No pude encontrarlo). Me parece útil la advertencia push-disable-pop.
1
Realmente no me imagino que "no agregar características" a gcc tiende a tener tanto una justificación como la ausencia de alguien que envíe un parche que funcione.
caos
14
No es que nadie esté dispuesto a hacer el trabajo para este tipo de control de advertencia detallado en gcc, o enviar el código; conozco una corporación importante de Silicon Valley que ya hizo esto, y otra que estaría encantada de pagarle a alguien. para hacerlo y obtener el código en la secuencia. Más bien, según una discusión con un tipo que (como uno de los mantenedores de gdb) está conectado a estas cosas, los mantenedores de gcc tienen una filosofía: "Si hay una advertencia, es un error y necesitas arreglarlo". Entonces (en mi opinión) es un argumento religioso, y controlan el código para ganar.
Bob Murphy
Para agregar al comentario de Bob, los desarrolladores de GCC tienen un historial de desagrado por la #pragmadirectiva, por lo que es más probable que cualquier cosa que sea específica de GCC se implemente como un __attribute__((foo)).
Tom
10
nuevo gcc (> = 4.4) tiene #pragma GCC push_optionspara que pueda jugar con más que solo diagnósticos ... gcc.gnu.org/onlinedocs/gcc/…
Spudd86
33

Yo hice algo similar. Para el código de terceros, no quería ver ninguna advertencia. Entonces, en lugar de especificar -I/path/to/libfoo/include, usé -isystem /path/to/libfoo/include. Esto hace que el compilador trate esos archivos de encabezado como "encabezados del sistema" con el propósito de advertencias, y mientras no los habilite -Wsystem-headers, estará seguro en su mayor parte. Todavía he visto algunas advertencias que se filtran, pero reducen la mayor parte de la basura.

Tenga en cuenta que esto solo le ayudará si puede aislar el código infractor mediante el directorio de inclusión. Si es solo un subconjunto de su propio proyecto, o está mezclado con otro código, no tiene suerte.

Tom
fuente
1
Buen consejo. Si usa LLVM, agregue el indicador -isystem en "Otros indicadores C" en la sección "Compilador LLVM de Apple - Idioma".
Nestor
@Tom Gracias por compartir. No puedo entender dónde usar su solución. ¿Puedes decir un poquito más?
Lorenzo B
1

Esta es una expansión de la respuesta de Matt Joiner .

Si no desea generar pragmas en todo su código, puede usar el 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
fuente