GCC does not honor 'pragma GCC diagnostic' to silence warnings

jww picture jww · Jul 20, 2015 · Viewed 9.2k times · Source

We recently enabled -Wall for a project. Its enabled when GCC is at 4.7 or above (or Clang) because we can use GCC diagnostic to manage the output from the elevated warnings. We want to manage them from the source code, and not via command line arguments. (We don't want to pollute the command line, or ask library users to rediscover what is needed).

Under GCC 4.8 and 5.1, we are catching warnings that were disabled in a GCC diagnostic block for -Wunused-variable, -Wunused-value, -Wunused-function and -Wunknown-pragmas. Both GCCs accept -fopenmp, and both define _OPENMP in response to it, so I'm fairly certain it we should never see a -Wunknown-pragmas in response to #prgam omp ... (it is disabled, but it is not unknown).

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
 ^
...

In this particular case, the file nbtheroy.cpp has the following guard in place to help manage that warning (only relevant parts are shown, but you can see everything from the GitHub link):

// 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);
}
...

Because the file is *.cpp (its effectively the translation unit), we do not perform a #pragma GCC diagnostic push at the beginning and #pragma GCC diagnostic pop at the end. (We do that for header files that are included, however). (We also tried doing it, but it did not help).

And here is GCC_DIAGNOSTIC_AWARE (from 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__))

I know the guard is working because adding a #error in the block causes an error. Also, commenting out the guard and calling out #pragma GCC diagnostic ignored "-Wunknown-pragmas" does not help. Finally, it works fine under Clang.

I'm also experiencing it for other warnings, like -Wunused-variable, -Wunused-value and -Wunused-function. I really don't want to pollute the command line as suggested with the potential duplicate.

How do I get the GCC pragma diagnostic mechanism to work as expected to silence warnings under GCC when using -Wall?


Related, if you want to reproduce it (its GNUmakefile based, and does not require configurations or autotools):

git clone https://github.com/weidai11/cryptopp.git cryptopp-warn
cd cryptopp-warn
make

EDIT: we checked-in a patch that disables -Wall except for Clang. If you want to reproduce the old behavior, then:

git clone https://github.com/weidai11/cryptopp.git cryptopp-warn
cd cryptopp-warn
export CXXFLAGS="-g2 -O3 -DNDEBUG -Wall"
make

Answer

paxdiablo picture paxdiablo · Jul 20, 2015

This appears to be a bug in gcc at least. The following code:

#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();
}

has no problems ignoring the uninitialised x value but still complains about the pragma (without the uninitialized pragma, it generates a warning for x as you'd expect).

If you change the command line options to be -Wall -Wno-unknown-pragmas, then it ignores it just fine. That's okay for your specific case since you want it applied over your entire translation unit but it won't allow the fine-grained control that you would get from the #pragma method (if it worked).


I went to raise a bug report on GCC but found that it already exists (#53431).

While that specific bug has to do with -Wundef, a snippet in one of the comments indicates that it probably applies to all variants affecting the preprocessor (slightly modified for emphasis):

The C++ parser lexes (and preprocesses) before handling the pragmas, whereas the C parser processes the pragmas as it sees them.

We must somehow parse these pragmas also in cp/parser.c:631. Maybe one can do something similar to what we do for cp_parser_initial_pragma, but within the loop and only handling pragma diagnostic. Surely, it will need some trial and error to get it right. If any of you wants to give it a try and need some help, just ask here or in the mailing list.

That explains why we don't see the same problem with -Wuninitialized, because it's detected during later stages of the compilation process, after the pragmas have been activated at the end of preprocessing.

So, if you want to see it fixed in a more timely manner (it was raised over three years ago), I'd suggest (as I have) hassling the GCC bugzilla site to try get some exposure.