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
Related
I'm compiling on with GCC on Linux, but CMake is kind enough to produce a Clang compatible compilation database. This means that I can run fancy, modern Clang based tools on my codebase and those tools have perfect knowledge of how each file is to be built (flags, defines, include paths, etc.) So far so good.
But today the Clang based static analysis in my IDE started showing a Clang specific warning. I don't think it particularly matters for my question which warning it is, but it was warning: disabled expansion of recursive macro, generated by -Wdisabled-macro-expansion. This particular macro is provided by a third party, so fixing the warning isn't an option, but I would like to suppress it as it occurs several times in the file in question.
What I'm struggling with is how to suppress the warning in Clang based analysis tools without causing new warnings in the GCC build.
Adding #pragma clang diagnostic ignored "-Wdisabled-macro-expansion" suppresses the warning for Clang tools, but causes GCC to issue warning: ignoring #pragma clang diagnostic [-Wunknown-pragmas].
Similarly, adding #pragma GCC diagnostic ignored "-Wdisabled-macro-expansion" suppresses the Clang warning (because Clang tries to be compatible with GCC diagnostics), but causes GCC to issue warning: unknown option after ‘#pragma GCC diagnostic’ kind [-Wpragmas].
Wrapping either of the above with #ifdef __clang__ makes GCC happy, but doesn't suppress the Clang warning because the tooling is smart enough to know that the code isn't compiled with __clang__, but with __GNUC__ instead.
Is there a way to make a diagnostic #pragma visible to Clang tooling, but not to GCC?
the tooling is smart enough to know that the code isn't compiled with __clang__, but with __GNUC__ instead
If it's reporting a clang-only warning, but does not think that __clang__ is defined, that sounds like a problem with the tooling. If it's trying to be that clever about misrepresenting itself, you may be up a creek... but also you should be complaining to the tool author for creating this situation in the first place.
That said, you could try:
#if defined(__has_warning)
# if __has_warning("-Wdisabled-macro-expansion")
# pragma GCC diagnostic ignored "-Wdisabled-macro-expansion"
# endif
#endif
I'm not sure if this will work... it depends on how hard the tooling is pretending to not be clang (__has_warning is a clang-only extension).
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.
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
#pragma GCC diagnostic push
it pop: warning: expected [error|warning|ignored] after â#pragma GCC diagnosticâ
Why? I use GCC in Linux.
I have one question, if I can't use pop/push, if the ignore only influence the compiled cpp, not influence other cpp? if some other include the cap, if influence it?
#pragma GCC diagnostic push and #pragma GCC diagnostic pop were added in gcc 4.6. You're using an older version.
These pragmas are typically used in conjunction with other #pragma GCC diagnostic directives to suppress, turn on, or turn into an error specific warnings for a small section of your code only. If they're ignored, the changes to warning levels will apply to the rest of the source file rather than just until the next #pragma GCC diagnostic pop. This may not be a problem, or it may be the end of the world; you'll need to understand your code to know for sure.
Either way, you should probably update your compiler. You wouldn't compile C99 with a C89 compiler; don't compile code containing pragmas for gcc 4.6 with gcc 4.4.
I am wondering if it is possible to have werror in gcc/g++ exclude certain files (ones that I do not have source code to modify) so that I can continue using werror in a uninhibited state.
Use pragma directives with a newer (4.2 I think) version of gcc to turn off -Werror for certain headers prior to including them.
You might want to accept answers for your previous questions.
My only thought is to compile the files you can modify separately with -Werror and then link them with the other object/library files without -Werror.
#Sam Miller already gave the reference documentation about how to do this...
You can temporarily disable -Werror on certain warnings with #pragma GCC diagnostics warning "-W<kind>". For example:
#pragma GCC diagnostic push
# pragma GCC diagnostic warning "-Wreturn-type"
# pragma GCC diagnostic warning "-Wmissing-braces"
# include "legacy-crap.h"
#pragma GCC diagnostic pop
Newer gcc will print the name of the diagnostics category in brackets as part of the the warning/error:
warning-test.c:11:1: warning: return type defaults to ‘int’ [-Wreturn-type]
or
warning-test.c:11:1: error: return type defaults to ‘int’ [-Wreturn-type]
This can be used to accurately select the exact diagnostics which should be treated as warning instead of error during processing of the third party crap you have no power to change. I do not know a short hand to disable all the warnings ("-Wall" will not have desired effect for the above #pragma), but I think it is also good to be explicit here.