warning: disabled expansion of recursive macro - c++

I am currently building the GDCM project using MacOSX default compiler: clang. This compiler trigger a warning in its own header (see ref):
In file included from /Users/builder/external/GDCM/Source/MediaStorageAndFileFormat/gdcmJPEG12Codec.cxx:21:
/Users/builder/external/GDCM/Source/MediaStorageAndFileFormat/gdcmJPEGBITSCodec.cxx:336:9: warning: disabled expansion of recursive macro [-Wdisabled-macro-expansion]
if (setjmp(jerr.setjmp_buffer))
^
/Users/builder/llvm/llvm-rel-install/bin/../include/c++/v1/setjmp.h:40:21: note: expanded from macro 'setjmp'
#define setjmp(env) setjmp(env)
^
In file included from /Users/builder/external/GDCM/Source/MediaStorageAndFileFormat/gdcmJPEG12Codec.cxx:21:
/Users/builder/external/GDCM/Source/MediaStorageAndFileFormat/gdcmJPEGBITSCodec.cxx:724:9: warning: disabled expansion of recursive macro [-Wdisabled-macro-expansion]
if (setjmp(jerr.setjmp_buffer))
^
/Users/builder/llvm/llvm-rel-install/bin/../include/c++/v1/setjmp.h:40:21: note: expanded from macro 'setjmp'
#define setjmp(env) setjmp(env)
^
2 warnings generated.
This is either a clear bug in llvm header (which I find hard to believe), or I am missing something about the use of setjmp in C++98.

It's neither. It's not a bug in an LLVM header, it's not that you're missing something about the use of setjmp, it's that you've enabled a warning that happens to also trigger on perfectly valid code. Most warnings do. That's why they're warnings rather than errors. This particular warning happens to mostly trigger on valid code. That's why it's not enabled by default, not even included in -Wall, and not even included in -Wextra. Yet you enabled it anyway. That's fine, but then you should be prepared to deal with the results.

Related

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

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

G++ ignores _Pragma diagnostic ignored

I am trying to disable g++ warnings in code expanded from macros. By my understanding, _Pragma should follow macro usage and this should not trigger Wparentheses when being compiled with g++:
#include <stdio.h>
#define TEST(expr) \
int a = 1; \
_Pragma( "GCC diagnostic push" ) \
_Pragma( "GCC diagnostic ignored \"-Wparentheses\"" ) \
if (a <= expr) { \
printf("filler\n"); \
} \
_Pragma( "GCC diagnostic pop" )
int main(){
int b = 2, c = 3;
TEST(b == c);
}
When I compile this with g++, I get Wparentheses warning, which I am trying to disable.
xarn#DESKTOP-B2A3CNC:/mnt/c/ubuntu$ g++ -Wall -Wextra test3.c
test3.c: In function ‘int main()’:
test3.c:8:11: warning: suggest parentheses around comparison in operand of ‘==’ [-Wparentheses]
if (a <= expr) { \
^
test3.c:15:5: note: in expansion of macro ‘TEST’
TEST(b == c);
^
However it works as expected when using gcc:
xarn#DESKTOP-B2A3CNC:/mnt/c/ubuntu$ gcc -Wall -Wextra test3.c
test3.c: In function ‘main’:
test3.c:16:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
I am using g++ version 4.8.5.
There are long-standing bugs in g++ handling of _Pragmas, that are not present when using the gcc front-end. The only solution is to either go forward to a sufficiently modern version of g++ (IIRC 6+), or to disable the warning for the entire TU.
Xarn's answer was very helpful in working out why we were hitting the same issues with our macros when compiling with g++ < 9.0, but fortunately I'm stubborn and don't take "the only solution" for an answer. Some more digging revealed that there is a workaround for affected versions of GCC.
One of the original 2012 reports for this issue at GNU's bugzilla included an offhand mention from the reporter, that _Pragma() would be processed as expected if they added either -save-temps or -no-integrated-cpp to the compile command.
Turns out, either of those options cause g++ NOT to run in its default streamlined mode, which folds the preprocessing and compiling stages together into a single pass. From the man page for g++ 9.1.1:
-no-integrated-cpp
Perform preprocessing as a separate pass before compilation. By
default, GCC performs preprocessing as an integrated part of input
tokenization and parsing. If this option is provided, the
appropriate language front end (cc1, cc1plus, or cc1obj for C, C++,
and Objective-C, respectively) is instead invoked twice, once for
preprocessing only and once for actual compilation of the
preprocessed input. This option may be useful in conjunction with
the -B or -wrapper options to specify an alternate preprocessor or
perform additional processing of the program source between normal
preprocessing and compilation.
Which means that adding -no-integrated-cpp does indeed work around the _Pragma() bug in every affected version of GCC we've tested — so far that's 5.4, 7.3, and I believe 8.1 — but otherwise has no effect on the final results of the build. (One can deduce from this that the _Pragma() bug was introduced with and by that single-pass streamlining.)
The only real tradeoff is that compilation is indeed a bit slower, if you build with that option enabled. While that's certainly worth it when your GCC is one of the affected versions, we're using a conditional in our CMake build setup to ensure -no-integrated-cpp is only set when necessary:
#### Work around a GCC < 9 bug with handling of _Pragma() in macros
#### See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55578
if ((${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") AND
(${CMAKE_CXX_COMPILER_VERSION} VERSION_LESS "9.0.0"))
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -no-integrated-cpp")
endif()
(Substitute appropriately modern calls to target_compile_options() for the ugly brute-forcing of CMAKE_CXX_FLAGS, if your CMake setup is better than ours.)
Typically you use warning suppression only to deal with unavoidable warning coming from third-party code so they won't clutter compilation logs. In your case it would be better to
1) use regular function because macros are evil
2) deal with warning by adding round brackets around potentially broken expression
if (a <= (expr)) {

How to fix "error: no previous declaration for void awn::vala_array_destroy"?

I'm on Ubuntu 13.04 32 platform. I'm trying to compile awn with latest vala. I get following error message.
vala-utils.cc: In function 'void awn::vala_array_destroy(gpointer, gint, GDestroyNotify)':
vala-utils.cc:358:6: error: no previous declaration for 'void awn::vala_array_destroy(gpointer, gint, GDestroyNotify)' [-Werror=missing-declarations]
cc1plus: some warnings being treated as errors
How can I fix that error?
At the top of vala-utils.cc insert the function prototype:
void vala_array_destroy(gpointer array, gint array_length, GDestroyNotify destroy_func);
This will silence the warning which is causing the build to fail due to -Werror defined in the Makefile. Consider raising a pull request for the benefit of the maintainers.
Alternatively modify ln.89 in configure.ac and remove the -Werror to stop the warning failing the build.
This actually a warning, and a rather pedantic one at that.
It's saying that the global function awn::vala_array_destroy has not been declared beforehand. Usually this is a sign of a programmer's mistake, but from the source it seems to me that:
this function is only supposed to be used by awn::vala_array_free directly below it (in which case it should really have been given internal linkage), or
a declaration is available in some header elsewhere (in which case it's probably in the wrong header, as it ought to be in vala-utils.h).
The long and short of it is that the code is probably fine, if a little strangely designed. This case is being treated as an error because you have -Werror turned on for this warning, turning it into an error.
I don't know how you're building the library, but you could adjust the compiler flags to avoid this; by default, GCC does not emit this warning, nor turn it into an error. Alternatively, you could add the function declaration into vala-utils.h yourself. You should also take up the issue with the library's maintainers.
Update: I found the culprit on line 89 of AWN's configure.ac. You should definitely take this up with the library maintainers. I'd be amazed if this had not already been reported as a bug; I believe it was introduced in this revision.

Cleaning up C/C++ code reveals problems with variadic macros

We're doing some code cleanup, fixing signed/unsigned comparisons, running static analysis, etc, on the code base of C, C++, and Java.
One of the warnings we're getting is
warning: ISO C does not permit named variadic macros
And its companion warning
warning: ISO C99 requires rest arguments to be used
Now, in the C code I used the C99 standard variadic macro to fix the problem, but in the C++ code, what is the correct answer? Using the same C99 style results in a different warning
warning: anonymous variadic macros were introduced in C99
For which I don't see any answers.
We're using GCC (G++) 4.4.3 in Linux.
I'm hoping there is some flag, or other method that can correct, or disable it for the specific section of code - but its for the logging which is used in almost every file...
Use the gcc option -Wno-variadic-macros to disable that particular warning.
Edit: (from comments)
To disable the warning for a section of code but leave it on in general, use #pragma GCC diagnostic described here.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wvariadic-macros"
// Your code and/or include files
// (No variadic warnings here)
#pragma GCC diagnostic pop

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.