This introduces two new headers:
<bits/ranges_base.h> defines the minimal components needed
for using C++20 ranges (customization point objects such as
std::ranges::begin, concepts such as std::ranges::range, etc.)
<bits/ranges_util.h> includes <bits/ranges_base.h> and additionally
defines subrange, which is needed by <bits/ranges_algo.h>.
Most of the content of <bits/ranges_base.h> was previously defined in
<bits/range_access.h>, but a few pieces were only defined in <ranges>.
This meant the entire <ranges> header was needed in <algorithm> and
<memory>, even though they don't use all the range adaptors.
By moving the ranges components out of <bits/range_access.h> that file
is left defining just the contents of [iterator.range] i.e. std::begin,
std::end, std::size etc. and not C++20 ranges components.
For consistency with other C++20 ranges headers, <bits/range_cmp.h> is
renamed to <bits/ranges_cmp.h>.
libstdc++-v3/ChangeLog:
* include/Makefile.am: Add new headers and adjust for renamed
header.
* include/Makefile.in: Regenerate.
* include/bits/iterator_concepts.h: Adjust for renamed header.
* include/bits/range_access.h (ranges::*): Move to new
<bits/ranges_base.h> header.
* include/bits/ranges_algobase.h: Include new <bits/ranges_base.h>
header instead of <ranges>.
* include/bits/ranges_algo.h: Include new <bits/ranges_util.h>
header.
* include/bits/range_cmp.h: Moved to...
* include/bits/ranges_cmp.h: ...here.
* include/bits/ranges_base.h: New header.
* include/bits/ranges_util.h: New header.
* include/experimental/string_view: Include new
<bits/ranges_base.h> header.
* include/std/functional: Adjust for renamed header.
* include/std/ranges (ranges::view_base, ranges::enable_view)
(ranges::dangling, ranges::borrowed_iterator_t): Move to new
<bits/ranges_base.h> header.
(ranges::view_interface, ranges::subrange)
(ranges::borrowed_subrange_t): Move to new <bits/ranges_util.h>
header.
* include/std/span: Include new <bits/ranges_base.h> header.
* include/std/string_view: Likewise.
* testsuite/24_iterators/back_insert_iterator/pr93884.cc: Add
missing <ranges> header.
* testsuite/24_iterators/front_insert_iterator/pr93884.cc:
Likewise.
While backporting 5494edae83 I noticed
that it's still not correct. I made the allocator-extended constructor
use the right type for the uses-allocator construction detection, but I
used an rvalue when it should be a const lvalue.
This should fix it properly this time.
libstdc++-v3/ChangeLog:
PR libstdc++/96803
* include/std/tuple
(_Tuple_impl(allocator_arg_t, Alloc, const _Tuple_impl<U...>&)):
Use correct value category in __use_alloc call.
* testsuite/20_util/tuple/cons/96803.cc: Check with constructors
that require correct value category to be used.
For a span with statically empty extent, we currently model the
preconditions of front(), back(), and operator[] as if they are
mandates, by using a static_assert to verify that extent != 0. This
causes us to reject valid programs that would instantiate these member
functions and at runtime never call them.
Since they are already followed by more general runtime asserts, this
patch just removes these static_asserts altogether,
libstdc++-v3/ChangeLog:
* include/std/span (span::front): Remove static_assert.
(span::back): Likewise.
(span::operator[]): Likewise.
* testsuite/23_containers/span/back_neg.cc: Rewrite to verify
that we check the preconditions of back() only when it's called.
* testsuite/23_containers/span/front_neg.cc: Likewise for
front().
* testsuite/23_containers/span/index_op_neg.cc: Likewise for
operator[].
This fixes a division by zero in the selection-sampling std::__sample
overload when the input range is empty (and hence __unsampled_sz is 0).
libstdc++-v3/ChangeLog:
* include/bits/stl_algo.h (__sample): Exit early when the
input range is empty.
* testsuite/25_algorithms/sample/3.cc: New test.
As per P0202.
libstdc++-v3/ChangeLog:
* include/bits/stl_algo.h (for_each_n): Mark constexpr for C++20.
(search): Likewise for the overload that takes a searcher.
* testsuite/25_algorithms/for_each/constexpr.cc: Test constexpr
std::for_each_n.
* testsuite/25_algorithms/search/constexpr.cc: Test constexpr
std::search overload that takes a searcher.
libstdc++-v3/ChangeLog:
* include/bits/c++config (__replacement_assert): Add noreturn
attribute.
(__glibcxx_assert_impl): Use __builtin_expect to hint that the
assertion is expected to pass.
libstdc++-v3/ChangeLog:
* include/std/ranges (drop_view::begin()): Adjust constraints
to match the correct condition for O(1) ranges::next (LWG 3482).
* testsuite/std/ranges/adaptors/drop.cc: Check that iterator is
cached for non-sized_range.
libstdc++-v3/ChangeLog:
* include/std/ranges (transform_view, elements_view): Relax
constraints on operator- for iterators, as per LWG 3483.
* testsuite/std/ranges/adaptors/elements.cc: Check that we
can take the difference of two iterators from a non-random
access range.
* testsuite/std/ranges/adaptors/transform.cc: Likewise.
The cast from void* to T* in std::assume_aligned is not valid in a
constexpr function. The optimization hint is redundant during constant
evaluation anyway (the compiler can see the object and knows its
alignment). Simply return the original pointer without applying the
__builtin_assume_aligned hint to it when doing constant evaluation.
This change also removes the preprocessor branch that works around
uintptr_t not being available. We already assume that type is present
elsewhere in the library.
libstdc++-v3/ChangeLog:
PR libstdc++/97132
* include/bits/align.h (align) [!_GLIBCXX_USE_C99_STDINT_TR1]:
Remove unused code.
(assume_aligned): Do not use __builtin_assume_aligned during
constant evaluation.
* testsuite/20_util/assume_aligned/1.cc: Improve test.
* testsuite/20_util/assume_aligned/97132.cc: New test.
libstdc++-v3/ChangeLog:
PR libstdc++/97101
* include/std/functional (bind_front): Fix order of parameters
in is_nothrow_constructible_v specialization.
* testsuite/20_util/function_objects/bind_front/97101.cc: New test.
We would like to be able to use std::align and std::assume_aligned
without pulling in everything in <memory>.
libstdc++-v3/ChangeLog:
* include/Makefile.am (bits_headers): Add new header.
* include/Makefile.in: Regenerate.
* include/bits/align.h: New file.
* include/std/memory (align): Move definition to bits/align.h.
(assume_aligned): Likewise.
In C++11 constexpr functions can only have a return statement, so we
need to fix __detail::ceil to make it valid in C++11. This can be done
by moving the comparison and increment into a new function, __ceil_impl,
and calling that with the result of the duration_cast.
This would mean the standard C++17 std::chrono::ceil function would make
two further calls, which would add too much overhead when not inlined.
For C++17 and later use a using-declaration to add chrono::ceil to
namespace __detail. For C++11 and C++14 define chrono::__detail::__ceil
as a C++11-compatible constexpr function template.
libstdc++-v3/ChangeLog:
* include/std/chrono [C++17] (chrono::__detail::ceil): Add
using declaration to make chrono::ceil available for internal
use with a consistent name.
(chrono::__detail::__ceil_impl): New function template.
(chrono::__detail::ceil): Use __ceil_impl to compare and
increment the value. Remove SFINAE constraint.
The fix for PR68519 in 83fd5e73b3 only
applied to condition_variable::wait_for. This problem can also apply to
condition_variable::wait_until but only if the custom clock is using a
more recent epoch so that a small enough delta can be calculated. let's
use the newly-added chrono::__detail::ceil to fix this and also make use
of that function to simplify the previous wait_for fixes.
Also, simplify the existing test case for PR68519 a little and make its
variables local so we can add a new test case for the above problem.
Unfortunately, the test would have only started failing if sufficient
time has passed since the chrono::steady_clock epoch had passed anyway,
but it's better than nothing.
libstdc++-v3/ChangeLog:
* include/std/condition_variable (condition_variable::wait_until):
Convert delta to steady_clock duration before adding to current
steady_clock time to avoid rounding errors described in PR68519.
(condition_variable::wait_for): Simplify calculation of absolute
time by using chrono::__detail::ceil in both overloads.
* testsuite/30_threads/condition_variable/members/68519.cc:
(test_wait_for): Renamed from test01. Replace unassigned val
variable with constant false. Reduce scope of mx and cv
variables to just test_wait_for function.
(test_wait_until): Add new test case.
Convert the specified duration to the target clock's duration type
before adding it to the current time in
__atomic_futex_unsigned::_M_load_when_equal_for and
_M_load_when_equal_until. This removes the risk of the timeout being
rounded down to the current time resulting in there being no wait at all
when the duration type lacks sufficient precision to hold the
steady_clock current time.
Rather than using the style of fix from PR68519, let's expose the C++17
std::chrono::ceil function as std::chrono::__detail::ceil so that it can
be used in code compiled with earlier standards versions and simplify
the fix. This was suggested by John Salmon in
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91486#c5 .
This problem has become considerably less likely to trigger since I
switched the __atomic__futex_unsigned::__clock_t reference clock from
system_clock to steady_clock and added the loop, but the consequences of
triggering it have changed too.
By my calculations it takes just over 194 days from the epoch for the
current time not to be representable in a float. This means that
system_clock is always subject to the problem (with the standard 1970
epoch) whereas steady_clock with float duration only runs out of
resolution machine has been running for that long (assuming the Linux
implementation of CLOCK_MONOTONIC.)
The recently-added loop in
__atomic_futex_unsigned::_M_load_when_equal_until turns this scenario
into a busy wait.
Unfortunately the combination of both of these things means that it's
not possible to write a test case for this occurring in
_M_load_when_equal_until as it stands.
libstdc++-v3/ChangeLog:
PR libstdc++/91486
* include/bits/atomic_futex.h
(__atomic_futex_unsigned::_M_load_when_equal_for)
(__atomic_futex_unsigned::_M_load_when_equal_until): Use
__detail::ceil to convert delta to the reference clock
duration type to avoid resolution problems.
* include/std/chrono (__detail::ceil): Move implementation
of std::chrono::ceil into private namespace so that it's
available to pre-C++17 code.
* testsuite/30_threads/async/async.cc (test_pr91486):
Test __atomic_futex_unsigned::_M_load_when_equal_for.
If std::future::wait_until is passed a time point measured against a
clock that is neither std::chrono::steady_clock nor
std::chrono::system_clock then the generic implementation of
__atomic_futex_unsigned::_M_load_when_equal_until is called which
calculates the timeout based on __clock_t and calls the
_M_load_when_equal_until method for that clock to perform the actual
wait.
There's no guarantee that __clock_t is running at the same speed as the
caller's clock, so if the underlying wait times out timeout we need to
check the timeout against the caller's clock again before potentially
looping.
Also add two extra tests to the testsuite's async.cc:
* run test03 with steady_clock_copy, which behaves identically to
chrono::steady_clock, but isn't chrono::steady_clock. This causes
the overload of __atomic_futex_unsigned::_M_load_when_equal_until
that takes an arbitrary clock to be called.
* invent test04 which uses a deliberately slow running clock in order
to exercise the looping behaviour of
__atomic_futex_unsigned::_M_load_when_equal_until described above.
libstdc++-v3/ChangeLog:
* include/bits/atomic_futex.h
(__atomic_futex_unsigned::_M_load_when_equal_until): Add
loop on generic _Clock to check the timeout against _Clock
again after _M_load_when_equal_until returns indicating a
timeout.
* testsuite/30_threads/async/async.cc: Invent slow_clock
that runs at an eleventh of steady_clock's speed. Use it
to test the user-supplied-clock variant of
__atomic_futex_unsigned::_M_load_when_equal_until works
generally with test03 and loops correctly when the timeout
time hasn't been reached in test04.
The user-visible effect of this change is that std::future::wait_for now
uses std::chrono::steady_clock to determine the timeout. This makes it
immune to changes made to the system clock. It also means that anyone
using their own clock types with std::future::wait_until will have the
timeout converted to std::chrono::steady_clock rather than
std::chrono::system_clock.
Now that use of both std::chrono::steady_clock and
std::chrono::system_clock are correctly supported for the wait timeout, I
believe that std::chrono::steady_clock is a better choice for the reference
clock that all other clocks are converted to since it is guaranteed to
advance steadily. The previous behaviour of converting to
std::chrono::system_clock risks timeouts changing dramatically when the
system clock is changed.
libstdc++-v3/ChangeLog:
* include/bits/atomic_futex.h (__atomic_futex_unsigned): Change
__clock_t typedef to use steady_clock so that unknown clocks are
synced to it rather than system_clock. Change existing __clock_t
overloads of _M_load_and_text_until_impl and
_M_load_when_equal_until to use system_clock explicitly. Remove
comment about DR 887 since these changes address that problem as
best as we currently able.
The user-visible effect of this change is for std::future::wait_until to
use CLOCK_MONOTONIC when passed a timeout of std::chrono::steady_clock
type. This makes it immune to any changes made to the system clock
CLOCK_REALTIME.
Add an overload of __atomic_futex_unsigned::_M_load_and_text_until_impl
that accepts a std::chrono::steady_clock, and correctly passes this
through to __atomic_futex_unsigned_base::_M_futex_wait_until_steady
which uses CLOCK_MONOTONIC for the timeout within the futex system call.
These functions are mostly just copies of the std::chrono::system_clock
versions with small tweaks.
Prior to this commit, a std::chrono::steady timeout would be converted
via std::chrono::system_clock which risks reducing or increasing the
timeout if someone changes CLOCK_REALTIME whilst the wait is happening.
(The commit immediately prior to this one increases the window of
opportunity for that from a short period during the calculation of a
relative timeout, to the entire duration of the wait.)
FUTEX_WAIT_BITSET was added in kernel v2.6.25. If futex reports ENOSYS
to indicate that this operation is not supported then the code falls
back to using clock_gettime(2) to calculate a relative time to wait for.
I believe that I've added this functionality in a way that it doesn't
break ABI compatibility, but that has made it more verbose and less type
safe. I believe that it would be better to maintain the timeout as an
instance of the correct clock type all the way down to a single
_M_futex_wait_until function with an overload for each clock. The
current scheme of separating out the seconds and nanoseconds early risks
accidentally calling the wait function for the wrong clock.
Unfortunately, doing this would break code that compiled against the old
header.
libstdc++-v3/ChangeLog:
* config/abi/pre/gnu.ver: Update for addition of
__atomic_futex_unsigned_base::_M_futex_wait_until_steady.
* include/bits/atomic_futex.h (__atomic_futex_unsigned_base):
Add comments to clarify that _M_futex_wait_until and
_M_load_and_test_until use CLOCK_REALTIME.
(__atomic_futex_unsigned_base::_M_futex_wait_until_steady)
(__atomic_futex_unsigned_base::_M_load_and_text_until_steady):
New member functions that use CLOCK_MONOTONIC.
(__atomic_futex_unsigned_base::_M_load_and_test_until_impl)
(__atomic_futex_unsigned_base::_M_load_when_equal_until): Add
overloads that accept a steady_clock time_point and use the
new member functions.
* src/c++11/futex.cc: Include headers required for
clock_gettime.
(futex_clock_monotonic_flag): New constant to tell futex to
use CLOCK_MONOTONIC to match existing futex_clock_realtime_flag.
(futex_clock_monotonic_unavailable): New global to store the
result of trying to use CLOCK_MONOTONIC.
(__atomic_futex_unsigned_base::_M_futex_wait_until_steady): Add
new variant of _M_futex_wait_until that uses CLOCK_MONOTONIC to
support waiting using steady_clock.
The futex system call supports waiting for an absolute time if
FUTEX_WAIT_BITSET is used rather than FUTEX_WAIT. Doing so provides two
benefits:
1. The call to gettimeofday is not required in order to calculate a
relative timeout.
2. If someone changes the system clock during the wait then the futex
timeout will correctly expire earlier or later. Currently that only
happens if the clock is changed prior to the call to gettimeofday.
According to futex(2), support for FUTEX_CLOCK_REALTIME was added in the
v2.6.28 Linux kernel and FUTEX_WAIT_BITSET was added in v2.6.25. To
ensure that the code still works correctly with earlier kernel versions,
an ENOSYS error from futex[1] results in the
futex_clock_realtime_unavailable flag being set. This flag is used to
avoid the unnecessary unsupported futex call in the future and to fall
back to the previous gettimeofday and relative time implementation.
glibc applied an equivalent switch in pthread_cond_timedwait to use
FUTEX_CLOCK_REALTIME and FUTEX_WAIT_BITSET rather than FUTEX_WAIT for
glibc-2.10 back in 2009. See
glibc:cbd8aeb836c8061c23a5e00419e0fb25a34abee7
The futex_clock_realtime_unavailable flag is accessed using
std::memory_order_relaxed to stop it becoming a bottleneck. If the
first two calls to _M_futex_wait_until happen to happen simultaneously
then the only consequence is that both will try to use
FUTEX_CLOCK_REALTIME, both risk discovering that it doesn't work and, if
so, both set the flag.
[1] This is how glibc's nptl-init.c determines whether these flags are
supported.
libstdc++-v3/ChangeLog:
* src/c++11/futex.cc: Add new constants for required futex
flags. Add futex_clock_realtime_unavailable flag to store
result of trying to use FUTEX_CLOCK_REALTIME.
(__atomic_futex_unsigned_base::_M_futex_wait_until): Try to
use FUTEX_WAIT_BITSET with FUTEX_CLOCK_REALTIME and only
fall back to using gettimeofday and FUTEX_WAIT if that's not
supported.
Add tests for waiting for the future using both chrono::steady_clock and
chrono::system_clock in preparation for dealing with those clocks
properly in futex.cc.
libstdc++-v3/ChangeLog:
* testsuite/30_threads/async/async.cc (test02): Test steady_clock
with std::future::wait_until.
(test03): Add new test templated on clock type waiting for future
associated with async to resolve.
(main): Call test03 to test both system_clock and steady_clock.
When building with -fno-exceptions, bad_exception_allowed is set but
not used, causing a warning during the build.
This patch adds __attribute__((unused)) to avoid it.
2020-09-11 Torbjörn SVENSSON <torbjorn.svensson@st.com>
Christophe Lyon <christophe.lyon@linaro.org>
libstdc++-v3/
* libsupc++/eh_call.cc: Avoid warning with -fno-exceptions.
When building with -fno-exceptions, __throw_exception_again expands to
nothing, causing a "suggest braces around empty body in an 'if'
statement" warning.
This patch adds braces, like what was done in eh_personality.cc in svn
r193295 (git g:54ba39f599fc2f3d59fd3cd828a301ce9b731a20)
2020-09-11 Torbjörn SVENSSON <torbjorn.svensson@st.com>
Christophe Lyon <christophe.lyon@linaro.org>
libstdc++-v3/
* libsupc++/eh_call.cc: Avoid warning with -fno-exceptions.
Including <version> after <iterator> gives a warning about redefining
the __cpp_lib_array_constexpr macro. What happens is that <iterator>
sets the C++20 value, then <version> redefines it to the C++17 value,
then undefines it and defines it again to the C++20 value.
This change avoids defining it to the C++17 value when compiling C++20
or later (which also means we no longer need the #undef).
A similar warning happens for __cpp_lib_constexpr_char_traits when
including <version> after any header that includes <bits/char_traits.h>.
libstdc++-v3/ChangeLog:
* include/std/version (__cpp_lib_array_constexpr):
(__cpp_lib_constexpr_char_traits): Only define C++17 value when
compiling C++17.
libstdc++-v3/ChangeLog:
* include/experimental/bits/shared_ptr.h (shared_ptr(auto_ptr&&))
(operator=(auto_ptr&&)): Add diagnostic pragmas to suppress
warnings for uses of std::auto_ptr.
* include/experimental/type_traits (is_literal_type_v):
Likewise, for use of std::is_literal_type.
* include/std/condition_variable (condition_variable_any::_Unlock):
Likewise, for use of std::uncaught_exception.
When a pool resource is constructed with max_blocks_per_chunk=1 it ends
up creating a pool with blocks_per_chunk=0 which means it never
allocates anything. Instead it returns null pointers, which should be
impossible.
To avoid this problem, round the max_blocks_per_chunk value to a
multiple of four, so it's never smaller than four.
libstdc++-v3/ChangeLog:
PR libstdc++/94160
* src/c++17/memory_resource.cc (munge_options): Round
max_blocks_per_chunk to a multiple of four.
(__pool_resource::_M_alloc_pools()): Simplify slightly.
* testsuite/20_util/unsynchronized_pool_resource/allocate.cc:
Check that valid pointers are returned when small values are
used for max_blocks_per_chunk.
The primary reason for this change is to reduce the size of buffers
allocated by std::pmr::monotonic_buffer_resource. Previously, a new
buffer would always add the size of the linked list node (11 bytes) and
then round up to the next power of two. This results in a huge increase
if the expected size of the next buffer is already a power of two. For
example, if the resource is constructed with a desired initial size of
4096 the first buffer it allocates will be std::bit_ceil(4096+11) which
is 8192. If the user has carefully selected the initial size to match
their expected memory requirements then allocating double that amount
wastes a lot of memory.
After this patch the allocated size will be rounded up to a 64-byte
boundary, instead of to a power of two. This means for an initial size
of 4096 only 4160 bytes get allocated.
Previously only the base-2 logarithm of the size was stored, which could
be stored in a single 8-bit integer. Now that the size isn't always a
power of two we need to use more bits to store it. As the size is always
a multiple of 64 the low six bits are not needed, and so we can use the
same approach that the pool resources already use of storing the base-2
logarithm of the alignment in the low bits that are not used for the
size. To avoid code duplication, a new aligned_size<N> helper class is
introduced by this patch, which is then used by both the pool resources'
big_block type and the monotonic_buffer_resource::_Chunk type.
Originally the big_block type used two bit-fields to store the size and
alignment in the space of a single size_t member. The aligned_size type
uses a single size_t member and uses masks and bitwise operations to
manipulate the size and alignment values. This results in better code
than the old version, because the bit-fields weren't optimally ordered
for little endian architectures, so the alignment was actually stored in
the high bits, not the unused low bits, requiring additional shifts to
calculate the values. Using bitwise operations directly avoids needing
to reorder the bit-fields depending on the endianness.
While adapting the _Chunk and big_block types to use aligned_size<N> I
also added checks for size overflows (technically, unsigned wraparound).
The memory resources now ensure that when they require an allocation
that is too large to represent in size_t they will request SIZE_MAX
bytes from the upstream resource, rather than requesting a small value
that results from wrapround. The testsuite is enhanced to verify this.
libstdc++-v3/ChangeLog:
PR libstdc++/96942
* include/std/memory_resource (monotonic_buffer_resource::do_allocate):
Use __builtin_expect when checking if a new buffer needs to be
allocated from the upstream resource, and for checks for edge
cases like zero sized buffers and allocations.
* src/c++17/memory_resource.cc (aligned_size): New class template.
(aligned_ceil): New helper function to round up to a given
alignment.
(monotonic_buffer_resource::chunk): Replace _M_size and _M_align
with an aligned_size member. Remove _M_canary member. Change _M_next
to pointer instead of unaligned buffer.
(monotonic_buffer_resource::chunk::allocate): Round up to multiple
of 64 instead of to power of two. Check for size overflow. Remove
redundant check for minimum required alignment.
(monotonic_buffer_resource::chunk::release): Adjust for changes
to data members.
(monotonic_buffer_resource::_M_new_buffer): Use aligned_ceil.
(big_block): Replace _M_size and _M_align with aligned_size
member.
(big_block::big_block): Check for size overflow.
(big_block::size, big_block::align): Adjust to use aligned_size.
(big_block::alloc_size): Use aligned_ceil.
(munge_options): Use aligned_ceil.
(__pool_resource::allocate): Use big_block::align for alignment.
* testsuite/20_util/monotonic_buffer_resource/allocate.cc: Check
upstream resource gets expected values for impossible sizes.
* testsuite/20_util/unsynchronized_pool_resource/allocate.cc:
Likewise. Adjust checks for expected alignment in existing test.
We can simplify this constexpr function further because we know that
period::num >= 1 and period::den >= 1 so only the remainder can ever be
zero.
libstdc++-v3/ChangeLog:
* include/std/chrono (duration::_S_gcd): Use invariant that
neither value is zero initially.
This "fix" makes no sense, but it avoids an error from G++ about
std::is_constructible being incomplete. The real problem is elsewhere,
but this "fixes" the regression for now.
libstdc++-v3/ChangeLog:
PR libstdc++/96592
* include/std/tuple (_TupleConstraints<true, T...>): Use
alternative is_constructible instead of std::is_constructible.
* testsuite/20_util/tuple/cons/96592.cc: New test.
The current std::gcd and std::chrono::duration::_S_gcd algorithms are
both recursive. This is potentially expensive to evaluate in constant
expressions, because each level of recursion makes a new copy of the
function to evaluate. The maximum number of steps is bounded
(proportional to the number of decimal digits in the smaller value) and
so unlikely to exceed the limit for constexpr nesting, but the memory
usage is still suboptimal. By using an iterative algorithm we avoid
that compile-time cost. Because looping in constexpr functions is not
allowed until C++14, we need to keep the recursive implementation in
duration::_S_gcd for C++11 mode.
For std::gcd we can also optimise runtime performance by using the
binary GCD algorithm.
libstdc++-v3/ChangeLog:
* include/std/chrono (duration::_S_gcd): Use iterative algorithm
for C++14 and later.
* include/std/numeric (__detail::__gcd): Replace recursive
Euclidean algorithm with iterative version of binary GCD algorithm.
* testsuite/26_numerics/gcd/1.cc: Test additional inputs.
* testsuite/26_numerics/gcd/gcd_neg.cc: Adjust dg-error lines.
* testsuite/26_numerics/lcm/lcm_neg.cc: Likewise.
* testsuite/experimental/numeric/gcd.cc: Test additional inputs.
* testsuite/26_numerics/gcd/2.cc: New test.
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.
The spaceship operator for std::array uses memcmp when the
__is_byte<value_type> trait is true, but memcmp isn't usable in
constexpr contexts. Also, memcmp should only be used for unsigned byte
types, because it gives the wrong answer for signed chars with negative
values.
We can simply check std::is_constant_evaluated() so that we don't use
memcmp during constant evaluation.
To fix the problem of using memcmp for inappropriate types, this patch
adds new __is_memcmp_ordered and __is_memcmp_ordered_with traits. These
say whether using memcmp will give the right answer for ordering
operations such as lexicographical_compare and three-way comparisons.
The new traits can be used in several places, and can also be used to
implement my suggestion in PR 93059 comment 37 to use memcmp for
unsigned integers larger than one byte on big endian targets.
libstdc++-v3/ChangeLog:
PR libstdc++/96851
* include/bits/cpp_type_traits.h (__is_memcmp_ordered):
New trait that says if memcmp can be used for ordering.
(__is_memcmp_ordered_with): Likewise, for two types.
* include/bits/deque.tcc (__lex_cmp_dit): Use new traits
instead of __is_byte and __numeric_traits.
(__lexicographical_compare_aux1): Likewise.
* include/bits/ranges_algo.h (__lexicographical_compare_fn):
Likewise.
* include/bits/stl_algobase.h (__lexicographical_compare_aux1)
(__is_byte_iter): Likewise.
* include/std/array (operator<=>): Likewise. Only use memcmp
when std::is_constant_evaluated() is false.
* testsuite/23_containers/array/comparison_operators/96851.cc:
New test.
* testsuite/23_containers/array/tuple_interface/get_neg.cc:
Adjust dg-error line numbers.