[Bug c++/113852] -Wsign-compare doesn't warn on unsigned result types

2024-02-13 Thread rguenther at suse dot de via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113852

--- Comment #8 from rguenther at suse dot de  ---
On Mon, 12 Feb 2024, admin at computerquip dot com wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113852
> 
> --- Comment #7 from Zachary L  ---
> (In reply to Richard Biener from comment #6)
> > Well, given athat a1 * a2 is carried out in 'int' you are invoking undefined
> > behavior if it overflows.  GCC assumes that doesn't happen so it's correct
> > to elide the diagnostic.  Unless you make overflow well-defined with 
> > -fwrapv.
> > 
> > I think that errors on the right side for the purpose of -Wsign-compare.
> 
> Removing a diagnostic because the program could be ill-formed seems backwards
> to me, especially since it seems like there's already logic in performing this
> diagnostic. Perhaps I've misunderstood the situation?

Well, we could, for each int * int diagnose a "may invoke undefined 
behavior if overflow happens at runtime" but that's hardly useful.
So we want to diagnose cases where it's _likely_ that there's an
issue.

For the case at hand it's not likely that ushort * ushort invokes
undefined behavior (because invoking undefined should be unlikely,
very much so).  So we choose to not diagnose it as "maybe".

Yes, with constexpr evaluation we actually _see_ we invoke undefined
behavior and diagnose that.  The subsequent diagnostic of
-Wsign-compare is then spurious though and IMO should be not given.
The error is the integer overflow invoking undefined behavior even
- if that didn't happen there would be no issue with comparing 
signed/unsigned values.

[Bug c++/113852] -Wsign-compare doesn't warn on unsigned result types

2024-02-12 Thread admin at computerquip dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113852

--- Comment #7 from Zachary L  ---
(In reply to Richard Biener from comment #6)
> Well, given athat a1 * a2 is carried out in 'int' you are invoking undefined
> behavior if it overflows.  GCC assumes that doesn't happen so it's correct
> to elide the diagnostic.  Unless you make overflow well-defined with -fwrapv.
> 
> I think that errors on the right side for the purpose of -Wsign-compare.

Removing a diagnostic because the program could be ill-formed seems backwards
to me, especially since it seems like there's already logic in performing this
diagnostic. Perhaps I've misunderstood the situation?

[Bug c++/113852] -Wsign-compare doesn't warn on unsigned result types

2024-02-12 Thread rguenth at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113852

Richard Biener  changed:

   What|Removed |Added

 CC||rguenth at gcc dot gnu.org

--- Comment #6 from Richard Biener  ---
Well, given athat a1 * a2 is carried out in 'int' you are invoking undefined
behavior if it overflows.  GCC assumes that doesn't happen so it's correct
to elide the diagnostic.  Unless you make overflow well-defined with -fwrapv.

I think that errors on the right side for the purpose of -Wsign-compare.

[Bug c++/113852] -Wsign-compare doesn't warn on unsigned result types

2024-02-09 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113852

--- Comment #5 from Jonathan Wakely  ---
The behaviour changed with r247495

common.opt (fstrict-overflow): Alias negative to fwrapv.

2017-05-02  Richard Biener 

* common.opt (fstrict-overflow): Alias negative to fwrapv.
* doc/invoke.texi (fstrict-overflow): Remove all traces of
-fstrict-overflow documentation.
* tree.h (TYPE_OVERFLOW_UNDEFINED): Do not test flag_strict_overflow.
(POINTER_TYPE_OVERFLOW_UNDEFINED): Test !flag_wrapv instead of
flag_strict_overflow.
* ipa-inline.c (can_inline_edge_p): Do not test flag_strict_overflow.
* lto-opts.c (lto_write_options): Do not stream it.
* lto-wrapper.c (merge_and_complain): Do not handle it.
* opts.c (default_options_table): Do not set -fstrict-overflow.
(finish_options): Likewise do not clear it when sanitizing.
* simplify-rtx.c (simplify_const_relational_operation): Do not
test flag_strict_overflow.

[Bug c++/113852] -Wsign-compare doesn't warn on unsigned result types

2024-02-09 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113852

--- Comment #4 from Jonathan Wakely  ---
Reduced:

int main()
{
unsigned short a1 = (1u << 16) - 1;
unsigned short a2 = a1;

/* a1 * a2 should be 4294836225 in math terms */
unsigned long long a3 = 4294836225;

/*
 * The result of (a1 * a2) is of type int and the result is negative.
 * (a1 * a2) ends up as some bogus high number because the common
 * type here ends up as uint64_t and sign-extension occurs.
 */
if ((a1 * a2) > a3) {
__builtin_abort();
}
}

[Bug c++/113852] -Wsign-compare doesn't warn on unsigned result types

2024-02-09 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113852

--- Comment #3 from Jonathan Wakely  ---
(In reply to Jonathan Wakely from comment #2)
> I assume what's happening is that GCC assumes integer promotion from
> uint16_t to int is value preserving and so we get two positive values, and
> therefore comparison with an unsigned value is fine - there are no negative
> values involved and so it doesn't matter that we're comparing int with
> unsigned long. But of course that's not true here. We have two positive ints
> but their product overflows to produce a negative int. I guess we're also
> assuming no overflow happens, because that would be undefined and we assume
> no UB.

Ah yes, if you add -fwrapv then you get the -Wsign-compare warning, because now
a negative product can occur without undefined overflow.

[Bug c++/113852] -Wsign-compare doesn't warn on unsigned result types

2024-02-09 Thread redi at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113852

Jonathan Wakely  changed:

   What|Removed |Added

   Keywords||diagnostic
 Ever confirmed|0   |1
 Status|UNCONFIRMED |NEW
   Last reconfirmed||2024-02-09

--- Comment #2 from Jonathan Wakely  ---
If a1 and a2 are const then GCC also notices the undefined overflow:

: In function 'int main()':
:18:13: warning: integer overflow in expression of type 'int' results
in '-131071' [-Woverflow]
   18 | if ((a1 * a2) > a3) {
  |  ~~~^~~~
:18:19: warning: comparison of integer expressions of different
signedness: 'int' and 'uint64_t' {aka 'long unsigned int'} [-Wsign-compare]
   18 | if ((a1 * a2) > a3) {
  | ~~^~~~

I don't know why the -Wsign-compare warning is only given when we've detected
the overflow. The types are always the same, whether the values are known to
overflow or not.

I assume what's happening is that GCC assumes integer promotion from uint16_t
to int is value preserving and so we get two positive values, and therefore
comparison with an unsigned value is fine - there are no negative values
involved and so it doesn't matter that we're comparing int with unsigned long.
But of course that's not true here. We have two positive ints but their product
overflows to produce a negative int. I guess we're also assuming no overflow
happens, because that would be undefined and we assume no UB.

When the values are constant we can tell the overflow happens, and no longer
assume it doesn't happen.

[Bug c++/113852] -Wsign-compare doesn't warn on unsigned result types

2024-02-09 Thread admin at computerquip dot com via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113852

--- Comment #1 from Zachary L  ---
Sorry, that should say "If *both* a1 or a2 are constexpr, the warning will
occur."