Bug 53431 - C++ preprocessor ignores #pragma GCC diagnostic
Summary: C++ preprocessor ignores #pragma GCC diagnostic
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.7.0
: P3 minor
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
: 48914 57241 61653 70888 72837 79701 80650 84127 89038 89806 (view as bug list)
Depends on:
Blocks:
 
Reported: 2012-05-21 06:21 UTC by Marco Lattuada
Modified: 2019-11-20 06:26 UTC (History)
11 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-11-16 00:00:00


Attachments
WIP patch (2.74 KB, patch)
2015-06-03 08:27 UTC, Manuel López-Ibáñez
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Marco Lattuada 2012-05-21 06:21:03 UTC
The following code:

#pragma GCC diagnostic ignored "-Wundef"
#if FOO
#endif
int main (void) { return 42; }

compiled with 

g++ -o test test.c -Wundef -Werror

gives:

test.c:2:5: error: "FOO" is not defined [-Werror=undef]
cc1plus: all warnings being treated as errors

On the contrary

gcc -o test test.c -Wundef -Werror

does not give any error
gcc version is
gcc (Debian 4.7.0-8) 4.7.0
Comment 1 George Galeev 2013-02-17 17:04:16 UTC
Same behavior, gcc-4.6.3, Linux gentoo x86-64
Comment 2 Markus F.X.J. Oberhumer 2013-03-03 04:09:42 UTC
Still NOT fixed in gcc-4.8-20130210.
Comment 3 Fabio 2013-07-12 09:20:24 UTC
Same BUG in MinGW (version shipped with the Qt5.1 framework)

> gcc --version
gcc (rev2, Built by MinGW-builds project) 4.8.0
Copyright (C) 2013 Free Software Foundation, Inc.
Comment 4 George Galeev 2013-11-16 18:13:14 UTC
Guys, how to get a look at this bug? I'm tired of reading 100500 warnings from third-party libraries.

GCC-4.6, GCC-4.7, GCC-4.8, C++11
Gentoo Linux x86-64
Comment 5 Manuel López-Ibáñez 2013-11-16 19:51:30 UTC
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.
Comment 6 Manuel López-Ibáñez 2013-11-16 20:22:55 UTC
*** Bug 57241 has been marked as a duplicate of this bug. ***
Comment 7 Manuel López-Ibáñez 2014-07-01 14:13:23 UTC
*** Bug 61653 has been marked as a duplicate of this bug. ***
Comment 8 Manuel López-Ibáñez 2014-09-05 16:59:34 UTC
*** Bug 48914 has been marked as a duplicate of this bug. ***
Comment 9 Manuel López-Ibáñez 2014-09-05 17:42:36 UTC
(In reply to Manuel López-Ibáñez from comment #5)
> 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.

There are two problems that need fixing to implement this:

1. At the point the pragma is lexed we don't know that this is pragma GCC diagnostic, since the pragmas are registered dynamically and there is no (enum pragma_kind) PRAGMA_GCC_DIAGNOSTIC. Perhaps one could do what is done for PRAGMA_GCC_PCH_PREPROCESS.

2. The second problem is that handle_pragma_diagnostic does not work during lexing (at least for C++). We would need to rewrite the whole function and call it directly.
Comment 10 Manuel López-Ibáñez 2015-06-03 08:27:33 UTC
Created attachment 35688 [details]
WIP patch

A WIP patch. I took a different approach: Move the handling of the pragma to the preprocessor. 

It is a bit ugly, but the problem is that we cannot access diagnostic.h and similar headers from the preprocessor. In my ideal world, we would have a libdiagnostic.a that can be linked to the preprocessor and the FEs, and avoid those callbacks (if someone wants to implement a different diagnostic output, they can simply implement a basic libdiagnostic.a).

The main problem I didn't know how to solve is that, once processed, the preprocessor removes the pragmas. Ideally, the pragmas should be evaluated when lexing, independently of whether the file is preprocessed or not. Otherwise, it will break things like ccache.
Comment 11 Allan Chandler 2015-07-20 07:22:11 UTC
http://stackoverflow.com/questions/31509434/gcc-does-not-honor-pragma-gcc-diagnostic-to-silence-warnings

Now you've done it. This was reported over three years ago and now it's affected someone on Stack Overflow. You guys are in for it now :-)
Comment 12 Manuel López-Ibáñez 2015-07-20 09:38:48 UTC
(In reply to Allan Chandler from comment #11)
> Now you've done it. This was reported over three years ago and now it's
> affected someone on Stack Overflow. You guys are in for it now :-)

Unfortunately, the C/C++ FEs in GCC have very very few developers relative to their importance and amount work they require. There is a patch in comment #10, but it requires some additional work for which I do not have enough free time. If you or someone else has some free time to finish this work, this is how I would proceed:

1. Try to figure out why the preprocessor removes the pragmas (and not other #-directives)
2. If you cannot figure it out, ask in gcc@ with explicit CC to C/C++/libcpp maintainers (see MAINTAINERS file).
3. Complete the patch, bootstrap&regression test, add a Changelog, submit to gcc-patches and ping until it is approved.

More details: https://gcc.gnu.org/wiki/GettingStarted#Basics:_Contributing_to_GCC_in_10_easy_steps

Otherwise, given that this hasn't been fixed in more than 4 years (see PR48914), it seems likely that active developers have higher priority things to work on and it will remain unfixed until some new volunteer steps up to the task.

If/When I have a little free time to work on GCC, there are at least a couple of other bugs I would rather fix before this one.
Comment 13 Jeffrey Walton 2015-07-22 00:00:18 UTC
This issued caused Crypto++ to remove -Wall (and above) under GCC. Crypto++ is C++ with lots of interfaces, and it performs a fair amount of intermediate calculations used in an assert. It really needed the following to work as expected:

// GCC diagnostcs available after GCC 4.2 (https://gcc.gnu.org/ml/gcc-help/2015-07/msg00063.html)
#define GCC_DIAGNOSTIC_AWARE ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)) || defined(__clang__))

#if GCC_DIAGNOSTIC_AWARE
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-value"
# pragma GCC diagnostic ignored "-Wunused-variable"
#endif

Crypto++ is fortunate in that its multi-compiler friendly and cross-platform. It can use Clang, ICC, Comeau or, say MSVC with /W4. Other projects are not so lucky. They include Asterisk (the PBX software package). Asterisk uses trampolines, so it cannot compile under Clang. And it never supported MSVC.
Comment 14 Manuel López-Ibáñez 2015-07-22 10:40:14 UTC
(In reply to Jeffrey Walton from comment #13)
> #if GCC_DIAGNOSTIC_AWARE
> # pragma GCC diagnostic push
> # pragma GCC diagnostic ignored "-Wunused-value"
> # pragma GCC diagnostic ignored "-Wunused-variable"
> #endif

As far as I understand, the #pragma should work as expected for those two warnings. Only those warnings given during preprocessing and lexing are affected by this bug.
Comment 15 Jonathan Wakely 2015-07-22 10:51:31 UTC
(In reply to Jeffrey Walton from comment #13)
> This issued caused Crypto++ to remove -Wall (and above) under GCC.

That seems to be throwing the baby out with the bathwater. Why not simply use

 -Wall -Wno-unused-value -Wno-unused-variable

?
Comment 16 Jeffrey Walton 2015-07-22 11:24:01 UTC
(In reply to Jonathan Wakely from comment #15)
> (In reply to Jeffrey Walton from comment #13)
> > This issued caused Crypto++ to remove -Wall (and above) under GCC.
> 
> That seems to be throwing the baby out with the bathwater.

Yeah, for us its a calculated risk. We had other compilers available that worked as expected, so we could lower the bar for GCC. The residual risk is the set of issues GCC will catch minus the set of issues the other compilers will catch. Hopefully, the set is the empty set.

> Why not simply use
> 
>  -Wall -Wno-unused-value -Wno-unused-variable
> 
We don't want to pollute the command line.

All in all, the best solution for us from a usability and engineering standpoint is to have the GCC diagnostic block work as advertised. Then, we manage our warnings in our headers and source code through the GCC block, and they don't cross pollinate into the user's code.

And the users of the library do not need to worry about disabling warnings on the command line. Without GCC diagnostic blocks, users of the library must guess at what needs to be on the command line when compiling and linking against the library. And then they wonder why we did not take the time to clear or silence the warning.
Comment 17 Jeffrey Walton 2015-07-23 10:34:00 UTC
(In reply to Jonathan Wakely from comment #15)
> (In reply to Jeffrey Walton from comment #13)
> > This issued caused Crypto++ to remove -Wall (and above) under GCC.
> 
> That seems to be throwing the baby out with the bathwater. Why not simply use
> 
>  -Wall -Wno-unused-value -Wno-unused-variable
> 

Here's a concrete example that just hit my inbox: https://groups.google.com/d/msg/cryptopp-users/ixwCeessWZ8/xR2eOC3-j0MJ.

Its a user who compiling/linking against the library. We can't control what options he puts on the command line. But he will discuss a noisy compile :)
Comment 18 Jonathan Wakely 2015-07-23 10:47:31 UTC
You can't control what warnings users enable, but that's no reason not to use -Wall -Wno-unused yourself when building cryptopp. Not polluting you command line seems like a weak excuse given the pollution in the code to support compilers from last millennium (which I know you're getting rid of) and the pollution that loads of compiler-specific pragmas cause.

The -Wno-xxx options exist, today, and they work, and even if this bug is fixed it isn't going to be fixed in GCC 4.x or 5.x so the pragmas won't be a complete solution for many years until noone uses today's compilers.

Or you could just change the code causing the warnings.
Comment 19 Manuel López-Ibáñez 2015-07-23 11:32:06 UTC
For what is worth, anyone please feel free to take my WIP patch in comment #10 and get it finished. You may also claim for yourself any bounty or compensation that may derive from it.
Comment 20 Jeffrey Walton 2015-07-23 11:59:25 UTC
(In reply to Manuel López-Ibáñez from comment #19)
> For what is worth, anyone please feel free to take my WIP patch in comment
> #10 and get it finished. You may also claim for yourself any bounty or
> compensation that may derive from it.

Or, let me know where you would like a donation made (I've found the FOSS folks often don't due it for money).
Comment 21 Manuel López-Ibáñez 2015-07-23 13:19:26 UTC
(In reply to Manuel López-Ibáñez from comment #14)
> (In reply to Jeffrey Walton from comment #13)
> > #if GCC_DIAGNOSTIC_AWARE
> > # pragma GCC diagnostic push
> > # pragma GCC diagnostic ignored "-Wunused-value"
> > # pragma GCC diagnostic ignored "-Wunused-variable"
> > #endif
> 
> As far as I understand, the #pragma should work as expected for those two
> warnings. Only those warnings given during preprocessing and lexing are
> affected by this bug.

Now that you posted a complete example here: https://gcc.gnu.org/ml/gcc-help/2015-07/msg00070.html you seem to actually be hitting PR66290, not this one.
Comment 22 Jeffrey Walton 2015-07-23 13:19:57 UTC
(In reply to Jonathan Wakely from comment #18)
> ...
> Or you could just change the code causing the warnings.

Fair enough.

There are two warnings that are big offenders. First is the "unused variable" warning due to a static assert. I asked for help with it at https://gcc.gnu.org/ml/gcc-help/2015-07/msg00070.html.

Second is the "unknown pragma" warning. Here's part of the problem, but I don't expect much to come of it: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53431. Here's another piece of the same problem: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66943.

I really don't understand the 66942 warning since GCC is an OpenMP conforming compiler. '#pragma omp' is known to it in all configurations. The only thing that changes is OMP is "active" when '-fopenmp' is passed on the command line.

Jeff
Comment 23 Manuel López-Ibáñez 2015-07-23 13:20:45 UTC
(In reply to Manuel López-Ibáñez from comment #21)
> Now that you posted a complete example here:
> https://gcc.gnu.org/ml/gcc-help/2015-07/msg00070.html you seem to actually
> be hitting PR66290, not this one.

Sorry, I meant PR64079.
Comment 24 Jeffrey Walton 2015-07-23 13:40:13 UTC
(In reply to Manuel López-Ibáñez from comment #23)
> (In reply to Manuel López-Ibáñez from comment #21)
> > Now that you posted a complete example here:
> > https://gcc.gnu.org/ml/gcc-help/2015-07/msg00070.html you seem to actually
> > be hitting PR66290, not this one.
> 
> Sorry, I meant PR64079.

NP. In that example I posted, I meant GCC_DIAGNOSTIC_AWARE, not GCC_OPTIMIZE_AWARE. Sorry about that.
Comment 25 Jeffrey Walton 2015-07-23 23:26:42 UTC
Jonathan, Manuel, et al -

I'm putting this to bed on our side. We've re-enabled -Wall, and are moving towards -Wextra.

I did come up with one more use case... The "unused parameter" warning. Typically, I just comment it out:

   int Foo(int /*bar*/);

However, when generating documentation from sources, that's not a good strategy. I now see the program omits the parameter altogether from the markup.

In the case of Crypto++, which has a lot of "interface programming" aspects, it makes for a noisy compile as objects are composed and derived. There's often no way to avoid something being unused along the inheritance chain.
Comment 26 Mikhail Maltsev 2015-07-30 17:22:16 UTC
Probably, you could use __attribute__((unused)) as a workaround. Some wrapper macro can make it less verbose, e.g. like here:

https://github.com/gcc-mirror/gcc/blob/master/include/ansidecl.h#L157
https://github.com/gcc-mirror/gcc/blob/master/gcc/c-family/c-common.c#L6980

You can then add "ARG_UNUSED(x)=x" (or "__attribute__(x)=") to PREDEFINED parameter of your doxygen config (you did not mention the documentation system, but doxygen is used on cryptopp.com).

I.e. in your code you'll have:
int Foo(int ARG_UNUSED(bar));

the compiler will see it as:
int Foo(int bar __attribute__((unused)));

and doxygen (and other compilers, if you tweak the macro a bit) as:
int Foo(int bar);
Comment 27 Manuel López-Ibáñez 2016-05-01 19:41:50 UTC
*** Bug 70888 has been marked as a duplicate of this bug. ***
Comment 28 Manuel López-Ibáñez 2016-08-08 19:25:53 UTC
*** Bug 72837 has been marked as a duplicate of this bug. ***
Comment 29 Hamlet 2017-01-08 21:29:04 UTC
For what it's worth, I confirm this (and bug 70888) with gcc 6.3.0 from Gentoo/Linux.
In particular, the following program ("test.cpp"):
    
    #pragma GCC diagnostic ignored "-Wlong-long"
    const unsigned long long int ticks_per_day = 86400000000LL;
    
compiled with `g++-6.3.0 -c -std=c++03 -pedantic -Werror test.cpp` (C++03 standard) issues an error:
    
    test.cpp:2:46: error: use of C++11 long long integer constant [-Werror=long-long]
     const unsigned long long int ticks_per_day = 86400000000LL;
                                              ^~~~~~~~~~~~~
     
about the long long literal value, while it correctly suppresses the one about the variable itself. Skipping the preprocessor (`-fpreprocessed`) does not affect the outcome (the preprocessor correctly leaves the `#pragma` directive untouched anyway). 
Using `-Wno-long-long` in the command line instead works as expected (but it's not a viable solution when dealing with third party libraries).


Info on GCC:

Using built-in specs.
COLLECT_GCC=gcc-6.3.0
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-linux-gnu/6.3.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /var/tmp/portage/sys-devel/gcc-6.3.0/work/gcc-6.3.0/configure --host=x86_64-pc-linux-gnu --build=x86_64-pc-linux-gnu --prefix=/usr --bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/6.3.0 --includedir=/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.0/include --datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/6.3.0 --mandir=/usr/share/gcc-data/x86_64-pc-linux-gnu/6.3.0/man --infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/6.3.0/info --with-gxx-include-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/6.3.0/include/g++-v6 --with-python-dir=/share/gcc-data/x86_64-pc-linux-gnu/6.3.0/python --enable-languages=c,c++,java,fortran --enable-obsolete --enable-secureplt --disable-werror --with-system-zlib --enable-nls --without-included-gettext --enable-checking=release --with-bugurl=https://bugs.gentoo.org/ --with-pkgversion='Gentoo 6.3.0 p1.0' --disable-esp --enable-libstdcxx-time --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --enable-multilib --with-multilib-list=m32,m64 --disable-altivec --disable-fixed-point --enable-targets=all --enable-libgomp --disable-libmudflap --disable-libssp --disable-libcilkrts --disable-libmpx --enable-vtable-verify --enable-libvtv --enable-lto --without-isl --enable-libsanitizer --disable-default-pie --disable-default-ssp
Thread model: posix
gcc version 6.3.0 (Gentoo 6.3.0 p1.0)
Comment 30 Manuel López-Ibáñez 2017-08-19 12:03:30 UTC
*** Bug 80650 has been marked as a duplicate of this bug. ***
Comment 31 Manuel López-Ibáñez 2017-08-19 12:06:18 UTC
*** Bug 79701 has been marked as a duplicate of this bug. ***
Comment 32 sandra 2017-09-19 20:51:09 UTC
Here's another case which I think is the same bug, observed in GCC 7.2:

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"
#include_next <foo.h>
#pragma GCC diagnostic pop

does nothing to suppress the -Wpedantic warning about #include_next.
Comment 33 Martin Sebor 2018-01-31 16:50:25 UTC
*** Bug 84127 has been marked as a duplicate of this bug. ***
Comment 34 Robert J. Simpson 2018-11-26 17:36:48 UTC
Appears to still be an issue in gcc-8:

gcc 8.2.0

#pragma GCC diagnostic ignored "-Wcomment"
// multi-line comment \
// 

../canvas.cpp:85:1: warning: multi-line comment [-Wcomment]
 // multi-line comment \
 ^
Comment 35 Jonathan Wakely 2019-01-25 13:33:55 UTC
*** Bug 89038 has been marked as a duplicate of this bug. ***
Comment 36 Jonathan Wakely 2019-03-25 13:38:38 UTC
*** Bug 89806 has been marked as a duplicate of this bug. ***
Comment 37 Jonathan Wakely 2019-03-25 13:39:07 UTC
From PR 89806:

Sample code:

#pragma GCC diagnostic ignored "-Wdate-time"
const char* g_test = "dirty-" __DATE__;

When compiling with g++ (g++ -Werror=date-time) this produces:

<source>:2:31: error: macro "__DATE__" might prevent reproducible builds [-Werror=date-time]

    2 | const char* g_test = "dirty-" __DATE__;

      |                               ^~~~~~~~

cc1plus: some warnings being treated as errors

Compiler returned: 1

But with GCC this compiles without errors (gcc -Werror=date-time).
Comment 38 Nickolay Kolchin-Semyonov 2019-03-25 14:40:04 UTC
Since this is a long standing problem, maybe this limitation should be mentioned in official documentation?
Comment 39 Eric Gallager 2019-11-20 06:26:16 UTC
(In reply to Nickolay Kolchin-Semyonov from comment #38)
> Since this is a long standing problem, maybe this limitation should be
> mentioned in official documentation?

Maybe... although, if documented, people might think current behavior is the intended behavior, when it isn't... I guess it depends on the wording used to do said documentation...