c++ gcc openmp compiler-warnings pragma

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 para cp_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.