aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog62
-rw-r--r--libstdc++-v3/include/bits/regex.tcc49
-rw-r--r--libstdc++-v3/include/bits/version.def9
-rw-r--r--libstdc++-v3/include/bits/version.h10
-rw-r--r--libstdc++-v3/include/std/regex1
-rw-r--r--libstdc++-v3/include/std/tuple53
-rw-r--r--libstdc++-v3/include/std/type_traits17
-rw-r--r--libstdc++-v3/src/c++23/std.cc.in4
-rw-r--r--libstdc++-v3/testsuite/17_intro/headers/c++2011/42319.cc4
-rw-r--r--libstdc++-v3/testsuite/20_util/is_implicit_lifetime/value.cc129
-rw-r--r--libstdc++-v3/testsuite/20_util/is_implicit_lifetime/version.cc27
-rw-r--r--libstdc++-v3/testsuite/20_util/tuple/requirements/empty_trivial.cc17
-rw-r--r--libstdc++-v3/testsuite/23_containers/tuple/cons/119721.cc121
-rw-r--r--libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock_until/116586.cc29
-rw-r--r--libstdc++-v3/testsuite/30_threads/thread/swap/1.cc2
15 files changed, 502 insertions, 32 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index 77ab059..e270c67 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,65 @@
+2025-10-30 Jakub Jelinek <jakub@redhat.com>
+
+ * include/bits/version.def (is_implicit_lifetime): New.
+ * include/bits/version.h: Regenerate.
+ * include/std/type_traits (std::is_implicit_lifetime,
+ std::is_implicit_lifetime_v): New trait.
+ * src/c++23/std.cc.in (std::is_implicit_lifetime,
+ std::is_implicit_lifetime_v): Export.
+ * testsuite/20_util/is_implicit_lifetime/version.cc: New test.
+ * testsuite/20_util/is_implicit_lifetime/value.cc: New test.
+
+2025-10-29 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/regex.tcc (regex_traits::value): Use __c instead
+ of __ch.
+
+2025-10-29 Jonathan Wakely <jwakely@redhat.com>
+
+ * testsuite/17_intro/headers/c++2011/42319.cc: Include <ios>
+ instead of <bits/char_traits.h>. Add no_pch option. Remove
+ explicit -std=gnu++11 option.
+ * testsuite/30_threads/thread/swap/1.cc: Include <utility>
+ instead of <bits/move.h>.
+
+2025-10-29 Tomasz Kamiński <tkaminsk@redhat.com>
+
+ PR libstdc++/119721
+ * include/std/tuple (tuple<>::operator=(const _Tuple&) const)
+ [__cpp_lib_ranges_zip]: Define.
+ * testsuite/23_containers/tuple/cons/119721.cc: Test const
+ assignment.
+
+2025-10-29 Osama Abdelkader <osama.abdelkader@gmail.com>
+ Tomasz Kamiński <tkaminsk@redhat.com>
+
+ PR libstdc++/119721
+ * include/std/tuple (tuple<>::tuple(const tuple&))
+ (tuple<>::operator=(const tuple&)): Define as defaulted.
+ (tuple<>::swap): Moved the defintion after assignments.
+ (tuple<>::tuple(_UTuple&&))
+ (tuple<>::tuple(allocator_arg_t, const _Alloc&, _UTuple&&))
+ (tuple<>::operator=(_UTuple&&)) [__cpp_lib_tuple_like]: Define.
+ (tuple<>::operator==, tuple<>::opeator<=>): Parenthesize
+ constrains individually.
+ * testsuite/23_containers/tuple/cons/119721.cc: New test for
+ constructors and assignments with empty tuple-like types.
+ * testsuite/20_util/tuple/requirements/empty_trivial.cc:
+ New test verifying tuple<> remains trivially copyable.
+
+2025-10-29 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/regex.tcc (regex_traits::value): Implement
+ without using istringstream.
+ * include/std/regex: Do not include <sstream>.
+
+2025-10-28 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/122401
+ * testsuite/30_threads/shared_timed_mutex/try_lock_until/116586.cc:
+ Do not try to acquire locks on the thread that already holds a
+ lock. Add -pthread for et pthread.
+
2025-10-27 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/122401
diff --git a/libstdc++-v3/include/bits/regex.tcc b/libstdc++-v3/include/bits/regex.tcc
index b94fe44..48917cd 100644
--- a/libstdc++-v3/include/bits/regex.tcc
+++ b/libstdc++-v3/include/bits/regex.tcc
@@ -331,20 +331,53 @@ namespace __detail
&& __c == __fctyp.widen('_'));
}
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
template<typename _Ch_type>
int
regex_traits<_Ch_type>::
value(_Ch_type __ch, int __radix) const
{
- std::basic_istringstream<char_type> __is(string_type(1, __ch));
- long __v;
- if (__radix == 8)
- __is >> std::oct;
- else if (__radix == 16)
- __is >> std::hex;
- __is >> __v;
- return __is.fail() ? -1 : __v;
+ if constexpr (sizeof(_Ch_type) > 1)
+ {
+ const auto& __ctyp = std::use_facet<ctype<_Ch_type>>(_M_locale);
+ const char __c = __ctyp.narrow(__ch, '\0');
+ return regex_traits<char>{}.value(__c, __radix);
+ }
+ else
+ {
+ const char __c = static_cast<char>(__ch);
+ const char __max_digit = __radix == 8 ? '7' : '9';
+ if ('0' <= __c && __c <= __max_digit)
+ return __c - '0';
+ if (__radix < 16)
+ return -1;
+ switch (__c)
+ {
+ case 'a':
+ case 'A':
+ return 10;
+ case 'b':
+ case 'B':
+ return 11;
+ case 'c':
+ case 'C':
+ return 12;
+ case 'd':
+ case 'D':
+ return 13;
+ case 'e':
+ case 'E':
+ return 14;
+ case 'f':
+ case 'F':
+ return 15;
+ default:
+ return -1;
+ }
+ }
}
+#pragma GCC diagnostic pop
template<typename _Bi_iter, typename _Alloc>
template<typename _Out_iter>
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index 1bf98f7..29ecf15 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -2191,6 +2191,15 @@ ftms = {
};
};
+ftms = {
+ name = is_implicit_lifetime;
+ values = {
+ v = 202302;
+ cxxmin = 23;
+ extra_cond = "__has_builtin(__builtin_is_implicit_lifetime)";
+ };
+};
+
// Standard test specifications.
stds[97] = ">= 199711L";
stds[03] = ">= 199711L";
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index 66de8b4..5901d27 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -2455,4 +2455,14 @@
#endif /* !defined(__cpp_lib_philox_engine) */
#undef __glibcxx_want_philox_engine
+#if !defined(__cpp_lib_is_implicit_lifetime)
+# if (__cplusplus >= 202100L) && (__has_builtin(__builtin_is_implicit_lifetime))
+# define __glibcxx_is_implicit_lifetime 202302L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_is_implicit_lifetime)
+# define __cpp_lib_is_implicit_lifetime 202302L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_is_implicit_lifetime) */
+#undef __glibcxx_want_is_implicit_lifetime
+
#undef __glibcxx_want_all
diff --git a/libstdc++-v3/include/std/regex b/libstdc++-v3/include/std/regex
index 0223066..9121d26 100644
--- a/libstdc++-v3/include/std/regex
+++ b/libstdc++-v3/include/std/regex
@@ -41,7 +41,6 @@
#include <bitset>
#include <locale>
-#include <sstream>
#include <stack>
#include <stdexcept>
#include <string>
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index c064a92..d4db125 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -1984,14 +1984,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
class tuple<>
{
public:
+ // We need the default since we're going to define no-op
+ // allocator constructors.
+ tuple() = default;
+ // Defaulted copy operations to maintain trivial copyability.
+ // and support non-const assignment expressions.
+ tuple(const tuple&) = default;
+ tuple& operator=(const tuple&) = default;
+
_GLIBCXX20_CONSTEXPR
void swap(tuple&) noexcept { /* no-op */ }
+
#if __cpp_lib_ranges_zip // >= C++23
- constexpr void swap(const tuple&) const noexcept { /* no-op */ }
+ template<same_as<tuple> _Tuple = tuple>
+ constexpr const tuple&
+ operator=(const _Tuple&) const noexcept
+ { return *this; }
+
+ constexpr void swap(const tuple&) const noexcept
+ { /* no-op */ }
#endif
- // We need the default since we're going to define no-op
- // allocator constructors.
- tuple() = default;
+
// No-op allocator constructors.
template<typename _Alloc>
_GLIBCXX20_CONSTEXPR
@@ -2001,16 +2014,42 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { }
#if __cpp_lib_tuple_like // >= C++23
- // Comparison operators for tuple<> with other empty tuple-like types
template<__tuple_like _UTuple>
- requires (!__is_tuple_v<_UTuple> && tuple_size_v<_UTuple> == 0)
+ requires (!is_same_v<remove_cvref_t<_UTuple>, tuple>)
+ && (!is_same_v<remove_cvref_t<_UTuple>, allocator_arg_t>)
+ && (tuple_size_v<remove_cvref_t<_UTuple>> == 0)
+ constexpr
+ tuple(_UTuple&&) noexcept { }
+
+ template<typename _Alloc, __tuple_like _UTuple>
+ requires (!is_same_v<remove_cvref_t<_UTuple>, tuple>)
+ && (tuple_size_v<remove_cvref_t<_UTuple>> == 0)
+ constexpr
+ tuple(allocator_arg_t, const _Alloc&, _UTuple&&) noexcept { }
+
+ template<__tuple_like _UTuple>
+ requires (!is_same_v<remove_cvref_t<_UTuple>, tuple>)
+ && (tuple_size_v<remove_cvref_t<_UTuple>> == 0)
+ constexpr tuple&
+ operator=(_UTuple&&) noexcept
+ { return *this; }
+
+ template<__tuple_like _UTuple>
+ requires (!is_same_v<remove_cvref_t<_UTuple>, tuple>)
+ && (tuple_size_v<remove_cvref_t<_UTuple>> == 0)
+ constexpr const tuple&
+ operator=(_UTuple&&) const noexcept
+ { return *this; }
+
+ template<__tuple_like _UTuple>
+ requires (!__is_tuple_v<_UTuple>) && (tuple_size_v<_UTuple> == 0)
[[nodiscard]]
friend constexpr bool
operator==(const tuple&, const _UTuple&) noexcept
{ return true; }
template<__tuple_like _UTuple>
- requires (!__is_tuple_v<_UTuple> && tuple_size_v<_UTuple> == 0)
+ requires (!__is_tuple_v<_UTuple>) && (tuple_size_v<_UTuple> == 0)
friend constexpr strong_ordering
operator<=>(const tuple&, const _UTuple&) noexcept
{ return strong_ordering::equal; }
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 77ebb7e..d28b0773 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -47,6 +47,7 @@
#define __glibcxx_want_is_aggregate
#define __glibcxx_want_is_constant_evaluated
#define __glibcxx_want_is_final
+#define __glibcxx_want_is_implicit_lifetime
#define __glibcxx_want_is_invocable
#define __glibcxx_want_is_layout_compatible
#define __glibcxx_want_is_nothrow_convertible
@@ -4053,6 +4054,22 @@ template<typename _Ret, typename _Fn, typename... _Args>
# endif
#endif
+#ifdef __cpp_lib_is_implicit_lifetime // C++ >= 23
+ /// True if the type is an implicit-lifetime type.
+ /// @since C++23
+
+ template<typename _Tp>
+ struct is_implicit_lifetime
+ : bool_constant<__builtin_is_implicit_lifetime(_Tp)>
+ { };
+
+ /// @ingroup variable_templates
+ /// @since C++23
+ template<typename _Tp>
+ inline constexpr bool is_implicit_lifetime_v
+ = __builtin_is_implicit_lifetime(_Tp);
+#endif
+
#ifdef __cpp_lib_reference_from_temporary // C++ >= 23 && ref_{converts,constructs}_from_temp
/// True if _Tp is a reference type, a _Up value can be bound to _Tp in
/// direct-initialization, and a temporary object would be bound to
diff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in
index 4c11b1b..28f0e8c 100644
--- a/libstdc++-v3/src/c++23/std.cc.in
+++ b/libstdc++-v3/src/c++23/std.cc.in
@@ -3230,6 +3230,10 @@ export namespace std
using std::is_scoped_enum;
using std::is_scoped_enum_v;
#endif
+#if __cpp_lib_is_implicit_lifetime
+ using std::is_implicit_lifetime;
+ using std::is_implicit_lifetime_v;
+#endif
}
// <typeindex>
diff --git a/libstdc++-v3/testsuite/17_intro/headers/c++2011/42319.cc b/libstdc++-v3/testsuite/17_intro/headers/c++2011/42319.cc
index cd576ca..350a548 100644
--- a/libstdc++-v3/testsuite/17_intro/headers/c++2011/42319.cc
+++ b/libstdc++-v3/testsuite/17_intro/headers/c++2011/42319.cc
@@ -1,5 +1,5 @@
// { dg-do compile }
-// { dg-options "-std=gnu++11" }
+// { dg-add-options no_pch }
// Copyright (C) 2009-2025 Free Software Foundation, Inc.
//
@@ -19,4 +19,4 @@
// <http://www.gnu.org/licenses/>.
// libstdc++/42319
-#include <bits/char_traits.h>
+#include <ios>
diff --git a/libstdc++-v3/testsuite/20_util/is_implicit_lifetime/value.cc b/libstdc++-v3/testsuite/20_util/is_implicit_lifetime/value.cc
new file mode 100644
index 0000000..d8cb181
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_implicit_lifetime/value.cc
@@ -0,0 +1,129 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++23 } }
+// { dg-add-options no_pch }
+
+#include <type_traits>
+
+#ifndef __cpp_lib_is_implicit_lifetime
+# error "Feature test macro for is_implicit_lifetime is missing in <type_traits>"
+#elif __cpp_lib_is_implicit_lifetime < 202302L
+# error "Feature test macro for is_implicit_lifetime has wrong value in <type_traits>"
+#endif
+
+#include <testsuite_tr1.h>
+
+template<typename T>
+ concept Is_implicit_lifetime
+ = __gnu_test::test_category<std::is_implicit_lifetime, T>(true);
+
+static_assert( ! Is_implicit_lifetime<void> );
+static_assert( ! Is_implicit_lifetime<const void> );
+static_assert( ! Is_implicit_lifetime<volatile void> );
+static_assert( Is_implicit_lifetime<char> );
+static_assert( Is_implicit_lifetime<signed char> );
+static_assert( Is_implicit_lifetime<const unsigned char> );
+static_assert( Is_implicit_lifetime<short> );
+static_assert( Is_implicit_lifetime<volatile unsigned short> );
+static_assert( Is_implicit_lifetime<int> );
+static_assert( Is_implicit_lifetime<unsigned int> );
+static_assert( Is_implicit_lifetime<const volatile long> );
+static_assert( Is_implicit_lifetime<unsigned long> );
+static_assert( Is_implicit_lifetime<long long> );
+static_assert( Is_implicit_lifetime<unsigned long long> );
+static_assert( Is_implicit_lifetime<float> );
+static_assert( Is_implicit_lifetime<double> );
+static_assert( Is_implicit_lifetime<long double volatile> );
+enum W { W1 };
+static_assert( Is_implicit_lifetime<W> );
+enum class X : int { X1 };
+static_assert( Is_implicit_lifetime<const volatile X> );
+static_assert( Is_implicit_lifetime<int *> );
+static_assert( Is_implicit_lifetime<int (*) (int)> );
+struct Y { int g; int foo (int); };
+static_assert( Is_implicit_lifetime<int (Y::*)> );
+static_assert( Is_implicit_lifetime<int (Y::*) (int)> );
+static_assert( ! Is_implicit_lifetime<int &> );
+static_assert( ! Is_implicit_lifetime<char &&> );
+static_assert( Is_implicit_lifetime<int []> );
+static_assert( Is_implicit_lifetime<int [1]> );
+static_assert( Is_implicit_lifetime<const Y [42]> );
+static_assert( ! Is_implicit_lifetime<int ()> );
+static_assert( ! Is_implicit_lifetime<int () &> );
+static_assert( ! Is_implicit_lifetime<int () const> );
+static_assert( ! Is_implicit_lifetime<int (&) ()> );
+struct Z;
+static_assert( Is_implicit_lifetime<Z []> );
+static_assert( Is_implicit_lifetime<Z [5]> );
+struct A { int a, b, c; };
+static_assert( Is_implicit_lifetime<A> );
+class B { static int a; private: static int b; public: int c; };
+static_assert( Is_implicit_lifetime<B> );
+struct C { C () {} int a, b, c; };
+static_assert( Is_implicit_lifetime<C> );
+struct D { explicit D (int) {} int a, b, c; };
+static_assert( Is_implicit_lifetime<D> );
+struct E : public A { int d, e, f; };
+static_assert( Is_implicit_lifetime<E> );
+struct F : public C { using C::C; int d, e, f; };
+static_assert( Is_implicit_lifetime<F> );
+class G { int a, b; };
+static_assert( Is_implicit_lifetime<G> );
+struct H { private: int a, b; };
+static_assert( Is_implicit_lifetime<H> );
+struct I { protected: int a, b; };
+static_assert( Is_implicit_lifetime<I> );
+struct J { int a, b; void foo (); };
+static_assert( Is_implicit_lifetime<J> );
+struct K { int a, b; virtual void foo (); };
+static_assert( ! Is_implicit_lifetime<K> );
+struct L : virtual public A { int d, e; };
+static_assert( ! Is_implicit_lifetime<L> );
+struct M : protected A { int d, e; };
+static_assert( Is_implicit_lifetime<M> );
+struct N : private A { int d, e; };
+static_assert( Is_implicit_lifetime<N> );
+struct O { O () = delete; int a, b, c; };
+static_assert( Is_implicit_lifetime<O> );
+struct P { P () = default; int a, b, c; };
+static_assert( Is_implicit_lifetime<P> );
+struct Q { Q (); Q (const Q &); int a, b, c; };
+static_assert( ! Is_implicit_lifetime<Q> );
+struct R { R (); R (const R &); R (R &&) = default; int a, b, c; };
+static_assert( Is_implicit_lifetime<R> );
+struct S { S (); ~S (); int a, b, c; };
+static_assert( ! Is_implicit_lifetime<S> );
+static_assert( Is_implicit_lifetime<S [3]> );
+struct T { T (); ~T () = default; int a, b, c; };
+static_assert( Is_implicit_lifetime<T> );
+struct U { U (); U (const U &) = default; int a, b, c; };
+static_assert( Is_implicit_lifetime<U> );
+struct V { V () = default; V (const V &); int a, b, c; };
+static_assert( Is_implicit_lifetime<V> );
+struct AA { Q a; Q b; };
+static_assert( Is_implicit_lifetime<AA> );
+struct AB { Q a; Q b; ~AB () = default; };
+static_assert( Is_implicit_lifetime<AB> );
+struct AC { Q a; Q b; ~AC () {} };
+static_assert( ! Is_implicit_lifetime<AC> );
+struct AD : public Q {};
+static_assert( Is_implicit_lifetime<AD> );
+struct AE : public Q { ~AE () = default; };
+static_assert( Is_implicit_lifetime<AE> );
+struct AF : public Q { ~AF () {} };
+static_assert( ! Is_implicit_lifetime<AF> );
diff --git a/libstdc++-v3/testsuite/20_util/is_implicit_lifetime/version.cc b/libstdc++-v3/testsuite/20_util/is_implicit_lifetime/version.cc
new file mode 100644
index 0000000..ed90b47
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_implicit_lifetime/version.cc
@@ -0,0 +1,27 @@
+// Copyright (C) 2025 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++23 } }
+// { dg-add-options no_pch }
+
+#include <version>
+
+#ifndef __cpp_lib_is_implicit_lifetime
+# error "Feature test macro for is_implicit_lifetime is missing in <version>"
+#elif __cpp_lib_is_implicit_lifetime < 202302L
+# error "Feature test macro for is_implicit_lifetime has wrong value in <version>"
+#endif
diff --git a/libstdc++-v3/testsuite/20_util/tuple/requirements/empty_trivial.cc b/libstdc++-v3/testsuite/20_util/tuple/requirements/empty_trivial.cc
new file mode 100644
index 0000000..ee18bb3
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/tuple/requirements/empty_trivial.cc
@@ -0,0 +1,17 @@
+// { dg-do compile { target c++11 } }
+
+#include <tuple>
+#include <type_traits>
+
+// Check that tuple<> has the expected trivial properties
+static_assert(std::is_trivially_copyable<std::tuple<>>::value,
+ "tuple<> should be trivially copyable");
+static_assert(std::is_trivially_copy_constructible<std::tuple<>>::value,
+ "tuple<> should be trivially copy constructible");
+static_assert(std::is_trivially_move_constructible<std::tuple<>>::value,
+ "tuple<> should be trivially move constructible");
+static_assert(std::is_trivially_copy_assignable<std::tuple<>>::value,
+ "tuple<> should be trivially copy assignable");
+static_assert(std::is_trivially_move_assignable<std::tuple<>>::value,
+ "tuple<> should be trivially move assignable");
+
diff --git a/libstdc++-v3/testsuite/23_containers/tuple/cons/119721.cc b/libstdc++-v3/testsuite/23_containers/tuple/cons/119721.cc
new file mode 100644
index 0000000..1d15238
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/tuple/cons/119721.cc
@@ -0,0 +1,121 @@
+// { dg-do run { target c++23 } }
+
+// Test for PR libstdc++/119721: tuple<> construction/assignment with array<T, 0>
+
+#include <tuple>
+#include <array>
+#include <memory>
+#include <testsuite_hooks.h>
+
+constexpr void
+test01()
+{
+ std::array<int, 0> a{};
+
+ // Constructor from array<int, 0>
+ std::tuple<> t1(a);
+ std::tuple<> t2(std::move(a));
+
+ // Assignment from array<int, 0>
+ std::tuple<> t3;
+ t3 = a;
+ t3 = std::move(a);
+
+ VERIFY( t1 == a );
+ VERIFY( t2 == a );
+ VERIFY( t3 == a );
+}
+
+constexpr void
+test02()
+{
+ // Test with non-comparable element type
+ struct NonComparable
+ {
+ void operator==(const NonComparable&) const = delete;
+ void operator<=>(const NonComparable&) const = delete;
+ };
+
+ std::array<NonComparable, 0> a{};
+
+ std::tuple<> t1(a);
+ std::tuple<> t2(std::move(a));
+
+ std::tuple<> t3;
+ t3 = a;
+ t3 = std::move(a);
+
+ VERIFY( t1 == a );
+}
+
+constexpr void
+test03()
+{
+ // Test assignment return type (non-const assignment)
+ std::tuple<> t, u;
+ std::tuple<>& r1 = (t = u);
+ VERIFY( &r1 == &t );
+
+ std::tuple<>& r2 = (t = {});
+ VERIFY( &r2 == &t );
+
+ std::array<int, 0> a{};
+ std::tuple<>& r3 = (t = a);
+ VERIFY( &r3 == &t );
+}
+
+constexpr void
+test04()
+{
+ std::array<int, 0> a{};
+ const std::tuple<> t1;
+
+ // Const assignment from array
+ std::tuple<> t2;
+ const std::tuple<>& r1 = (t1 = t2);
+ VERIFY( &r1 == &t1 );
+ const std::tuple<>& r2 = (t1 = std::move(t2));
+ VERIFY( &r2 == &t1 );
+
+ const std::tuple<>& r3 = (t1 = {});
+ VERIFY( &r3 == &t1 );
+
+ // Const assignment from array
+ const std::tuple<>& r4 = (t1 = a);
+ VERIFY( &r4 == &t1 );
+ const std::tuple<>& r5 = (t1 = std::move(a));
+ VERIFY( &r5 == &t1 );
+}
+
+void
+test05()
+{
+ std::array<int, 0> a{};
+ std::allocator<int> alloc;
+
+ // Allocator constructor from array
+ std::tuple<> t1(std::allocator_arg, alloc, a);
+ std::tuple<> t2(std::allocator_arg, alloc, std::move(a));
+
+ VERIFY( t1 == a );
+ VERIFY( t2 == a );
+}
+
+int main()
+{
+ auto test_all = [] {
+ test01();
+ test02();
+ test03();
+ test04();
+ return true;
+ };
+
+ test_all();
+ static_assert( test_all() );
+
+ // allocator test is not constexpr
+ test05();
+ return 0;
+}
+
diff --git a/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock_until/116586.cc b/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock_until/116586.cc
index cebbb3a..5736b7d 100644
--- a/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock_until/116586.cc
+++ b/libstdc++-v3/testsuite/30_threads/shared_timed_mutex/try_lock_until/116586.cc
@@ -1,4 +1,7 @@
// { dg-do run { target c++14 } }
+// { dg-additional-options "-pthread" { target pthread } }
+// { dg-require-gthreads "" }
+// { dg-require-effective-target hosted }
#include <shared_mutex>
#include <chrono>
@@ -8,10 +11,18 @@
namespace chrono = std::chrono;
-// thread.timedmutex.requirements.general:
+// [thread.timedmutex.requirements.general]:
// If abs_time has already passed, the function attempts to obtain
// ownership without blocking (as if by calling try_lock()).
+// C++14 [thread.sharedtimedmutex.class] 3.2 says it's undefined for a thread
+// to attempt to recursively gain any ownership of a shared_timed_mutex.
+// This isn't just theoretical, as Glibc's pthread_rwlock_timedrdlock will
+// return EDEADLK if called on the same thread that already holds the
+// exclusive (write) lock.
+#define VERIFY_IN_NEW_THREAD(X) \
+ (void) std::async(std::launch::async, [&] { VERIFY(X); })
+
template <typename Clock>
void
test_exclusive_absolute(chrono::nanoseconds offset)
@@ -19,7 +30,7 @@ test_exclusive_absolute(chrono::nanoseconds offset)
std::shared_timed_mutex stm;
chrono::time_point<Clock> tp(offset);
VERIFY(stm.try_lock_until(tp));
- VERIFY(!stm.try_lock_until(tp));
+ VERIFY_IN_NEW_THREAD(!stm.try_lock_until(tp));
}
template <typename Clock>
@@ -32,15 +43,7 @@ test_shared_absolute(chrono::nanoseconds offset)
stm.unlock_shared();
VERIFY(stm.try_lock_for(chrono::seconds{10}));
-
- {
- // NPTL will give us EDEADLK if pthread_rwlock_timedrdlock() is called on
- // the same thread that already holds the exclusive (write) lock, so let's
- // arrange for a different thread to try to acquire the shared lock.
- auto t = std::async(std::launch::async, [&stm, tp]() {
- VERIFY(!stm.try_lock_shared_until(tp));
- });
- }
+ VERIFY_IN_NEW_THREAD(!stm.try_lock_shared_until(tp));
}
// The type of clock used for the actual wait depends on whether
@@ -53,7 +56,7 @@ test_exclusive_relative(chrono::nanoseconds offset)
std::shared_timed_mutex stm;
const auto d = -Clock::now().time_since_epoch() + offset;
VERIFY(stm.try_lock_for(d));
- VERIFY(!stm.try_lock_for(d));
+ VERIFY_IN_NEW_THREAD(!stm.try_lock_for(d));
}
template <typename Clock>
@@ -66,7 +69,7 @@ test_shared_relative(chrono::nanoseconds offset)
stm.unlock_shared();
// Should complete immediately
VERIFY(stm.try_lock_for(chrono::seconds{10}));
- VERIFY(!stm.try_lock_shared_for(d));
+ VERIFY_IN_NEW_THREAD(!stm.try_lock_shared_for(d));
}
int main()
diff --git a/libstdc++-v3/testsuite/30_threads/thread/swap/1.cc b/libstdc++-v3/testsuite/30_threads/thread/swap/1.cc
index 9616b15..b1fde09 100644
--- a/libstdc++-v3/testsuite/30_threads/thread/swap/1.cc
+++ b/libstdc++-v3/testsuite/30_threads/thread/swap/1.cc
@@ -23,7 +23,7 @@
#include <thread>
#include <system_error>
-#include <bits/move.h> // std::move
+#include <utility> // std::move
#include <testsuite_hooks.h>
void f() { }