GCC does not honor 'pragma GCC diagnostic' to silence warnings [duplicate] - c++

This question already has an answer here:
Suppress -Wunknown-pragmas warning in GCC
(1 answer)
Closed 3 years ago.
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

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.

Related

Make gcc to skip "-Werror=unused-parameter" for a specific .cpp file [duplicate]

In Visual C++, it's possible to use #pragma warning (disable: ...). Also I found that in GCC you can override per file compiler flags. How can I do this for "next line", or with push/pop semantics around areas of code using GCC?
It appears this can be done. I'm unable to determine the version of GCC that it was added, but it was sometime before June 2010.
Here's an example:
#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 */
To net everything out, this is an example of temporarily disabling a warning:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
write(foo, bar, baz);
#pragma GCC diagnostic pop
You can check the GCC documentation on diagnostic pragmas for more details.
TL;DR: If it works, avoid, or use specifiers like _Noreturn, [[nodiscard]], __attribute__, otherwise _Pragma.
This is a short version of my blog article
Suppressing Warnings in GCC and Clang.
Consider the following Makefile,
CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror
.PHONY: all
all: puts
for building the following puts.c source code:
#include <stdio.h>
int main(int argc, const char *argv[])
{
while (*++argv)
puts(*argv);
return 0;
}
It will not compile because argc is unused, and the settings are hardcore (-W -Wall -pedantic -Werror).
There are five things you could do:
Improve the source code, if possible
Use an attribute, like [[maybe_unused]]
Use a declaration specifier, like __attribute__
Use _Pragma
Use #pragma
Use a command line option.
Improving the source
The first attempt should be checking if the source code can be improved to get rid of the warning. In this case we don't want to change the algorithm just because of that, as argc is redundant with !*argv (NULL after last element).
Using an attribute, like [[maybe_unused]]
#include <stdio.h>
int main([[maybe_unused]] int argc, const char *argv[])
{
while (*++argv) puts(*argv);
return 0;
}
If you're lucky, the standard provides an attribute for your situation, like [[maybe_unused]]. Attributes are a new feature of C2x. So far, C2x defines four attributes, [[deprecated]], [[fallthrough]], [[maybe_unused]], and [[nodiscard]].
Using a declaration specifier, like __attribute__
#include <stdio.h>
int main(__attribute__((unused)) int argc, const char *argv[])
{
while (*++argv) puts(*argv);
return 0;
}
If you're lucky, the standard provides a specifier for your situation, like _Noreturn.
__attribute__ is proprietary GCC extension (supported by Clang and some other compilers like armcc as well) and will not be understood by many other compilers. Put __attribute__((unused)) inside a macro if you want portable code.
_Pragma operator
_Pragma can be used as an alternative to #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")
The main advantage of the _Pragma operator is that you could put it inside macros, which is not possible with the #pragma directive.
Downside: It's almost a tactical nuke, as it works line-based instead of declaration-based.
The _Pragma operator was introduced in C99.
#pragma directive.
We could change the source code to suppress the warning for a region of code, typically an entire function:
#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
Downside: It's almost a tactical nuke, as it works line-based instead of declaration-based.
Note that a similar syntax exists in Clang.
Suppressing the warning on the command line for a single file
We could add the following line to the Makefile to suppress the warning specifically for puts:
CPPFLAGS:=-std=c11 -W -Wall -pedantic -Werror
.PHONY: all
all: puts
puts.o: CPPFLAGS+=-Wno-unused-parameter
This is probably not want you want in your particular case, but it may help other readers who are in similar situations.
I know the question is about GCC, but for people looking for how to do this in other and/or multiple compilers…
TL;DR
You might want to take a look at Hedley, which is a public-domain single C/C++ header I wrote which does a lot of this stuff for you. I'll put a quick section about how to use Hedley for all this at the end of this post.
Disabling the warning
#pragma warning (disable: …) has equivalents in most compilers:
MSVC: #pragma warning(disable:4996)
GCC: #pragma GCC diagnostic ignored "-W…" where the ellipsis is the name of the warning; e.g., #pragma GCC diagnostic ignored "-Wdeprecated-declarations.
Clang: #pragma clang diagnostic ignored "-W…". The syntax is basically the same as GCC's, and many of the warning names are the same (though many aren't).
Intel C++ Compiler (ICC): Use the MSVC syntax, but keep in mind that warning numbers are totally different. Example: #pragma warning(disable:1478 1786).
PGI/Nvidia: There is a diag_suppress pragma: #pragma diag_suppress 1215,1444. Note that all warning numbers increased by one in 20.7 (the first Nvidia HPC release).
TI (CCS): There is a diag_suppress pragma with the same syntax (but different warning numbers!) as PGI: pragma diag_suppress 1291,1718
Oracle Developer Studio (ODS) (suncc): there is an error_messages pragma. Annoyingly, the warnings are different for the C and C++ compilers. Both of these disable basically the same warnings:
C: #pragma error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)
C++: #pragma error_messages(off,symdeprecated,symdeprecated2)
IAR: also uses diag_suppress like PGI and TI, but the syntax is different. Some of the warning numbers are the same, but I others have diverged: #pragma diag_suppress=Pe1444,Pe1215
Pelles C: similar to MSVC, though again the numbers are different #pragma warn(disable:2241)
For most compilers it is often a good idea to check the compiler version before trying to disable it, otherwise you'll just end up triggering another warning. For example, GCC 7 added support for the -Wimplicit-fallthrough warning, so if you care about GCC before 7 you should do something like
#if defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
For Clang and compilers based on Clang, such as newer versions of XL C/C++ and armclang, you can check to see if the compiler knows about a particular warning using the __has_warning() macro.
#if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#endif
Of course you also have to check to see if the __has_warning() macro exists:
#if defined(__has_warning)
# if __has_warning("-Wimplicit-fallthrough")
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
# endif
#endif
You may be tempted to do something like
#if !defined(__has_warning)
# define __has_warning(warning)
#endif
So you can use __has_warning a bit more easily. Clang even suggests something similar for the __has_builtin() macro in their manual. Do not do this. Other code may check for __has_warning and fall back on checking compiler versions if it doesn't exist, and if you define __has_warning you'll break their code. The right way to do this is to create a macro in your namespace. For example:
#if defined(__has_warning)
# define MY_HAS_WARNING(warning) __has_warning(warning)
#else
# define MY_HAS_WARNING(warning) (0)
#endif
Then you can do stuff like
#if MY_HAS_WARNING(warning)
# pragma clang diagnostic ignored "-Wimplicit-fallthrough"
#elif defined(__GNUC__) && (__GNUC__ >= 7)
# pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#endif
Pushing and popping
Many compilers also support a way to push and pop warnings onto a stack. For example, this will disable a warning on GCC for one line of code, then return it to its previous state:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated"
call_deprecated_function();
#pragma GCC diagnostic pop
Of course there isn't a lot of agreement across compilers about the syntax:
GCC 4.6+: #pragma GCC diagnostic push / #pragma GCC diagnostic pop
Clang: #pragma clang diagnostic push / #pragma clang diagnostic pop
Intel 13+ (and probably earlier): #pragma warning(push) / #pragma warning(pop)
MSVC 15+ (Visual Studio 9.0 / 2008): #pragma warning(push) / #pragma warning(pop)
ARM 5.6+: #pragma push / #pragma pop
TI 8.1+: #pragma diag_push / #pragma diag_pop
Pelles C 2.90+ (and probably earlier): #pragma warning(push) / #pragma warning(pop)
If memory serves, for some very old versions of GCC (like 3.x, IIRC) the push/pop pragmas had to be outside of the function.
Hiding the gory details
For most compilers it's possible to hide the logic behind macros using _Pragma, which was introduced in C99. Even in non-C99 mode, most compilers support _Pragma; the big exception is MSVC, which has its own __pragma keyword with a different syntax. The standard _Pragma takes a string, Microsoft's version doesn't:
#if defined(_MSC_VER)
# define PRAGMA_FOO __pragma(foo)
#else
# define PRAGMA_FOO _Pragma("foo")
#endif
PRAGMA_FOO
Is roughly equivalent, once preprocessed, to
#pragma foo
This let’s us create macros so we can write code like
MY_DIAGNOSTIC_PUSH
MY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated_function();
MY_DIAGNOSTIC_POP
And hide away all the ugly version checks in the macro definitions.
The easy way: Hedley
Now that you understand the mechanics of how to do stuff like this portably while keeping your code clean, you understand what one of my projects, Hedley does. Instead of digging through tons of documentation and/or installing as many versions of as many compilers as you can to test with, you can just include Hedley (it is a single public domain C/C++ header) and be done with it. For example:
#include "hedley.h"
HEDLEY_DIAGNOSTIC_PUSH
HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
call_deprecated();
HEDLEY_DIAGNOSTIC_POP
Will disable the warning about calling a deprecated function on GCC, Clang, ICC, PGI, MSVC, TI, IAR, ODS, Pelles C, and possibly others (I probably won't bother updating this answer as I update Hedley). And, on compilers which aren't known to work, the macros will be preprocessed away to nothing, so your code will continue to work with any compiler. Of course HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED isn't the only warning Hedley knows about, nor is disabling warnings all Hedley can do, but hopefully you get the idea.
#pragma GCC diagnostic ignored "-Wformat"
Replace "-Wformat" with the name of your warning flag.
AFAIK there is no way to use push/pop semantics for this option.
Use:
#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
This should do the trick for GCC, Clang and MSVC.
It can be called with e.g.:
DISABLE_WARNING(unused-variable,unused-variable,42)
[.... some code with warnings in here ....]
ENABLE_WARNING(unused-variable,unused-variable,42)
See 7 Pragmas, Controlling Diagnostics via Pragmas and Pragma directives and the __pragma and _Pragma keywords for more details.
You need at least version 4.02 to use these kind of pragmas for GCC, and I am not sure about MSVC and Clang about the versions.
It looks like the push pop pragma handling for GCC is a little bit broken. If you enable the warning again, you still get the warning for the block that was inside the DISABLE_WARNING/ENABLE_WARNING block. For some versions of GCC it works, and for some it doesn't.
I had same issue with external libraries like ROS headers. I like to use following options in CMakeLists.txt for stricter compilation:
set(CMAKE_CXX_FLAGS "-std=c++0x -Wall -Wextra -Wstrict-aliasing -pedantic -Werror -Wunreachable-code ${CMAKE_CXX_FLAGS}")
However, doing this causes all kind of pedantic errors in externally included libraries as well. The solution is to disable all pedantic warnings before you include external libraries and re-enable them like this:
// 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
Rather than silencing the warnings, GCC style is usually to use either standard C constructs or the __attribute__ extension to tell the compiler more about your intention.
For instance, the warning about assignment used as a condition is suppressed by putting the assignment in parentheses, i.e. if ((p=malloc(cnt))) instead of if (p=malloc(cnt)).
Warnings about unused function arguments can be suppressed by some odd __attribute__ I can never remember, or by self-assignment, etc.
But generally I prefer just globally disabling any warning option that generates warnings for things that will occur in correct code.
Here is a way to do this in IAR. Try this:
#pragma diag_suppress=Pe177
void foo1(void)
{
/* The following line of code would normally provoke diagnostic
message #177-D: variable "x" was declared but never referenced.
Instead, we have suppressed this warning throughout the entire
scope of foo1().
*/
int x;
}
#pragma diag_default=Pe177
See official documentation for reference.

How to enable GCC compiler flags via preprocessor directives, rather than command line options?

I'm wondering how to activate GCC compiler flags in code, as opposed to including them in the compilation command on the command line.
Consider the following minimal example, which produces the warning -Wswitch-bool (I think by default but at least with -Wall enabled):
switch (true) {
default:
break;
}
This warning can be suppressed by providing the flag -Wno-switch-bool when compiling the program via the command line.
Is it possible to activate this flag in code? The following naive attempt doesn't work, since Wno-switch-bool is not a legal identifier (dashes are interpreted as minuses):
#define Wno-switch-bool
What is the appropriate command/syntax to use?
Note: This question is not specifically about warnings. I.e. I'm not asking about how to deactivate a specific class of warnings, which I know is best done via #pragma GCC diagnostic ignore, etc. This is a general question about how to enable GCC compiler flags in code. For instance, another example could be how I could activate -Werror, or -fno-implicit-templates via preprocessor directives (whether or not that would be ill-advised).
Is it possible to activate this flag in code?
Yes, you can use GCC's diagnostic pragmas to apply a specific pragma temporarily around a specific snippet of code, by remembering and subsequently restoring the state of the diagnostics prior to a source-local tweaking of it. E.g.:
#pragma GCC diagnostic push
// ^^^^^^^^^^^^^^^ remember the state of the diagnostics
#pragma GCC diagnostic ignored "-Wswitch-bool"
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tweak diagnostics
switch (true) {
default:
break;
}
#pragma GCC diagnostic pop
// ^^^^^^^^^^^^^^^ restore the state of the diagnostics

How to enable -fpermissive for a section of code

I have a C single-header library that I would like to use in my C++ project. Normally, I would just include the file and that would be fine because C++ is almost a superset of C. However, this library has a goto that jumps over an initialization, violating the C++ standard.
I can get around this be enabling the -fpermissive compiler flag on GCC, but I want the errors to trigger properly for the rest of my code.
Is there a way I can enable it just for this one header file (perhaps similar to #pragma GCC diagnostic XXX).
There's #pragma GCC optimize "blah" or the function attribute __attribute__((optimize("blah"))) that act like the argument -fblah was given for the rest of that file/that specific function, but it doesn't seem to work with -fpermissive:
$ cat foo.cpp
#pragma GCC optimize "permissive"
void foo(int x) {
}
$ g++-8 -c -Wall -Wextra foo.cpp
foo.cpp:1:22: warning: bad option ‘-fpermissive’ to pragma ‘optimize’ [-Wpragmas]
#pragma GCC optimize "permissive"
^~~~~~~~~~~~
foo.cpp:3:16: warning: bad option ‘-fpermissive’ to attribute ‘optimize’ [-Wattributes]
void foo(int x) {
One option would be to put the function that needs this in a file by itself, and configure your build system to compile just that file with -fpermissive, though that breaks the header-only model. Or fix the code so it doesn't need that option at all.
Per gcc man page:
-fpermissive
Downgrade some diagnostics about nonconformant code from errors to warnings. Thus, using -fpermissive allows some nonconforming code to compile.
So in theory, one can allow a section to compile as permissive using a sequence of gcc warning pragmas:
// Start permissive code
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-result"
#pragma GCC diagnostic ignored "-Wuninitialized"
// .. Other #pragmas
// Permissive Code here.
// Restore normal processing.
#pragma GCC diagnostic pop
One challenge is that there is no published list of errors that will be ignored with -fpermissive (At least I could not find it). One possible approach will be to compile the code, and enter the '#pragma's one at at a time, until the code compiles cleanly.
If one can identify all (or most) of the rules, possible to put them into #include file.
#pragma GCC diagostic push
#include "permissive.h"
// Permissive Code here
#pragma GCC diagostic pop

Temporarily disable warnings on specific versions of GCC

I have the following situation -
I need to compile my code with two different versions of GCC (3.2 and 4.4) and wish to see all warnings and treat them as errors (it's a slippery slope otherwise). I must include header files I cannot change that include some code. This code makes the newer GCC throw warnings (like unused parameter).
If I add something like
#pragma GCC diagnostic ignored "-Wunused-parameter"
#include <bad_header.hpp>
#pragma GCC diagnostic error "-Wunused-parameter"
it solves the issue with the newer GCC but the older one is not familiar with this pragma and issues a warning (which becomes an error).
What can I do?
Stop treating warning as errors
Surround my pragma with some sort of version checking macro
I don't like both solutions, is there anything else I can do?
Update following Sander De Dycker's answer
My build system does not allow me to use -isystem flag with gcc
Since you only want to suppress warnings from headers you don't control, you can mark those headers as system headers by using -isystem instead of -I, and gcc will no longer generate warnings for them (how gcc treats system headers).
The solution I'm going to use for now (until I'll see a better one) is to wrap the GCC diagnostic pragmas with macros to check GCC version, something like
#if (defined __GNUC__) && (__GNUC__ > 3)
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
#include <bad_header.hpp>
#if (defined __GNUC__) && (__GNUC__ > 3)
#pragma GCC diagnostic error "-Wunused-parameter"
#endif

In GCC, how can I mute the '-fpermissive' warning?

I am including a file from a third-party library that raises an error that can be downgraded to a warning with -fpermissive. But because I do not want to "pollute" my compilation log with these warnings, I want to completely disable this messages.
So far, I set the -fpermissive option with a diagnostic pragma when including the file; something like:
#pragma GCC diagnostic push
#pragma GCC diagnostic warning "-fpermissive"
#include <third-party-file.h>
#pragma GCC diagnostic pop
Since GCC usually provides both a "positive" and "negative" version of the -f flags, I thought about ignoring the "no-permissive" feature:
#pragma GCC diagnostic ignored "-fno-permissive"
#include <third-party-file.h>
But there does not seem to be a "negative" version of the -fpermissive flag (I am using GCC 4.6.3; but even the version 4.7.0 does not have it).
Can I mimic this behavior?
tldr: You cannot turn off the fpermissive output after GCC 4.7.
Just posting this here so it has more visibility: unfortunately, zwol's answer (while well-intentioned, and potentially helpful to those with older GCC versions) does not work for more recent versions of GCC. From GCC 4.8 and beyond, you cannot turn off the fpermissive output. o11c in his comment to the OP helpfully provides the following bug which tracks this:
Bug 81787. [5/6/7/8 Regression] #pragma GCC diagnostic warning "-fpermissive" no longer
Note that it is in the state "RESOLVED INVALID", so the inability to turn it off is the expected behavior and there are no plans to change it.
One of these ought to do what you wanted:
#pragma GCC diagnostic ignored "-fpermissive"
or
#pragma GCC diagnostic ignored "-pedantic"
"ignored" is how you squelch a diagnostic entirely, and the inverse of -fpermissive is -pedantic, for historical reasons.