[Bug c/99997] Missed optimisation with -Os
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=7 Matthew Wilcox changed: What|Removed |Added CC||matthew at wil dot cx --- Comment #1 from Matthew Wilcox --- Actually, it should eliminate the one _after_ the L2 label. It just moved the constant 1 into %eax and doesn't need to limit it again.
[Bug c/97287] New: Warn for expanding range of an arithmetic type
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97287 Bug ID: 97287 Summary: Warn for expanding range of an arithmetic type Product: gcc Version: 11.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: matthew at wil dot cx Target Milestone: --- I've just fixed multiple instances of bugs that look a lot like function f() when they should have been function g(). This affects filesystems in Linux which have to remember to cast an unsigned long to an off_t before shifting (or there will be a bug on 32-bit kernels when dealing with files that are larger than 4GB). When I looked for a warning option to add, I thought -Warith-conversions might do the job, but it doesn't. Maybe this functionality should be added there, or maybe it should have its own warning. I think what we're looking for is an operation which expands the range of the type (left shift, multiplication, addition; maybe subtraction?) and the rules of C require the operation to be done in a narrower type, but the result is assigned to a wider type. unsigned long long f(unsigned int i) { return i * 4096; } unsigned long long g(unsigned int i) { return i * 4096ULL; }
[Bug c/101645] New: -Wsign-conversion misses negation of unsigned int
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101645 Bug ID: 101645 Summary: -Wsign-conversion misses negation of unsigned int Product: gcc Version: 12.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: matthew at wil dot cx Target Milestone: --- Test case: unsigned long a(void); void b(long); void c(void) { unsigned int x = a(); b(-x); } There is a missed warning in the call to b(). x is negated, but as an int. It is then passed to b() which sees a very large positive number instead of a small negative number. This has recently affected the Linux codebase, and it's disappointing that gcc doesn't have a warning that we could enable to find it. https://godbolt.org/z/xvaxh1rqr shows that Clang does spot this with -Wsign-conversion, but GCC currently doesn't (it only warns for line 4 and not line 5). Admittedly the Clang diagnostic message isn't the greatest, but at least it says _something_.
[Bug c/101645] warn about neg of unsigned type should be added to -Wsign-conversion
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101645 --- Comment #4 from Matthew Wilcox --- On second thoughts -Wsign-conversion is useless. Consider that it warns on this: unsigned long f(unsigned long x, int y) { return x + y; } Both gcc and clang emit a warning, which makes it useless. That code obviously does what the programmer intended. What would be useful is a warning which diagnoses code which behaves differently in infinite-precision arithmetic vs the C promotion rules. For example, unsigned long g(unsigned char v, int s) { return v << s; } By the C standard, v is promoted to int, shifted by s and then promoted to unsigned long. This is a fertile source of bugs as it's easy to overlook that v will not be promoted to unsigned long first. (by the way, this is another example where clang diagnoses with -Wsign-compare and gcc doesn't.) Another example plucked from real life: long long h(unsigned int x) { return x * 4096; } (slightly changed to demonstrate the problem on LP64; the original was from unsigned long to long long, and it is only a bug on ILP32)