[gcc r15-7764] libstdc++: Add static_assertions to ranges::to adaptor factory [PR112803]
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]
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
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
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
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
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]
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]
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]
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]
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
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]
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]
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
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]
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
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)
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]
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]
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]
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
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]
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]
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
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
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]
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]
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]
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
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]
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
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
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]
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
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
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));