How can I get GCC or Clang to warn me about the error below, where M was supposed to be N in line 2?
Even with -Wall -Wextra -Wunknown-pragmas, none of these compilers emit any sort of warning.
#define N 4
#pragma pack(push, M)
int main() {
return 0;
}
#pragma pack(pop)
The compiler cannot know your intentions, only if the code is valid. You can check up on yourself with this
#ifndef M
#error M not defined
#endif
Or if M was defined separately from N with this
#if M != N
#error M is not N
#endif
If you look at the output of the preprocessor the pragma is not evaluated ie if you add N you won't get a 4 after the preprocessor is done.
I don't think you can have it warn here, at least not easily, maybe a preprocessor wizard might be able to figure it out. The following warning does not help unless it's in an undefined value in an #if statement.
-Wundef
If you try and add anything to the pragma ie
#pragma pack(push, (M + 0))
You get a warning because the pragma is expecting an integer or identifier ie
warning: expected integer or identifier in '#pragma pack'
Related
There are a ton of questions about suppressing "variable set but not used" warnings, but I haven't found one that addresses my very specific problem, which is a debugging macro defined as follows:
#ifdef DEBUG
# define dbg_printf(...) ((void)printf(__VA_ARGS__))
#else
# define dbg_printf(...) ((void)( /* ??? */ ))
#endif
A variable that is set unconditionally, and then used only as one of the arguments to dbg_printf, should not trigger "variable set but not used" warnings, whether or not DEBUG is defined. It should not be necessary to annotate such variables at the point of definition. For example, this should be warning-free:
struct Thing { int value; struct Thing *next; };
struct Thing *find_first_match(int n, struct Thing *list)
{
struct Thing *p;
int searched = 0;
for (p = list; p; p = p->next) {
searched++;
if (p->value == n) break;
}
dbg_printf("%s: %s after scanning %d entries\n",
__func__, p ? "found" : "not found", searched);
return p;
}
I have tried a couple things in place of the /* ??? */, but nothing I have tried so far has worked without undesirable side effects:
# define dbg_printf(...) ((void)(0 && (__VA_ARGS__)))
Causes some versions of clang to complain about unused values, e.g.
void foo(void) {
dbg_printf("%d\n", 23);
}
⟶
test.c:4:14: warning: expression result unused [-Wunused-value]
dbg_printf("%d\n", 23);
^~~~~~
# define dbg_printf(...) ((void)(sizeof(__VA_ARGS__)))
Causes some versions of clang to complain about misuse of sizeof, e.g. same test case
test.c:4:14: warning: sizeof on pointer operation will return size of 'const char *'
instead of 'const char [4]' [-Wsizeof-array-decay]
dbg_printf("%d\n", 23);
^~~~~~
[Edited to add:] An inline variadic function that does nothing, instead of a macro, e.g.
static inline void dbg_printf(const char *msg, ...) {
(void)msg;
}
is no good because its arguments will still be evaluated for their
side effects, and the offending code base has lots of instances of
stuff like
// code that mutates a global data structure, and then ...
dbg_printf("validation status after %s: %s\n", __func__,
expensive_global_data_structure_validation());
Please suggest a construct that can be used in place of the /* ??? */ that will suppress "variable set but not used" warnings without introducing other spurious diagnostics in their place. If this can be done with strictly conforming C2011 code, that is preferable. Compiler extensions are acceptable if and only if they work correctly on all four of:
gcc 4.8
gcc 9.x
clang 7.0
clang 10.0
Yes, we are stuck using old compilers for good reasons, or at least reasons which nobody has the spare cycles to overcome.
I use this trick to disable such warnings:
#ifdef DEBUG
# define dbg_printf(...) ((void)printf(__VA_ARGS__))
#else
# define dbg_printf(...) do { if ((0)) (void)printf(__VA_ARGS__); } while (0)
#endif
This macro generates no code in optimized builds but does not complain about variables initialized and only used inside the argument list.
I use do { ... } while (0) to encapsulate the if statement in a block so the macro can be used as a regular function call in a context where a single statement is needed such as this:
if (something_went_wrong())
dbg_printf("something went wrong\n");
else
keep_going();
I write the test if ((0)) with a double pair or parentheses to avoid a warning on constant expression always false and/or unreachable code. clang would issue a warning about unreachable code with -Weverything (which includes -Wunreachable-code). They recommend the use of redundant parentheses to silence this warning in contexts where it is the programmer's intent.
do { } while (0) does not trigger this warning because it is a classic idiom to group statements as a single statement.
The {} are redundant to, the macro could be simplified as:
#define dbg_printf(...) do if((0))(void)printf(__VA_ARGS__);while(0)
The same goal can be reached with a simpler logical expression, that may or may not trigger other compiler warnings:
#define dbg_printf(...) ((void)(((0)) && printf(__VA_ARGS__)))
This will work:
#ifdef DEBUG
# define dbg_printf(...) ((void)printf(__VA_ARGS__))
#else
# define dbg_printf(...) ((void)(0 && printf(__VA_ARGS__)))
#endif
As the right-hand side of the && operator won't be evaluated.
Alternately:
#ifdef DEBUG
# undef DEBUG
# define DEBUG 1
#else
# define DEBUG 0
#endif
Then:
#define dbg_printf(...) ((void)(DEBUG && printf(__VA_ARGS__)))
That way you have if multiple such definitions depending on DEBUG you only need a single #ifdef.
For instance:
Bool NullFunc(const struct timespec *when, const char *who)
{
return TRUE;
}
In C++ I was able to put a /*...*/ comment around the parameters. But not in C of course, where it gives me the error:
error: parameter name omitted
I usually write a macro like this:
#define UNUSED(x) (void)(x)
You can use this macro for all your unused parameters. (Note that this works on any compiler.)
For example:
void f(int x) {
UNUSED(x);
...
}
In GCC, you can label the parameter with the unused attribute.
This attribute, attached to a variable, means that the variable is
meant to be possibly unused. GCC will not produce a warning for this
variable.
In practice this is accomplished by putting __attribute__ ((unused)) just before the parameter. For example:
void foo(workerid_t workerId) { }
becomes
void foo(__attribute__((unused)) workerid_t workerId) { }
You can use GCC or Clang's unused attribute. However, I use these macros in a header to avoid having GCC specific attributes all over the source, also having __attribute__ everywhere is a bit verbose/ugly.
#ifdef __GNUC__
# define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
#else
# define UNUSED(x) UNUSED_ ## x
#endif
#ifdef __GNUC__
# define UNUSED_FUNCTION(x) __attribute__((__unused__)) UNUSED_ ## x
#else
# define UNUSED_FUNCTION(x) UNUSED_ ## x
#endif
Then you can do...
void foo(int UNUSED(bar)) { ... }
I prefer this because you get an error if you try use bar in the code anywhere, so you can't leave the attribute in by mistake.
And for functions...
static void UNUSED_FUNCTION(foo)(int bar) { ... }
Note 1):
As far as I know, MSVC doesn't have an equivalent to __attribute__((__unused__)).
Note 2):
The UNUSED macro won't work for arguments which contain parenthesis,
so if you have an argument like float (*coords)[3] you can't do,
float UNUSED((*coords)[3]) or float (*UNUSED(coords))[3]. This is the only downside to the UNUSED macro I found so far, and in these cases I fall back to (void)coords;.
Seeing that this is marked as gcc you can use the command line switch Wno-unused-parameter.
For example:
gcc -Wno-unused-parameter test.c
Of course this effects the whole file (and maybe project depending where you set the switch) but you don't have to change any code.
With GCC with the unused attribute:
int foo (__attribute__((unused)) int bar) {
return 0;
}
A gcc/g++ specific way to suppress the unused parameter warning for a block of source code is to enclose it with the following pragma statements:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
<code with unused parameters here>
#pragma GCC diagnostic pop
Since C++ 17, the [[maybe_unused]] attribute can be used to suppress warnings about unused parameters.
Based on the OP's example code:
Bool NullFunc([[maybe_unused]] const struct timespec *when, [[maybe_unused]] const char *who)
{
return TRUE;
}
I got the same problem. I used a third-part library. When I compile this library, the compiler (gcc/clang) will complain about unused variables.
Like this
test.cpp:29:11: warning: variable 'magic' set but not used [-Wunused-but-set-variable]
short magic[] = {
test.cpp:84:17: warning: unused variable 'before_write' [-Wunused-variable]
int64_t before_write = Thread::currentTimeMillis();
So the solution is pretty clear. Adding -Wno-unused as gcc/clang CFLAG will suppress all "unused" warnings, even thought you have -Wall set.
In this way, you DO NOT NEED to change any code.
Labelling the attribute is ideal way. MACRO leads to sometime confusion.
and by using void(x),we are adding an overhead in processing.
If not using input argument, use
void foo(int __attribute__((unused))key)
{
}
If not using the variable defined inside the function
void foo(int key)
{
int hash = 0;
int bkt __attribute__((unused)) = 0;
api_call(x, hash, bkt);
}
Now later using the hash variable for your logic but doesn’t need bkt. define bkt as unused, otherwise compiler says'bkt set bt not used".
NOTE: This is just to suppress the warning not for optimization.
In MSVC to suppress a particular warning it is enough to specify the it's number to compiler as /wd#. My CMakeLists.txt contains such the block:
If (MSVC)
Set (CMAKE_EXE_LINKER_FLAGS "$ {CMAKE_EXE_LINKER_FLAGS} / NODEFAULTLIB: LIBCMT")
Add_definitions (/W4 /wd4512 /wd4702 /wd4100 /wd4510 /wd4355 /wd4127)
Add_definitions (/D_CRT_SECURE_NO_WARNINGS)
Elseif (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUC)
Add_definitions (-Wall -W -pedantic)
Else ()
Message ("Unknown compiler")
Endif ()
Now I can not say what exactly /wd4512 /wd4702 /wd4100 /wd4510 /wd4355 /wd4127 mean, because I do not pay any attention to MSVC for three years, but they suppress superpedantic warnings that does not influence the result.
I've seen this style being used:
if (when || who || format || data || len);
For the record, I like Job's answer, but I'm curious about a solution just using the variable name by itself in a "do-nothing" statement:
void foo(int x) {
x; /* unused */
...
}
Sure, this has drawbacks; for instance, without the "unused" note it looks like a mistake rather than an intentional line of code.
The benefit is that no DEFINE is needed and it gets rid of the warning.
Given the following code written according to the C99 standard:
#define LOW 1
#define MEDIUM 2
#define HIGH 3
#define LOGGING_LEVEL HIGH
#if LOGGING_LEVEL >= MEDIUM
#define LOG_MEDIUM(message) printf(message)
#else
#define LOG_MEDIUM(message) ((void)0)
#endif
void load_configuration() {
//...
LOG_MEDIUM("Configuration loaded\n");
}
what's the purpose of ((void)0) I searched the web a lot but nothing found regarding this.
Plus, why didn't we wrote ; after using printf(message)
The void-cast fixes a compiler warning. Here's an analogous testcase:
int main(void)
{
0; // generates "foo.c:3:2: warning: statement with no effect"
(void)0;
return 0;
}
and (using a script to add gcc's warning flags) you see a warning for the line without a cast:
$ gcc-stricter -c foo.c
foo.c: In function ‘main’:
foo.c:3:2: warning: statement with no effect [-Wunused-value]
0;
^
The extra parentheses and lack of semicolon allow the macro's result to be used interchangeably with the printf.
Main idea is to exclude all LOG_MEDIUM if the criteria was not meet.
After compilation those calls will not affect functionality.
I have a logging macro which in release mode becomes:
#define LOG (void)
So statement
LOG("foobar %d", 0xbabecafe);
is expanded to
(void)("foobar %d", 0xbabecafe);
The problem is that the last expression produces an warning under gcc:
warning: left-hand operand of comma expression has no effect [-Wunused-value]
How can I change the logging macro such that no warning is issued? (Note, that I don't want to add compiling flag -Wunused-value).
EDIT I see already a couple of answers involving (...). The same file is compiled under Minix which doesn't support variadic macros. The best would be to have a C89 conforming solution. While your answer is correct (and I upvoted it), it is my fault that I didn't include this small detail.
I think the old school way of dealing with this is to take advantage of double parens. Something like this:
LOG(("message: %d", 10));
Then for your macro, you define it like this:
#define LOG(x) printf x
or
#define LOG(x) (void)0
Because of the double parens, the pre-processor treats the whole inner paren as a single parameter. This at least used to work in visual studio.
EDIT: I did a quick test, it works with gcc with -ansi, so it should be good:
gcc -DNDEBUG -ansi -pedantic -W -Wall test.c -o test
#include <stdio.h>
#ifdef NDEBUG
#define LOG(x) printf x
#else
#define LOG(x) (void)0
#endif
int main() {
LOG(("message: %d\n", 10));
return 0;
}
The easiest should be
#define LOG(...) (void)0
(gcc supports the C99 variadic macros and most other compilers also do these days) That will discard the arguments list, which has two advantages:
it does not create statements with no effect and
the arguments are not evaluated at all (if you call non-inline functions in the argument list, in your version the compiler can't eliminate them, while with the variadic macro, the compiler won't see them at all.
#define LOG(...) seems to do the trick.
For your problems with a non-conforming C implementation (not even C89?) you could do something like
static void LOG(char *format, ...) { /* empty */ }
even a completely dumb compiler should be able to optimize that out.
I've used
#define LOG( t) t
for the development version and
#define LOG( t)
for the release version, with a typical use being
LOG( printf( "here\n"));
For instance:
Bool NullFunc(const struct timespec *when, const char *who)
{
return TRUE;
}
In C++ I was able to put a /*...*/ comment around the parameters. But not in C of course, where it gives me the error:
error: parameter name omitted
I usually write a macro like this:
#define UNUSED(x) (void)(x)
You can use this macro for all your unused parameters. (Note that this works on any compiler.)
For example:
void f(int x) {
UNUSED(x);
...
}
In GCC, you can label the parameter with the unused attribute.
This attribute, attached to a variable, means that the variable is
meant to be possibly unused. GCC will not produce a warning for this
variable.
In practice this is accomplished by putting __attribute__ ((unused)) just before the parameter. For example:
void foo(workerid_t workerId) { }
becomes
void foo(__attribute__((unused)) workerid_t workerId) { }
You can use GCC or Clang's unused attribute. However, I use these macros in a header to avoid having GCC specific attributes all over the source, also having __attribute__ everywhere is a bit verbose/ugly.
#ifdef __GNUC__
# define UNUSED(x) UNUSED_ ## x __attribute__((__unused__))
#else
# define UNUSED(x) UNUSED_ ## x
#endif
#ifdef __GNUC__
# define UNUSED_FUNCTION(x) __attribute__((__unused__)) UNUSED_ ## x
#else
# define UNUSED_FUNCTION(x) UNUSED_ ## x
#endif
Then you can do...
void foo(int UNUSED(bar)) { ... }
I prefer this because you get an error if you try use bar in the code anywhere, so you can't leave the attribute in by mistake.
And for functions...
static void UNUSED_FUNCTION(foo)(int bar) { ... }
Note 1):
As far as I know, MSVC doesn't have an equivalent to __attribute__((__unused__)).
Note 2):
The UNUSED macro won't work for arguments which contain parenthesis,
so if you have an argument like float (*coords)[3] you can't do,
float UNUSED((*coords)[3]) or float (*UNUSED(coords))[3]. This is the only downside to the UNUSED macro I found so far, and in these cases I fall back to (void)coords;.
Seeing that this is marked as gcc you can use the command line switch Wno-unused-parameter.
For example:
gcc -Wno-unused-parameter test.c
Of course this effects the whole file (and maybe project depending where you set the switch) but you don't have to change any code.
With GCC with the unused attribute:
int foo (__attribute__((unused)) int bar) {
return 0;
}
A gcc/g++ specific way to suppress the unused parameter warning for a block of source code is to enclose it with the following pragma statements:
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
<code with unused parameters here>
#pragma GCC diagnostic pop
Since C++ 17, the [[maybe_unused]] attribute can be used to suppress warnings about unused parameters.
Based on the OP's example code:
Bool NullFunc([[maybe_unused]] const struct timespec *when, [[maybe_unused]] const char *who)
{
return TRUE;
}
I got the same problem. I used a third-part library. When I compile this library, the compiler (gcc/clang) will complain about unused variables.
Like this
test.cpp:29:11: warning: variable 'magic' set but not used [-Wunused-but-set-variable]
short magic[] = {
test.cpp:84:17: warning: unused variable 'before_write' [-Wunused-variable]
int64_t before_write = Thread::currentTimeMillis();
So the solution is pretty clear. Adding -Wno-unused as gcc/clang CFLAG will suppress all "unused" warnings, even thought you have -Wall set.
In this way, you DO NOT NEED to change any code.
Labelling the attribute is ideal way. MACRO leads to sometime confusion.
and by using void(x),we are adding an overhead in processing.
If not using input argument, use
void foo(int __attribute__((unused))key)
{
}
If not using the variable defined inside the function
void foo(int key)
{
int hash = 0;
int bkt __attribute__((unused)) = 0;
api_call(x, hash, bkt);
}
Now later using the hash variable for your logic but doesn’t need bkt. define bkt as unused, otherwise compiler says'bkt set bt not used".
NOTE: This is just to suppress the warning not for optimization.
In MSVC to suppress a particular warning it is enough to specify the it's number to compiler as /wd#. My CMakeLists.txt contains such the block:
If (MSVC)
Set (CMAKE_EXE_LINKER_FLAGS "$ {CMAKE_EXE_LINKER_FLAGS} / NODEFAULTLIB: LIBCMT")
Add_definitions (/W4 /wd4512 /wd4702 /wd4100 /wd4510 /wd4355 /wd4127)
Add_definitions (/D_CRT_SECURE_NO_WARNINGS)
Elseif (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUC)
Add_definitions (-Wall -W -pedantic)
Else ()
Message ("Unknown compiler")
Endif ()
Now I can not say what exactly /wd4512 /wd4702 /wd4100 /wd4510 /wd4355 /wd4127 mean, because I do not pay any attention to MSVC for three years, but they suppress superpedantic warnings that does not influence the result.
I've seen this style being used:
if (when || who || format || data || len);
For the record, I like Job's answer, but I'm curious about a solution just using the variable name by itself in a "do-nothing" statement:
void foo(int x) {
x; /* unused */
...
}
Sure, this has drawbacks; for instance, without the "unused" note it looks like a mistake rather than an intentional line of code.
The benefit is that no DEFINE is needed and it gets rid of the warning.