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

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

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

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

#pragma once position: before or after #include's

In existing code I saw #pragma once be used after header #includes
//Some_Header.h
#include "header1.h"
#include "header2.h"
#pragma once
//implementations
Instead of
//Some_Header.h
#pragma once
#include "header1.h"
#include "header2.h"
//implementations
I thought it always needed to be like the second example, does it matter where your #pragma once is defined or does the preprocessor pick it up anywhere in your file?
Edit
I know #pragma once is not part of the standard and include guards are but that is not my question.
#pragma once should be placed before any headers are included. Argument of #pragma directive is a subject to macro expansion. So content of included headers can alter the pragma behavior:
// whatever.hpp
...
#define once lol_no
// your_header.hpp
#include "whatever.hpp"
#pragma once // warning C4068: unknown pragma
#pragma once relates only to a file where it is placed. It matters to the compiler whether the file contains this pragma or not, and the position of it is unimportant. Therefore, the line with #pragma once can be placed anywhere in the file except for chunk of code that is excluded from compilation by the conditional preprocessor directives like #if, #ifdef and #ifndef. The excluded chunk of code is not parsed by the compiler and if it contains the preprocessor directive it has no effect.
Despite the fact that #pragma once can be placed at any line that is parsed by the compiler, I strongly recommend to follow the common practice and put #pragma once at the beginning of a header file.
Also, as #user7860670 mentioned, arguments of #pragma directive is a subject to macro expansion for MSVC compiler. But neither gcc nor clang support it:
example for msvc
example for gcc
example for clang
There isn't really a complete answer on this question covering more than the big 3 compilers, so here's my attempt at a more complete answer.
Summary
TL;DR: If you care for portability, put it before any #include or #define statements that may conflict with it (e.g. put it first in the header).
Supported by all major compilers ("the big 3" x86_64 compilers as well as intel, and embedded compilers)
Placement generally does not matter as long as it reaches the preprocessor (e.g. not blocked by an #if-branch)
Different compilers are opinionated on whether it should be first, without documenting what happens if not.
Most compilers already detect include guards and treat it as a pragma once anyway, making the benefit largely just not creating a unique guard name.
Below is a quick, summarized guide:
Compiler
Support
Documentation
Clang
Supported
GNU-compatible. Not documented, but code shows it as normal preprocessing
GCC
Supported
gcc pragmas
MSVC
Supported (1)
MSVC one pragma
Intel (ICC)
Supported (1)
Intel Compiler Reference Manual - Supported Pragmas
Intel (ICL)
Supported (1)
ICL uses MSVC front-end
Intel (ICX)
Supported
ICX is based on Clang
Texas Instruments
Supported (2)
Reference Manual 5.11.23
Texas Instruments (Clang)
Supported
This is a fork of Clang with all major features still in effect
ArmCC
Supported (3)
Compiler Docs for #pragma once
(1) - Supported, but is subject to macro expansion
(2) - Supported, but is documented to be expected at the beginning of the header.
(3) - Supported, but not recommended.
Details
GCC
From the GCC reference manual:
If #pragma once is seen when scanning a header file, that file will never be read again, no matter what. It is a less-portable alternative to using ‘#ifndef’ to guard the contents of header files against multiple inclusions.
(emphasis mine)
Scanning is done at preprocessing time, and so as long as the #pragma statement is visible to the preprocessor (not in an unreachable conditional block from #if), then it will take effect.
GCC's #pragma once is not affected by preprocessor substitution.
Live Example
Clang
Clang's reference manual doesn't actually specify #pragma once so far as I can tell, however Clang is meant to be compatible with most, if not all, GCC builtins and features.
Viewing the source code for Clang's preprocessor phase indicates what you would expect; it handles #pragma once during preprocessing (source)
void Preprocessor::HandlePragmaOnce(Token &OnceTok) {
...
// Mark the file as a once-only file now.
HeaderInfo.MarkFileIncludeOnce(getCurrentFileLexer()->getFileEntry());
}
Like GCC, the placement of the #pragma once does not matter if it's first, and is not affected by preprocessor substitution.
Live Example
MSVC
MSVC's documentation on #pragma once does not indicate where it belongs, just that it should be in a source (and has an example of it at the top).
As mentioned by others, when using #pragma once in MSVC, it is subject to preprocessor-expansion.
With Substitution
Live Example
Without Substitution
Live Example
Intel (CL-Based)
When using the Intel compiler on Windows, the compiler uses an MSVC Compatibility mode (ICL). Although it's not documented in the Supported Pragma, though it does appear to be supported.
The placement does not appear to matter as well so long as the preprocessor reaches it.
ICL's #pragma once is subject to the preprocessor-expansion issue that MSVC experiences.
Note: icl is not supported on compiler-explorer, so no example is available.
Intel (GNU-Based)
When using the Intel compiler on Linux or older macOS versions (ICC), the compiler uses a GNU compatibility mode.
Like above, it's not explicitly listed as a Supported Pragma, though it does appear to be supported in practice. The placement does not appear to matter as well so long as the preprocessor reaches it.
ICC's #pragma once is subject to the preprocessor-expansion issue that MSVC experiences.
With Substitution
Live Example
Without Substitution
Live Example
Intel (Clang-Based)
The newer Intel ICX NextGen compiler is based off of Clang / LLVM technology. Behaviourally, this matches what Clang does.
Unlike other Intel compilers, but like Clang, thisdoes not suffer from the preprocessor-expansion issue.
Live Example
Arm (armcc)
The armcc compiler advises against #pragma once, but does also provide an example of it existing after #define statements as an optional feature to work with inclusion guards.
Given the example, placement should likely not be an issue.
It's unclear where this will experience any preprocessor expansion.
Note: armcc is not supported on compiler-explorer, so no example is available.
Texas Instruments (TI ArmCL)
As mentioned in the reference manual, section 5.11.23:
This pragma should be used at the beginning of a header file that should only be included once. For example:
// hdr.h
#pragma once
#warn You will only see this message one time
struct foo
{
int member;
};
(Emphasis mine)
I haven't tested what happens if it's moved anywhere lower than the comment header, but the compiler only officially supports it at the beginning of the file.
I would suspect this should not matter, but cannot confirm.
It's unclear where this will experience any preprocessor expansion.
Note: tiarmcl (and other similar ti compilers) are not supported on compiler-explorer, so no example is available.
Texas Instruments (tiarmclang)
This is a fork of clang, so it behaves the same as clang does.
The #pragma once in this implementation can be effectively placed anywhere the preprocessor reaches, and does not deal with preprocessor substitution.
Note: tiarmclang is not supported on compiler-explorer, so no example is available.

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.

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.