#pragma(* diagnostic) when mixing Clang analyzers with a GCC compiler - c++

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

Related

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

Inline way to disable clang-tidy checks

I'm trying to set up clang-tidy for a project. I'd like to be able to have clean output, and encourage the use of -fix mode where possible. However, there are individual cases where an exception is needed.
Much as it is possible to use
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreserved-id-macro"
// Code that is being specially exempted
#pragma clang diagnostic pop
for the equivalent case where one wants to locally disable a compiler warning, is it possible to do something similar from clang-tidy?
I have tried
#pragma clang diagnostic push
#pragma clang diagnostic ignored "readability-identifier-naming"
// Code that is being specially exempted
#pragma clang diagnostic pop
and also with clang replaced with clang-tidy. Unfortunately when using clang as the pragma target and compiling with regular clang, I get the compilation warning
warning: pragma diagnostic expected option name (e.g. "-Wundef") [-Wunknown-pragmas]
and
warning: unknown pragma ignored [clang-diagnostic-unknown-pragmas]
when compiling if I use clang-tidy in place of clang. Neither make an impact on what clang-tidy itself outputs when run over the source.
This is with clang and clang-tidy 3.8 on x86_64 Linux.
Just add a comment containing the string NOLINT anywhere on the line you want clang-tidy to ignore. For example:
badcode; // NOLINT
// NOLINTNEXTLINE
badcode;
badcode; // NOLINT(cert-err-58-cpp)
See the documentation here.

Why "pragma GCC diagnostic push" pop warning in GCC/C++?

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

How to prevent `#warning` messages from being treated as an error?

I'm trying to compile introduce the -Werror flag in an existing codebase. One of the issues I'm encountering is that at some places #warning is used to display informational messages. These should not be treated as an error.
One solution would be to use #pragma message instead, but this does not seem to be supported by older versions of gcc. (Our build servers use gcc 4.1.2).
Can anyone help me fix this?
In gcc-4.6 and above, you can use -Wno-error=cpp. In at least the clang released with Lion and later, you can use -Wno-error=#warnings. But since your build servers use an ancient gcc, you're probably out of luck there.
In general, pass -fdiagnostics-show-option to have warnings show output like:
test.cc:1:2: warning: #warning hello [-Wcpp]
which tells you a warning flag that controls the warning. In gcc >=4.6 and clang, this is the default, so knowing to pass it may not be too useful anymore.
Locally disable effect of -Werror for #warning as follows:
#pragma GCC diagnostic push
#pragma GCC diagnostic warning "-Wcpp"
#warning Informative message: everything is nice and good!!!
#pragma GCC diagnostic pop
The benefit with this approach is that you can still induce error with #warning elsewhere in the code.

Werror ignore certain files

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.