Permit compiling with -W, which comes handy when compiling radix.c in (userland) applications with stricter build policies.
Details
- Reviewers
donner melifaro - Group Reviewers
network - Commits
- rGb77bee7642ae: Appease -Wsign-compare in radix.c
rG63dceebe6856: Appease -Wsign-compare in radix.c
Diff Detail
- Repository
- rG FreeBSD src repository
- Lint
Lint Not Applicable - Unit
Tests Not Applicable
Event Timeline
May you please provide a full context diff?
I can't see, why the compiler issued a warning and how the fix will break other things (i.e. logic errors)
Diff updated, the build breaks at:
../../../net/radix.c:459:13: warning: comparison of integers of different signs: 'int' and 'unsigned int' [-Wsign-compare]
} while (b > (unsigned) x->rn_bit); ~ ^ ~~~~~~~~~~~~~~~~~~~~
The variable b and the struct member rn_bit are both signed values because they are supposed to hold negative numbers.
sys/net/radix.c | ||
---|---|---|
459 | In this special case, the negative values of rn_bit are considered as absurd high values, while b is used as a signed value later on. | |
459 | The correct way might be something like b > x->rn_bit && x->rn_bit >= 0 |
sys/net/radix.c | ||
---|---|---|
459 |
This is exactly what the original author (@rgrimes? ksklower?) left in a comment a line below. The current form of that condition: b > (unsigned) x->rn_bit looks like an optimization which removes one branch. The problem is that the compiler silently converts (signed) b to unsigned, but complaints if -Wsign-compare is turned on. If you're concerned with declaring b as unsigned, we could simply make the current reality more explicit: (unsigned) b > (unsigned) x->rn_bit which looks plain ugly to me, but is guaranteed to be a no-op change, and will silence the -Wsign-compare, which is the end goal I want to achieve. | |
459 |
Without pretending I actually understand everything what the existing code does, I fail to see how b could become negative here, and the fact that it is later used unmodified as an argument to rn_newpair() can't make it negative / overflow either. |
sys/net/radix.c | ||
---|---|---|
459 |
Yes it is.
This is not logical equivalent to the original statement. It's more (b > x->rn_bit && x->rn_bit >= 0 && b >= 0) || (b < x->rn_bit && x->rn_bit < 0 && b < 0) |
sys/net/radix.c | ||
---|---|---|
459 |
You might be right, but I did not have enough knowledge of the code to validate this easily. |
sys/net/radix.c | ||
---|---|---|
459 |
The current condition in line 459 is this: b > (unsigned) x->rn_bit where, as an alternative to the original diff you objected to, I'm suggesting to make explicit type casting instead of implicit: (unsigned) b > (unsigned) x->rn_bit Please elaborate how exactly the two conditions differ. |
sys/net/radix.c | ||
---|---|---|
459 |
b = -2 and x->rn_bit = 1 give false and true, respectively |
sys/net/radix.c | ||
---|---|---|
459 |
Wrong answer. Pls. compile the snippet below and report back the results. #include <stdio.h> int int b, x; scanf("%d", &b); scanf("%d", &x); printf("b: %d x: %d\n", b, x); if (b > (unsigned) x) printf("%d > %d\n", b, x); if ((unsigned) b > (unsigned) x) printf("%d > %d\n", b, x); } |
https://blog.regehr.org/archives/268
It's complicated.
#include <stdio.h> int main(int argc, char **argv) { int b; unsigned short x; scanf("%d", &b); scanf("%hd", &x); printf("b: %d x: %d\n", b, x); if (b > x) printf("%d > %d\n", b, x); else printf("failed\n"); if ((unsigned) b > x) printf("%d > %d\n", b, x); else printf("failed\n"); }
So the (unsigned) conversion is also a size conversion (to int). This can become relevant, if somebody try to refine the types of the struct to save memory.
So yes, covert both sides is a solution.