En Visual C++, es posible usar #pragma warning (disable: ...)
. También encontré que en GCC puedes anular las banderas del compilador por archivo. ¿Cómo puedo hacer esto para la “siguiente línea”, o con semántica push/pop alrededor de áreas de código usando GCC?
Cómo deshabilitar las advertencias de GCC para algunas líneas de código
carpintero mate
carpintero mate
parece esto se puede hacer. No puedo determinar la versión de GCC que se agregó, pero fue en algún momento antes de junio de 2010.
Aquí hay un ejemplo:
#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 */
-
uno
push
y dospop
s – puede ser otropush
al principio falta?– abismo.7
17 de noviembre de 2012 a las 14:03
-
“#pragma GCC push de diagnóstico #pragma GCC pop de diagnóstico Hace que GCC recuerde el estado de los diagnósticos en cada pulsación y restaure a ese punto en cada pulsación. Si una pulsación no coincide con la pulsación, se restauran las opciones de la línea de comandos. ” — del manual de GCC: gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
– bobpaul
11 de enero de 2013 a las 18:43
-
Como referencia, la versión 4.4.3 de gcc admite error/advertencia/ignorado, pero no push/pop
– Frankster
12 de febrero de 2013 a las 14:21
-
La primera versión de GCC que tenía push/pop de diagnóstico es CCG 4.6.4. Lo determiné mirando la sección Diagnostic-Pragmas.html#Diagnostic-Pragmas para cada versión de GCC en Documentación del CCG
– Alex Bitek
20 de agosto de 2014 a las 15:48
-
Es una pena que esto no funcione en la práctica. En algunos casos, produce más advertencias. O tal vez, más correctamente, no funciona en la práctica para GCC 4.7 a 5.1. Véase, por ejemplo, GCC no respeta el ‘diagnóstico pragma GCC’ para silenciar las advertencias.
– jww
20 de julio de 2015 a las 7:05
Ian Pillcher
Para liquidar todo, este es un ejemplo de temporalmente deshabilitar una advertencia:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
write(foo, bar, baz);
#pragma GCC diagnostic pop
Puedes comprobar el Documentación de GCC sobre pragmas de diagnóstico para más detalles.
-
Debería funcionar, pero mi
gcc-4.9
simplemente ignora esta línea por completo.– Alekséi Petrenko
18 de septiembre de 2017 a las 13:42
cristian hujer
TL;RD: si funciona, evítelo o use especificadores como __attribute__
de lo contrario _Pragma
.
Esta es una versión corta del artículo de mi blog.
Supresión de advertencias en GCC y Clang.
Considera lo siguiente Makefile
,
CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror
.PHONY: all
all: puts
para construir lo siguiente puts.c
código fuente:
#include <stdio.h>
int main(int argc, const char *argv[])
{
while (*++argv)
puts(*argv);
return 0;
}
No compilará porque argc
no se usa, y la configuración es extrema (-W -Wall -pedantic -Werror
).
Hay cinco cosas que podrías hacer:
- Mejorar el código fuente, si es posible.
- Use un especificador de declaración, como
__attribute__
- Usar
_Pragma
- Usar
#pragma
- Utilice una opción de línea de comandos.
Mejorando la fuente
El primer intento debe ser verificar si el código fuente se puede mejorar para eliminar la advertencia. En este caso no queremos cambiar el algoritmo solo por eso, ya que argc
es redundante con !*argv
(NULL
después del último elemento).
Usando un especificador de declaración, como __attribute__
#include <stdio.h>
int main(__attribute__((unused)) int argc, const char *argv[])
{
while (*++argv) puts(*argv);
return 0;
}
Si tiene suerte, el estándar proporciona un especificador para su situación, como _Noreturn
.
__attribute__
es una extensión GCC propietaria (compatible con Clang y algunos otros compiladores como armcc
también) y no será entendido por muchos otros compiladores. Poner __attribute__((unused))
dentro de una macro si quieres un código portátil.
_Pragma
operador
_Pragma
se puede utilizar como alternativa a #pragma
.
#include <stdio.h>
_Pragma("GCC diagnostic push")
_Pragma("GCC diagnostic ignored \"-Wunused-parameter\"")
int main(int argc, const char *argv[])
{
while (*++argv)
puts(*argv);
return 0;
}
_Pragma("GCC diagnostic pop")
La principal ventaja de la _Pragma
operador es que podría ponerlo dentro de macros, lo cual no es posible con el #pragma
directiva.
Desventaja: es casi una bomba nuclear táctica, ya que funciona basado en líneas en lugar de en declaraciones.
Él _Pragma
El operador fue introducido en C99.
#pragma
directiva.
Podríamos cambiar el código fuente para suprimir la advertencia de una región de código, normalmente una función completa:
#include <stdio.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
int main(int argc, const char *argv[])
{
while (*++argc) puts(*argv);
return 0;
}
#pragma GCC diagnostic pop
Desventaja: es casi una bomba nuclear táctica, ya que funciona basado en líneas en lugar de en declaraciones.
Tenga en cuenta que existe una sintaxis similar en Clang.
Supresión de la advertencia en la línea de comando para un solo archivo
Podríamos agregar la siguiente línea al Makefile
para suprimir la advertencia específicamente para puts:
CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror
.PHONY: all
all: puts
puts.o: CPPFLAGS+=-Wno-unused-parameter
Probablemente esto no sea lo que usted quiere en su caso particular, pero puede ayudar a otros lectores que se encuentran en situaciones similares.
-
re:
improving the source
también funcionaría cambiar la declaración de main aint main(int, const char* argv[]) { ... }
al no darle un nombre al argumento, le dice al compilador que no se usará.– Jesse Chisholm
09/08/2018 a las 18:05
-
@JesseChisholm no es posible omitir el nombre del parámetro en la definición de la función. Ver 6.9.1 Definiciones de funciones de ISO/IEC9899, §5 “Si el declarador incluye una lista de tipos de parámetros, la declaración de cada parámetro debe incluir un identificador […]” Y correctamente por lo que el código sería rechazado por
gcc
así comoclang
.– Christian Hujer
29 de noviembre de 2018 a las 17:33
-
Otro patrón es simplemente hacer una conversión de la variable a anular. De hecho, he visto en un proyecto la siguiente macro:
#define UNUSED(x) ((void)x)
utilizado para silenciar las advertencias. Creo que fue en ReactOS?–Paul Stelian
13 de abril de 2019 a las 15:11
-
Ellos camino
__attribute__
la sintaxis funciona, utiliza inteligentemente paréntesis dobles((
))
entonces, si su compilador no lo entiende, puede#define __attribute__(x)
y todos desaparecen.– doug65536
15 de junio de 2021 a las 4:14
nemequ
Sé que la pregunta es sobre GCC, pero para las personas que buscan cómo hacer esto en otros y/o múltiples compiladores…
TL;RD
Es posible que desee echar un vistazo a Hedleyque es un encabezado C/C++ único de dominio público que escribí y que hace un lote de estas cosas para ti. 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 los puntos suspensivos son el nombre de la advertencia; p.ej,#pragma GCC diagnostic ignored "-Wdeprecated-declarations
. - Sonido metálico:
#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++ (ICC): use la sintaxis de MSVC, pero tenga en cuenta que los números de advertencia son totalmente diferentes. Ejemplo:
#pragma warning(disable:1478 1786)
. - IGP/Nvidia: Hay un
diag_suppress
pragma:#pragma diag_suppress 1215,1444
. Tenga en cuenta que todos los números de advertencia aumentaron en uno en 20.7 (la primera Nvidia HPC liberación). - TI (CCS): Hay un
diag_suppress
pragma con la misma sintaxis (pero diferentes números de advertencia) como PGI:pragma diag_suppress 1291,1718
- Estudio para desarrolladores de Oracle (ODS) (suncc): hay un
error_messages
pragma. Curiosamente, las advertencias son diferentes para los compiladores de 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)
- C:
- IAR: también utiliza
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 deshabilitarlo, de lo contrario, terminará activando otra advertencia. Por ejemplo, GCC 7 agregó soporte para el -Wimplicit-fallthrough
advertencia, por lo que si te preocupa GCC antes de las 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 versiones más nuevas de XLC/C++ y armclang, puede verificar si el compilador conoce una advertencia en particular usando el __has_warning()
macro.
#if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif
Por supuesto, también hay que comprobar si el __has_warning()
macro existe:
#if defined(__has_warning)
# if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
# endif
#endif
Usted puede estar tentado a hacer algo como
#if !defined(__has_warning)
# define __has_warning(warning)
#endif
Entonces puedes usar __has_warning
un poco más fácilmente. Clang incluso sugiere algo similar para el __has_builtin()
macro en su manual. No hagas esto. Otro código puede verificar __has_warning
y recurra a verificar las versiones del compilador si no existe, y si define __has_warning
Romperás 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 insertar y mostrar advertencias en una pila. Por ejemplo, esto deshabilitará una advertencia en GCC para una línea de código y 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:
- CCG 4.6+:
#pragma GCC diagnostic push
/#pragma GCC diagnostic pop
- Sonido metálico:
#pragma clang diagnostic push
/#pragma diagnostic pop
- Intel 13+ (y probablemente antes):
#pragma warning(push)
/#pragma warning(pop)
- MSVC 15+ (Estudio visual 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 no me falla, para algunas versiones muy antiguas de GCC (como 3.x, IIRC) los pragmas push/pop tenían que ser fuera de la función
Ocultar los detalles sangrientos
Para la mayoría de los compiladores, es posible ocultar la lógica detrás de las macros usando _Pragma
que se introdujo en C99. Incluso en modo no C99, la mayoría de los compiladores admiten _Pragma
; la gran excepción es MSVC, que tiene su propio __pragma
palabra clave con una sintaxis diferente. El estandar _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 más o menos 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 oculte todas las comprobaciones de versión 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 su código limpio, comprende cuál de mis proyectos, Hedley hace. En lugar de buscar en toneladas de documentación y/o instalar tantas versiones de tantos compiladores como pueda para probar, puede simplemente incluir Hedley (es un solo encabezado C/C++ de dominio público) y listo. Por ejemplo:
#include "hedley.h"
HEDLEY_DIAGNOSTIC_PUSH
HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated();
HEDLEY_DIAGNOSTIC_POP
Deshabilitará la advertencia sobre llamar a una función obsoleta en GCC, Clang, ICC, PGI, MSVC, TI, IAR, ODS, Pelles C y posiblemente otros (probablemente no me molestaré en actualizar esta respuesta mientras actualizo a Hedley). Y, en los compiladores que no se sabe que funcionan, las macros se preprocesarán hasta quedar en nada, por lo que su código seguirá funcionando con cualquier compilador. Por supuesto HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
no es la única advertencia que conoce Hedley, ni tampoco desactivar las advertencias es todo lo que Hedley puede hacer, pero espero que entiendas la idea.
Martín Gerhardy
Usar:
#define DIAG_STR(s) #s
#define DIAG_JOINSTR(x,y) DIAG_STR(x ## y)
#ifdef _MSC_VER
#define DIAG_DO_PRAGMA(x) __pragma (#x)
#define DIAG_PRAGMA(compiler,x) DIAG_DO_PRAGMA(warning(x))
#else
#define DIAG_DO_PRAGMA(x) _Pragma (#x)
#define DIAG_PRAGMA(compiler,x) DIAG_DO_PRAGMA(compiler diagnostic x)
#endif
#if defined(__clang__)
# define DISABLE_WARNING(gcc_unused,clang_option,msvc_unused) DIAG_PRAGMA(clang,push) DIAG_PRAGMA(clang,ignored DIAG_JOINSTR(-W,clang_option))
# define ENABLE_WARNING(gcc_unused,clang_option,msvc_unused) DIAG_PRAGMA(clang,pop)
#elif defined(_MSC_VER)
# define DISABLE_WARNING(gcc_unused,clang_unused,msvc_errorcode) DIAG_PRAGMA(msvc,push) DIAG_DO_PRAGMA(warning(disable:##msvc_errorcode))
# define ENABLE_WARNING(gcc_unused,clang_unused,msvc_errorcode) DIAG_PRAGMA(msvc,pop)
#elif defined(__GNUC__)
#if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406
# define DISABLE_WARNING(gcc_option,clang_unused,msvc_unused) DIAG_PRAGMA(GCC,push) DIAG_PRAGMA(GCC,ignored DIAG_JOINSTR(-W,gcc_option))
# define ENABLE_WARNING(gcc_option,clang_unused,msvc_unused) DIAG_PRAGMA(GCC,pop)
#else
# define DISABLE_WARNING(gcc_option,clang_unused,msvc_unused) DIAG_PRAGMA(GCC,ignored DIAG_JOINSTR(-W,gcc_option))
# define ENABLE_WARNING(gcc_option,clang_option,msvc_unused) DIAG_PRAGMA(GCC,warning DIAG_JOINSTR(-W,gcc_option))
#endif
#endif
Esto debería hacer el truco para GCC, Sonido metálico y MSVC.
Se puede llamar con, por ejemplo:
DISABLE_WARNING(unused-variable,unused-variable,42)
[.... some code with warnings in here ....]
ENABLE_WARNING(unused-variable,unused-variable,42)
Ver 7 pragmas, Control de diagnósticos a través de Pragmas y Directivas pragma y las palabras clave __pragma y _Pragma para más detalles.
Necesita al menos la versión 4.02 para usar este tipo de pragmas para GCC, y no estoy seguro acerca de MSVC y Clang acerca de las versiones.
Parece que el manejo de pragma push pop para GCC está un poco roto. Si habilita la advertencia nuevamente, seguirá recibiendo la advertencia para el bloque que estaba dentro del bloque DISABLE_WARNING/ENABLE_WARNING. Para algunas versiones de GCC funciona y para otras no.
jose d
#pragma GCC diagnostic ignored "-Wformat"
Reemplace “-Wformat” con el nombre de su bandera de advertencia.
AFAIK no hay forma de usar la semántica push/pop para esta opción.
Pedro Mortensen
Tuve el mismo problema con bibliotecas externas como ROS encabezados Me gusta usar las siguientes opciones en CMakeLists.txt para una compilación más estricta:
set(CMAKE_CXX_FLAGS "-std=c++0x -Wall -Wextra -Wstrict-aliasing -pedantic -Werror -Wunreachable-code ${CMAKE_CXX_FLAGS}")
Sin embargo, hacer esto también provoca todo tipo de errores pedantes en las bibliotecas incluidas externamente. La solución es deshabilitar todas las advertencias pedantes antes de incluir bibliotecas externas y volver a habilitarlas de esta manera:
// Save compiler switches
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
// Bad headers with a problem goes here
#include <ros/ros.h>
#include <sensor_msgs/LaserScan.h>
// Restore compiler switches
#pragma GCC diagnostic pop
-
¿No debería ser mejor manejar esto con gcc’s? sistema directorios?
– Rojo XIII
17 de enero de 2017 a las 10:19
-
@RedXIII: sí, esa es una opción si puede hacer una lista de dichos directorios y especificarlos en la línea de comandos de gcc. Sin embargo, muchas veces se invoca al compilador en lo profundo de la canalización o no tiene mucho control sobre cómo otra persona debe compilar su código. En los casos anteriores es probablemente una mejor solución.
– Shital Shah
2 de diciembre de 2019 a las 11:15
posible duplicado de deshabilitar advertencias específicas en gcc – Ups, en realidad esa pregunta en sí es un engaño (pero no cerrada). Resulta que ese es el que apareció en “Relacionado”. De todos modos, esto se ha preguntado y respondido varias veces en SO.
– Tyler McHenry
31 de julio de 2010 a las 14:49
@paxdiablo: Estoy haciendo lo contrario. He aumentado el nivel de advertencia muy alto y quiero aplastar las advertencias línea por línea que he verificado que están bien.
– Matt Carpintero
31 de julio de 2010 a las 16:28
@Tyler McHenry: si revisó con más cuidado, puede notar que la pregunta vinculada contiene una solución por archivo, precisamente la que mencioné en mi propia pregunta como insatisfactoria (incluso robé el enlace).
– Matt Carpintero
31 de julio de 2010 a las 16:30
@paxdiablo, los compiladores dan falsos positivos, a veces desea compilar con -Werror pero que estos falsos positivos no bloqueen una compilación. por lo tanto, deshabilitar casos específicos y comentar por qué, tiene sentido en algunos casos. También hay otros casos en los que esto podría ser útil, como el código de generación automática que produce advertencias inofensivas que no son tan fáciles de ingresar y cambiar (ya que se genera el código), aunque en ese caso es más probable que deshabilitar por archivo la solución.
– ideasman42
4 de noviembre de 2012 a las 6:56