c++ - GCC no respeta el ''diagnóstico pragma GCC'' para silenciar las advertencias
openmp compiler-warnings (1)
Recientemente habilitamos -Wall
para un proyecto. Se habilita cuando GCC está en 4.7 o superior (o Clang) porque podemos usar el GCC diagnostic
para administrar la salida de las advertencias elevadas. Queremos gestionarlos desde el código fuente, y no a través de argumentos de línea de comandos. (No queremos contaminar la línea de comandos o pedir a los usuarios de la biblioteca que redescubran lo que se necesita).
Bajo GCC 4.8 y 5.1, estamos detectando advertencias que se deshabilitaron en un bloque de diagnóstico GCC para -Wunused-variable
, -Wunused-value
, -Wunused-function
y -Wunknown-pragmas
. Ambos GCC aceptan -fopenmp
, y ambos definen _OPENMP
en respuesta a él, así que estoy bastante seguro de que nunca deberíamos ver un -Wunknown-pragmas
en respuesta a #prgam omp ...
( está deshabilitado, pero no es desconocido ).
g++ -DNDEBUG -g2 -O3 -Wall -march=native -pipe -c nbtheory.cpp
nbtheory.cpp:655:0: warning: ignoring #pragma omp parallel [-Wunknown-pragmas]
#pragma omp parallel
^
nbtheory.cpp:656:0: warning: ignoring #pragma omp sections [-Wunknown-pragmas]
#pragma omp sections
^
...
En este caso particular, el archivo nbtheroy.cpp
tiene la siguiente protección para ayudar a administrar esa advertencia (solo se muestran las partes relevantes, pero se puede ver todo desde el enlace de GitHub ):
// Defines GCC_DIAGNOSTIC_AWARE if GCC 4.7 or above.
#include <misc.h>
...
#if GCC_DIAGNOSTIC_AWARE
# pragma GCC diagnostic ignored "-Wunknown-pragmas"
#endif
...
Integer ModularRoot(const Integer &a, const Integer &dp, const Integer &dq,
const Integer &p, const Integer &q, const Integer &u)
{
Integer p2, q2;
#pragma omp parallel
#pragma omp sections
{
#pragma omp section
p2 = ModularExponentiation((a % p), dp, p);
#pragma omp section
q2 = ModularExponentiation((a % q), dq, q);
}
return CRT(p2, p, q2, q, u);
}
...
Debido a que el archivo es *.cpp
(en realidad es la unidad de traducción), no realizamos un #pragma GCC diagnostic push
al principio y un #pragma GCC diagnostic pop
al final. (Lo hacemos para los archivos de encabezado que se incluyen, sin embargo). (También intentamos hacerlo, pero no ayudó).
Y aquí está GCC_DIAGNOSTIC_AWARE
(de misc.h
):
// Used to suppress some warnings in some header and implementation files.
// Some platforms, like CentOS and OpenBSD, use old compilers that don''t understand -Wno-unknown-pragma.
#define GCC_DIAGNOSTIC_AWARE ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) || defined(__clang__))
Sé que la guarda está funcionando porque agregar un #error
error en el bloque causa un error. Además, comentar al guardia y llamar a #pragma GCC diagnostic ignored "-Wunknown-pragmas"
no ayuda. Por último, funciona bien bajo Clang.
También lo estoy experimentando para otras advertencias, como -Wunused-variable
, -Wunused-value
y -Wunused-function
. Realmente no quiero contaminar la línea de comandos como se sugiere con el posible duplicado.
¿Cómo puedo hacer que el mecanismo de GCC pragma diagnostic
funcione como se espera para silenciar las advertencias bajo GCC cuando se usa -Wall
?
Relacionado, si desea reproducirlo (está basado en GNUmakefile y no requiere configuraciones o autotools):
git clone https://github.com/weidai11/cryptopp.git cryptopp-warn
cd cryptopp-warn
make
EDITAR : hemos registrado un parche que desactiva -Wall
excepto para Clang. Si quieres reproducir el comportamiento anterior, entonces:
git clone https://github.com/weidai11/cryptopp.git cryptopp-warn
cd cryptopp-warn
export CXXFLAGS="-g2 -O3 -DNDEBUG -Wall"
make
Esto parece ser un error en gcc
al menos. El siguiente código:
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wuninitialized"
int fn(void) {
#pragma xyzzy
int x;
return x;
}
int main (void) {
return fn();
}
no tiene problemas para ignorar el valor de x
no inicializado pero aún se queja sobre el pragma (sin el pragma uninitialized
, genera una advertencia para x
como cabría esperar).
Si cambia las opciones de la línea de comandos para que sean -Wall -Wno-unknown-pragmas
, entonces lo ignora muy bien. Eso está bien para su caso específico, ya que desea que se aplique a toda su unidad de traducción, pero no permitirá el control detallado que obtendría del método #pragma
(si funcionara).
Fui a plantear un informe de error en GCC pero encontré que ya existe ( #53431 ).
Si bien ese error específico tiene que ver con -Wundef
, un fragmento de uno de los comentarios indica que probablemente se aplique a todas las variantes que afectan al preprocesador (ligeramente modificado para dar énfasis):
El analizador de C ++ lexes ( y preprocesos) antes de manejar los pragmas, mientras que el analizador de C procesa los pragmas a medida que los ve.
De alguna manera debemos analizar estos pragmas también en
cp/parser.c:631
. Tal vez uno pueda hacer algo similar a lo que hacemos paracp_parser_initial_pragma
, pero dentro del bucle y solo manejando el diagnóstico de pragma. Seguramente, necesitará un poco de prueba y error para hacerlo bien. Si alguno de ustedes quiere probarlo y necesita ayuda, solo pregunte aquí o en la lista de correo.
Eso explica por qué no vemos el mismo problema con -Wuninitialized
, porque se detecta durante las etapas posteriores del proceso de compilación, después de que los pragmas se hayan activado al final del preprocesamiento.
Por lo tanto, si desea verlo arreglado de manera más oportuna (se planteó hace más de tres años), sugeriría (como lo he hecho) acosar el sitio de bugzilla de GCC para intentar obtener cierta exposición.