Conversation
Addresses -Wformat compiler warning.
Addresses -Wimplicit-int compiler warnings.
c409575 to
225d9d5
Compare
lib/gis/spawn.c
Outdated
| } | ||
| else if (arg == SF_REDIRECT_FILE) { | ||
| sp->redirects[sp->num_redirects].dst_fd = NEXT_ARG(va, int); | ||
| sp->redirects[sp->num_redirects].dst_fd = (int)NEXT_ARG(va, intptr_t); |
There was a problem hiding this comment.
The use of intptr_t might need some clarification.
Where pointer size differs from size of integer, the following warning will be issued:
spawn.c: In function ‘parse_argvec’:
spawn.c:734:30: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
734 | #define NEXT_ARG(var, type) ((type) *(var)++)
| ^
spawn.c:747:48: note: in expansion of macro ‘NEXT_ARG’
747 | sp->redirects[sp->num_redirects].dst_fd = NEXT_ARG(va, int);
| ^~~~~~~~
Test of concept:
#include <stdio.h>
#define SF_SIGNAL ((const char *) 4)
#define NEXT_ARG(var, type) ((type) *(var)++)
int main(int argc, const char * argv[])
{
const char *new_argv[2];
const char **va = new_argv;
int int1, int2;
new_argv[0] = SF_SIGNAL;
new_argv[1] = SF_SIGNAL;
// old implementation
int1 = NEXT_ARG(va, int);
// new implementation
int2 = (int)NEXT_ARG(va, intptr_t);
if (int1 == int2)
puts("equal");
else
puts("not equal");
return 0;
}There was a problem hiding this comment.
Are you aware of any system/compiler where pointer size is smaller than integer size? Only under this condition becomes the warning meaningful.
intptr_t requires C99.
According to the logic of spawn.c, it should really be NEXT_ARG(va, int); in L747, because va contains pointers to different types, and here it should be int, thus (int) *(va)++ equals (intptr_t) *(va)++ only if int and intptr_t have the same size.
IMHO, this is the wrong way to suppress the compiler warning.
There was a problem hiding this comment.
Are you aware of any system/compiler where pointer size is smaller than integer size? Only under this condition becomes the warning meaningful.
This is the kind of warning that only adds noise. This code causing the warnings will most likely never cause failure (partly as you say because pointers are not likely to be smaller than ints ). In particular as the int values passed by va are mostly (perhaps exclusively) in the range of 0-9. This is probably the reason I cannot provoke Clang to come up with this warning (despite difference in size between pointer and int). The warnings come from the CIs GCC builds.
However, if there is a valid way to reduce noise, why not.
intptr_t requires C99.
I know.
According to the logic of spawn.c, it should really be NEXT_ARG(va, int); in L747, because va contains pointers to different types, and here it should be int, thus (int) *(va)++ equals (intptr_t) *(va)++ only if int and intptr_t have the same size.
If I'm not totally mistaken, the va pointers "to" ints, are in fact pointers with the value of the int to be passed, not pointer to int. The (int) *(va)++ in fact casts the value of a pointer (of size intptr_t) to an int (hence the warning).
IMHO, this is the wrong way to suppress the compiler warning.
What would you say of adding a macro for reading int:
#define NEXT_ARG_INT(var) (int)((intptr_t) *(var)++)
...
// to be used like:
sp->redirects[sp->num_redirects].dst_fd = NEXT_ARG_INT(va);
this way the code will be cleaner and made obvious of what is expected?
The alternative solutions I can think of are all inelegant and unnecessarily complicated -- or we accept the warnings.
There was a problem hiding this comment.
According to the logic of spawn.c, it should really be NEXT_ARG(va, int); in L747, because va contains pointers to different types, and here it should be int, thus (int) *(va)++ equals (intptr_t) *(va)++ only if int and intptr_t have the same size.
If I'm not totally mistaken, the va pointers "to" ints, are in fact pointers with the value of the int to be passed, not pointer to int. The
(int) *(va)++in fact casts the value of a pointer (of size intptr_t) to an int (hence the warning).
You're right, va is a pointer to pointers of char, the value of interest is not where **va points to, but the address of *va, and the address of the pointer is cast to int (in this case).
IMHO, this is the wrong way to suppress the compiler warning.
What would you say of adding a macro for reading int:
#define NEXT_ARG_INT(var) (int)((intptr_t) *(var)++) ... // to be used like: sp->redirects[sp->num_redirects].dst_fd = NEXT_ARG_INT(va);this way the code will be cleaner and made obvious of what is expected?
But with this on 64bit systems, you are still casting a 64bit int to a 32bit int. We want to cast a pointer to a char (the address of that pointer) to an int, right? Without the compiler complaining about it. This will be an arms race with compilers becoming more clever.
So far,
#define NEXT_ARG_INT(var) (int)((intptr_t) *(var)++)
seems to work without complaints, even though it casts a 64bit int to a 32bit int. Seems to be a feature (?) in gcc that int conversion to a different size is allowed, potentially causing integer overflow.
There was a problem hiding this comment.
It is my understanding that
#define NEXT_ARG_INT(var) (int)((intptr_t) *(var)++) reflects what the compiler actually does. The difference is that in this way the casts are explicit and therefore makes gcc happy.
metzm
left a comment
There was a problem hiding this comment.
This is what we want the compiler to do: cast a pointer to an integer of smaller size. The compiler does not like this and issues a warning. Thus we cast the pointer to an integer of the same size, then cast that integer to a smaller size which the compiler thinks is ok, thus we are tricking the compiler. In this case we are sure that this casting is ok. OK for me to merge.
Thanks a lot for the discussion!
Just pushed an update using new I wouldn't say we're "tricking" the compiler, we just say this particular downcast (if there is any) is ok, is just what we want. |
Addresses -Wformat compiler warning.
Addresses -Wformat-zero-length compiler warnings.
For now only comments out relevant parts. Addresses -Wimplicit-int compiler warnings.
Addresses -Wpointer-to-int-cast compiler warnings.
|
Cherry picked and pushed manually. |
Addresses -Wformat compiler warning.
Addresses -Wformat-zero-length compiler warnings.
For now only comments out relevant parts. Addresses -Wimplicit-int compiler warnings.
Addresses -Wpointer-to-int-cast compiler warnings.
Addresses -Wformat compiler warning.
Addresses -Wformat-zero-length compiler warnings.
For now only comments out relevant parts. Addresses -Wimplicit-int compiler warnings.
Addresses -Wpointer-to-int-cast compiler warnings.
Addresses -Wformat compiler warning.
Addresses -Wformat-zero-length compiler warnings.
For now only comments out relevant parts. Addresses -Wimplicit-int compiler warnings.
Addresses -Wpointer-to-int-cast compiler warnings.
Addresses -Wformat compiler warning.
Addresses -Wformat-zero-length compiler warnings.
For now only comments out relevant parts. Addresses -Wimplicit-int compiler warnings.
Addresses -Wpointer-to-int-cast compiler warnings.
This is a partial, manual backport of OSGeo#1405. The warning is treated as an error by Clang 16+ and the compilation fails.
For now only comments out relevant parts. Addresses -Wimplicit-int compiler warnings. The warning is treated as an error by Clang 16+ and the compilation fails. This is a partial, manual backport of OSGeo#1405, commit 594c947.
Fixes compiler warnings:
Eleventh part addressing #1247.
Modules / code parts directly affected: