public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug libstdc++/92978] std::gcd mishandles mixed-signedness
[not found] <bug-92978-4@http.gcc.gnu.org/bugzilla/>
@ 2020-08-28 14:23 ` redi at gcc dot gnu.org
2020-08-28 22:11 ` cvs-commit at gcc dot gnu.org
` (10 subsequent siblings)
11 siblings, 0 replies; 12+ messages in thread
From: redi at gcc dot gnu.org @ 2020-08-28 14:23 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92978
Jonathan Wakely <redi at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|NEW |ASSIGNED
Assignee|unassigned at gcc dot gnu.org |redi at gcc dot gnu.org
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Bug libstdc++/92978] std::gcd mishandles mixed-signedness
[not found] <bug-92978-4@http.gcc.gnu.org/bugzilla/>
2020-08-28 14:23 ` [Bug libstdc++/92978] std::gcd mishandles mixed-signedness redi at gcc dot gnu.org
@ 2020-08-28 22:11 ` cvs-commit at gcc dot gnu.org
2020-08-28 22:12 ` redi at gcc dot gnu.org
` (9 subsequent siblings)
11 siblings, 0 replies; 12+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2020-08-28 22:11 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92978
--- Comment #1 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:
https://gcc.gnu.org/g:82db1a42e9254c9009bbf8ac01366da4d1ab6df5
commit r11-2929-g82db1a42e9254c9009bbf8ac01366da4d1ab6df5
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Fri Aug 28 22:45:24 2020 +0100
libstdc++: Fix std::gcd and std::lcm for unsigned integers [PR 92978]
This fixes a bug with mixed signed and unsigned types, where converting
a negative value to the unsigned result type alters the value. The
solution is to obtain the absolute values of the arguments immediately
and to perform the actual GCD or LCM algorithm on two arguments of the
same type.
In order to operate on the most negative number without overflow when
taking its absolute, use an unsigned type for the result of the abs
operation. For example, -INT_MIN will overflow, but -(unsigned)INT_MIN
is (unsigned)INT_MAX+1U which is the correct value.
libstdc++-v3/ChangeLog:
PR libstdc++/92978
* include/std/numeric (__abs_integral): Replace with ...
(__detail::__absu): New function template that returns an
unsigned type, guaranteeing it can represent the most
negative signed value.
(__detail::__gcd, __detail::__lcm): Require arguments to
be unsigned and therefore already non-negative.
(gcd, lcm): Convert arguments to absolute value as unsigned
type before calling __detail::__gcd or __detail::__lcm.
* include/experimental/numeric (gcd, lcm): Likewise.
* testsuite/26_numerics/gcd/gcd_neg.cc: Adjust expected
errors.
* testsuite/26_numerics/lcm/lcm_neg.cc: Likewise.
* testsuite/26_numerics/gcd/92978.cc: New test.
* testsuite/26_numerics/lcm/92978.cc: New test.
* testsuite/experimental/numeric/92978.cc: New test.
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Bug libstdc++/92978] std::gcd mishandles mixed-signedness
[not found] <bug-92978-4@http.gcc.gnu.org/bugzilla/>
2020-08-28 14:23 ` [Bug libstdc++/92978] std::gcd mishandles mixed-signedness redi at gcc dot gnu.org
2020-08-28 22:11 ` cvs-commit at gcc dot gnu.org
@ 2020-08-28 22:12 ` redi at gcc dot gnu.org
2020-09-02 16:23 ` cvs-commit at gcc dot gnu.org
` (8 subsequent siblings)
11 siblings, 0 replies; 12+ messages in thread
From: redi at gcc dot gnu.org @ 2020-08-28 22:12 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92978
Jonathan Wakely <redi at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Target Milestone|--- |9.4
--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Fixed on trunk so far.
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Bug libstdc++/92978] std::gcd mishandles mixed-signedness
[not found] <bug-92978-4@http.gcc.gnu.org/bugzilla/>
` (2 preceding siblings ...)
2020-08-28 22:12 ` redi at gcc dot gnu.org
@ 2020-09-02 16:23 ` cvs-commit at gcc dot gnu.org
2020-09-02 16:32 ` cvs-commit at gcc dot gnu.org
` (7 subsequent siblings)
11 siblings, 0 replies; 12+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2020-09-02 16:23 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92978
--- Comment #3 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:
https://gcc.gnu.org/g:c71644776f4e8477289a4de16239dbb420db6945
commit r11-2983-gc71644776f4e8477289a4de16239dbb420db6945
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Wed Sep 2 17:20:37 2020 +0100
libstdc++: Fix test to use correct function
This was copied from a test for std::lcm but I forgot to change one of
the calls to use the experimental version of the function.
libstdc++-v3/ChangeLog:
PR libstdc++/92978
* testsuite/experimental/numeric/92978.cc: Use experimental::lcm
not std::lcm.
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Bug libstdc++/92978] std::gcd mishandles mixed-signedness
[not found] <bug-92978-4@http.gcc.gnu.org/bugzilla/>
` (3 preceding siblings ...)
2020-09-02 16:23 ` cvs-commit at gcc dot gnu.org
@ 2020-09-02 16:32 ` cvs-commit at gcc dot gnu.org
2020-09-21 23:14 ` cvs-commit at gcc dot gnu.org
` (6 subsequent siblings)
11 siblings, 0 replies; 12+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2020-09-02 16:32 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92978
--- Comment #4 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-10 branch has been updated by Jonathan Wakely
<redi@gcc.gnu.org>:
https://gcc.gnu.org/g:31782bd45331ef3006f624d7b1cc9cd11b4abb84
commit r10-8703-g31782bd45331ef3006f624d7b1cc9cd11b4abb84
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Fri Aug 28 22:45:24 2020 +0100
libstdc++: Fix std::gcd and std::lcm for unsigned integers [PR 92978]
This fixes a bug with mixed signed and unsigned types, where converting
a negative value to the unsigned result type alters the value. The
solution is to obtain the absolute values of the arguments immediately
and to perform the actual GCD or LCM algorithm on two arguments of the
same type.
In order to operate on the most negative number without overflow when
taking its absolute, use an unsigned type for the result of the abs
operation. For example, -INT_MIN will overflow, but -(unsigned)INT_MIN
is (unsigned)INT_MAX+1U which is the correct value.
libstdc++-v3/ChangeLog:
PR libstdc++/92978
* include/std/numeric (__abs_integral): Replace with ...
(__detail::__absu): New function template that returns an
unsigned type, guaranteeing it can represent the most
negative signed value.
(__detail::__gcd, __detail::__lcm): Require arguments to
be unsigned and therefore already non-negative.
(gcd, lcm): Convert arguments to absolute value as unsigned
type before calling __detail::__gcd or __detail::__lcm.
* include/experimental/numeric (gcd, lcm): Likewise.
* testsuite/26_numerics/gcd/gcd_neg.cc: Adjust expected
errors.
* testsuite/26_numerics/lcm/lcm_neg.cc: Likewise.
* testsuite/26_numerics/gcd/92978.cc: New test.
* testsuite/26_numerics/lcm/92978.cc: New test.
* testsuite/experimental/numeric/92978.cc: New test.
(cherry picked from commit 82db1a42e9254c9009bbf8ac01366da4d1ab6df5)
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Bug libstdc++/92978] std::gcd mishandles mixed-signedness
[not found] <bug-92978-4@http.gcc.gnu.org/bugzilla/>
` (4 preceding siblings ...)
2020-09-02 16:32 ` cvs-commit at gcc dot gnu.org
@ 2020-09-21 23:14 ` cvs-commit at gcc dot gnu.org
2020-11-16 21:58 ` cvs-commit at gcc dot gnu.org
` (5 subsequent siblings)
11 siblings, 0 replies; 12+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2020-09-21 23:14 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92978
--- Comment #5 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-9 branch has been updated by Jonathan Wakely
<redi@gcc.gnu.org>:
https://gcc.gnu.org/g:b3043e490896ea37cd0273e6e149c3eeb3298720
commit r9-8928-gb3043e490896ea37cd0273e6e149c3eeb3298720
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Fri Aug 28 22:45:24 2020 +0100
libstdc++: Fix std::gcd and std::lcm for unsigned integers [PR 92978]
This fixes a bug with mixed signed and unsigned types, where converting
a negative value to the unsigned result type alters the value. The
solution is to obtain the absolute values of the arguments immediately
and to perform the actual GCD or LCM algorithm on two arguments of the
same type.
In order to operate on the most negative number without overflow when
taking its absolute, use an unsigned type for the result of the abs
operation. For example, -INT_MIN will overflow, but -(unsigned)INT_MIN
is (unsigned)INT_MAX+1U which is the correct value.
libstdc++-v3/ChangeLog:
PR libstdc++/92978
* include/std/numeric (__abs_integral): Replace with ...
(__detail::__absu): New function template that returns an
unsigned type, guaranteeing it can represent the most
negative signed value.
(__detail::__gcd, __detail::__lcm): Require arguments to
be unsigned and therefore already non-negative.
(gcd, lcm): Convert arguments to absolute value as unsigned
type before calling __detail::__gcd or __detail::__lcm.
* include/experimental/numeric (gcd, lcm): Likewise.
* testsuite/26_numerics/gcd/gcd_neg.cc: Adjust expected
errors.
* testsuite/26_numerics/lcm/lcm_neg.cc: Likewise.
* testsuite/26_numerics/gcd/92978.cc: New test.
* testsuite/26_numerics/lcm/92978.cc: New test.
* testsuite/experimental/numeric/92978.cc: New test.
(cherry picked from commit 82db1a42e9254c9009bbf8ac01366da4d1ab6df5)
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Bug libstdc++/92978] std::gcd mishandles mixed-signedness
[not found] <bug-92978-4@http.gcc.gnu.org/bugzilla/>
` (5 preceding siblings ...)
2020-09-21 23:14 ` cvs-commit at gcc dot gnu.org
@ 2020-11-16 21:58 ` cvs-commit at gcc dot gnu.org
2020-11-16 21:59 ` redi at gcc dot gnu.org
` (4 subsequent siblings)
11 siblings, 0 replies; 12+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2020-11-16 21:58 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92978
--- Comment #6 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-8 branch has been updated by Jonathan Wakely
<redi@gcc.gnu.org>:
https://gcc.gnu.org/g:7dbed9dead9002ee0cd4aa9c22b20942c6f13757
commit r8-10624-g7dbed9dead9002ee0cd4aa9c22b20942c6f13757
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Fri Aug 28 22:45:24 2020 +0100
libstdc++: Fix std::gcd and std::lcm for unsigned integers [PR 92978]
This fixes a bug with mixed signed and unsigned types, where converting
a negative value to the unsigned result type alters the value. The
solution is to obtain the absolute values of the arguments immediately
and to perform the actual GCD or LCM algorithm on two arguments of the
same type.
In order to operate on the most negative number without overflow when
taking its absolute, use an unsigned type for the result of the abs
operation. For example, -INT_MIN will overflow, but -(unsigned)INT_MIN
is (unsigned)INT_MAX+1U which is the correct value.
libstdc++-v3/ChangeLog:
PR libstdc++/92978
* include/std/numeric (__abs_integral): Replace with ...
(__detail::__absu): New function template that returns an
unsigned type, guaranteeing it can represent the most
negative signed value.
(__detail::__gcd, __detail::__lcm): Require arguments to
be unsigned and therefore already non-negative.
(gcd, lcm): Convert arguments to absolute value as unsigned
type before calling __detail::__gcd or __detail::__lcm.
* include/experimental/numeric (gcd, lcm): Likewise.
* testsuite/26_numerics/gcd/gcd_neg.cc: Adjust expected
errors.
* testsuite/26_numerics/lcm/lcm_neg.cc: Likewise.
* testsuite/26_numerics/gcd/92978.cc: New test.
* testsuite/26_numerics/lcm/92978.cc: New test.
* testsuite/experimental/numeric/92978.cc: New test.
(cherry picked from commit 82db1a42e9254c9009bbf8ac01366da4d1ab6df5)
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Bug libstdc++/92978] std::gcd mishandles mixed-signedness
[not found] <bug-92978-4@http.gcc.gnu.org/bugzilla/>
` (6 preceding siblings ...)
2020-11-16 21:58 ` cvs-commit at gcc dot gnu.org
@ 2020-11-16 21:59 ` redi at gcc dot gnu.org
2022-06-10 14:24 ` cvs-commit at gcc dot gnu.org
` (3 subsequent siblings)
11 siblings, 0 replies; 12+ messages in thread
From: redi at gcc dot gnu.org @ 2020-11-16 21:59 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92978
Jonathan Wakely <redi at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Resolution|--- |FIXED
Status|ASSIGNED |RESOLVED
Target Milestone|9.4 |8.5
--- Comment #7 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Fixed for 8.4, 9.4, 10.3 and 11.
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Bug libstdc++/92978] std::gcd mishandles mixed-signedness
[not found] <bug-92978-4@http.gcc.gnu.org/bugzilla/>
` (7 preceding siblings ...)
2020-11-16 21:59 ` redi at gcc dot gnu.org
@ 2022-06-10 14:24 ` cvs-commit at gcc dot gnu.org
2022-08-03 13:46 ` cvs-commit at gcc dot gnu.org
` (2 subsequent siblings)
11 siblings, 0 replies; 12+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2022-06-10 14:24 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92978
--- Comment #8 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:
https://gcc.gnu.org/g:671970a5621e18e7079b4ca113e56434c858db66
commit r13-1040-g671970a5621e18e7079b4ca113e56434c858db66
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Fri Jun 10 14:39:13 2022 +0100
libstdc++: Make std::lcm and std::gcd detect overflow [PR105844]
When I fixed PR libstdc++/92978 I introduced a regression whereby
std::lcm(INT_MIN, 1) and std::lcm(50000, 49999) would no longer produce
errors during constant evaluation. Those calls are undefined, because
they violate the preconditions that |m| and the result can be
represented in the return type (which is int in both those cases). The
regression occurred because __absu<unsigned>(INT_MIN) is well-formed,
due to the explicit casts to unsigned in that new helper function, and
the out-of-range multiplication is well-formed, because unsigned
arithmetic wraps instead of overflowing.
To fix 92978 I made std::gcm and std::lcm calculate |m| and |n|
immediately, yielding a common unsigned type that was used to calculate
the result. That was partly correct, but there's no need to use an
unsigned type. Doing so only suppresses the overflow errors so the
compiler can't detect them. This change replaces __absu with __abs_r
that returns the common type (not its corresponding unsigned type). This
way we can detect overflow in __abs_r when required, while still
supporting the most-negative value when it can be represented in the
result type. To detect LCM results that are out of range of the result
type we still need explicit checks, because neither constant evaluation
nor UBsan will complain about unsigned wrapping for cases such as
std::lcm(500000u, 499999u). We can detect those overflows efficiently by
using __builtin_mul_overflow and asserting.
libstdc++-v3/ChangeLog:
PR libstdc++/105844
* include/experimental/numeric (experimental::gcd): Simplify
assertions. Use __abs_r instead of __absu.
(experimental::lcm): Likewise. Remove use of __detail::__lcm so
overflow can be detected.
* include/std/numeric (__detail::__absu): Rename to __abs_r and
change to allow signed result type, so overflow can be detected.
(__detail::__lcm): Remove.
(gcd): Simplify assertions. Use __abs_r instead of __absu.
(lcm): Likewise. Remove use of __detail::__lcm so overflow can
be detected.
* testsuite/26_numerics/gcd/gcd_neg.cc: Adjust dg-error lines.
* testsuite/26_numerics/lcm/lcm_neg.cc: Likewise.
* testsuite/26_numerics/gcd/105844.cc: New test.
* testsuite/26_numerics/lcm/105844.cc: New test.
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Bug libstdc++/92978] std::gcd mishandles mixed-signedness
[not found] <bug-92978-4@http.gcc.gnu.org/bugzilla/>
` (8 preceding siblings ...)
2022-06-10 14:24 ` cvs-commit at gcc dot gnu.org
@ 2022-08-03 13:46 ` cvs-commit at gcc dot gnu.org
2023-05-03 15:02 ` cvs-commit at gcc dot gnu.org
2023-05-03 16:34 ` cvs-commit at gcc dot gnu.org
11 siblings, 0 replies; 12+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2022-08-03 13:46 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92978
--- Comment #9 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-12 branch has been updated by Jonathan Wakely
<redi@gcc.gnu.org>:
https://gcc.gnu.org/g:8a57deb926cd660c2eae7ed621d61a301ae0d523
commit r12-8654-g8a57deb926cd660c2eae7ed621d61a301ae0d523
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Fri Jun 10 14:39:13 2022 +0100
libstdc++: Make std::lcm and std::gcd detect overflow [PR105844]
When I fixed PR libstdc++/92978 I introduced a regression whereby
std::lcm(INT_MIN, 1) and std::lcm(50000, 49999) would no longer produce
errors during constant evaluation. Those calls are undefined, because
they violate the preconditions that |m| and the result can be
represented in the return type (which is int in both those cases). The
regression occurred because __absu<unsigned>(INT_MIN) is well-formed,
due to the explicit casts to unsigned in that new helper function, and
the out-of-range multiplication is well-formed, because unsigned
arithmetic wraps instead of overflowing.
To fix 92978 I made std::gcm and std::lcm calculate |m| and |n|
immediately, yielding a common unsigned type that was used to calculate
the result. That was partly correct, but there's no need to use an
unsigned type. Doing so only suppresses the overflow errors so the
compiler can't detect them. This change replaces __absu with __abs_r
that returns the common type (not its corresponding unsigned type). This
way we can detect overflow in __abs_r when required, while still
supporting the most-negative value when it can be represented in the
result type. To detect LCM results that are out of range of the result
type we still need explicit checks, because neither constant evaluation
nor UBsan will complain about unsigned wrapping for cases such as
std::lcm(500000u, 499999u). We can detect those overflows efficiently by
using __builtin_mul_overflow and asserting.
libstdc++-v3/ChangeLog:
PR libstdc++/105844
* include/experimental/numeric (experimental::gcd): Simplify
assertions. Use __abs_r instead of __absu.
(experimental::lcm): Likewise. Remove use of __detail::__lcm so
overflow can be detected.
* include/std/numeric (__detail::__absu): Rename to __abs_r and
change to allow signed result type, so overflow can be detected.
(__detail::__lcm): Remove.
(gcd): Simplify assertions. Use __abs_r instead of __absu.
(lcm): Likewise. Remove use of __detail::__lcm so overflow can
be detected.
* testsuite/26_numerics/gcd/gcd_neg.cc: Adjust dg-error lines.
* testsuite/26_numerics/lcm/lcm_neg.cc: Likewise.
* testsuite/26_numerics/gcd/105844.cc: New test.
* testsuite/26_numerics/lcm/105844.cc: New test.
(cherry picked from commit 671970a5621e18e7079b4ca113e56434c858db66)
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Bug libstdc++/92978] std::gcd mishandles mixed-signedness
[not found] <bug-92978-4@http.gcc.gnu.org/bugzilla/>
` (9 preceding siblings ...)
2022-08-03 13:46 ` cvs-commit at gcc dot gnu.org
@ 2023-05-03 15:02 ` cvs-commit at gcc dot gnu.org
2023-05-03 16:34 ` cvs-commit at gcc dot gnu.org
11 siblings, 0 replies; 12+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2023-05-03 15:02 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92978
--- Comment #10 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-11 branch has been updated by Jonathan Wakely
<redi@gcc.gnu.org>:
https://gcc.gnu.org/g:7c31a9c66269805d57591549edb031f84d84f9b0
commit r11-10739-g7c31a9c66269805d57591549edb031f84d84f9b0
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Fri Jun 10 14:39:13 2022 +0100
libstdc++: Make std::lcm and std::gcd detect overflow [PR105844]
When I fixed PR libstdc++/92978 I introduced a regression whereby
std::lcm(INT_MIN, 1) and std::lcm(50000, 49999) would no longer produce
errors during constant evaluation. Those calls are undefined, because
they violate the preconditions that |m| and the result can be
represented in the return type (which is int in both those cases). The
regression occurred because __absu<unsigned>(INT_MIN) is well-formed,
due to the explicit casts to unsigned in that new helper function, and
the out-of-range multiplication is well-formed, because unsigned
arithmetic wraps instead of overflowing.
To fix 92978 I made std::gcm and std::lcm calculate |m| and |n|
immediately, yielding a common unsigned type that was used to calculate
the result. That was partly correct, but there's no need to use an
unsigned type. Doing so only suppresses the overflow errors so the
compiler can't detect them. This change replaces __absu with __abs_r
that returns the common type (not its corresponding unsigned type). This
way we can detect overflow in __abs_r when required, while still
supporting the most-negative value when it can be represented in the
result type. To detect LCM results that are out of range of the result
type we still need explicit checks, because neither constant evaluation
nor UBsan will complain about unsigned wrapping for cases such as
std::lcm(500000u, 499999u). We can detect those overflows efficiently by
using __builtin_mul_overflow and asserting.
libstdc++-v3/ChangeLog:
PR libstdc++/105844
* include/experimental/numeric (experimental::gcd): Simplify
assertions. Use __abs_r instead of __absu.
(experimental::lcm): Likewise. Remove use of __detail::__lcm so
overflow can be detected.
* include/std/numeric (__detail::__absu): Rename to __abs_r and
change to allow signed result type, so overflow can be detected.
(__detail::__lcm): Remove.
(gcd): Simplify assertions. Use __abs_r instead of __absu.
(lcm): Likewise. Remove use of __detail::__lcm so overflow can
be detected.
* testsuite/26_numerics/gcd/gcd_neg.cc: Adjust dg-error lines.
* testsuite/26_numerics/lcm/lcm_neg.cc: Likewise.
* testsuite/26_numerics/gcd/105844.cc: New test.
* testsuite/26_numerics/lcm/105844.cc: New test.
(cherry picked from commit 671970a5621e18e7079b4ca113e56434c858db66)
^ permalink raw reply [flat|nested] 12+ messages in thread
* [Bug libstdc++/92978] std::gcd mishandles mixed-signedness
[not found] <bug-92978-4@http.gcc.gnu.org/bugzilla/>
` (10 preceding siblings ...)
2023-05-03 15:02 ` cvs-commit at gcc dot gnu.org
@ 2023-05-03 16:34 ` cvs-commit at gcc dot gnu.org
11 siblings, 0 replies; 12+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2023-05-03 16:34 UTC (permalink / raw)
To: gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92978
--- Comment #11 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-10 branch has been updated by Jonathan Wakely
<redi@gcc.gnu.org>:
https://gcc.gnu.org/g:14175f2262c94868e26f01eef1e14418f2b5e6a9
commit r10-11388-g14175f2262c94868e26f01eef1e14418f2b5e6a9
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Fri Jun 10 14:39:13 2022 +0100
libstdc++: Make std::lcm and std::gcd detect overflow [PR105844]
When I fixed PR libstdc++/92978 I introduced a regression whereby
std::lcm(INT_MIN, 1) and std::lcm(50000, 49999) would no longer produce
errors during constant evaluation. Those calls are undefined, because
they violate the preconditions that |m| and the result can be
represented in the return type (which is int in both those cases). The
regression occurred because __absu<unsigned>(INT_MIN) is well-formed,
due to the explicit casts to unsigned in that new helper function, and
the out-of-range multiplication is well-formed, because unsigned
arithmetic wraps instead of overflowing.
To fix 92978 I made std::gcm and std::lcm calculate |m| and |n|
immediately, yielding a common unsigned type that was used to calculate
the result. That was partly correct, but there's no need to use an
unsigned type. Doing so only suppresses the overflow errors so the
compiler can't detect them. This change replaces __absu with __abs_r
that returns the common type (not its corresponding unsigned type). This
way we can detect overflow in __abs_r when required, while still
supporting the most-negative value when it can be represented in the
result type. To detect LCM results that are out of range of the result
type we still need explicit checks, because neither constant evaluation
nor UBsan will complain about unsigned wrapping for cases such as
std::lcm(500000u, 499999u). We can detect those overflows efficiently by
using __builtin_mul_overflow and asserting.
libstdc++-v3/ChangeLog:
PR libstdc++/105844
* include/experimental/numeric (experimental::gcd): Simplify
assertions. Use __abs_r instead of __absu.
(experimental::lcm): Likewise. Remove use of __detail::__lcm so
overflow can be detected.
* include/std/numeric (__detail::__absu): Rename to __abs_r and
change to allow signed result type, so overflow can be detected.
(__detail::__lcm): Remove.
(gcd): Simplify assertions. Use __abs_r instead of __absu.
(lcm): Likewise. Remove use of __detail::__lcm so overflow can
be detected.
* testsuite/26_numerics/gcd/gcd_neg.cc: Adjust dg-error lines.
* testsuite/26_numerics/lcm/lcm_neg.cc: Likewise.
* testsuite/26_numerics/gcd/105844.cc: New test.
* testsuite/26_numerics/lcm/105844.cc: New test.
(cherry picked from commit 671970a5621e18e7079b4ca113e56434c858db66)
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2023-05-03 16:34 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <bug-92978-4@http.gcc.gnu.org/bugzilla/>
2020-08-28 14:23 ` [Bug libstdc++/92978] std::gcd mishandles mixed-signedness redi at gcc dot gnu.org
2020-08-28 22:11 ` cvs-commit at gcc dot gnu.org
2020-08-28 22:12 ` redi at gcc dot gnu.org
2020-09-02 16:23 ` cvs-commit at gcc dot gnu.org
2020-09-02 16:32 ` cvs-commit at gcc dot gnu.org
2020-09-21 23:14 ` cvs-commit at gcc dot gnu.org
2020-11-16 21:58 ` cvs-commit at gcc dot gnu.org
2020-11-16 21:59 ` redi at gcc dot gnu.org
2022-06-10 14:24 ` cvs-commit at gcc dot gnu.org
2022-08-03 13:46 ` cvs-commit at gcc dot gnu.org
2023-05-03 15:02 ` cvs-commit at gcc dot gnu.org
2023-05-03 16:34 ` cvs-commit at gcc dot gnu.org
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).