[gcc r15-7764] libstdc++: Add static_assertions to ranges::to adaptor factory [PR112803]

2025-02-28 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:a9cfcd0d9e3780c71442057f636f62a7142056cb

commit r15-7764-ga9cfcd0d9e3780c71442057f636f62a7142056cb
Author: Jonathan Wakely 
Date:   Thu Feb 27 15:48:49 2025 +

libstdc++: Add static_assertions to ranges::to adaptor factory [PR112803]

The standard requires that we reject attempts to create a ranges::to
adaptor for cv-qualified types and non-class types. Currently we only
diagnose it once the adaptor is used in a pipeline.

This adds static assertions to diagnose it immediately.

libstdc++-v3/ChangeLog:

PR libstdc++/112803
* include/std/ranges (ranges::to): Add static assertions to
enforce Mandates conditions.
* testsuite/std/ranges/conv/112803.cc: New test.

Diff:
---
 libstdc++-v3/include/std/ranges  |  3 +++
 libstdc++-v3/testsuite/std/ranges/conv/112803.cc | 20 
 2 files changed, 23 insertions(+)

diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index 6c65722b687e..c0b1134ab328 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -9569,6 +9569,9 @@ namespace __detail
 constexpr auto
 to [[nodiscard]] (_Args&&... __args)
 {
+  static_assert(!is_const_v<_Cont> && !is_volatile_v<_Cont>);
+  static_assert(is_class_v<_Cont>);
+
   using __detail::_To;
   using views::__adaptor::_Partial;
   return _Partial<_To<_Cont>, decay_t<_Args>...>{0, 
std::forward<_Args>(__args)...};
diff --git a/libstdc++-v3/testsuite/std/ranges/conv/112803.cc 
b/libstdc++-v3/testsuite/std/ranges/conv/112803.cc
new file mode 100644
index ..0a73b0200b0c
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/ranges/conv/112803.cc
@@ -0,0 +1,20 @@
+// { dg-do compile { target c++23 } }
+
+// Bug 112803 - : to(Args&&... args) is missing Mandates
+
+#include 
+
+void
+test()
+{
+  struct C { };
+
+  (void) std::ranges::to(); // { dg-error "here" }
+  (void) std::ranges::to(); // { dg-error "here" }
+  (void) std::ranges::to(); // { dg-error "here" }
+  (void) std::ranges::to(); // { dg-error "here" }
+  (void) std::ranges::to(); // { dg-error "here" }
+  (void) std::ranges::to(); // { dg-error "here" }
+}
+
+// { dg-error "static assertion failed" "" { target *-*-* } 0 }


[gcc r15-7765] libstdc++: Fix ranges::move and ranges::move_backward to use iter_move [PR105609]

2025-02-28 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:3866ca796d5281d33f25b4165badacf8f198c6d1

commit r15-7765-g3866ca796d5281d33f25b4165badacf8f198c6d1
Author: Jonathan Wakely 
Date:   Thu Feb 27 13:27:17 2025 +

libstdc++: Fix ranges::move and ranges::move_backward to use iter_move 
[PR105609]

The ranges::move and ranges::move_backward algorithms are supposed to
use ranges::iter_move(iter) instead of std::move(*iter), which matters
for an iterator type with an iter_move overload findable by ADL.

Currently those algorithms use std::__assign_one which uses std::move,
so define a new ranges::__detail::__assign_one helper function that uses
ranges::iter_move.

libstdc++-v3/ChangeLog:

PR libstdc++/105609
* include/bits/ranges_algobase.h (__detail::__assign_one): New
helper function.
(__copy_or_move, __copy_or_move_backward): Use new function
instead of std::__assign_one.
* testsuite/25_algorithms/move/constrained.cc: Check that
ADL iter_move is used in preference to std::move.
* testsuite/25_algorithms/move_backward/constrained.cc:
Likewise.

Diff:
---
 libstdc++-v3/include/bits/ranges_algobase.h| 26 ++-
 .../testsuite/25_algorithms/move/constrained.cc| 29 ++
 .../25_algorithms/move_backward/constrained.cc | 29 ++
 3 files changed, 78 insertions(+), 6 deletions(-)

diff --git a/libstdc++-v3/include/bits/ranges_algobase.h 
b/libstdc++-v3/include/bits/ranges_algobase.h
index eceb859e88ba..a08f659b3aef 100644
--- a/libstdc++-v3/include/bits/ranges_algobase.h
+++ b/libstdc++-v3/include/bits/ranges_algobase.h
@@ -188,6 +188,20 @@ namespace ranges
 
   inline constexpr __equal_fn equal{};
 
+namespace __detail
+{
+  template
+[[__gnu__::__always_inline__]]
+constexpr void
+__assign_one(_OutIter& __out, _InIter& __in)
+{
+  if constexpr (_IsMove)
+   *__out = ranges::iter_move(__in);
+  else
+   *__out = *__in;
+}
+} // namespace __detail
+
   template
 struct in_out_result
 {
@@ -291,14 +305,14 @@ namespace ranges
__builtin_memmove(__result, __first,
  sizeof(_ValueTypeI) * __num);
  else if (__num == 1)
-   std::__assign_one<_IsMove>(__result, __first);
+   __detail::__assign_one<_IsMove>(__result, __first);
  return {__first + __num, __result + __num};
}
}
 
  for (auto __n = __last - __first; __n > 0; --__n)
{
- std::__assign_one<_IsMove>(__result, __first);
+ __detail::__assign_one<_IsMove>(__result, __first);
  ++__first;
  ++__result;
}
@@ -308,7 +322,7 @@ namespace ranges
{
  while (__first != __last)
{
- std::__assign_one<_IsMove>(__result, __first);
+ __detail::__assign_one<_IsMove>(__result, __first);
  ++__first;
  ++__result;
}
@@ -420,7 +434,7 @@ namespace ranges
__builtin_memmove(__result, __first,
  sizeof(_ValueTypeI) * __num);
  else if (__num == 1)
-   std::__assign_one<_IsMove>(__result, __first);
+   __detail::__assign_one<_IsMove>(__result, __first);
  return {__first + __num, __result};
}
}
@@ -432,7 +446,7 @@ namespace ranges
{
  --__tail;
  --__result;
- std::__assign_one<_IsMove>(__result, __tail);
+ __detail::__assign_one<_IsMove>(__result, __tail);
}
  return {std::move(__lasti), std::move(__result)};
}
@@ -445,7 +459,7 @@ namespace ranges
{
  --__tail;
  --__result;
- std::__assign_one<_IsMove>(__result, __tail);
+ __detail::__assign_one<_IsMove>(__result, __tail);
}
  return {std::move(__lasti), std::move(__result)};
}
diff --git a/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc 
b/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc
index 587b2f3728b1..e2b45b070ef2 100644
--- a/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc
@@ -204,6 +204,35 @@ test05()
   VERIFY( ranges::equal(v, (int[]){1,2,3,0}) );
 }
 
+namespace pr105609
+{
+  struct I {
+using value_type = int;
+using difference_type = std::ptrdiff_t;
+int operator*() const;
+I& operator++();
+I operator++(int);
+I& operator--();
+I operator--(int);
+bool operator==(I) const;
+friend int& iter_move(const I&);
+  };
+}
+
+void
+test06(pr105609::I i)
+{
+  // PR libstdc++/105609
+  // ranges::move should use ranges::iter_move instead of std:

[gcc r14-11366] libstdc++: Hide std::tuple internals from Doxygen docs

2025-02-28 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:9c02bad2b5e012e36bb0a440063569bc40b95f2e

commit r14-11366-g9c02bad2b5e012e36bb0a440063569bc40b95f2e
Author: Jonathan Wakely 
Date:   Fri Aug 23 22:06:43 2024 +0100

libstdc++: Hide std::tuple internals from Doxygen docs

libstdc++-v3/ChangeLog:

* include/std/tuple: Do not include implementation details in
Doxygen documentation.

(cherry picked from commit 5cfee9360c90da8171e9f6bb71568bdc4c296e6e)

Diff:
---
 libstdc++-v3/include/std/tuple | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 3065058e184d..85a380842b6e 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -65,6 +65,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
 class tuple;
 
+  /// @cond undocumented
   template
 struct __is_empty_non_tuple : is_empty<_Tp> { };
 
@@ -828,6 +829,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static constexpr bool __is_explicitly_constructible()
{ return false; }
 };
+  /// @endcond
 
   /// Primary class template, tuple
   template


[gcc r14-11363] libstdc++: Optimize std::basic_string_view::starts_with

2025-02-28 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:8443a90c4332b9c1b8c370c971777807512f7602

commit r14-11363-g8443a90c4332b9c1b8c370c971777807512f7602
Author: Jonathan Wakely 
Date:   Thu May 30 20:36:42 2024 +0100

libstdc++: Optimize std::basic_string_view::starts_with

We get smaller code at all optimization levels by not creating a
temporary object, just comparing lengths first and then using
traits_type::compare. This does less work than calling substr then
operator==.

libstdc++-v3/ChangeLog:

* include/std/string_view (starts_with(basic_string_view)):
Compare lengths first and then call traits_type::compare
directly.

(cherry picked from commit 482f97e79fc29ea2d61f1425b32564a668b51e1c)

Diff:
---
 libstdc++-v3/include/std/string_view | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/string_view 
b/libstdc++-v3/include/std/string_view
index a7c5a1264613..740aa9344f01 100644
--- a/libstdc++-v3/include/std/string_view
+++ b/libstdc++-v3/include/std/string_view
@@ -385,7 +385,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   [[nodiscard]]
   constexpr bool
   starts_with(basic_string_view __x) const noexcept
-  { return this->substr(0, __x.size()) == __x; }
+  {
+   return _M_len >= __x._M_len
+ && traits_type::compare(_M_str, __x._M_str, __x._M_len) == 0;
+  }
 
   [[nodiscard]]
   constexpr bool


[gcc r14-11365] libstdc++: Fix outdated comment in

2025-02-28 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:2b9449c2c1b60ddc191d51617d892fa461b5cfcb

commit r14-11365-g2b9449c2c1b60ddc191d51617d892fa461b5cfcb
Author: Jonathan Wakely 
Date:   Thu Feb 27 21:58:09 2025 +

libstdc++: Fix outdated comment in 

My r15-998-g2a83084ce55363 change replaced the use of nothrow
operator new with a call to __get_temporary_buffer, so update the
comment to match.

libstdc++-v3/ChangeLog:

* include/std/stacktrace (_Impl::_M_allocate): Fix outdated
comment.

(cherry picked from commit e8302282cdb53ae1d347c12d7a50c4209fbab4f7)

Diff:
---
 libstdc++-v3/include/std/stacktrace | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/stacktrace 
b/libstdc++-v3/include/std/stacktrace
index c7558069d5d1..fc1b3af9e4f6 100644
--- a/libstdc++-v3/include/std/stacktrace
+++ b/libstdc++-v3/include/std/stacktrace
@@ -555,7 +555,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
  if constexpr (is_same_v>)
{
- // For std::allocator we use nothrow-new directly so we
+ // Use non-throwing __get_temporary_buffer, so that we
  // don't need to handle exceptions from __alloc.allocate(n).
  auto __p = __detail::__get_temporary_buffer(__n);
  if (__p == nullptr) [[unlikely]]


[gcc r14-11361] libstdc++: Fix warning regressions in

2025-02-28 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:c795413cf3a879e1e9155774652180fb3fbf5830

commit r14-11361-gc795413cf3a879e1e9155774652180fb3fbf5830
Author: Jonathan Wakely 
Date:   Tue Jun 18 20:53:53 2024 +0100

libstdc++: Fix warning regressions in 

I caused some new warnings with -Wsystem-headers with my recent changes
to std::get_temporary_buffer and std::_Temporary_buffer. There's a
-Wsign-compare warning which can be avoided by casting the ptrdiff_t
argument to size_t (which also conveniently rejects negative values).

There's also a -Wdeprecated-declarations warning because I moved where
std::get_temporary_buffer is called, but didn't move the diagnostic
pragmas that suppress the warning for calling it.

libstdc++-v3/ChangeLog:

* include/bits/stl_tempbuf.h (__get_temporary_buffer): Cast
argument to size_t to handle negative values and suppress
-Wsign-compare warning.
(_Temporary_buffer): Move diagnostic pragmas to new location of
call to std::get_temporary_buffer.

(cherry picked from commit 8c52adcf5f9812ef66aeef357590fb2f148302f7)

Diff:
---
 libstdc++-v3/include/bits/stl_tempbuf.h | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libstdc++-v3/include/bits/stl_tempbuf.h 
b/libstdc++-v3/include/bits/stl_tempbuf.h
index fa03fd277042..759c4937744b 100644
--- a/libstdc++-v3/include/bits/stl_tempbuf.h
+++ b/libstdc++-v3/include/bits/stl_tempbuf.h
@@ -82,7 +82,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   inline _Tp*
   __get_temporary_buffer(ptrdiff_t __len) _GLIBCXX_NOTHROW
   {
-   if (__builtin_expect(__len > (size_t(-1) / sizeof(_Tp)), 0))
+   if (__builtin_expect(size_t(__len) > (size_t(-1) / sizeof(_Tp)), 0))
  return 0;
 
 #if __cpp_aligned_new
@@ -200,6 +200,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   size_type  _M_original_len;
   struct _Impl
   {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
explicit
_Impl(ptrdiff_t __original_len)
{
@@ -208,6 +210,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  _M_len = __p.second;
  _M_buffer = __p.first;
}
+#pragma GCC diagnostic pop
 
~_Impl()
{ std::__detail::__return_temporary_buffer(_M_buffer, _M_len); }
@@ -315,8 +318,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  __ucr(__first, __last, __seed);
 }
 
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
   template
 _Temporary_buffer<_ForwardIterator, _Tp>::
 _Temporary_buffer(_ForwardIterator __seed, size_type __original_len)
@@ -324,7 +325,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 {
   std::__uninitialized_construct_buf(begin(), end(), __seed);
 }
-#pragma GCC diagnostic pop
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace


[gcc r14-11362] libstdc++: Do not use C++11 alignof in C++98 mode [PR104395]

2025-02-28 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:3b9885ac4df2e83cec2080d5a7013b71345a7a7b

commit r14-11362-g3b9885ac4df2e83cec2080d5a7013b71345a7a7b
Author: Jonathan Wakely 
Date:   Wed Jun 26 14:09:07 2024 +0100

libstdc++: Do not use C++11 alignof in C++98 mode [PR104395]

When -faligned-new (or Clang's -faligned-allocation) is used our
allocators try to support extended alignments, gated on the
__cpp_aligned_new macro. However, because they use alignof(_Tp) which is
not a keyword in C++98 mode, using -std=c++98 -faligned-new results in
errors from  and other headers.

We could change them to use __alignof__ instead of alignof, but that
would potentially alter the result of the conditions, because e.g.
alignof(long long) != __alignof__(long long) on some targets. That's
probably not an issue for any types with extended alignment, so maybe it
would be a safe change.

For now, it seems acceptable to just disable the extended alignment
support in C++98 mode, so that -faligned-new enables std::align_val_t
and the corresponding operator new overloads, but doesn't affect
std::allocator, __gnu_cxx::__bitmap_allocator etc.

libstdc++-v3/ChangeLog:

PR libstdc++/104395
* include/bits/new_allocator.h: Disable extended alignment
support in C++98 mode.
* include/bits/stl_tempbuf.h: Likewise.
* include/ext/bitmap_allocator.h: Likewise.
* include/ext/malloc_allocator.h: Likewise.
* include/ext/mt_allocator.h: Likewise.
* include/ext/pool_allocator.h: Likewise.
* testsuite/ext/104395.cc: New test.

(cherry picked from commit 03d3aeb0e0fa7dec9bd702cabf57ef73cdc32704)

Diff:
---
 libstdc++-v3/include/bits/new_allocator.h   | 4 ++--
 libstdc++-v3/include/bits/stl_tempbuf.h | 6 +++---
 libstdc++-v3/include/ext/bitmap_allocator.h | 4 ++--
 libstdc++-v3/include/ext/malloc_allocator.h | 2 +-
 libstdc++-v3/include/ext/mt_allocator.h | 4 ++--
 libstdc++-v3/include/ext/pool_allocator.h   | 4 ++--
 libstdc++-v3/testsuite/ext/104395.cc| 8 
 7 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/libstdc++-v3/include/bits/new_allocator.h 
b/libstdc++-v3/include/bits/new_allocator.h
index 21e7e22cae00..3a749dc91dbb 100644
--- a/libstdc++-v3/include/bits/new_allocator.h
+++ b/libstdc++-v3/include/bits/new_allocator.h
@@ -140,7 +140,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::__throw_bad_alloc();
  }
 
-#if __cpp_aligned_new
+#if __cpp_aligned_new && __cplusplus >= 201103L
if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
  {
std::align_val_t __al = std::align_val_t(alignof(_Tp));
@@ -161,7 +161,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 # define _GLIBCXX_SIZED_DEALLOC(p, n) (p)
 #endif
 
-#if __cpp_aligned_new
+#if __cpp_aligned_new && __cplusplus >= 201103L
if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
  {
_GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n),
diff --git a/libstdc++-v3/include/bits/stl_tempbuf.h 
b/libstdc++-v3/include/bits/stl_tempbuf.h
index 759c4937744b..0f267054613f 100644
--- a/libstdc++-v3/include/bits/stl_tempbuf.h
+++ b/libstdc++-v3/include/bits/stl_tempbuf.h
@@ -85,7 +85,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__builtin_expect(size_t(__len) > (size_t(-1) / sizeof(_Tp)), 0))
  return 0;
 
-#if __cpp_aligned_new
+#if __cpp_aligned_new && __cplusplus >= 201103L
if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
  return (_Tp*) _GLIBCXX_OPERATOR_NEW(__len * sizeof(_Tp),
  align_val_t(alignof(_Tp)),
@@ -107,7 +107,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 # define _GLIBCXX_SIZED_DEALLOC(T, p, n) (p)
 #endif
 
-#if __cpp_aligned_new
+#if __cpp_aligned_new && __cplusplus >= 201103L
if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
  {
_GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(_Tp, __p, __len),
@@ -168,7 +168,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 inline void
 return_temporary_buffer(_Tp* __p)
 {
-#if __cpp_aligned_new
+#if __cpp_aligned_new && __cplusplus >= 201103L
   if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
_GLIBCXX_OPERATOR_DELETE(__p, align_val_t(alignof(_Tp)));
   else
diff --git a/libstdc++-v3/include/ext/bitmap_allocator.h 
b/libstdc++-v3/include/ext/bitmap_allocator.h
index ef2ee13187b9..45b2283ca30d 100644
--- a/libstdc++-v3/include/ext/bitmap_allocator.h
+++ b/libstdc++-v3/include/ext/bitmap_allocator.h
@@ -1017,7 +1017,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (__n > this->max_size())
  std::__throw_bad_alloc();
 
-#if __cpp_aligned_new
+#if __cpp_aligned_new && __cplusplus >= 201103L
if (alignof(value_type) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
  {
const size_type __b = __n * sizeof(value_type);
@@ -1044,7 +1044,7 @@ _GLIBCX

[gcc r14-11367] libstdc++: Use init_priority attribute for tzdb globals [PR118811]

2025-02-28 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:3a8d05b61a9568d60ee922f899408555470eeff1

commit r14-11367-g3a8d05b61a9568d60ee922f899408555470eeff1
Author: Jonathan Wakely 
Date:   Wed Feb 12 17:29:59 2025 +

libstdc++: Use init_priority attribute for tzdb globals [PR118811]

When linking statically to libstdc++.a (or to libstdc++_nonshared.a in
the RHEL devtoolset compiler) there's a static initialization order
problem where user code might be constructed before the
std::chrono::tzdb_list globals, and so might try to use them after
they've already been destroyed.

Use the init_priority attribute on those globals so that they are
initialized early. Since r15-7511-g4e7f74225116e7 we can disable the
warnings for using a reserved priority using a diagnostic pragma.

However, for the backport to the release branch the warnings can only be
suppressed by defining the objects in a system header.  Move them to a
new file that uses '#pragma GCC system_header' and then include that in
tzdb.cc.

libstdc++-v3/ChangeLog:

PR libstdc++/118811
* src/c++20/tzdb.cc (tzdb_list::_Node): Move definitions of
static data members to new header.
* src/c++20/tzdb_globals.h: New header. Use init_priority
attribute on static data members.
* testsuite/std/time/tzdb_list/pr118811.cc: New test.

(cherry picked from commit 99f57446e63b8ebeaeeae8dc48981cd5f1dfb831)

Diff:
---
 libstdc++-v3/src/c++20/tzdb.cc | 14 +++-
 libstdc++-v3/src/c++20/tzdb_globals.h  | 14 
 .../testsuite/std/time/tzdb_list/pr118811.cc   | 25 ++
 3 files changed, 42 insertions(+), 11 deletions(-)

diff --git a/libstdc++-v3/src/c++20/tzdb.cc b/libstdc++-v3/src/c++20/tzdb.cc
index 7e8cce7ce8cf..3fe426d2800b 100644
--- a/libstdc++-v3/src/c++20/tzdb.cc
+++ b/libstdc++-v3/src/c++20/tzdb.cc
@@ -133,6 +133,8 @@ namespace std::chrono
 // of this type gives them access to the private members of time_zone
 // and tzdb, without needing them declared in the  header.
 
+// The tzdb_list singleton. This doesn't contain the actual linked list,
+// but it has member functions that give access to it.
 static tzdb_list _S_the_list;
 
 #if USE_ATOMIC_SHARED_PTR
@@ -177,17 +179,7 @@ namespace std::chrono
   // Implementation of the private constructor used for the singleton object.
   constexpr tzdb_list::tzdb_list(nullptr_t) { }
 
-  // The tzdb_list singleton. This doesn't contain the actual linked list,
-  // but it has member functions that give access to it.
-  constinit tzdb_list tzdb_list::_Node::_S_the_list(nullptr);
-
-  // Shared pointer to the first Node in the list.
-  constinit tzdb_list::_Node::head_ptr 
tzdb_list::_Node::_S_head_owner{nullptr};
-
-#if USE_ATOMIC_LIST_HEAD
-  // Lock-free access to the first Node in the list.
-  constinit atomic tzdb_list::_Node::_S_head_cache{nullptr};
-#endif
+#include "tzdb_globals.h"
 
   // The data structures defined in this file (Rule, on_day, at_time etc.)
   // are used to represent the information parsed from the tzdata.zi file
diff --git a/libstdc++-v3/src/c++20/tzdb_globals.h 
b/libstdc++-v3/src/c++20/tzdb_globals.h
new file mode 100644
index ..94d54dad1401
--- /dev/null
+++ b/libstdc++-v3/src/c++20/tzdb_globals.h
@@ -0,0 +1,14 @@
+// This is only in a header so we can use the system_header pragma,
+// to suppress the warning caused by using a reserved init_priority.
+#pragma GCC system_header
+
+[[gnu::init_priority(98)]]
+constinit tzdb_list tzdb_list::_Node::_S_the_list(nullptr);
+
+[[gnu::init_priority(98)]]
+constinit tzdb_list::_Node::head_ptr tzdb_list::_Node::_S_head_owner{nullptr};
+
+#if USE_ATOMIC_LIST_HEAD
+[[gnu::init_priority(98)]]
+constinit atomic tzdb_list::_Node::_S_head_cache{nullptr};
+#endif
diff --git a/libstdc++-v3/testsuite/std/time/tzdb_list/pr118811.cc 
b/libstdc++-v3/testsuite/std/time/tzdb_list/pr118811.cc
new file mode 100644
index ..3968be3f0eca
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/time/tzdb_list/pr118811.cc
@@ -0,0 +1,25 @@
+// { dg-do run { target c++20 } }
+// { dg-require-effective-target tzdb }
+// { dg-require-effective-target cxx11_abi }
+// { dg-require-static-libstdcxx }
+// { dg-additional-options "-static-libstdc++" }
+
+#include 
+
+struct Global
+{
+  Global()
+  {
+(void) std::chrono::current_zone(); // initialize tzdb on first use
+  }
+
+  ~Global()
+  {
+(void) std::chrono::current_zone(); // attempt to use it again on exit
+  }
+
+} global;
+
+int main()
+{
+}


[gcc r14-11360] libstdc++: Handle extended alignment in std::get_temporary_buffer [PR105258]

2025-02-28 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:fb9a2af992813f874c942472fb35506b6180ffbf

commit r14-11360-gfb9a2af992813f874c942472fb35506b6180ffbf
Author: Jonathan Wakely 
Date:   Wed Apr 13 13:03:44 2022 +0100

libstdc++: Handle extended alignment in std::get_temporary_buffer [PR105258]

This adds extended alignment support to std::get_temporary_buffer etc.
so that when std::stable_sort uses a temporary buffer it works for
overaligned types.

Also simplify the _Temporary_buffer type by using RAII for the
allocation, via a new data member. This simplifies the _Temporary_buffer
constructor and destructor by makingthem only responsible for
constructing and destroying the elements, not managing the memory.

libstdc++-v3/ChangeLog:

PR libstdc++/105258
* include/bits/stl_tempbuf.h (__detail::__get_temporary_buffer):
New function to do allocation for get_temporary_buffer, with
extended alignment support.
(__detail::__return_temporary_buffer): Support extended
alignment.
(get_temporary_buffer): Use __get_temporary_buffer.
(return_temporary_buffer): Support extended alignment. Add
deprecated attribute.
(_Temporary_buffer): Move allocation and deallocation into a
subobject and remove try-catch block in constructor.
(__uninitialized_construct_buf): Use argument deduction for
value type.
* testsuite/20_util/temporary_buffer.cc: Add dg-warning for new
deprecated warning.
* testsuite/25_algorithms/stable_sort/overaligned.cc: New test.

(cherry picked from commit b0efdcbf58a76af3b8fff75f1d53d334fb5b46ee)

Diff:
---
 libstdc++-v3/include/bits/stl_tempbuf.h| 131 ++---
 libstdc++-v3/testsuite/20_util/temporary_buffer.cc |   2 +-
 .../25_algorithms/stable_sort/overaligned.cc   |  29 +
 3 files changed, 116 insertions(+), 46 deletions(-)

diff --git a/libstdc++-v3/include/bits/stl_tempbuf.h 
b/libstdc++-v3/include/bits/stl_tempbuf.h
index 77b121460f90..fa03fd277042 100644
--- a/libstdc++-v3/include/bits/stl_tempbuf.h
+++ b/libstdc++-v3/include/bits/stl_tempbuf.h
@@ -66,19 +66,58 @@ namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
+#if __has_builtin(__builtin_operator_new) >= 201802L
+# define _GLIBCXX_OPERATOR_NEW __builtin_operator_new
+# define _GLIBCXX_OPERATOR_DELETE __builtin_operator_delete
+#else
+# define _GLIBCXX_OPERATOR_NEW ::operator new
+# define _GLIBCXX_OPERATOR_DELETE ::operator delete
+#endif
+
   namespace __detail
   {
+// Equivalent to std::get_temporary_buffer but won't return a smaller size.
+// It either returns a buffer of __len elements, or a null pointer.
+template
+  inline _Tp*
+  __get_temporary_buffer(ptrdiff_t __len) _GLIBCXX_NOTHROW
+  {
+   if (__builtin_expect(__len > (size_t(-1) / sizeof(_Tp)), 0))
+ return 0;
+
+#if __cpp_aligned_new
+   if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
+ return (_Tp*) _GLIBCXX_OPERATOR_NEW(__len * sizeof(_Tp),
+ align_val_t(alignof(_Tp)),
+ nothrow_t());
+#endif
+   return (_Tp*) _GLIBCXX_OPERATOR_NEW(__len * sizeof(_Tp), nothrow_t());
+  }
+
+// Equivalent to std::return_temporary_buffer but with a size argument.
+// The size is the number of elements, not the number of bytes.
 template
   inline void
   __return_temporary_buffer(_Tp* __p,
size_t __len __attribute__((__unused__)))
   {
 #if __cpp_sized_deallocation
-   ::operator delete(__p, __len * sizeof(_Tp));
+# define _GLIBCXX_SIZED_DEALLOC(T, p, n) (p), (n) * sizeof(T)
 #else
-   ::operator delete(__p);
+# define _GLIBCXX_SIZED_DEALLOC(T, p, n) (p)
 #endif
+
+#if __cpp_aligned_new
+   if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
+ {
+   _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(_Tp, __p, __len),
+align_val_t(alignof(_Tp)));
+   return;
+ }
+#endif
+   _GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(_Tp, __p, __len));
   }
+#undef _GLIBCXX_SIZED_DEALLOC
   }
 
   /**
@@ -90,7 +129,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*
*  This function tries to obtain storage for @c __len adjacent Tp
*  objects.  The objects themselves are not constructed, of course.
-   *  A pair<> is returned containing the buffer s address and
+   *  A pair<> is returned containing the buffer's address and
*  capacity (in the units of sizeof(_Tp)), or a pair of 0 values if
*  no storage can be obtained.  Note that the capacity obtained
*  may be less than that requested if the memory is unavailable;
@@ -110,13 +149,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   while (__len > 0)
{
- _Tp* __tmp = s

[gcc r15-7766] libstdc++: Fix ranges::iter_move handling of rvalues [PR106612]

2025-02-28 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:a8ee522c5923ba17851e4b71316a2dff19d6368f

commit r15-7766-ga8ee522c5923ba17851e4b71316a2dff19d6368f
Author: Jonathan Wakely 
Date:   Fri Feb 28 21:44:41 2025 +

libstdc++: Fix ranges::iter_move handling of rvalues [PR106612]

The specification for std::ranges::iter_move apparently requires us to
handle types which do not satisfy std::indirectly_readable, for example
with overloaded operator* which behaves differently for different value
categories.

libstdc++-v3/ChangeLog:

PR libstdc++/106612
* include/bits/iterator_concepts.h (_IterMove::__iter_ref_t):
New alias template.
(_IterMove::__result): Use __iter_ref_t instead of
std::iter_reference_t.
(_IterMove::__type): Remove incorrect __dereferenceable
constraint.
(_IterMove::operator()): Likewise. Add correct constraints. Use
__iter_ref_t instead of std::iter_reference_t. Forward parameter
as correct value category.
(iter_swap): Add comments.
* testsuite/24_iterators/customization_points/iter_move.cc: Test
that iter_move is found by ADL and that rvalue arguments are
handled correctly.

Reviewed-by: Patrick Palka 

Diff:
---
 libstdc++-v3/include/bits/iterator_concepts.h  | 33 ++--
 .../24_iterators/customization_points/iter_move.cc | 95 ++
 2 files changed, 119 insertions(+), 9 deletions(-)

diff --git a/libstdc++-v3/include/bits/iterator_concepts.h 
b/libstdc++-v3/include/bits/iterator_concepts.h
index 4265c475273b..a201e24d2e23 100644
--- a/libstdc++-v3/include/bits/iterator_concepts.h
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -103,32 +103,42 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   namespace ranges
   {
 /// @cond undocumented
+// Implementation of std::ranges::iter_move, [iterator.cust.move].
 namespace __imove
 {
   void iter_move() = delete;
 
+  // Satisfied if _Tp is a class or enumeration type and iter_move
+  // can be found by argument-dependent lookup.
   template
concept __adl_imove
  = (std::__detail::__class_or_enum>)
- && requires(_Tp&& __t) { iter_move(static_cast<_Tp&&>(__t)); };
+ && requires(_Tp&& __t) { iter_move(static_cast<_Tp&&>(__t)); };
 
   struct _IterMove
   {
   private:
+   // The type returned by dereferencing a value of type _Tp.
+   // Unlike iter_reference_t this preserves the value category of _Tp.
+   template
+ using __iter_ref_t = decltype(*std::declval<_Tp>());
+
template
  struct __result
- { using type = iter_reference_t<_Tp>; };
+ { using type = __iter_ref_t<_Tp>; };
 
+   // Use iter_move(E) if that works.
template
  requires __adl_imove<_Tp>
  struct __result<_Tp>
  { using type = decltype(iter_move(std::declval<_Tp>())); };
 
+   // Otherwise, if *E if an lvalue, use std::move(*E).
template
  requires (!__adl_imove<_Tp>)
- && is_lvalue_reference_v>
+   && is_lvalue_reference_v<__iter_ref_t<_Tp>>
  struct __result<_Tp>
- { using type = remove_reference_t>&&; };
+ { using type = remove_reference_t<__iter_ref_t<_Tp>>&&; };
 
template
  static constexpr bool
@@ -142,10 +152,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   public:
// The result type of iter_move(std::declval<_Tp>())
-   template
+   template
  using __type = typename __result<_Tp>::type;
 
-   template
+   template
+ requires __adl_imove<_Tp> || requires { typename __iter_ref_t<_Tp>; }
  [[nodiscard]]
  constexpr __type<_Tp>
  operator()(_Tp&& __e) const
@@ -153,10 +164,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  {
if constexpr (__adl_imove<_Tp>)
  return iter_move(static_cast<_Tp&&>(__e));
-   else if constexpr (is_lvalue_reference_v>)
- return static_cast<__type<_Tp>>(*__e);
+   else if constexpr (is_lvalue_reference_v<__iter_ref_t<_Tp>>)
+ return std::move(*static_cast<_Tp&&>(__e));
else
- return *__e;
+ return *static_cast<_Tp&&>(__e);
  }
   };
 } // namespace __imove
@@ -167,6 +178,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 }
   } // namespace ranges
 
+  /// The result type of ranges::iter_move(std::declval<_Tp&>())
   template<__detail::__dereferenceable _Tp>
 requires 
__detail::__can_reference>
 using iter_rvalue_reference_t = ranges::__imove::_IterMove::__type<_Tp&>;
@@ -873,11 +885,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 namespace ranges
 {
   /// @cond undocumented
+  // Implementation of std::ranges::iter_swap, [iterator.cust.swap].
   namespace __iswap
   {
 template
   void iter_swap(_It1, _It2) = delete;
 
+// Satisfied i

[gcc r14-11364] libstdc++: Reuse temporary buffer utils in

2025-02-28 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:85f4136aa83b33783c2ee80bffc2e61e80e4b887

commit r14-11364-g85f4136aa83b33783c2ee80bffc2e61e80e4b887
Author: Jonathan Wakely 
Date:   Sat Jun 1 10:45:55 2024 +0100

libstdc++: Reuse temporary buffer utils in 

The non-throwing allocation logic in std::stacktrace duplicates the
logic in , so we can just reuse those utilities.

libstdc++-v3/ChangeLog:

* include/std/stacktrace (basic_stacktrace::_Impl::_M_allocate):
Use __detail::__get_temporary_buffer.
(basic_stacktrace::_Impl::_M_deallocate): Use
__detail::__return_temporary_buffer.

(cherry picked from commit 2a83084ce5536353ceb8554e906f87273a59c4fd)

Diff:
---
 libstdc++-v3/include/std/stacktrace | 29 -
 1 file changed, 4 insertions(+), 25 deletions(-)

diff --git a/libstdc++-v3/include/std/stacktrace 
b/libstdc++-v3/include/std/stacktrace
index dcff886c095f..c7558069d5d1 100644
--- a/libstdc++-v3/include/std/stacktrace
+++ b/libstdc++-v3/include/std/stacktrace
@@ -45,6 +45,7 @@
 #include 
 #include 
 #include 
+#include  // __get_temporary_buffer
 #include 
 
 namespace std _GLIBCXX_VISIBILITY(default)
@@ -546,21 +547,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  return std::min(__size_max, __alloc_max);
}
 
-#if __has_builtin(__builtin_operator_new) >= 201802L
-# define _GLIBCXX_OPERATOR_NEW __builtin_operator_new
-# define _GLIBCXX_OPERATOR_DELETE __builtin_operator_delete
-#else
-# define _GLIBCXX_OPERATOR_NEW ::operator new
-# define _GLIBCXX_OPERATOR_DELETE ::operator delete
-#endif
-
-#if __cpp_sized_deallocation
-# define _GLIBCXX_SIZED_DELETE(T, p, n) \
-  _GLIBCXX_OPERATOR_DELETE((p), (n) * sizeof(T))
-#else
-# define _GLIBCXX_SIZED_DELETE(T, p, n) _GLIBCXX_OPERATOR_DELETE(p)
-#endif
-
// Precondition: _M_frames == nullptr && __n != 0
pointer
_M_allocate(allocator_type& __alloc, size_type __n) noexcept
@@ -571,11 +557,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
  // For std::allocator we use nothrow-new directly so we
  // don't need to handle exceptions from __alloc.allocate(n).
- size_t __nb = __n * sizeof(value_type);
- void* const __p = _GLIBCXX_OPERATOR_NEW (__nb, nothrow_t{});
+ auto __p = __detail::__get_temporary_buffer(__n);
  if (__p == nullptr) [[unlikely]]
return nullptr;
- _M_frames = static_cast(__p);
+ _M_frames = __p;
}
  else
{
@@ -600,9 +585,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  if (_M_capacity)
{
  if constexpr (is_same_v>)
-   _GLIBCXX_SIZED_DELETE(value_type,
- static_cast(_M_frames),
- _M_capacity);
+   __detail::__return_temporary_buffer(_M_frames, _M_capacity);
  else
__alloc.deallocate(_M_frames, _M_capacity);
  _M_frames = nullptr;
@@ -610,10 +593,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
}
 
-#undef _GLIBCXX_SIZED_DELETE
-#undef _GLIBCXX_OPERATOR_DELETE
-#undef _GLIBCXX_OPERATOR_NEW
-
// Precondition: __n <= _M_size
void
_M_resize(size_type __n, allocator_type& __alloc) noexcept


[gcc r15-7748] testsuite: Fix up gcc.target/i386/pr118940.c test [PR118940]

2025-02-28 Thread Jakub Jelinek via Gcc-cvs
https://gcc.gnu.org/g:146cb828ef0fd6ceb8087ebbb0f792abd615283f

commit r15-7748-g146cb828ef0fd6ceb8087ebbb0f792abd615283f
Author: Jakub Jelinek 
Date:   Fri Feb 28 10:12:14 2025 +0100

testsuite: Fix up gcc.target/i386/pr118940.c test [PR118940]

The testcase uses -m32 in dg-options, something we try hard not to do,
if something should be tested only for -m32, it is { target ia32 } test,
if it can be tested for -m64/-mx32 too, just some extra options are
needed for ia32, it should have dg-additional-options with ia32 target.

Also, the test wasn't reduced, so I've reduced it using cvise and manual
tweaks and verified the test still FAILs before r15-7700 and succeeds
with current trunk.

2025-02-28  Jakub Jelinek  

PR target/118940
* gcc.target/i386/pr118940.c: Drop -w, -g and -m32 from dg-options, 
move
-march=i386 -mregparm=3 to dg-additional-options for ia32 and 
-fno-pie
to dg-additional-options for pie.  Reduce the test.

Diff:
---
 gcc/testsuite/gcc.target/i386/pr118940.c | 151 ++-
 1 file changed, 27 insertions(+), 124 deletions(-)

diff --git a/gcc/testsuite/gcc.target/i386/pr118940.c 
b/gcc/testsuite/gcc.target/i386/pr118940.c
index be094310173c..a26fa1192a2d 100644
--- a/gcc/testsuite/gcc.target/i386/pr118940.c
+++ b/gcc/testsuite/gcc.target/i386/pr118940.c
@@ -1,127 +1,30 @@
+/* PR target/118940 */
 /* { dg-do compile } */
-/* { dg-options "-w -g -Os -march=i386 -mregparm=3 -m32 -fno-PIE" } */
-
-typedef unsigned char uint8_t;
-typedef unsigned int uint32_t;
-typedef unsigned int size_t;
-typedef uint32_t bigint_element_t;
-
-/**
- * Define a big-integer type
- *
- * @v size Number of elements
- * @ret bigint_t   Big integer type
- */
- #define bigint_t( size )  \
- struct {  \
-  bigint_element_t element[ (size) ];  \
- }
-
-/**
-* Determine number of elements required for a big-integer type
-*
-* @v len   Maximum length of big integer, in bytes
-* @ret sizeNumber of elements
-*/
-#define bigint_required_size( len )\
- ( ( (len) + sizeof ( bigint_element_t ) - 1 ) /   \
-   sizeof ( bigint_element_t ) )
-
-/**
- * Determine number of elements in big-integer type
- *
- * @v bigint   Big integer
- * @ret size   Number of elements
- */
- #define bigint_size( bigint ) \
- ( sizeof ( *(bigint) ) / sizeof ( (bigint)->element[0] ) )
-
- /**
- * Initialise big integer
- *
- * @v valueBig integer to initialise
- * @v data Raw data
- * @v len  Length of raw data
- */
-#define bigint_init( value, data, len ) do {   \
-   unsigned int size = bigint_size (value);\
-   bigint_init_raw ( (value)->element, size, (data), (len) );  \
-   } while ( 0 )
-
-
-/**
- * Calculate temporary working space required for moduluar exponentiation
- *
- * @v modulus  Big integer modulus
- * @ret lenLength of temporary working space
- */
- #define bigint_mod_exp_tmp_len( modulus ) ( { \
-   unsigned int size = bigint_size (modulus);  \
-   sizeof ( struct {   \
-   bigint_t ( size ) temp[4];  \
-   } ); } )
-
-
-/**
- * Initialise big integer
- *
- * @v value0   Element 0 of big integer to initialise
- * @v size Number of elements
- * @v data Raw data
- * @v len  Length of raw data
- */
- static inline __attribute__ (( always_inline )) void
- bigint_init_raw ( uint32_t *value0, unsigned int size,
- const void *data, size_t len ) {
-  bigint_t ( size ) __attribute__ (( may_alias )) *value =
-   ( ( void * ) value0 );
-  long pad_len = ( sizeof ( *value ) - len );
-  void *discard_D;
-  long discard_c;
-
-  /* Copy raw data in reverse order, padding with zeros */
-  __asm__ __volatile__ ( "\n1:\n\t"
-   "movb -1(%3,%1), %%al\n\t"
-   "stosb\n\t"
-   "loop 1b\n\t"
-   "xorl %%eax, %%eax\n\t"
-   "mov %4, %1\n\t"
-   "rep stosb\n\t"
-   : "=&D" ( discard_D ), "=&c" ( discard_c ),
-  "+m" ( *value )
-   : "r" ( data ), "g" ( pad_len ), "0" ( value0 ),
-  "1" ( len )
-   : "eax" );
- }
-
-extern void touch (void *, ...);
-extern void touch3 (void *, void *, void *);
-extern void touch2 (void *, void *);
-
-/**
- * Perform big integer self-tests
- *
- */
-void bigint_test_exec ( void 

[gcc r15-7747] Fortran: Ensure finalizer is called for unreferenced variable [PR118730]

2025-02-28 Thread Andre Vehreschild via Gcc-cvs
https://gcc.gnu.org/g:c1606e383a3c3abd260dfbb1177637abf05dd9a2

commit r15-7747-gc1606e383a3c3abd260dfbb1177637abf05dd9a2
Author: Andre Vehreschild 
Date:   Thu Feb 27 12:27:10 2025 +0100

Fortran: Ensure finalizer is called for unreferenced variable [PR118730]

PR fortran/118730

gcc/fortran/ChangeLog:

* resolve.cc: Mark unused derived type variable with finalizers
referenced to execute finalizer when leaving scope.

gcc/testsuite/ChangeLog:

* gfortran.dg/class_array_15.f03: Remove unused variable.
* gfortran.dg/coarray_poly_7.f90: Adapt scan-tree-dump expr.
* gfortran.dg/coarray_poly_8.f90: Same.
* gfortran.dg/finalize_60.f90: New test.

Diff:
---
 gcc/fortran/resolve.cc   |  8 +++
 gcc/testsuite/gfortran.dg/class_array_15.f03 |  2 +-
 gcc/testsuite/gfortran.dg/coarray_poly_7.f90 |  2 +-
 gcc/testsuite/gfortran.dg/coarray_poly_8.f90 |  2 +-
 gcc/testsuite/gfortran.dg/finalize_60.f90| 33 
 5 files changed, 44 insertions(+), 3 deletions(-)

diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index 6a83a7967a8b..f83d122a3a21 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -17063,6 +17063,14 @@ skip_interfaces:
   return;
 }
 
+  /* Ensure that variables of derived or class type having a finalizer are
+ marked used even when the variable is not used anything else in the scope.
+ This fixes PR118730.  */
+  if (sym->attr.flavor == FL_VARIABLE && !sym->attr.referenced
+  && (sym->ts.type == BT_DERIVED || sym->ts.type == BT_CLASS)
+  && gfc_may_be_finalized (sym->ts))
+gfc_set_sym_referenced (sym);
+
   if (sym->attr.flavor == FL_DERIVED && !resolve_fl_derived (sym))
 return;
 
diff --git a/gcc/testsuite/gfortran.dg/class_array_15.f03 
b/gcc/testsuite/gfortran.dg/class_array_15.f03
index 332b39833ebf..f53b2356952a 100644
--- a/gcc/testsuite/gfortran.dg/class_array_15.f03
+++ b/gcc/testsuite/gfortran.dg/class_array_15.f03
@@ -100,7 +100,7 @@ subroutine pr54992  ! This test remains as the original.
   implicit none
   type (tn), target  :: b
   class(ncBh), pointer :: bh
-  class(ncBh), allocatable, dimension(:) :: t
+
   allocate(b%cBh(1),source=defaultBhC)
   b%cBh(1)%hostNode => b
 ! #1 this worked
diff --git a/gcc/testsuite/gfortran.dg/coarray_poly_7.f90 
b/gcc/testsuite/gfortran.dg/coarray_poly_7.f90
index d8d83aea39b5..21a3054f59c9 100644
--- a/gcc/testsuite/gfortran.dg/coarray_poly_7.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_poly_7.f90
@@ -18,4 +18,4 @@ end
 ! { dg-final { scan-tree-dump-times "foo \\(struct __class_MAIN___T_1_1t & 
restrict x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) 
caf_offset..\\)" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "bar \\(struct __class_MAIN___T_1_1t \\* 
restrict x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) 
caf_offset..\\)" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "bar \\(0B, 0B, 0\\);" 1 "original" } }
-! { dg-final { scan-tree-dump-times "foo \\(&class.., y._data.token, 
\\(integer\\(kind=\[48\]\\)\\) class..._data.data - 
\\(integer\\(kind=\[48\]\\)\\) y._data.data\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "foo \\(&class.\[0-9\]+, y._data.token, 
\\(integer\\(kind=\[48\]\\)\\) class.\[0-9\]+._data.data - 
\\(integer\\(kind=\[48\]\\)\\) y._data.data\\);" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/coarray_poly_8.f90 
b/gcc/testsuite/gfortran.dg/coarray_poly_8.f90
index abdfc0ca5f82..9ceece419aeb 100644
--- a/gcc/testsuite/gfortran.dg/coarray_poly_8.f90
+++ b/gcc/testsuite/gfortran.dg/coarray_poly_8.f90
@@ -18,4 +18,4 @@ end
 ! { dg-final { scan-tree-dump-times "foo \\(struct __class_MAIN___T_1_1t & 
restrict x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) 
caf_offset..\\)" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "bar \\(struct __class_MAIN___T_1_1t \\* 
restrict x, void \\* restrict caf_token.., integer\\(kind=\[48\]\\) 
caf_offset..\\)" 1 "original" } }
 ! { dg-final { scan-tree-dump-times "bar \\(0B, 0B, 0\\);" 1 "original" } }
-! { dg-final { scan-tree-dump-times "foo \\(&class.., y._data.token, 
\\(integer\\(kind=\[48\]\\)\\) class..._data.data - 
\\(integer\\(kind=\[48\]\\)\\) y._data.data\\);" 1 "original" } }
+! { dg-final { scan-tree-dump-times "foo \\(&class.\[0-9\]+, y._data.token, 
\\(integer\\(kind=\[48\]\\)\\) class.\[0-9\]+._data.data - 
\\(integer\\(kind=\[48\]\\)\\) y._data.data\\);" 1 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/finalize_60.f90 
b/gcc/testsuite/gfortran.dg/finalize_60.f90
new file mode 100644
index ..1ce50b3a3f4f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/finalize_60.f90
@@ -0,0 +1,33 @@
+!{ dg-do run }
+!
+! Check that the finalizer is called on unused variables too.
+! Contributed by LXYAN  
+
+module pr118730_mod
+  implicit none
+
+  logical :: finished = .FALSE.
+

[gcc r15-7749] testsuite: Remove -m32 from another i386/ test

2025-02-28 Thread Jakub Jelinek via Gcc-cvs
https://gcc.gnu.org/g:616d1bd1ae28bb7617a21eb9d118e2bbeb01a409

commit r15-7749-g616d1bd1ae28bb7617a21eb9d118e2bbeb01a409
Author: Jakub Jelinek 
Date:   Fri Feb 28 10:13:57 2025 +0100

testsuite: Remove -m32 from another i386/ test

I found another test which uses -m32 in gcc.target/i386/ .  Similarly
to the previously posted test, the test ought to be tested during i686-linux
testing or x86_64-linux test with --target_board=unix\{-m32,-m64\}
There is nothing ia32 specific on the test, so I've just dropped the -m32.

2025-02-28  Jakub Jelinek  

* gcc.target/i386/strub-pr118006.c: Remove -m32 from dg-options.

Diff:
---
 gcc/testsuite/gcc.target/i386/strub-pr118006.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/testsuite/gcc.target/i386/strub-pr118006.c 
b/gcc/testsuite/gcc.target/i386/strub-pr118006.c
index 6337ce10df31..f1167906629c 100644
--- a/gcc/testsuite/gcc.target/i386/strub-pr118006.c
+++ b/gcc/testsuite/gcc.target/i386/strub-pr118006.c
@@ -1,6 +1,6 @@
 /* { dg-require-effective-target strub } */
 /* { dg-do compile } */
-/* { dg-options "-fstrub=all -O2 -m32 -mno-accumulate-outgoing-args" } */
+/* { dg-options "-fstrub=all -O2 -mno-accumulate-outgoing-args" } */
 
 __attribute__((noipa))
 long _raw_syscall(void *, long, long) {


[gcc r15-7756] c++: Fix cxx_eval_store_expression {REAL, IMAG}PART_EXPR handling [PR119045]

2025-02-28 Thread Jakub Jelinek via Gcc-cvs
https://gcc.gnu.org/g:7eb8ec1856f71b039d1c2235b1c941934fa28e22

commit r15-7756-g7eb8ec1856f71b039d1c2235b1c941934fa28e22
Author: Jakub Jelinek 
Date:   Fri Feb 28 15:22:47 2025 +0100

c++: Fix cxx_eval_store_expression {REAL,IMAG}PART_EXPR handling [PR119045]

I've added the asserts that probe == target because {REAL,IMAG}PART_EXPR
always implies a scalar type and so applying ARRAY_REF/COMPONENT_REF
etc. on it further doesn't make sense and the later code relies on it
to be the last one in refs array.  But as the following testcase shows,
we can fail those assertions in case there is a reference or pointer
to the __real__ or __imag__ part, in that case we just evaluate the
constant expression and so probe won't be the same as target.
That case doesn't push anything into the refs array though.

The following patch changes those asserts to verify that refs is still
empty, which fixes it.

2025-02-28  Jakub Jelinek  

PR c++/119045
* constexpr.cc (cxx_eval_store_expression) :
Assert that refs->is_empty () rather than probe == target.
(cxx_eval_store_expression) : Likewise.

* g++.dg/cpp1y/constexpr-complex2.C: New test.

Diff:
---
 gcc/cp/constexpr.cc |  4 ++--
 gcc/testsuite/g++.dg/cpp1y/constexpr-complex2.C | 18 ++
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index c68666cc5ddc..3cbc9c8b302e 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -6415,7 +6415,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree 
t,
  break;
 
case REALPART_EXPR:
- gcc_assert (probe == target);
+ gcc_assert (refs->is_empty ());
  vec_safe_push (refs, NULL_TREE);
  vec_safe_push (refs, probe);
  vec_safe_push (refs, TREE_TYPE (probe));
@@ -6423,7 +6423,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree 
t,
  break;
 
case IMAGPART_EXPR:
- gcc_assert (probe == target);
+ gcc_assert (refs->is_empty ());
  vec_safe_push (refs, NULL_TREE);
  vec_safe_push (refs, probe);
  vec_safe_push (refs, TREE_TYPE (probe));
diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-complex2.C 
b/gcc/testsuite/g++.dg/cpp1y/constexpr-complex2.C
new file mode 100644
index ..7baafd83a322
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-complex2.C
@@ -0,0 +1,18 @@
+// PR c++/119045
+// { dg-do compile { target c++14 } }
+
+constexpr float
+foo ()
+{
+  __complex__ float f {1, 2};
+  float s = __real__ f + __imag__ f;
+  float &r = __real__ f;
+  float &i = __imag__ f;
+  r = 42;
+  s += __real__ f;
+  i = 3;
+  s += __imag__ f;
+  return s;
+}
+
+static_assert (foo () == 48.0f, "");


[gcc r15-7754] lto/91299 - weak definition inlined with LTO

2025-02-28 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:bc34db5b12e008f6ec4fdf4ebd22263c8617e5e3

commit r15-7754-gbc34db5b12e008f6ec4fdf4ebd22263c8617e5e3
Author: Richard Biener 
Date:   Fri Feb 28 14:09:29 2025 +0100

lto/91299 - weak definition inlined with LTO

The following fixes a thinko in the handling of interposed weak
definitions which confused the interposition check in
get_availability by setting DECL_EXTERNAL too early.

PR lto/91299
gcc/lto/
* lto-symtab.cc (lto_symtab_merge_symbols): Set DECL_EXTERNAL
only after calling get_availability.

gcc/testsuite/
* gcc.dg/lto/pr91299_0.c: New testcase.
* gcc.dg/lto/pr91299_1.c: Likewise.

Diff:
---
 gcc/lto/lto-symtab.cc|  2 +-
 gcc/testsuite/gcc.dg/lto/pr91299_0.c | 16 
 gcc/testsuite/gcc.dg/lto/pr91299_1.c |  6 ++
 3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/gcc/lto/lto-symtab.cc b/gcc/lto/lto-symtab.cc
index bc3c144e4441..66674a4415f8 100644
--- a/gcc/lto/lto-symtab.cc
+++ b/gcc/lto/lto-symtab.cc
@@ -1016,7 +1016,6 @@ lto_symtab_merge_symbols (void)
  || node->resolution == LDPR_RESOLVED_EXEC
  || node->resolution == LDPR_RESOLVED_DYN))
{
- DECL_EXTERNAL (node->decl) = 1;
  /* If alias to local symbol was preempted by external definition,
 we know it is not pointing to the local symbol.  Remove it.  */
  if (node->alias
@@ -1042,6 +1041,7 @@ lto_symtab_merge_symbols (void)
  node->remove_all_references ();
}
}
+ DECL_EXTERNAL (node->decl) = 1;
}
 
  if (!(cnode = dyn_cast  (node))
diff --git a/gcc/testsuite/gcc.dg/lto/pr91299_0.c 
b/gcc/testsuite/gcc.dg/lto/pr91299_0.c
new file mode 100644
index ..d9a8b21d6b84
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr91299_0.c
@@ -0,0 +1,16 @@
+/* { dg-lto-do run } */
+/* { dg-lto-options { { -O2 -flto } } } */
+
+__attribute__((weak)) int get_t(void)
+{
+  return 0;
+}
+
+int a;
+int main(void)
+{
+  a = get_t();
+  if (a != 1)
+__builtin_abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/lto/pr91299_1.c 
b/gcc/testsuite/gcc.dg/lto/pr91299_1.c
new file mode 100644
index ..29a28520f7b5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/pr91299_1.c
@@ -0,0 +1,6 @@
+/* { dg-options "-fno-lto" } */
+
+int get_t(void)
+{
+return 1;
+}


[gcc r15-7760] ipa-sra: Avoid clashes with ipa-cp when pulling accesses across calls (PR 118243)

2025-02-28 Thread Martin Jambor via Gcc-cvs
https://gcc.gnu.org/g:0bffcd469e68d68ba9c724f515651deff8494b82

commit r15-7760-g0bffcd469e68d68ba9c724f515651deff8494b82
Author: Martin Jambor 
Date:   Fri Feb 28 17:34:10 2025 +0100

ipa-sra: Avoid clashes with ipa-cp when pulling accesses across calls (PR 
118243)

Among other things, IPA-SRA checks whether splitting out a bit of an
aggregate or something passed by reference would lead into a clash
with an already known IPA-CP constant a way which would cause problems
later on.  Unfortunately the test is done only in
adjust_parameter_descriptions and is missing when accesses are
propagated from callees to callers, which leads to miscompilation
reported as PR 118243 (where the callee is a function created by
ipa-split).

The matter is then further complicated by the fact that we consider
complex numbers as scalars even though they can be modified piecemeal
(IPA-CP can detect and propagate the pieces separately too) which then
confuses the parameter manipulation machinery furter.

This patch simply adds the missing check to avoid the IPA-SRA
transform in these cases too, which should be suitable for backporting
to all affected release branches.  It is a bit of a shame as in the PR
testcase we do propagate both components of the complex number in
question and the transformation phase could recover.  I have some
prototype patches in this direction but that is something for (a)
stage 1.

gcc/ChangeLog:

2025-02-10  Martin Jambor  

PR ipa/118243
* ipa-sra.cc (pull_accesses_from_callee): New parameters
caller_ipcp_ts and param_idx.  Check that scalar pulled accesses 
would
not clash with a known IPA-CP aggregate constant.
(param_splitting_across_edge): Pass IPA-CP transformation summary 
and
caller parameter index to pull_accesses_from_callee.

gcc/testsuite/ChangeLog:

2025-02-10  Martin Jambor  

PR ipa/118243
* g++.dg/ipa/pr118243.C: New test.

Diff:
---
 gcc/ipa-sra.cc  | 38 +--
 gcc/testsuite/g++.dg/ipa/pr118243.C | 40 +
 2 files changed, 68 insertions(+), 10 deletions(-)

diff --git a/gcc/ipa-sra.cc b/gcc/ipa-sra.cc
index ad80d22f8ced..5d1703ed394f 100644
--- a/gcc/ipa-sra.cc
+++ b/gcc/ipa-sra.cc
@@ -3640,15 +3640,19 @@ enum acc_prop_kind {ACC_PROP_DONT, ACC_PROP_COPY, 
ACC_PROP_CERTAIN};
 
 /* Attempt to propagate all definite accesses from ARG_DESC to PARAM_DESC,
(which belongs to CALLER) if they would not violate some constraint there.
-   If successful, return NULL, otherwise return the string reason for failure
-   (which can be written to the dump file).  DELTA_OFFSET is the known offset
-   of the actual argument withing the formal parameter (so of ARG_DESCS within
-   PARAM_DESCS), ARG_SIZE is the size of the actual argument or zero, if not
-   known. In case of success, set *CHANGE_P to true if propagation actually
-   changed anything.  */
+   CALLER_IPCP_TS describes the caller, PARAM_IDX is the index of the parameter
+   described by PARAM_DESC.  If successful, return NULL, otherwise return the
+   string reason for failure (which can be written to the dump file).
+   DELTA_OFFSET is the known offset of the actual argument withing the formal
+   parameter (so of ARG_DESCS within PARAM_DESCS), ARG_SIZE is the size of the
+   actual argument or zero, if not known. In case of success, set *CHANGE_P to
+   true if propagation actually changed anything.  */
 
 static const char *
-pull_accesses_from_callee (cgraph_node *caller, isra_param_desc *param_desc,
+pull_accesses_from_callee (cgraph_node *caller,
+  ipcp_transformation *caller_ipcp_ts,
+  int param_idx,
+  isra_param_desc *param_desc,
   isra_param_desc *arg_desc,
   unsigned delta_offset, unsigned arg_size,
   bool *change_p)
@@ -3673,6 +3677,17 @@ pull_accesses_from_callee (cgraph_node *caller, 
isra_param_desc *param_desc,
continue;
 
   unsigned offset = argacc->unit_offset + delta_offset;
+
+  if (caller_ipcp_ts && !AGGREGATE_TYPE_P (argacc->type))
+   {
+ ipa_argagg_value_list avl (caller_ipcp_ts);
+ tree value = avl.get_value (param_idx, offset);
+ if (value && ((tree_to_uhwi (TYPE_SIZE (TREE_TYPE (value)))
+/ BITS_PER_UNIT)
+   != argacc->unit_size))
+   return " propagated access would conflict with an IPA-CP constant";
+   }
+
   /* Given that accesses are initially stored according to increasing
 offset and decreasing size in case of equal offsets, the following
 searches could be written more efficiently if we kept the ordering
@@ -3781,6 +3796,8 @@ para

[gcc r15-7758] libstdc++: Improve optional's <=> constraint recursion workaround [PR104606]

2025-02-28 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:815f1f27a1dba2f0acd1f02d0beafedadebe967c

commit r15-7758-g815f1f27a1dba2f0acd1f02d0beafedadebe967c
Author: Patrick Palka 
Date:   Fri Feb 28 10:15:45 2025 -0500

libstdc++: Improve optional's <=> constraint recursion workaround [PR104606]

It turns out the reason the behavior of this testcase changed after CWG
2369 is because validity of the substituted return type is now checked
later, after constraints.  So a more reliable workaround for this issue
is to add a constraint to check the validity of the return type earlier,
matching the pre-CWG 2369 semantics.

PR libstdc++/104606

libstdc++-v3/ChangeLog:

* include/std/optional (operator<=>): Revert r14-9771 change.
Add constraint checking the validity of the return type
compare_three_way_result_t before the three_way_comparable_with
constraint.

Reviewed-by: Jonathan Wakely 

Diff:
---
 libstdc++-v3/include/std/optional | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/std/optional 
b/libstdc++-v3/include/std/optional
index 832dc6fd84ba..a616dc07b107 100644
--- a/libstdc++-v3/include/std/optional
+++ b/libstdc++-v3/include/std/optional
@@ -1685,7 +1685,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
 requires (!__is_derived_from_optional<_Up>)
-  && three_way_comparable_with<_Up, _Tp>
+  && requires { typename compare_three_way_result_t<_Tp, _Up>; }
+  && three_way_comparable_with<_Tp, _Up>
 constexpr compare_three_way_result_t<_Tp, _Up>
 operator<=> [[nodiscard]] (const optional<_Tp>& __x, const _Up& __v)
 { return bool(__x) ? *__x <=> __v : strong_ordering::less; }


[gcc r14-11353] libstdc++: Implement LWG 2937 for std::filesystem::equivalent [PR118158]

2025-02-28 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:a66d9754b8779446214853c86af41d74577da14a

commit r14-11353-ga66d9754b8779446214853c86af41d74577da14a
Author: Jonathan Wakely 
Date:   Mon Dec 30 13:08:41 2024 +

libstdc++: Implement LWG 2937 for std::filesystem::equivalent [PR118158]

Do not report an error for (is_other(s1) && is_other(s2)) as the
standard originally said, nor for (is_other(s1) || is_other(s2)) as
libstdc++ was doing. We can compare inode numbers for special files and
so give sensible answers.

libstdc++-v3/ChangeLog:

PR libstdc++/118158
* src/c++17/fs_ops.cc (fs::equivalent): Remove error reporting
for is_other(s1) && is_other(s2) case, as per LWG 2937.
* testsuite/27_io/filesystem/operations/pr118158.cc: New test.

(cherry picked from commit 301a961ffd0567eece55ece42e80a7ba9e855ba0)

Diff:
---
 libstdc++-v3/src/c++17/fs_ops.cc   | 22 +++-
 .../27_io/filesystem/operations/pr118158.cc| 62 ++
 2 files changed, 69 insertions(+), 15 deletions(-)

diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 946fefd9e449..53c8b6d445ab 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -914,24 +914,16 @@ fs::equivalent(const path& p1, const path& p2, 
error_code& ec) noexcept
   else
 err = errno;
 
-  if (exists(s1) && exists(s2))
-{
-  if (is_other(s1) && is_other(s2))
-   {
- ec = std::__unsupported();
- return false;
-   }
-  ec.clear();
-  if (is_other(s1) || is_other(s2))
-   return false;
-  return fs::equiv_files(p1.c_str(), st1, p2.c_str(), st2, ec);
-}
+  if (err)
+ec.assign(err, std::generic_category());
   else if (!exists(s1) || !exists(s2))
 ec = std::make_error_code(std::errc::no_such_file_or_directory);
-  else if (err)
-ec.assign(err, std::generic_category());
   else
-ec.clear();
+{
+  ec.clear();
+  if (s1.type() == s2.type())
+   return fs::equiv_files(p1.c_str(), st1, p2.c_str(), st2, ec);
+}
   return false;
 #else
   ec = std::make_error_code(std::errc::function_not_supported);
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/operations/pr118158.cc 
b/libstdc++-v3/testsuite/27_io/filesystem/operations/pr118158.cc
new file mode 100644
index ..b57a2d184f41
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/filesystem/operations/pr118158.cc
@@ -0,0 +1,62 @@
+// { dg-do run { target c++17 } }
+// { dg-require-filesystem-ts "" }
+
+#include 
+#include 
+#include 
+
+#if defined(_GLIBCXX_HAVE_SYS_STAT_H) && defined(_GLIBCXX_HAVE_SYS_TYPES_H)
+# include 
+# include   // mkfifo
+#endif
+
+namespace fs = std::filesystem;
+
+void
+test_pr118158()
+{
+#if defined(_GLIBCXX_HAVE_SYS_STAT_H) && defined(_GLIBCXX_HAVE_SYS_TYPES_H) \
+  && defined(S_IWUSR) && defined(S_IRUSR)
+  auto p1 = __gnu_test::nonexistent_path();
+  auto p2 = __gnu_test::nonexistent_path();
+  auto p3 = __gnu_test::nonexistent_path();
+  const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
+  std::error_code ec;
+  bool result;
+
+  VERIFY( ! ::mkfifo(p1.c_str(), S_IWUSR | S_IRUSR) );
+  __gnu_test::scoped_file f1(p1, __gnu_test::scoped_file::adopt_file);
+
+  // Special file is equivalent to itself.
+  VERIFY( equivalent(p1, p1) );
+  VERIFY( equivalent(p1, p1, ec) );
+  VERIFY( ! ec );
+
+  VERIFY( ! ::mkfifo(p2.c_str(), S_IWUSR | S_IRUSR) );
+  __gnu_test::scoped_file f2(p2, __gnu_test::scoped_file::adopt_file);
+
+  ec = bad_ec;
+  // Distinct special files are not equivalent.
+  VERIFY( ! equivalent(p1, p2, ec) );
+  VERIFY( ! ec );
+
+  // Non-existent paths are always an error.
+  VERIFY( ! equivalent(p1, p3, ec) );
+  VERIFY( ec == std::errc::no_such_file_or_directory );
+  ec = bad_ec;
+  VERIFY( ! equivalent(p3, p2, ec) );
+  VERIFY( ec == std::errc::no_such_file_or_directory );
+
+  // Special file is not equivalent to regular file.
+  __gnu_test::scoped_file f3(p3);
+  ec = bad_ec;
+  VERIFY( ! equivalent(p1, p3, ec) );
+  VERIFY( ! ec );
+#endif
+}
+
+int
+main()
+{
+  test_pr118158();
+}


[gcc r14-11356] libstdc++: Add missing equality comparison in new tests [PR117921]

2025-02-28 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:6e97d601f18141a67d0896122187e556d5f3d6c4

commit r14-11356-g6e97d601f18141a67d0896122187e556d5f3d6c4
Author: Jonathan Wakely 
Date:   Mon Dec 9 09:36:15 2024 +

libstdc++: Add missing equality comparison in new tests [PR117921]

These new tests fail in Debug Mode because the allocator types aren't
equality comparable.

libstdc++-v3/ChangeLog:

PR libstdc++/117921
* testsuite/23_containers/set/modifiers/swap/adl.cc: Add
equality comparison for Allocator.
* testsuite/23_containers/unordered_set/modifiers/swap-2.cc:
Likewise.

(cherry picked from commit 5cdd78b39725fb1d82cb6bd68e8f56bf4f5d51cd)

Diff:
---
 libstdc++-v3/testsuite/23_containers/set/modifiers/swap/adl.cc | 1 +
 libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/swap-2.cc | 1 +
 2 files changed, 2 insertions(+)

diff --git a/libstdc++-v3/testsuite/23_containers/set/modifiers/swap/adl.cc 
b/libstdc++-v3/testsuite/23_containers/set/modifiers/swap/adl.cc
index 2b7975a366fc..e2a1742c953a 100644
--- a/libstdc++-v3/testsuite/23_containers/set/modifiers/swap/adl.cc
+++ b/libstdc++-v3/testsuite/23_containers/set/modifiers/swap/adl.cc
@@ -36,6 +36,7 @@ namespace adl
   using propagate_on_container_swap = std::true_type;
 
   friend void swap(Allocator&, Allocator&) { swapped = true; }
+  friend bool operator==(Allocator, Allocator) { return true; }
 };
 }
 
diff --git 
a/libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/swap-2.cc 
b/libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/swap-2.cc
index a0fb1a6f662f..9d8b2200e24c 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/swap-2.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/swap-2.cc
@@ -43,6 +43,7 @@ namespace adl
   using propagate_on_container_swap = std::true_type;
 
   friend void swap(Allocator&, Allocator&) { swapped = true; }
+  friend bool operator==(Allocator, Allocator) { return true; }
 };
 }


[gcc r14-11357] libstdc++: Add missing character to __to_wstring_numeric map

2025-02-28 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:70452d24fa4bc6962f51232674ffdd6826723777

commit r14-11357-g70452d24fa4bc6962f51232674ffdd6826723777
Author: Jonathan Wakely 
Date:   Mon Dec 16 09:45:40 2024 +

libstdc++: Add missing character to __to_wstring_numeric map

The mapping from char to wchar_t needs to handle 'i' and 'I' but those
were absent from the table that is used for some non-ASCII encodings.

libstdc++-v3/ChangeLog:

* include/bits/basic_string.h (__to_wstring_numeric): Add 'i'
and 'I' to mapping.

(cherry picked from commit e1937cf33abded5c6ebbe4938a4a3e8cb3365176)

Diff:
---
 libstdc++-v3/include/bits/basic_string.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/libstdc++-v3/include/bits/basic_string.h 
b/libstdc++-v3/include/bits/basic_string.h
index 2794ec6419ac..abbe17cf4a15 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -4496,6 +4496,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
__wc['d'] = L'd';
__wc['e'] = L'e';
__wc['f'] = L'f';
+   __wc['i'] = L'i'; // for "inf"
__wc['n'] = L'n'; // for "nan" and "inf"
__wc['p'] = L'p'; // for hexfloats "0x1p1"
__wc['x'] = L'x';
@@ -4505,6 +4506,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
__wc['D'] = L'D';
__wc['E'] = L'E';
__wc['F'] = L'F';
+   __wc['I'] = L'I';
__wc['N'] = L'N';
__wc['P'] = L'P';
__wc['X'] = L'X';


[gcc r14-11355] libstdc++: Use ADL swap for containers' function objects [PR117921]

2025-02-28 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:dd8866d79632ddcf4811859e98f5c990627d5727

commit r14-11355-gdd8866d79632ddcf4811859e98f5c990627d5727
Author: Jonathan Wakely 
Date:   Thu Dec 5 12:46:26 2024 +

libstdc++: Use ADL swap for containers' function objects [PR117921]

The standard says that Compare, Pred and Hash objects should be swapped
as described in [swappable.requirements] which means calling swap
unqualified with std::swap visible to name lookup.

libstdc++-v3/ChangeLog:

PR libstdc++/117921
* include/bits/hashtable_policy.h (_Hash_code_base::_M_swap):
Use ADL swap for Hash members.
(_Hashtable_base::_M_swap): Use ADL swap for _Equal members.
* include/bits/stl_tree.h (_Rb_tree::swap): Use ADL swap for
_Compare members.
* testsuite/23_containers/set/modifiers/swap/adl.cc: New test.
* testsuite/23_containers/unordered_set/modifiers/swap-2.cc: New
test.

(cherry picked from commit 0368c42507328774cadbea589509b95aaf3cb826)

Diff:
---
 libstdc++-v3/include/bits/hashtable_policy.h   |  8 ++-
 libstdc++-v3/include/bits/stl_tree.h   |  4 +-
 .../23_containers/set/modifiers/swap/adl.cc| 54 +++
 .../unordered_set/modifiers/swap-2.cc  | 62 ++
 4 files changed, 125 insertions(+), 3 deletions(-)

diff --git a/libstdc++-v3/include/bits/hashtable_policy.h 
b/libstdc++-v3/include/bits/hashtable_policy.h
index 68ec8d9470a7..738a4da9382e 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -1396,7 +1396,10 @@ namespace __detail
 
   void
   _M_swap(_Hash_code_base& __x)
-  { std::swap(__ebo_hash::_M_get(), __x.__ebo_hash::_M_get()); }
+  {
+   using std::swap;
+   swap(__ebo_hash::_M_get(), __x.__ebo_hash::_M_get());
+  }
 
   const _Hash&
   _M_hash() const { return __ebo_hash::_M_cget(); }
@@ -1780,7 +1783,8 @@ namespace __detail
   _M_swap(_Hashtable_base& __x)
   {
__hash_code_base::_M_swap(__x);
-   std::swap(_EqualEBO::_M_get(), __x._EqualEBO::_M_get());
+   using std::swap;
+   swap(_EqualEBO::_M_get(), __x._EqualEBO::_M_get());
   }
 
   const _Equal&
diff --git a/libstdc++-v3/include/bits/stl_tree.h 
b/libstdc++-v3/include/bits/stl_tree.h
index 978093fc5877..99575f6fe149 100644
--- a/libstdc++-v3/include/bits/stl_tree.h
+++ b/libstdc++-v3/include/bits/stl_tree.h
@@ -2089,7 +2089,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  std::swap(this->_M_impl._M_node_count, __t._M_impl._M_node_count);
}
   // No need to swap header's color as it does not change.
-  std::swap(this->_M_impl._M_key_compare, __t._M_impl._M_key_compare);
+
+  using std::swap;
+  swap(this->_M_impl._M_key_compare, __t._M_impl._M_key_compare);
 
   _Alloc_traits::_S_on_swap(_M_get_Node_allocator(),
__t._M_get_Node_allocator());
diff --git a/libstdc++-v3/testsuite/23_containers/set/modifiers/swap/adl.cc 
b/libstdc++-v3/testsuite/23_containers/set/modifiers/swap/adl.cc
new file mode 100644
index ..2b7975a366fc
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/set/modifiers/swap/adl.cc
@@ -0,0 +1,54 @@
+// { dg-do run { target c++11 } }
+
+// Bug 117921 - containers do not use ADL swap for Compare, Pred or Hash types
+
+#include 
+#include 
+
+namespace adl
+{
+  struct Less : std::less
+  {
+static bool swapped;
+friend void swap(Less&, Less&) { swapped = true; }
+  };
+  bool Less::swapped = false;
+
+  struct Allocator_base
+  {
+static bool swapped;
+  };
+  bool Allocator_base::swapped = false;
+
+  using std::size_t;
+
+  template
+struct Allocator : Allocator_base
+{
+  using value_type = T;
+
+  Allocator() { }
+  template Allocator(const Allocator&) { }
+
+  T* allocate(size_t n) { return std::allocator().allocate(n); }
+  void deallocate(T* p, size_t n) { std::allocator().deallocate(p, n); }
+
+  using propagate_on_container_swap = std::true_type;
+
+  friend void swap(Allocator&, Allocator&) { swapped = true; }
+};
+}
+
+void
+test_swap()
+{
+  std::set> s1, s2;
+  s1.swap(s2);
+  VERIFY( adl::Less::swapped );
+  VERIFY( adl::Allocator_base::swapped );
+}
+
+int main()
+{
+  test_swap();
+}
diff --git 
a/libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/swap-2.cc 
b/libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/swap-2.cc
new file mode 100644
index ..a0fb1a6f662f
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/swap-2.cc
@@ -0,0 +1,62 @@
+// { dg-do run { target c++11 } }
+
+// Bug 117921 - containers do not use ADL swap for Compare, Pred or Hash types
+
+#include 
+#include 
+
+namespace adl
+{
+  struct Hash : std::hash
+  {
+static bool swapped;
+friend void swap(Hash&, Hash&) { swapped = true;

[gcc r14-11359] libstdc++: fix a dangling reference crash in ranges::is_permutation [PR118160]

2025-02-28 Thread Jonathan Wakely via Gcc-cvs
https://gcc.gnu.org/g:f83bc0edb51e3e70e9cb5786f99f299ad2baa283

commit r14-11359-gf83bc0edb51e3e70e9cb5786f99f299ad2baa283
Author: Giuseppe D'Angelo 
Date:   Thu Feb 6 14:24:17 2025 +

libstdc++: fix a dangling reference crash in ranges::is_permutation 
[PR118160]

The code was caching the result of `invoke(proj, *it)` in a local
`auto &&` variable. The problem is that this may create dangling
references, for instance in case `proj` is `std::identity` (the common
case) and `*it` produces a prvalue: lifetime extension does not
apply here due to the expressions involved.

Instead, store (and lifetime-extend) the result of `*it` in a separate
variable, then project that variable. While at it, also forward the
result of the projection to the predicate, so that the predicate can
act on the proper value category.

libstdc++-v3/ChangeLog:

PR libstdc++/118160
PR libstdc++/100249
* include/bits/ranges_algo.h (__is_permutation_fn): Avoid a
dangling reference by storing the result of the iterator
dereference and the result of the projection in two distinct
variables, in order to lifetime-extend each one.
Forward the projected value to the predicate.
* testsuite/25_algorithms/is_permutation/constrained.cc: Add a
test with a range returning prvalues. Test it in a constexpr
context, in order to rely on the compiler to catch UB.

Signed-off-by: Giuseppe D'Angelo 
(cherry picked from commit 2a2bd96d0d2109384a0eedde843ba811d2e18738)

Diff:
---
 libstdc++-v3/include/bits/ranges_algo.h |  7 +--
 .../testsuite/25_algorithms/is_permutation/constrained.cc   | 13 +
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/include/bits/ranges_algo.h 
b/libstdc++-v3/include/bits/ranges_algo.h
index 0386e7aafa6d..6bac65bc564d 100644
--- a/libstdc++-v3/include/bits/ranges_algo.h
+++ b/libstdc++-v3/include/bits/ranges_algo.h
@@ -561,9 +561,12 @@ namespace ranges
 
for (auto __scan = __first1; __scan != __last1; ++__scan)
  {
-   auto&& __proj_scan = std::__invoke(__proj1, *__scan);
+   auto&& __scan_deref = *__scan;
+   auto&& __proj_scan =
+ std::__invoke(__proj1, 
std::forward(__scan_deref));
auto __comp_scan = [&]  (_Tp&& __arg) -> bool {
- return std::__invoke(__pred, __proj_scan,
+ return std::__invoke(__pred,
+  
std::forward(__proj_scan),
   std::forward<_Tp>(__arg));
};
if (__scan != ranges::find_if(__first1, __scan,
diff --git a/libstdc++-v3/testsuite/25_algorithms/is_permutation/constrained.cc 
b/libstdc++-v3/testsuite/25_algorithms/is_permutation/constrained.cc
index 2fbebe376094..7266aff5b17d 100644
--- a/libstdc++-v3/testsuite/25_algorithms/is_permutation/constrained.cc
+++ b/libstdc++-v3/testsuite/25_algorithms/is_permutation/constrained.cc
@@ -19,6 +19,7 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -76,10 +77,22 @@ test03()
   while (std::next_permutation(std::begin(cx), std::end(cx)));
 }
 
+constexpr
+bool
+test04() // PR118160, do not create dangling references
+{
+  int x[] = { 4, 3, 2, 1 };
+  auto y = std::views::iota(1, 5);
+  return ranges::is_permutation(x, y) && ranges::is_permutation(y, x);
+}
+
+static_assert(test04());
+
 int
 main()
 {
   test01();
   test02();
   test03();
+  VERIFY( test04() );
 }


[gcc r14-11354] libstdc++: Add debug assertions to std::list and std::forward_list

2025-02-28 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:1921b0c043014cdcc9981eefb674f2cab3a9d72e

commit r14-11354-g1921b0c043014cdcc9981eefb674f2cab3a9d72e
Author: Jonathan Wakely 
Date:   Fri Nov 15 22:03:20 2024 +

libstdc++: Add debug assertions to std::list and std::forward_list

While working on fancy pointer support for the linked lists I noticed
they didn't have any debug assertions. This adds the obvious non-empty
assertions to front() and back().

libstdc++-v3/ChangeLog:

* include/bits/forward_list.h (forward_list::front): Add
non-empty assertions.
* include/bits/stl_list.h (list::front, list::back): Add
non-empty assertions.

(cherry picked from commit e7aa614d7372b5d3cbcd2400838c80ef905ba381)

Diff:
---
 libstdc++-v3/include/bits/forward_list.h |  3 +++
 libstdc++-v3/include/bits/stl_list.h | 13 +++--
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/include/bits/forward_list.h 
b/libstdc++-v3/include/bits/forward_list.h
index 5ab2253f6093..1dae56c4734e 100644
--- a/libstdc++-v3/include/bits/forward_list.h
+++ b/libstdc++-v3/include/bits/forward_list.h
@@ -40,6 +40,7 @@
 #include 
 #include 
 #include 
+#include 
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -821,6 +822,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   reference
   front()
   {
+   __glibcxx_requires_nonempty();
_Node* __front = static_cast<_Node*>(this->_M_impl._M_head._M_next);
return *__front->_M_valptr();
   }
@@ -833,6 +835,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   const_reference
   front() const
   {
+   __glibcxx_requires_nonempty();
_Node* __front = static_cast<_Node*>(this->_M_impl._M_head._M_next);
return *__front->_M_valptr();
   }
diff --git a/libstdc++-v3/include/bits/stl_list.h 
b/libstdc++-v3/include/bits/stl_list.h
index 8b2521960a8f..089484844684 100644
--- a/libstdc++-v3/include/bits/stl_list.h
+++ b/libstdc++-v3/include/bits/stl_list.h
@@ -59,6 +59,7 @@
 
 #include 
 #include 
+#include 
 #if __cplusplus >= 201103L
 #include 
 #include 
@@ -1203,7 +1204,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   _GLIBCXX_NODISCARD
   reference
   front() _GLIBCXX_NOEXCEPT
-  { return *begin(); }
+  {
+   __glibcxx_requires_nonempty();
+   return *begin();
+  }
 
   /**
*  Returns a read-only (constant) reference to the data at the first
@@ -1212,7 +1216,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   _GLIBCXX_NODISCARD
   const_reference
   front() const _GLIBCXX_NOEXCEPT
-  { return *begin(); }
+  {
+   __glibcxx_requires_nonempty();
+   return *begin();
+  }
 
   /**
*  Returns a read/write reference to the data at the last element
@@ -1222,6 +1229,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   reference
   back() _GLIBCXX_NOEXCEPT
   {
+   __glibcxx_requires_nonempty();
iterator __tmp = end();
--__tmp;
return *__tmp;
@@ -1235,6 +1243,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   const_reference
   back() const _GLIBCXX_NOEXCEPT
   {
+   __glibcxx_requires_nonempty();
const_iterator __tmp = end();
--__tmp;
return *__tmp;


[gcc r14-11358] libstdc++: Qualify calls in to prevent ADL

2025-02-28 Thread Jonathan Wakely via Libstdc++-cvs
https://gcc.gnu.org/g:6561de33c3b184b039f79f49a5f1c949f9c6ecd5

commit r14-11358-g6561de33c3b184b039f79f49a5f1c949f9c6ecd5
Author: Jonathan Wakely 
Date:   Fri Jun 21 00:25:32 2024 +0100

libstdc++: Qualify calls in  to prevent ADL

libstdc++-v3/ChangeLog:

* include/bits/stl_uninitialized.h (uninitialized_default_construct)
(uninitialized_default_construct_n, uninitialized_value_construct)
(uninitialized_value_construct_n): Qualify calls to prevent ADL.

(cherry picked from commit 09ca26cd24778e0820525edfac1cce07262f7e6c)

Diff:
---
 libstdc++-v3/include/bits/stl_uninitialized.h | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libstdc++-v3/include/bits/stl_uninitialized.h 
b/libstdc++-v3/include/bits/stl_uninitialized.h
index 7f84da31578c..3c405d8fbe80 100644
--- a/libstdc++-v3/include/bits/stl_uninitialized.h
+++ b/libstdc++-v3/include/bits/stl_uninitialized.h
@@ -975,7 +975,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 uninitialized_default_construct(_ForwardIterator __first,
_ForwardIterator __last)
 {
-  __uninitialized_default_novalue(__first, __last);
+  std::__uninitialized_default_novalue(__first, __last);
 }
 
   /**
@@ -989,7 +989,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 inline _ForwardIterator
 uninitialized_default_construct_n(_ForwardIterator __first, _Size __count)
 {
-  return __uninitialized_default_novalue_n(__first, __count);
+  return std::__uninitialized_default_novalue_n(__first, __count);
 }
 
   /**
@@ -1003,7 +1003,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 uninitialized_value_construct(_ForwardIterator __first,
  _ForwardIterator __last)
 {
-  return __uninitialized_default(__first, __last);
+  return std::__uninitialized_default(__first, __last);
 }
 
   /**
@@ -1017,7 +1017,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 inline _ForwardIterator
 uninitialized_value_construct_n(_ForwardIterator __first, _Size __count)
 {
-  return __uninitialized_default_n(__first, __count);
+  return std::__uninitialized_default_n(__first, __count);
 }
 
   /**


[gcc r15-7759] c++: generic lambda, implicit 'this' capture, xobj memfn [PR119038]

2025-02-28 Thread Patrick Palka via Gcc-cvs
https://gcc.gnu.org/g:1a150f1f688486b12cd975bdc4cd1bd52a7e0110

commit r15-7759-g1a150f1f688486b12cd975bdc4cd1bd52a7e0110
Author: Patrick Palka 
Date:   Fri Feb 28 10:56:49 2025 -0500

c++: generic lambda, implicit 'this' capture, xobj memfn [PR119038]

When a generic lambda calls an overload set containing an iobj member
function we speculatively capture 'this'.  We need to do the same
for an xobj member function.

PR c++/119038

gcc/cp/ChangeLog:

* lambda.cc (maybe_generic_this_capture): Consider xobj
member functions as well, not just iobj.  Update function
comment.

gcc/testsuite/ChangeLog:

* g++.dg/cpp23/explicit-obj-lambda15.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/lambda.cc   |  7 +++
 gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda15.C | 11 +++
 2 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index 09898f6746ca..da075b988059 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -971,9 +971,8 @@ maybe_resolve_dummy (tree object, bool add_capture_p)
 /* When parsing a generic lambda containing an argument-dependent
member function call we defer overload resolution to instantiation
time.  But we have to know now whether to capture this or not.
-   Do that if FNS contains any non-static fns.
-   The std doesn't anticipate this case, but I expect this to be the
-   outcome of discussion.  */
+   Do that if FNS contains any non-static fns as per
+   [expr.prim.lambda.capture]/7.1.  */
 
 void
 maybe_generic_this_capture (tree object, tree fns)
@@ -992,7 +991,7 @@ maybe_generic_this_capture (tree object, tree fns)
for (lkp_iterator iter (fns); iter; ++iter)
  if (((!id_expr && TREE_CODE (*iter) != USING_DECL)
   || TREE_CODE (*iter) == TEMPLATE_DECL)
- && DECL_IOBJ_MEMBER_FUNCTION_P (*iter))
+ && DECL_OBJECT_MEMBER_FUNCTION_P (*iter))
{
  /* Found a non-static member.  Capture this.  */
  lambda_expr_this_capture (lam, /*maybe*/-1);
diff --git a/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda15.C 
b/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda15.C
new file mode 100644
index ..369f0895ed10
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/explicit-obj-lambda15.C
@@ -0,0 +1,11 @@
+// PR c++/119038
+// { dg-do compile { target c++23 } }
+
+struct A {
+  void f() {
+[&](auto x) { g(x); h(x); }(0);
+  }
+
+  void g(this A&, int);
+  void h(this auto&, auto);
+};


[gcc r15-7761] c++: ICE in replace_decl [PR118986]

2025-02-28 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:22018a4a8caa806a8f673eb0713de16d64d25063

commit r15-7761-g22018a4a8caa806a8f673eb0713de16d64d25063
Author: Marek Polacek 
Date:   Wed Feb 26 11:14:00 2025 -0500

c++: ICE in replace_decl [PR118986]

Yet another problem that started with r15-6052, compile time evaluation of
prvalues.

cp_fold_r/TARGET_EXPR sees:

  TARGET_EXPR >>> 

so when we call maybe_constant_init, the object we're initializing is 
D.2701,
and the init is the expr_stmt.  We unwrap the 
EXPR_STMT/INIT_EXPR/TARGET_EXPR
in maybe_constant_init_1 and so end up evaluating the f1 call.  But f1 
returns
c2 whereas the type of D.2701 is ._anon_0 -- the closure.

So then we crash in replace_decl on:

  gcc_checking_assert (same_type_ignoring_top_level_qualifiers_p
   (TREE_TYPE (decl), TREE_TYPE (replacement)));

due to the mismatched types.

cxx_eval_outermost_constant_expr is already ready for the types to be
different, in which case the result isn't constant.  But replace_decl
is called before that check.

I'm leaving the assert in replace_decl on purpose, maybe we'll find
another use for it.

PR c++/118986

gcc/cp/ChangeLog:

* constexpr.cc (cxx_eval_call_expression): Check that the types 
match
before calling replace_decl, if not, set *non_constant_p.
(maybe_constant_init_1): Don't strip INIT_EXPR if it would change 
the
type of the expression.

gcc/testsuite/ChangeLog:

* g++.dg/cpp2a/constexpr-prvalue1.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/constexpr.cc | 29 +
 gcc/testsuite/g++.dg/cpp2a/constexpr-prvalue1.C | 23 
 2 files changed, 43 insertions(+), 9 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 3cbc9c8b302e..97c227d57a67 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -3388,16 +3388,22 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, 
tree t,
 
/* Rewrite all occurrences of the function's RESULT_DECL with the
   current object under construction.  */
-   if (!*non_constant_p && ctx->object
+   if (!*non_constant_p
+   && ctx->object
&& CLASS_TYPE_P (TREE_TYPE (res))
&& !is_empty_class (TREE_TYPE (res)))
- if (replace_decl (&result, res, ctx->object))
-   {
- cacheable = false;
- result = cxx_eval_constant_expression (ctx, result, lval,
-non_constant_p,
-overflow_p);
-   }
+ {
+   if (!same_type_ignoring_top_level_qualifiers_p
+   (TREE_TYPE (res), TREE_TYPE (ctx->object)))
+ *non_constant_p = true;
+   else if (replace_decl (&result, res, ctx->object))
+ {
+   cacheable = false;
+   result = cxx_eval_constant_expression (ctx, result, lval,
+  non_constant_p,
+  overflow_p);
+ }
+ }
 
  /* Only cache a permitted result of a constant expression.  */
  if (cacheable && !reduced_constant_expression_p (result))
@@ -9605,7 +9611,12 @@ maybe_constant_init_1 (tree t, tree decl, bool 
allow_non_constant,
   if (TREE_CODE (t) == CONVERT_EXPR
   && VOID_TYPE_P (TREE_TYPE (t)))
 t = TREE_OPERAND (t, 0);
-  if (TREE_CODE (t) == INIT_EXPR)
+  /* If the types don't match, the INIT_EXPR is initializing a subobject of
+ DECL and losing that information would cause mischief later.  */
+  if (TREE_CODE (t) == INIT_EXPR
+  && (!decl
+ || same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (decl),
+   TREE_TYPE (t
 t = TREE_OPERAND (t, 1);
   if (TREE_CODE (t) == TARGET_EXPR)
 t = TARGET_EXPR_INITIAL (t);
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-prvalue1.C 
b/gcc/testsuite/g++.dg/cpp2a/constexpr-prvalue1.C
new file mode 100644
index ..f4e704d9487a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-prvalue1.C
@@ -0,0 +1,23 @@
+// PR c++/118986
+// { dg-do compile { target c++20 } }
+// { dg-options "-O" }
+
+struct c1 {
+constexpr c1(int *ptr) {}
+};
+struct c2 {
+c1 _M_t;
+constexpr ~c2() {}
+};
+constexpr inline
+c2 f1 ()
+{
+  return c2(new int);
+}
+
+void
+f ()
+{
+  auto l = [p = f1()](){};
+  [p = f1()](){};
+}


[gcc r15-7762] c++: fix rejects-valid and ICE with constexpr NSDMI [PR110822]

2025-02-28 Thread Marek Polacek via Gcc-cvs
https://gcc.gnu.org/g:96572464234a88949ebfc07207ae2ae04c63e53b

commit r15-7762-g96572464234a88949ebfc07207ae2ae04c63e53b
Author: Marek Polacek 
Date:   Tue Feb 18 12:18:31 2025 -0500

c++: fix rejects-valid and ICE with constexpr NSDMI [PR110822]

Since r10-7718 the attached tests produce an ICE in verify_address:

  error: constant not recomputed when 'ADDR_EXPR' changed

but before that we wrongly rejected the tests with "is not a constant
expression".  This patch fixes both problems.

Since r10-7718 replace_decl_r can replace

  {._M_dataplus=&._M_local_buf, ._M_local_buf=0}

with

  {._M_dataplus=&HelloWorld._M_local_buf, ._M_local_buf=0}

The initial &._M_local_buf was not constant, but since
HelloWorld is a static VAR_DECL, the resulting &HelloWorld._M_local_buf
should have been marked as TREE_CONSTANT.  And since we're taking
its address, the whole thing should be TREE_ADDRESSABLE.

PR c++/114913
PR c++/110822

gcc/cp/ChangeLog:

* constexpr.cc (replace_decl_r): If we've replaced something
inside of an ADDR_EXPR, call cxx_mark_addressable and
recompute_tree_invariant_for_addr_expr on the resulting ADDR_EXPR.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-nsdmi4.C: New test.
* g++.dg/cpp0x/constexpr-nsdmi5.C: New test.

Reviewed-by: Jason Merrill 

Diff:
---
 gcc/cp/constexpr.cc   | 21 -
 gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi4.C | 19 +++
 gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi5.C | 15 +++
 3 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 97c227d57a67..aa2fa44613a0 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -2707,7 +2707,26 @@ replace_decl_r (tree *tp, int *walk_subtrees, void *data)
 {
   replace_decl_data *d = (replace_decl_data *) data;
 
-  if (*tp == d->decl)
+  /* We could be replacing
+   &.bar -> &foo.bar
+ where foo is a static VAR_DECL, so we need to recompute TREE_CONSTANT
+ on the ADDR_EXPR around it.  */
+  if (TREE_CODE (*tp) == ADDR_EXPR)
+{
+  d->pset->add (*tp);
+  auto save_changed = d->changed;
+  d->changed = false;
+  cp_walk_tree (&TREE_OPERAND (*tp, 0), replace_decl_r, d, nullptr);
+  if (d->changed)
+   {
+ cxx_mark_addressable (*tp);
+ recompute_tree_invariant_for_addr_expr (*tp);
+   }
+  else
+   d->changed = save_changed;
+  *walk_subtrees = 0;
+}
+  else if (*tp == d->decl)
 {
   *tp = unshare_expr (d->replacement);
   d->changed = true;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi4.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi4.C
new file mode 100644
index ..360470dbccbf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi4.C
@@ -0,0 +1,19 @@
+// PR c++/114913
+// { dg-do compile { target c++11 } }
+
+struct strt {
+  char *_M_dataplus;
+  char _M_local_buf = 0;
+  constexpr strt()
+: _M_dataplus(&_M_local_buf) {}
+  constexpr strt(const strt &)
+: _M_dataplus(&_M_local_buf) {}
+};
+
+constexpr strt
+f ()
+{
+  return {};
+}
+constexpr strt HelloWorld = f();
+const char *a() { return HelloWorld._M_dataplus; }
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi5.C 
b/gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi5.C
new file mode 100644
index ..0a0acaa9fdff
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-nsdmi5.C
@@ -0,0 +1,15 @@
+// PR c++/110822
+// { dg-do compile { target c++11 } }
+
+void __ostream_insert(const char*);
+struct basic_string {
+  const char* _M_p;
+  char _M_local_buf[16] = {};
+  constexpr basic_string() : _M_p(_M_local_buf) {}
+  const char *data() const { return _M_p; }
+};
+constexpr basic_string f() { return {}; }
+constexpr basic_string text = f();
+int main() {
+  __ostream_insert(text._M_p);
+}


[gcc r15-7753] ipa/111245 - bogus modref analysis for store in call that might throw

2025-02-28 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:e6037af6d5e5a43c437257580d75bc8b35a6dcfd

commit r15-7753-ge6037af6d5e5a43c437257580d75bc8b35a6dcfd
Author: Richard Biener 
Date:   Fri Feb 28 11:44:26 2025 +0100

ipa/111245 - bogus modref analysis for store in call that might throw

We currently record a kill for

  *x_4(D) = always_throws ();

because we consider the store always executing since the appropriate
check for whether the stmt could throw is guarded by
!cfun->can_throw_non_call_exceptions.

PR ipa/111245
* ipa-modref.cc (modref_access_analysis::analyze_store): Do
not guard the check of whether the stmt could throw by
cfun->can_throw_non_call_exceptions.

* g++.dg/torture/pr111245.C: New testcase.

Diff:
---
 gcc/ipa-modref.cc   |  3 +--
 gcc/testsuite/g++.dg/torture/pr111245.C | 23 +++
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/gcc/ipa-modref.cc b/gcc/ipa-modref.cc
index f1d88abf3cf2..d3e510195b53 100644
--- a/gcc/ipa-modref.cc
+++ b/gcc/ipa-modref.cc
@@ -1753,8 +1753,7 @@ modref_access_analysis::analyze_store (gimple *stmt, 
tree, tree op, void *data)
 t->record_access_lto (t->m_summary_lto->stores, &r, a);
   if (t->m_always_executed
   && a.useful_for_kill_p ()
-  && (!cfun->can_throw_non_call_exceptions
- || !stmt_could_throw_p (cfun, stmt)))
+  && !stmt_could_throw_p (cfun, stmt))
 {
   if (dump_file)
fprintf (dump_file, "   - Recording kill\n");
diff --git a/gcc/testsuite/g++.dg/torture/pr111245.C 
b/gcc/testsuite/g++.dg/torture/pr111245.C
new file mode 100644
index ..785f4a51761d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr111245.C
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+
+struct Int {
+  int value;
+};
+
+__attribute__((noipa)) Int always_throws() { throw 123; }
+
+void foo(Int &x) {
+  try {
+x = always_throws();
+  } catch (...) {
+  }
+}
+
+int main()
+{
+  Int x;
+  x.value = 5;
+  foo(x);
+  if (x.value != 5)
+__builtin_abort ();
+}


[gcc r15-7752] ifcvt: Fix ICE with (fix:SI (fix:DF (reg:DF))) [PR117712]

2025-02-28 Thread Jakub Jelinek via Gcc-cvs
https://gcc.gnu.org/g:26e4783c707a96ebb42c6ec4537578e635974573

commit r15-7752-g26e4783c707a96ebb42c6ec4537578e635974573
Author: Jakub Jelinek 
Date:   Fri Feb 28 12:42:27 2025 +0100

ifcvt: Fix ICE with (fix:SI (fix:DF (reg:DF))) [PR117712]

As documented in the manual, FIX/UNSIGNED_FIX from floating point
mode to integral mode has unspecified rounding and FIX from floating point
mode to the same floating point mode is expressing rounding toward zero.
So, some targets (arc, arm, csky, m68k, mmix, nds32, pdp11, sparc and
visium) use
(fix:SI (fix:SF (match_operand:SF 1 "..._operand")))
etc. to express the rounding toward zero during conversion to integer.
For some reason other targets don't use that.

Anyway, the 2 FIXes (or inner FIX with outer UNSIGNED_FIX) cause problems
since the r15-2890 which removed some strict checks in ifcvt.cc on what
SET_SRC can be actually conditionalized (I must say I'm still worried
about the change, don't know why one can't get e.g. inline asm or
something with UNSPEC or some complex backend specific RTLs that
force_operand can't handle), force_operand just ICEs on it, it can only
handle (through expand_fix) conversions from floating point to integral.

The following patch fixes this by detecting this case and just pretend
the inner FIX isn't there, i.e. call expand_fix with the inner FIX's
operand instead, which works and on targets like arm it will just
create the nested FIXes again.

2025-02-28  Jakub Jelinek  

PR rtl-optimization/117712
* expr.cc (force_operand): Handle {,UNSIGNED_}FIX with
FIX operand using expand_fix on the inner FIX operand.

* gcc.dg/pr117712.c: New test.

Diff:
---
 gcc/expr.cc | 14 +-
 gcc/testsuite/gcc.dg/pr117712.c | 13 +
 2 files changed, 26 insertions(+), 1 deletion(-)

diff --git a/gcc/expr.cc b/gcc/expr.cc
index f684e26cef78..9f4382d7986b 100644
--- a/gcc/expr.cc
+++ b/gcc/expr.cc
@@ -8747,7 +8747,19 @@ force_operand (rtx value, rtx target)
 {
   if (!target)
target = gen_reg_rtx (GET_MODE (value));
-  op1 = force_operand (XEXP (value, 0), NULL_RTX);
+  /* FIX or UNSIGNED_FIX with integral mode has unspecified rounding,
+while FIX with floating point mode rounds toward zero.  So, some
+targets use expressions like (fix:SI (fix:DF (reg:DF ...)))
+to express rounding toward zero during the conversion to int.
+expand_fix isn't able to handle that, it can only handle
+FIX/UNSIGNED_FIX from floating point mode to integral one.  */
+  if ((code == FIX || code == UNSIGNED_FIX)
+ && GET_CODE (XEXP (value, 0)) == FIX
+ && (GET_MODE (XEXP (value, 0))
+ == GET_MODE (XEXP (XEXP (value, 0), 0
+   op1 = force_operand (XEXP (XEXP (value, 0), 0), NULL_RTX);
+  else
+   op1 = force_operand (XEXP (value, 0), NULL_RTX);
   switch (code)
{
case ZERO_EXTEND:
diff --git a/gcc/testsuite/gcc.dg/pr117712.c b/gcc/testsuite/gcc.dg/pr117712.c
new file mode 100644
index ..7377a610c06c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr117712.c
@@ -0,0 +1,13 @@
+/* PR rtl-optimization/117712 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -ffast-math" } */
+
+int b;
+
+int
+foo (int x)
+{
+  if (b)
+x = 0.96 * x;
+  return x;
+}


[gcc r15-7751] tree-optimization/87984 - hard register assignments not preserved

2025-02-28 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:535115caaf97f5201fb528f67f15b4c52be5619d

commit r15-7751-g535115caaf97f5201fb528f67f15b4c52be5619d
Author: Richard Biener 
Date:   Fri Feb 28 10:36:11 2025 +0100

tree-optimization/87984 - hard register assignments not preserved

The following disables redundant store elimination to hard register
variables which isn't valid.

PR tree-optimization/87984
* tree-ssa-dom.cc (dom_opt_dom_walker::optimize_stmt): Do
not perform redundant store elimination to hard register
variables.
* tree-ssa-sccvn.cc (eliminate_dom_walker::eliminate_stmt):
Likewise.

* gcc.target/i386/pr87984.c: New testcase.

Diff:
---
 gcc/testsuite/gcc.target/i386/pr87984.c | 23 +++
 gcc/tree-ssa-dom.cc |  4 +++-
 gcc/tree-ssa-sccvn.cc   |  2 ++
 3 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/gcc/testsuite/gcc.target/i386/pr87984.c 
b/gcc/testsuite/gcc.target/i386/pr87984.c
new file mode 100644
index ..39a6a7480f9e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr87984.c
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+/* { dg-options "-O" } */
+
+__attribute__((noipa))
+int f(void)
+{
+  int o = 0;
+  for (int i = 0; i < 3; i++)
+{
+  register int a asm("eax");
+  a = 1;
+  asm("add %1, %0" : "+r"(o) : "r"(a));
+  asm("xor %%eax, %%eax" ::: "eax");
+}
+  return o;
+}
+
+int main()
+{
+  if (f() != 3)
+__builtin_abort();
+  return 0;
+}
diff --git a/gcc/tree-ssa-dom.cc b/gcc/tree-ssa-dom.cc
index 291c3a4fa6b5..b1ac35e12fd9 100644
--- a/gcc/tree-ssa-dom.cc
+++ b/gcc/tree-ssa-dom.cc
@@ -2454,7 +2454,9 @@ dom_opt_dom_walker::optimize_stmt (basic_block bb, 
gimple_stmt_iterator *si,
 
   /* Perform simple redundant store elimination.  */
   if (gimple_assign_single_p (stmt)
- && TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
+ && TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME
+ && (TREE_CODE (gimple_assign_lhs (stmt)) != VAR_DECL
+ || !DECL_HARD_REGISTER (gimple_assign_lhs (stmt
{
  tree lhs = gimple_assign_lhs (stmt);
  tree rhs = gimple_assign_rhs1 (stmt);
diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index 146840664e2e..5a8c7c3aa10b 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -7081,6 +7081,8 @@ eliminate_dom_walker::eliminate_stmt (basic_block b, 
gimple_stmt_iterator *gsi)
   if (gimple_assign_single_p (stmt)
   && !gimple_has_volatile_ops (stmt)
   && !is_gimple_reg (gimple_assign_lhs (stmt))
+  && (TREE_CODE (gimple_assign_lhs (stmt)) != VAR_DECL
+ || !DECL_HARD_REGISTER (gimple_assign_lhs (stmt)))
   && (TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
  || is_gimple_min_invariant (gimple_assign_rhs1 (stmt
 {


[gcc r15-7750] middle-end/66279 - gimplification clobbers shared asm constraints

2025-02-28 Thread Richard Biener via Gcc-cvs
https://gcc.gnu.org/g:95f5d6cc17e7d6b689674756c62b6b5e1284afd0

commit r15-7750-g95f5d6cc17e7d6b689674756c62b6b5e1284afd0
Author: Richard Biener 
Date:   Fri Feb 28 09:58:36 2025 +0100

middle-end/66279 - gimplification clobbers shared asm constraints

When the C++ frontend clones a CTOR we do not copy ASM_EXPR constraints
fully as walk_tree does not recurse to TREE_PURPOSE of TREE_LIST nodes.
At this point doing that seems too dangerous so the following instead
avoids gimplification of ASM_EXPRs to clobber the shared constraints
and unshares it there, like it also unshares TREE_VALUE when it
re-writes a "+" output constraint to separate "=" output and matching
input constraint.

PR middle-end/66279
* gimplify.cc (gimplify_asm_expr): Copy TREE_PURPOSE before
rewriting it for "+" processing.

* g++.dg/pr66279.C: New testcase.

Diff:
---
 gcc/gimplify.cc|  1 +
 gcc/testsuite/g++.dg/pr66279.C | 23 +++
 2 files changed, 24 insertions(+)

diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 756cdea173fc..160e7fc9df66 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -7810,6 +7810,7 @@ gimplify_asm_expr (tree *expr_p, gimple_seq *pre_p, 
gimple_seq *post_p)
  /* Turn the in/out constraint into an output constraint.  */
  char *p = xstrdup (constraint);
  p[0] = '=';
+ TREE_PURPOSE (link) = unshare_expr (TREE_PURPOSE (link));
  TREE_VALUE (TREE_PURPOSE (link)) = build_string (constraint_len, p);
 
  /* And add a matching input constraint.  */
diff --git a/gcc/testsuite/g++.dg/pr66279.C b/gcc/testsuite/g++.dg/pr66279.C
new file mode 100644
index ..c878044a83b3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr66279.C
@@ -0,0 +1,23 @@
+// { dg-do run }
+
+struct A {};
+
+struct B : public virtual A
+{
+  B();
+};
+
+B::B()
+{
+  unsigned int x = 42;
+
+  __asm__ __volatile__ ("" : "+r"(x));
+
+  if (x != 42)
+__builtin_abort ();
+}
+
+int main()
+{
+  B b;
+}


[gcc r15-7757] libstdc++: Fix constraint recursion in basic_const_iterator relops [PR112490]

2025-02-28 Thread Patrick Palka via Libstdc++-cvs
https://gcc.gnu.org/g:4342c50ca84ae5448c0128c52120f4fe9005f203

commit r15-7757-g4342c50ca84ae5448c0128c52120f4fe9005f203
Author: Patrick Palka 
Date:   Fri Feb 28 09:39:57 2025 -0500

libstdc++: Fix constraint recursion in basic_const_iterator relops 
[PR112490]

Here for

  using RCI = reverse_iterator::iterator>>
  static_assert(std::totally_ordered);

we effectively need to check the requirement

  requires (RCI x) { x RELOP x; }  for each RELOP in {<, >, <=, >=}

which we expect to be straightforwardly satisfied by reverse_iterator's
namespace-scope relops.  But due to ADL we find ourselves also
considering the basic_const_iterator relop friends, which before CWG
2369 would be quickly discarded since RCI clearly isn't convertible to
basic_const_iterator.  After CWG 2369 though we must first check these
relops' constraints (with _It = vector::iterator and _It2 = RCI),
which entails checking totally_ordered recursively.

This patch fixes this by turning the problematic non-dependent function
parameters of type basic_const_iterator<_It> into dependent ones of
type basic_const_iterator<_It3> where _It3 is constrained to match _It.
Thus the basic_const_iterator relop friends now get quickly discarded
during deduction and before the constraint check if the second operand
isn't a specialization of basic_const_iterator (or derived from one)
like before CWG 2369.

PR libstdc++/112490

libstdc++-v3/ChangeLog:

* include/bits/stl_iterator.h (basic_const_iterator::operator<):
Replace non-dependent basic_const_iterator function parameter with
a dependent one of type basic_const_iterator<_It3> where _It3
matches _It.
(basic_const_iterator::operator>): Likewise.
(basic_const_iterator::operator<=): Likewise.
(basic_const_iterator::operator>=): Likewise.
* testsuite/24_iterators/const_iterator/112490.cc: New test.

Reviewed-by: Jonathan Wakely 

Diff:
---
 libstdc++-v3/include/bits/stl_iterator.h | 16 
 .../testsuite/24_iterators/const_iterator/112490.cc  | 12 
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/libstdc++-v3/include/bits/stl_iterator.h 
b/libstdc++-v3/include/bits/stl_iterator.h
index 3e025342fb52..33732b1a4287 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -2881,30 +2881,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
&& three_way_comparable_with<_It, _It2>
   { return _M_current <=> __y; }
 
-template<__detail::__not_a_const_iterator _It2>
+template<__detail::__not_a_const_iterator _It2, same_as<_It> _It3>
   friend constexpr bool
-  operator<(const _It2& __x, const basic_const_iterator& __y)
+  operator<(const _It2& __x, const basic_const_iterator<_It3>& __y)
   noexcept(noexcept(__x < __y._M_current))
   requires random_access_iterator<_It> && totally_ordered_with<_It, _It2>
   { return __x < __y._M_current; }
 
-template<__detail::__not_a_const_iterator _It2>
+template<__detail::__not_a_const_iterator _It2, same_as<_It> _It3>
   friend constexpr bool
-  operator>(const _It2& __x, const basic_const_iterator& __y)
+  operator>(const _It2& __x, const basic_const_iterator<_It3>& __y)
   noexcept(noexcept(__x > __y._M_current))
   requires random_access_iterator<_It> && totally_ordered_with<_It, _It2>
   { return __x > __y._M_current; }
 
-template<__detail::__not_a_const_iterator _It2>
+template<__detail::__not_a_const_iterator _It2, same_as<_It> _It3>
   friend constexpr bool
-  operator<=(const _It2& __x, const basic_const_iterator& __y)
+  operator<=(const _It2& __x, const basic_const_iterator<_It3>& __y)
   noexcept(noexcept(__x <= __y._M_current))
   requires random_access_iterator<_It> && totally_ordered_with<_It, _It2>
   { return __x <= __y._M_current; }
 
-template<__detail::__not_a_const_iterator _It2>
+template<__detail::__not_a_const_iterator _It2, same_as<_It> _It3>
   friend constexpr bool
-  operator>=(const _It2& __x, const basic_const_iterator& __y)
+  operator>=(const _It2& __x, const basic_const_iterator<_It3>& __y)
   noexcept(noexcept(__x >= __y._M_current))
   requires random_access_iterator<_It> && totally_ordered_with<_It, _It2>
   { return __x >= __y._M_current; }
diff --git a/libstdc++-v3/testsuite/24_iterators/const_iterator/112490.cc 
b/libstdc++-v3/testsuite/24_iterators/const_iterator/112490.cc
new file mode 100644
index ..9bb154847cff
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/const_iterator/112490.cc
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++23 } }
+
+// PR libstdc++/112490 - infinite meta error in
+// reverse_iterator::iterator>>
+
+#include 
+#include 
+
+usin

[gcc r15-7767] testsuite: Fix up toplevel-asm-1.c for LoongArch

2025-02-28 Thread Xi Ruoyao via Gcc-cvs
https://gcc.gnu.org/g:20d95bfa29057104b352e5d82699edede8658499

commit r15-7767-g20d95bfa29057104b352e5d82699edede8658499
Author: Xi Ruoyao 
Date:   Mon Feb 3 11:15:22 2025 +0800

testsuite: Fix up toplevel-asm-1.c for LoongArch

Like RISC-V, on LoongArch we don't really support %cN for SYMBOL_REFs
even with -fno-pic.

gcc/testsuite/ChangeLog:

* c-c++-common/toplevel-asm-1.c: Use %cc3 %cc4 instead of %c3
%c4 on LoongArch.

Diff:
---
 gcc/testsuite/c-c++-common/toplevel-asm-1.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gcc/testsuite/c-c++-common/toplevel-asm-1.c 
b/gcc/testsuite/c-c++-common/toplevel-asm-1.c
index d6766b00e724..e1687d28e0b9 100644
--- a/gcc/testsuite/c-c++-common/toplevel-asm-1.c
+++ b/gcc/testsuite/c-c++-common/toplevel-asm-1.c
@@ -9,7 +9,7 @@ int v[42];
 void foo (void) {}
 
 /* Not all targets can use %cN even in non-pic code.  */
-#if defined(__riscv)
+#if defined(__riscv) || defined(__loongarch__)
 asm ("# %0 %1 %2 %cc3 %cc4 %5 %% %="
 #else
 asm ("# %0 %1 %2 %c3 %c4 %5 %% %="


[gcc r15-7768] [PATCH] H8/300: PR target/109189 Silence -Wformat warnings on Windows

2025-02-28 Thread Jeff Law via Gcc-cvs
https://gcc.gnu.org/g:2fc17730dcef182bba3c9d4e32fc00302ef421fe

commit r15-7768-g2fc17730dcef182bba3c9d4e32fc00302ef421fe
Author: Jan Dubiec 
Date:   Fri Feb 28 22:01:42 2025 -0700

[PATCH] H8/300: PR target/109189 Silence -Wformat warnings on Windows

This patch fixes annoying -Wformat warnings when gcc is built
on Windows/MinGW64. Instead of %ld it uses HOST_WIDE_INT_PRINT_DEC
macro, just like many other targets do.

PR target/109189
gcc/ChangeLog:

* config/h8300/h8300.cc (h8300_print_operand): Replace %ld format
strings with HOST_WIDE_INT_PRINT_DEC macro in order to silence
-Wformat warnings when building on Windows/MinGW64.

Diff:
---
 gcc/config/h8300/h8300.cc | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/gcc/config/h8300/h8300.cc b/gcc/config/h8300/h8300.cc
index 00135e8d02dc..02056d0ff19f 100644
--- a/gcc/config/h8300/h8300.cc
+++ b/gcc/config/h8300/h8300.cc
@@ -1444,7 +1444,7 @@ h8300_print_operand (FILE *file, rtx x, int code)
  fprintf (file, "%sl", names_big[REGNO (x)]);
  break;
case CONST_INT:
- fprintf (file, "#%ld", (-INTVAL (x)) & 0xff);
+ fprintf (file, "#" HOST_WIDE_INT_PRINT_DEC, (-INTVAL (x)) & 0xff);
  break;
default:
  gcc_unreachable ();
@@ -1457,7 +1457,7 @@ h8300_print_operand (FILE *file, rtx x, int code)
  fprintf (file, "%sh", names_big[REGNO (x)]);
  break;
case CONST_INT:
- fprintf (file, "#%ld", ((-INTVAL (x)) & 0xff00) >> 8);
+ fprintf (file, "#" HOST_WIDE_INT_PRINT_DEC, ((-INTVAL (x)) & 0xff00) 
>> 8);
  break;
default:
  gcc_unreachable ();
@@ -1465,7 +1465,7 @@ h8300_print_operand (FILE *file, rtx x, int code)
   break;
 case 'G':
   gcc_assert (GET_CODE (x) == CONST_INT);
-  fprintf (file, "#%ld", 0xff & (-INTVAL (x)));
+  fprintf (file, "#" HOST_WIDE_INT_PRINT_DEC, 0xff & (-INTVAL (x)));
   break;
 case 'S':
   if (GET_CODE (x) == REG)
@@ -1542,7 +1542,7 @@ h8300_print_operand (FILE *file, rtx x, int code)
  h8300_print_operand (file, x, 0);
  break;
case CONST_INT:
- fprintf (file, "#%ld", ((INTVAL (x) >> 16) & 0x));
+ fprintf (file, "#" HOST_WIDE_INT_PRINT_DEC, ((INTVAL (x) >> 16) & 
0x));
  break;
case CONST_DOUBLE:
  {
@@ -1567,7 +1567,7 @@ h8300_print_operand (FILE *file, rtx x, int code)
  h8300_print_operand (file, x, 0);
  break;
case CONST_INT:
- fprintf (file, "#%ld", INTVAL (x) & 0x);
+ fprintf (file, "#" HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0x);
  break;
case CONST_DOUBLE:
  {
@@ -1621,7 +1621,7 @@ h8300_print_operand (FILE *file, rtx x, int code)
   break;
 case 's':
   if (GET_CODE (x) == CONST_INT)
-   fprintf (file, "#%ld", (INTVAL (x)) & 0xff);
+   fprintf (file, "#" HOST_WIDE_INT_PRINT_DEC, (INTVAL (x)) & 0xff);
   else if (GET_CODE (x) == REG)
fprintf (file, "%s", byte_reg (x, 0));
   else
@@ -1629,7 +1629,7 @@ h8300_print_operand (FILE *file, rtx x, int code)
   break;
 case 't':
   if (GET_CODE (x) == CONST_INT)
-   fprintf (file, "#%ld", (INTVAL (x) >> 8) & 0xff);
+   fprintf (file, "#" HOST_WIDE_INT_PRINT_DEC, (INTVAL (x) >> 8) & 0xff);
   else if (GET_CODE (x) == REG)
fprintf (file, "%s", byte_reg (x, 1));
   else
@@ -1637,7 +1637,7 @@ h8300_print_operand (FILE *file, rtx x, int code)
   break;
 case 'w':
   if (GET_CODE (x) == CONST_INT)
-   fprintf (file, "#%ld", INTVAL (x) & 0xff);
+   fprintf (file, "#" HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xff);
   else if (GET_CODE (x) == REG)
fprintf (file, "%s", byte_reg (x, 0));
   else
@@ -1645,7 +1645,7 @@ h8300_print_operand (FILE *file, rtx x, int code)
   break;
 case 'x':
   if (GET_CODE (x) == CONST_INT)
-   fprintf (file, "#%ld", (INTVAL (x) >> 8) & 0xff);
+   fprintf (file, "#" HOST_WIDE_INT_PRINT_DEC, (INTVAL (x) >> 8) & 0xff);
   else if (GET_CODE (x) == REG)
fprintf (file, "%s", byte_reg (x, 1));
   else
@@ -1653,7 +1653,7 @@ h8300_print_operand (FILE *file, rtx x, int code)
   break;
 case 'y':
   if (GET_CODE (x) == CONST_INT)
-   fprintf (file, "#%ld", (INTVAL (x) >> 16) & 0xff);
+   fprintf (file, "#" HOST_WIDE_INT_PRINT_DEC, (INTVAL (x) >> 16) & 0xff);
   else if (GET_CODE (x) == REG)
fprintf (file, "%s", byte_reg (x, 0));
   else
@@ -1661,7 +1661,7 @@ h8300_print_operand (FILE *file, rtx x, int code)
   break;
 case 'z':
   if (GET_CODE (x) == CONST_INT)
-   fprintf (file, "#%ld", (INTVAL (x) >> 24) & 0xff);
+   fprintf (file, "#" HOST_WIDE_INT_PRINT_DEC, (INTVAL (x) >> 24) & 0xff);
   else if (GET_CODE (x) == REG)
fprintf (file, "%s", byte_reg (x, 1));