Re: [COMMITED] [lto] ipcp don't propagate where not needed
On 06/11/24 13:39 +0100, Michal Jires wrote: Commited with suggested changes. - This patch disables propagation of ipcp information into partitions where all instances of the node are marked to be inlined. Motivation: Incremental LTO needs stable values between compilations to be effective. This requirement fails with following example: void heavily_used_function(int); ... heavily_used_function(__LINE__); Ipcp creates long list of all __LINE__ arguments, and then propagates it with every function clone, even though for inlined functions this information is not useful. gcc/ChangeLog: * ipa-prop.cc (write_ipcp_transformation_info): Disable uneeded value propagation. * lto-cgraph.cc (lto_symtab_encoder_encode): Default values. (lto_symtab_encoder_always_inlined_p): New. (lto_set_symtab_encoder_not_always_inlined): New. (add_node_to): Set always inlined. * lto-streamer.h (struct lto_encoder_entry): New field. (lto_symtab_encoder_always_inlined_p): New. --- gcc/ipa-prop.cc| 12 +--- gcc/lto-cgraph.cc | 47 +- gcc/lto-streamer.h | 11 +++ 3 files changed, 50 insertions(+), 20 deletions(-) diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc index 032358fde22..c5633796721 100644 --- a/gcc/ipa-prop.cc +++ b/gcc/ipa-prop.cc @@ -5404,9 +5404,15 @@ write_ipcp_transformation_info (output_block *ob, cgraph_node *node, streamer_write_bitpack (&bp); } - streamer_write_uhwi (ob, vec_safe_length (ts->m_vr)); - for (const ipa_vr &parm_vr : ts->m_vr) -parm_vr.streamer_write (ob); + /* If all instances of this node are inlined, ipcp info is not useful. */ + if (!lto_symtab_encoder_only_for_inlining_p (encoder, node)) +{ + streamer_write_uhwi (ob, vec_safe_length (ts->m_vr)); + for (const ipa_vr &parm_vr : ts->m_vr) + parm_vr.streamer_write (ob); +} + else +streamer_write_uhwi (ob, 0); } /* Stream in the aggregate value replacement chain for NODE from IB. */ diff --git a/gcc/lto-cgraph.cc b/gcc/lto-cgraph.cc index 53cc965bdfd..c66f32852a7 100644 --- a/gcc/lto-cgraph.cc +++ b/gcc/lto-cgraph.cc @@ -114,7 +114,7 @@ lto_symtab_encoder_encode (lto_symtab_encoder_t encoder, if (!encoder->map) { - lto_encoder_entry entry = {node, false, false, false}; + lto_encoder_entry entry (node); ref = encoder->nodes.length (); encoder->nodes.safe_push (entry); @@ -124,7 +124,7 @@ lto_symtab_encoder_encode (lto_symtab_encoder_t encoder, size_t *slot = encoder->map->get (node); if (!slot || !*slot) { - lto_encoder_entry entry = {node, false, false, false}; + lto_encoder_entry entry (node); ref = encoder->nodes.length (); if (!slot) encoder->map->put (node, ref + 1); @@ -168,6 +168,15 @@ lto_symtab_encoder_delete_node (lto_symtab_encoder_t encoder, return true; } +/* Return TRUE if the NODE and its clones are always inlined. */ + +bool +lto_symtab_encoder_only_for_inlining_p (lto_symtab_encoder_t encoder, + struct cgraph_node *node) +{ + int index = lto_symtab_encoder_lookup (encoder, node); + return encoder->nodes[index].only_for_inlining; +} /* Return TRUE if we should encode the body of NODE (if any). */ @@ -179,17 +188,6 @@ lto_symtab_encoder_encode_body_p (lto_symtab_encoder_t encoder, return encoder->nodes[index].body; } -/* Specify that we encode the body of NODE in this partition. */ - -static void -lto_set_symtab_encoder_encode_body (lto_symtab_encoder_t encoder, - struct cgraph_node *node) -{ - int index = lto_symtab_encoder_encode (encoder, node); - gcc_checking_assert (encoder->nodes[index].node == node); - encoder->nodes[index].body = true; -} - /* Return TRUE if we should encode initializer of NODE (if any). */ bool @@ -799,13 +797,28 @@ output_refs (lto_symtab_encoder_t encoder) static void add_node_to (lto_symtab_encoder_t encoder, struct cgraph_node *node, -bool include_body) +bool include_body, bool not_inlined) { if (node->clone_of) -add_node_to (encoder, node->clone_of, include_body); +add_node_to (encoder, node->clone_of, include_body, not_inlined); + + int index = lto_symtab_encoder_encode (encoder, node); + gcc_checking_assert (encoder->nodes[index].node == node); + if (include_body) -lto_set_symtab_encoder_encode_body (encoder, node); - lto_symtab_encoder_encode (encoder, node); +encoder->nodes[index].body = true; + if (not_inlined) +encoder->nodes[index].only_for_inlining = false; +} + +/* Add NODE into encoder as well as nodes it is cloned from. + Do it in a way so clones appear first. */ + +static void +add_node_to (lto_symtab_encoder_t encoder, struct cgraph_node *node, +bool include_body) +{ + add_node_to (encoder, node, include_body, include_body
[PATCH] libstdc++: Refactor std::hash specializations
This attempts to simplify and clean up our std::hash code. The primary benefit is improved diagnostics for users when they do something wrong involving std::hash or unordered containers. An additional benefit is that for the unstable ABI (--enable-symvers=gnu-versioned-namespace) we can reduce the memory footprint of several std::hash specializations. In the current design, __hash_enum is a base class of the std::hash primary template, but the partial specialization of __hash_enum for non-enum types is disabled. This means that if a user forgets to specialize std::hash for their class type (or forgets to use a custom hash function for unordered containers) they get error messages about std::__hash_enum not being constructible. This is confusing when there is no enum type involved: why should users care about __hash_enum not being constructible if they're not trying to hash enums? This change makes the std::hash primary template only derive from __hash_enum when the template argument type is an enum. Otherwise, it derives directly from a new class template, __hash_not_enabled. This new class template defines the deleted members that cause a given std::hash specialization to be a disabled specialization (as per P0513R0). Now when users try to use a disabled specialization, they get more descriptive errors that mention __hash_not_enabled instead of __hash_enum. Additionally, adjust __hash_base to remove the deprecated result_type and argument_type typedefs for C++20 and later. In the current code we use a __poison_hash base class in the std::hash specializations for std::unique_ptr, std::optional, and std::variant. The primary template of __poison_hash has deleted special members, which is used to conditionally disable the derived std::hash specialization. This can also result in confusing diagnostics, because seeing "poison" in an enabled specialization is misleading. Only some uses of __poison_hash actually "poison" anything, i.e. cause a specialization to be disabled. In other cases it's just an empty base class that does nothing. This change removes __poison_hash and changes the std::hash specializations that were using it to conditionally derive from __hash_not_enabled instead. When the std::hash specialization is enabled, there is no more __poison_hash base class. However, to preserve the ABI properties of those std::hash specializations, we need to replace __poison_hash with some other empty base class. This is needed because in the current code std::hash> has two __poison_hash base classes, which must have unique addresses, so sizeof(std::hash>) == 2. To preserve this unfortunate property, a new __hash_empty_base class is used as a base class to re-introduce du0plicate base classes that increase the class size. For the unstable ABI we don't use __hash_empty_base so the std::hash> specializations are always size 1, and the class hierarchy is much simpler so will compile faster. Additionally, remove the result_type and argument_type typedefs from all disabled specializations of std::hash for std::unique_ptr, std::optional, and std::variant. Those typedefs are useless for disabled specializations, and although the standard doesn't say they must *not* be present for disabled specializations, it certainly only requires them for enabled specializations. Finally, for C++20 the typedefs are also removed from enabled specializations of std::hash for std::unique_ptr, std::optional, and std::variant. libstdc++-v3/ChangeLog: * doc/xml/manual/evolution.xml: Document removal of nested types from std::hash specializations. * doc/html/manual/api.html: Regenerate. * include/bits/functional_hash.h (__hash_base): Remove deprecated nested types for C++20. (__hash_empty_base): Define new class template. (__is_hash_enabled_for): Define new variable template. (__poison_hash): Remove. (__hash_not_enabled): Define new class template. (__hash_enum): Remove partial specialization for non-enums. (hash): Derive from __hash_not_enabled for non-enums, instead of __hash_enum. * include/bits/unique_ptr.h (__uniq_ptr_hash): Derive from __hash_base. Conditionally derive from __hash_empty_base. (__uniq_ptr_hash<>): Remove disabled specialization. (hash): Do not derive from __hash_base unconditionally. Conditionally derive from either __uniq_ptr_hash or __hash_not_enabled. * include/std/optional (__optional_hash_call_base): Remove. (__optional_hash): Define new class template. (hash): Derive from either (hash): Conditionally derive from either __optional_hash or __hash_not_enabled. Remove nested typedefs. * include/std/variant (_Base_dedup): Replace __poison_hash with __hash_empty_base. (__variant_hash_call_base_impl): Remove. (__variant_hash): Define new class template. (hash): Conditionally derive from eit
Re: [PATCH 2/2] libstdc++: More user-friendly failed assertions from shared_ptr dereference
Pushed On Thu, 31 Oct 2024 at 20:08, Jonathan Wakely wrote: > > Currently dereferencing an empty shared_ptr prints a complicated > internal type in the assertion message: > > include/bits/shared_ptr_base.h:1377: std::__shared_ptr_access<_Tp, _Lp, > , >::element_type& std::__shared_ptr_access<_Tp, _Lp, > , >::operator*() const [with _Tp = > std::filesystem::__cxx11::recursive_directory_iterator::_Dir_stack; > __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool = false; > bool = false; element_type = > std::filesystem::__cxx11::recursive_directory_iterator::_Dir_stack]: > Assertion '_M_get() != nullptr' failed. > > Users don't care about any of the _Lp and template > parameters, so this is unnecessarily verbose. > > We can simplify it to something that only mentions "shared_ptr_deref" > and the element type: > > include/bits/shared_ptr_base.h:1371: _Tp* std::__shared_ptr_deref(_Tp*) [with > _Tp = filesystem::__cxx11::recursive_directory_iterator::_Dir_stack]: > Assertion '__p != nullptr' failed. > > libstdc++-v3/ChangeLog: > > * include/bits/shared_ptr_base.h (__shared_ptr_deref): New > function template. > (__shared_ptr_access, __shared_ptr_access<>): Use it. > --- > Tested x86_64-linux. > > Also available for review at: > https://forge.sourceware.org/gcc/gcc-TEST/pulls/13 > > libstdc++-v3/include/bits/shared_ptr_base.h | 28 + > 1 file changed, 17 insertions(+), 11 deletions(-) > > diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h > b/libstdc++-v3/include/bits/shared_ptr_base.h > index 9a7617e7014..ee01594ce0c 100644 > --- a/libstdc++-v3/include/bits/shared_ptr_base.h > +++ b/libstdc++-v3/include/bits/shared_ptr_base.h > @@ -1337,6 +1337,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > { }; > > > + template > +[[__gnu__::__always_inline__]] > +inline _Tp* > +__shared_ptr_deref(_Tp* __p) > +{ > + __glibcxx_assert(__p != nullptr); > + return __p; > +} > + >// Define operator* and operator-> for shared_ptr. >templatebool = is_array<_Tp>::value, bool = is_void<_Tp>::value> > @@ -1347,10 +1356,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > >element_type& >operator*() const noexcept > - { > - __glibcxx_assert(_M_get() != nullptr); > - return *_M_get(); > - } > + { return *std::__shared_ptr_deref(_M_get()); } > >element_type* >operator->() const noexcept > @@ -1392,10 +1398,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >[[__deprecated__("shared_ptr::operator* is absent from C++17")]] >element_type& >operator*() const noexcept > - { > - __glibcxx_assert(_M_get() != nullptr); > - return *_M_get(); > - } > + { return *std::__shared_ptr_deref(_M_get()); } > >[[__deprecated__("shared_ptr::operator-> is absent from C++17")]] >element_type* > @@ -1406,13 +1409,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >} > #endif > > +#pragma GCC diagnostic push > +#pragma GCC diagnostic ignored "-Wc++17-extensions" >element_type& >operator[](ptrdiff_t __i) const noexcept >{ > - __glibcxx_assert(_M_get() != nullptr); > - __glibcxx_assert(!extent<_Tp>::value || __i < extent<_Tp>::value); > - return _M_get()[__i]; > + if constexpr (extent<_Tp>::value) > + __glibcxx_assert(__i < extent<_Tp>::value); > + return std::__shared_ptr_deref(_M_get())[__i]; >} > +#pragma GCC diagnostic pop > > private: >element_type* > -- > 2.47.0 >
Re: [PATCH 1/2] libstdc++: Enable debug assertions for filesystem directory iterators
Pushed On Thu, 31 Oct 2024 at 20:06, Jonathan Wakely wrote: > > Several member functions of filesystem::directory_iterator and > filesystem::recursive_directory_iterator currently dereference their > shared_ptr data member without checking for non-null. Because they use > operator-> and that function only uses _GLIBCXX_DEBUG_PEDASSERT rather > than __glibcxx_assert there is no assertion even when the library is > built with _GLIBCXX_ASSERTIONS defined. This means that dereferencing > invalid directory iterators gives an unhelpful segfault. > > By using (*p). instead of p-> we get an assertion when the library is > built with _GLIBCXX_ASSERTIONS, with a "_M_get() != nullptr" message. > > libstdc++-v3/ChangeLog: > > * src/c++17/fs_dir.cc (fs::directory_iterator::operator*): Use > shared_ptr::operator* instead of shared_ptr::operator->. > (fs::recursive_directory_iterator::options): Likewise. > (fs::recursive_directory_iterator::depth): Likewise. > (fs::recursive_directory_iterator::recursion_pending): Likewise. > (fs::recursive_directory_iterator::operator*): Likewise. > (fs::recursive_directory_iterator::disable_recursion_pending): > Likewise. > --- > Tested x86_64-linux. > > Also available for review at: > https://forge.sourceware.org/gcc/gcc-TEST/pulls/13 > > > libstdc++-v3/src/c++17/fs_dir.cc | 12 ++-- > 1 file changed, 6 insertions(+), 6 deletions(-) > > diff --git a/libstdc++-v3/src/c++17/fs_dir.cc > b/libstdc++-v3/src/c++17/fs_dir.cc > index 28d27f6a9fa..8fe9e5e4cc8 100644 > --- a/libstdc++-v3/src/c++17/fs_dir.cc > +++ b/libstdc++-v3/src/c++17/fs_dir.cc > @@ -230,7 +230,7 @@ directory_iterator(const path& p, directory_options > options, error_code* ecptr) > const fs::directory_entry& > fs::directory_iterator::operator*() const noexcept > { > - return _M_dir->entry; > + return (*_M_dir).entry; > } > > fs::directory_iterator& > @@ -327,25 +327,25 @@ > fs::recursive_directory_iterator::~recursive_directory_iterator() = default; > fs::directory_options > fs::recursive_directory_iterator::options() const noexcept > { > - return _M_dirs->options; > + return (*_M_dirs).options; > } > > int > fs::recursive_directory_iterator::depth() const noexcept > { > - return int(_M_dirs->size()) - 1; > + return int((*_M_dirs).size()) - 1; > } > > bool > fs::recursive_directory_iterator::recursion_pending() const noexcept > { > - return _M_dirs->pending; > + return (*_M_dirs).pending; > } > > const fs::directory_entry& > fs::recursive_directory_iterator::operator*() const noexcept > { > - return _M_dirs->top().entry; > + return (*_M_dirs).top().entry; > } > > fs::recursive_directory_iterator& > @@ -453,7 +453,7 @@ fs::recursive_directory_iterator::pop() > void > fs::recursive_directory_iterator::disable_recursion_pending() noexcept > { > - _M_dirs->pending = false; > + (*_M_dirs).pending = false; > } > > // Used to implement filesystem::remove_all. > -- > 2.47.0 >
[committed v2] libstdc++: Deprecate useless compatibility headers for C++17
These headers make no sense for C++ programs, because they either define different content to the corresponding C header, or define nothing at all in namespace std. They were all deprecated in C++17, so add deprecation warnings to them, which can be disabled with -Wno-deprecated. For C++20 and later these headers are no longer in the standard at all, so compiling with _GLIBCXX_USE_DEPRECATED defined to 0 will give an error when they are included. Because #warning is non-standard before C++23 we need to use pragmas to ignore -Wc++23-extensions for the -Wsystem-headers -pedantic case. One g++ test needs adjustment because it includes , but that can be made conditional on the __cplusplus value without any reduction in test coverage. For the library tests, consolidate the std_c++0x_neg.cc XFAIL tests into the macros.cc test, using dg-error with a { target c++98_only } selector. This avoids having two separate test files, one for C++98 and one for everything later. Also add tests for the headers to ensure that they behave as expected and don't give deprecated warnings. libstdc++-v3/ChangeLog: * doc/xml/manual/evolution.xml: Document deprecations. * doc/html/*: Regenerate. * include/c_compatibility/complex.h (_GLIBCXX_COMPLEX_H): Move include guard to start of file. Include directly instead of . * include/c_compatibility/tgmath.h: Include and directly, instead of . * include/c_global/ccomplex: Add deprecated #warning for C++17 and #error for C++20 if _GLIBCXX_USE_DEPRECATED == 0. * include/c_global/ciso646: Likewise. * include/c_global/cstdalign: Likewise. * include/c_global/cstdbool: Likewise. * include/c_global/ctgmath: Likewise. * include/c_std/ciso646: Likewise. * include/precompiled/stdc++.h: Do not include ccomplex, ciso646, cstdalign, cstdbool, or ctgmath in C++17 and later. * testsuite/18_support/headers/cstdalign/macros.cc: Check for warnings and errors for unsupported dialects. * testsuite/18_support/headers/cstdbool/macros.cc: Likewise. * testsuite/26_numerics/headers/ctgmath/complex.cc: Likewise. * testsuite/27_io/objects/char/1.cc: Do not include . * testsuite/27_io/objects/wchar_t/1.cc: Likewise. * testsuite/18_support/headers/cstdbool/std_c++0x_neg.cc: Removed. * testsuite/18_support/headers/cstdalign/std_c++0x_neg.cc: Removed. * testsuite/26_numerics/headers/ccomplex/std_c++0x_neg.cc: Removed. * testsuite/26_numerics/headers/ctgmath/std_c++0x_neg.cc: Removed. * testsuite/18_support/headers/ciso646/macros.cc: New test. * testsuite/18_support/headers/ciso646/macros.h.cc: New test. * testsuite/18_support/headers/cstdbool/macros.h.cc: New test. * testsuite/26_numerics/headers/ccomplex/complex.cc: New test. * testsuite/26_numerics/headers/ccomplex/complex.h.cc: New test. * testsuite/26_numerics/headers/ctgmath/complex.h.cc: New test. gcc/testsuite/ChangeLog: * g++.old-deja/g++.other/headers1.C: Do not include ciso646 for C++17 and later. --- I tweaked the #error and #warning text slightly since the v1 patch. I'll also add something to the gcc-15/porting_to.html web page. Tested x86_64-linux, aarch64-linux, powerpc64le-linux. Pushed to trunk. .../g++.old-deja/g++.other/headers1.C | 2 + libstdc++-v3/doc/html/manual/api.html | 8 +++ libstdc++-v3/doc/xml/manual/evolution.xml | 10 .../include/c_compatibility/complex.h | 4 +- libstdc++-v3/include/c_compatibility/tgmath.h | 11 ++-- libstdc++-v3/include/c_global/ccomplex| 9 libstdc++-v3/include/c_global/ciso646 | 9 libstdc++-v3/include/c_global/cstdalign | 8 +++ libstdc++-v3/include/c_global/cstdbool| 8 +++ libstdc++-v3/include/c_global/ctgmath | 8 +++ libstdc++-v3/include/c_std/ciso646| 10 libstdc++-v3/include/precompiled/stdc++.h | 13 +++-- .../18_support/headers/ciso646/macros.cc | 51 +++ .../18_support/headers/ciso646/macros.h.cc| 49 ++ .../18_support/headers/cstdalign/macros.cc| 10 +++- .../18_support/headers/cstdalign/macros.h.cc | 25 + .../headers/cstdalign/std_c++0x_neg.cc| 24 - .../18_support/headers/cstdbool/macros.cc | 9 +++- .../18_support/headers/cstdbool/macros.h.cc | 21 .../headers/cstdbool/std_c++0x_neg.cc | 26 -- .../26_numerics/headers/ccomplex/complex.cc | 10 .../26_numerics/headers/ccomplex/complex.h.cc | 10 .../headers/ccomplex/std_c++0x_neg.cc | 26 -- .../26_numerics/headers/ctgmath/complex.cc| 9 +++- .../26_numerics/headers/ctgmath/complex.h.cc | 10 .../headers/ctgmath/std_c++0x_neg.cc | 26 -- .../testsuite/27_io/objects/char/1.cc | 1 - .../testsuite/27_io
[committed] libstdc++: Move include guards to start of headers
libstdc++-v3/ChangeLog: * include/c_compatibility/complex.h (_GLIBCXX_COMPLEX_H): Move include guard to start of the header. * include/c_global/ctgmath (_GLIBCXX_CTGMATH): Likewise. --- Tested x86_64-linux. Pushed to trunk. libstdc++-v3/include/c_compatibility/complex.h | 6 +++--- libstdc++-v3/include/c_global/ctgmath | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libstdc++-v3/include/c_compatibility/complex.h b/libstdc++-v3/include/c_compatibility/complex.h index 605d1f30e06..a3102d9fce3 100644 --- a/libstdc++-v3/include/c_compatibility/complex.h +++ b/libstdc++-v3/include/c_compatibility/complex.h @@ -26,6 +26,9 @@ * This is a Standard C++ Library header. */ +#ifndef _GLIBCXX_COMPLEX_H +#define _GLIBCXX_COMPLEX_H 1 + #include #if __cplusplus >= 201103L @@ -42,7 +45,4 @@ # endif #endif -#ifndef _GLIBCXX_COMPLEX_H -#define _GLIBCXX_COMPLEX_H 1 - #endif diff --git a/libstdc++-v3/include/c_global/ctgmath b/libstdc++-v3/include/c_global/ctgmath index 79c1a029f41..39c17668f16 100644 --- a/libstdc++-v3/include/c_global/ctgmath +++ b/libstdc++-v3/include/c_global/ctgmath @@ -26,13 +26,13 @@ * This is a Standard C++ Library header. */ +#ifndef _GLIBCXX_CTGMATH +#define _GLIBCXX_CTGMATH 1 + #ifdef _GLIBCXX_SYSHDR #pragma GCC system_header #endif -#ifndef _GLIBCXX_CTGMATH -#define _GLIBCXX_CTGMATH 1 - #if __cplusplus < 201103L # include #else -- 2.47.0
Re: [Bug libstdc++/115285] [12/13/14/15 Regression] std::unordered_set can have duplicate value
On 05/11/24 17:50 +, Jonathan Wakely wrote: On 28/10/24 21:51 +0100, François Dumont wrote: On 24/10/2024 21:49, Jonathan Wakely wrote: On Thu, 24 Oct 2024 at 19:43, François Dumont wrote: Committed as trivial the attached patch. libstdc++: Fix test broken when using COW std::string libstdc++-v3/ChangeLog: * testsuite/23_containers/unordered_map/96088.cc (test03): Thanks! I think it was affecting the unordered_set test too. Hi This was indeed revealing a problem in my attempt to fix this bug. Here is the complete patch that I will backport if validated. libstdc++: [_Hashtable] Avoid temporaries when inserting existing key Following PR 115285 fix, the hashtable _S_forward_key responsible for finding the best way to transmit the key part of the argument parameter to the hash functor was modified to return a key_type instance for any argument type. Only the overloads for const key_type& and key_type&& were still preventing a key_type instanciation. It revealed that a overload for key_type& was missing. To fix this problem we now deal with all sort of key_type of reference type in the unique _S_forward_key static method and remove the overloads. When decayed type of the input instance is the same as key_type we avoid the instanciation. Note that for the comparison we also decay key_type to properly managed when unordered container is instantiated with a const type. libstdc++-v3/ChangeLog: * include/bits/hashtable_policy.h (_ConvertToValueType<_Select1st, _Value>::operator(std::pair<>&)): New, allow consistent behavior with _ConvertToValueType<_Identity, _Value>. * include/bits/hashtable.h (_S_forward_key<_Kt>(_Kt&&)): Adapt to return _Kt&& when decayed _Kt is key_type, return a new key_type instance otherwise. (_S_forward_key(const key_type&)): Remove. (_S_forward_key(key_type&&)): Remove. * testsuite/23_containers/unordered_set/96088.cc (test03): Adapt expected allocation increment. Tested under linux x64, both std::string abi. Ok to commit ? No, because it's still not a complete fix, just more special cases. I think the attached patch (actually two patches, as there's one to add __is_pair first) fixes PR 115285, including all the other cases I added in comment 14. It also avoids regressing PR 96088. This seems small and safe enough to backport. On trunk I still plan to follow this with the bigger refactoring. Tests are still running ... commit 590091e997248dd475d7329f4613765d7cff8bb6 Author: Jonathan Wakely Date: Fri Nov 1 10:09:55 2024 libstdc++: Define __is_pair variable template for C++11 libstdc++-v3/ChangeLog: * include/bits/stl_pair.h (__is_pair): Define for C++11 and C++14 as well. diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h index e92fcad2d66..527fb9105f0 100644 --- a/libstdc++-v3/include/bits/stl_pair.h +++ b/libstdc++-v3/include/bits/stl_pair.h @@ -1189,12 +1189,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline constexpr size_t tuple_size_v> = 2; +#endif +#if __cplusplus >= 201103L +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++14-extensions" // variable templates +#pragma GCC diagnostic ignored "-Wc++17-extensions" // inline variables template inline constexpr bool __is_pair = false; template inline constexpr bool __is_pair> = true; +#pragma GCC diagnostic pop #endif /// @cond undocumented commit 23328cc25365593d045096ccf913cb273202edb0 Author: Jonathan Wakely Date: Tue Nov 5 17:19:06 2024 libstdc++: Fix conversions to key/value type for insertions into hash tables [PR115285] The conversions to key_type and value_type that are performed when inserting into _Hashtable need to be fixed to do any required conversions explicitly. The current code assumes that conversions from the parameter to the key_type or value_type can be done implicitly, which isn't necessarily true. Remove the _S_forward_key function which doesn't handle all cases and either forward the parameter if it already has type cv key_type, or explicitly construct a temporary of type key_type. Similarly, for the _ConvertToValueType specialization for maps, either forward a std::pair parameter unchanged, or explicitly construct a temporary of type value_type. libstdc++-v3/ChangeLog: PR libstdc++/115285 * include/bits/hashtable.h (_Hashtable::_S_forward_key): Remove. (_Hashtable::_M_insert_unique_aux): * include/bits/hashtable_policy.h (_ConvertToValueType): Add comment. (_ConvertToValueType<_Select1st, _Value>): Replace incomplete overload set with two overloads, one for std::pair
Re: [Bug libstdc++/115285] [12/13/14/15 Regression] std::unordered_set can have duplicate value
On 28/10/24 21:51 +0100, François Dumont wrote: On 24/10/2024 21:49, Jonathan Wakely wrote: On Thu, 24 Oct 2024 at 19:43, François Dumont wrote: Committed as trivial the attached patch. libstdc++: Fix test broken when using COW std::string libstdc++-v3/ChangeLog: * testsuite/23_containers/unordered_map/96088.cc (test03): Thanks! I think it was affecting the unordered_set test too. Hi This was indeed revealing a problem in my attempt to fix this bug. Here is the complete patch that I will backport if validated. libstdc++: [_Hashtable] Avoid temporaries when inserting existing key Following PR 115285 fix, the hashtable _S_forward_key responsible for finding the best way to transmit the key part of the argument parameter to the hash functor was modified to return a key_type instance for any argument type. Only the overloads for const key_type& and key_type&& were still preventing a key_type instanciation. It revealed that a overload for key_type& was missing. To fix this problem we now deal with all sort of key_type of reference type in the unique _S_forward_key static method and remove the overloads. When decayed type of the input instance is the same as key_type we avoid the instanciation. Note that for the comparison we also decay key_type to properly managed when unordered container is instantiated with a const type. libstdc++-v3/ChangeLog: * include/bits/hashtable_policy.h (_ConvertToValueType<_Select1st, _Value>::operator(std::pair<>&)): New, allow consistent behavior with _ConvertToValueType<_Identity, _Value>. * include/bits/hashtable.h (_S_forward_key<_Kt>(_Kt&&)): Adapt to return _Kt&& when decayed _Kt is key_type, return a new key_type instance otherwise. (_S_forward_key(const key_type&)): Remove. (_S_forward_key(key_type&&)): Remove. * testsuite/23_containers/unordered_set/96088.cc (test03): Adapt expected allocation increment. Tested under linux x64, both std::string abi. Ok to commit ? No, because it's still not a complete fix, just more special cases. I think the attached patch (actually two patches, as there's one to add __is_pair first) fixes PR 115285, including all the other cases I added in comment 14. It also avoids regressing PR 96088. This seems small and safe enough to backport. On trunk I still plan to follow this with the bigger refactoring. Tests are still running ... commit 590091e997248dd475d7329f4613765d7cff8bb6 Author: Jonathan Wakely Date: Fri Nov 1 10:09:55 2024 libstdc++: Define __is_pair variable template for C++11 libstdc++-v3/ChangeLog: * include/bits/stl_pair.h (__is_pair): Define for C++11 and C++14 as well. diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h index e92fcad2d66..527fb9105f0 100644 --- a/libstdc++-v3/include/bits/stl_pair.h +++ b/libstdc++-v3/include/bits/stl_pair.h @@ -1189,12 +1189,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline constexpr size_t tuple_size_v> = 2; +#endif +#if __cplusplus >= 201103L +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++14-extensions" // variable templates +#pragma GCC diagnostic ignored "-Wc++17-extensions" // inline variables template inline constexpr bool __is_pair = false; template inline constexpr bool __is_pair> = true; +#pragma GCC diagnostic pop #endif /// @cond undocumented commit 23328cc25365593d045096ccf913cb273202edb0 Author: Jonathan Wakely Date: Tue Nov 5 17:19:06 2024 libstdc++: Fix conversions to key/value type for insertions into hash tables [PR115285] The conversions to key_type and value_type that are performed when inserting into _Hashtable need to be fixed to do any required conversions explicitly. The current code assumes that conversions from the parameter to the key_type or value_type can be done implicitly, which isn't necessarily true. Remove the _S_forward_key function which doesn't handle all cases and either forward the parameter if it already has type cv key_type, or explicitly construct a temporary of type key_type. Similarly, for the _ConvertToValueType specialization for maps, either forward a std::pair parameter unchanged, or explicitly construct a temporary of type value_type. libstdc++-v3/ChangeLog: PR libstdc++/115285 * include/bits/hashtable.h (_Hashtable::_S_forward_key): Remove. (_Hashtable::_M_insert_unique_aux): * include/bits/hashtable_policy.h (_ConvertToValueType): Add comment. (_ConvertToValueType<_Select1st, _Value>): Replace incomplete overload set with two overloads, one for std::pair
Re: [PATCH] libstdc++: Remove workaround for modules issue [PR113814]
On Mon, 4 Nov 2024 at 22:46, Nathaniel Shead wrote: > > Thought I should probably clean this up before closing off the PR. > Regtested on x86_64-pc-linux-gnu with no regressions, OK for trunk? OK, thanks. > > -- >8 -- > > The modules bug requiring this workaround was fixed with commit > r15-4862-g815e48e3d42231. > > PR testsuite/113710 > PR c++/113814 > > libstdc++-v3/ChangeLog: > > * include/bits/stl_pair.h: Remove workaround. > > Signed-off-by: Nathaniel Shead > --- > libstdc++-v3/include/bits/stl_pair.h | 5 - > 1 file changed, 5 deletions(-) > > diff --git a/libstdc++-v3/include/bits/stl_pair.h > b/libstdc++-v3/include/bits/stl_pair.h > index 0d60eaba194..e92fcad2d66 100644 > --- a/libstdc++-v3/include/bits/stl_pair.h > +++ b/libstdc++-v3/include/bits/stl_pair.h > @@ -1183,11 +1183,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > struct tuple_element<1, pair<_Tp1, _Tp2>> > { typedef _Tp2 type; }; > > - // Forward declare the partial specialization for std::tuple > - // to work around modules bug PR c++/113814. > - template > -struct tuple_element<__i, tuple<_Types...>>; > - > #if __cplusplus >= 201703L >template > inline constexpr size_t tuple_size_v> = 2; > -- > 2.47.0 >
Re: [PATCH] Add fancy pointer support in std::map/set
On Mon, 4 Nov 2024 at 18:30, François Dumont wrote: > > > On 21/10/2024 06:56, François Dumont wrote: > > > On 17/10/2024 23:11, Jonathan Wakely wrote: > > > > On Thu, 17 Oct 2024 at 21:39, Jonathan Wakely wrote: >> >> >> >> On Thu, 17 Oct 2024 at 20:52, François Dumont wrote: >>> >>> Here is an updated version that compiles, I think, all your feedbacks. It's >>> much cleaner indeed. >> >> >> Thanks, I'll take a look tomorrow. >> >>> >>> It's also tested in C++98/17/23. >>> >>> I'm surprised that we do not need to consider potential >>> allocator::const_pointer. >> >> Do you mean consider the case where Alloc::const_pointer is not the same >> type as rebinding 'pointer' to a const element type? > > Yes, exactly. > > >> >> We don't need to consider that because we never get a 'const_pointer' from >> the allocator, and we never need to pass a 'const_pointer' to the allocator. >> The allocator's 'allocate' and 'deallocate' members both work with the >> 'pointer' type, so we only need to use that type when interacting with the >> allocator. For all the other uses, such as _Const_Node_ptr, what we need is >> a pointer-to-const that's compatible with the allocator's pointer type. It >> doesn't actually matter if it's the same type as >> allocator_traits::const_pointer, because we don't need > > > Sorry, I sent the email before finishing that thought! > > ... we don't need to pass a const_pointer to anything, we only need it for > the container's own purposes. > > But thinking about it some more, do we even need a const-pointer for the > container? Currently the const_iterator stores a const-pointer, and some > members like _M_root() and _M_leftmost() return a const-pointer. But they > don't need to. The nodes are all pointed to by a non-const _Base_ptr, none of > the storage managed by the container is const. > > Except _M_impl._M_header in a const context. > > Using const_cast would result in a similar UB that you fixed on > _GLIBCXX_DEBUG containers, no ? We only use a pointer to _M_header for the past-the-end iterator, which is not dereferenceable. It's OK to do the const_cast, it's not OK to write something through that pointer/reference if the object is really const. But you can't write through a past-the-end pointer anyway. > > I can provide a version with the const_cast but I'm not sure it worth it. > > François > >
Re: [PATCH] libstdc++: Fix up 117406.cc test [PR117406]
On Mon, 4 Nov 2024 at 10:55, Jakub Jelinek wrote: > > Hi! > > Christophe mentioned in bugzilla that the test FAILs on aarch64, > I'm not including and use INT_MAX. > Apparently during my testing I got it because the test preinclude > -include bits/stdc++.h > and that includes , dunno why that didn't happen on aarch64. > In any case, either I can add #include , or because the > test already has #include I've changed uses of INT_MAX > with std::numeric_limits::max(), that should be the same thing. > But if you prefer > #include > I can surely add that instead. Using std::numeric_limits is fine here. > Tested on x86_64-linux, ok for trunk? OK, thanks. > > 2024-11-04 Jakub Jelinek > > PR libstdc++/117406 > * testsuite/26_numerics/headers/cmath/117406.cc: Use > std::numeric_limits::max() instead of INT_MAX. > > --- libstdc++-v3/testsuite/26_numerics/headers/cmath/117406.cc.jj > 2024-11-02 18:48:47.466350158 +0100 > +++ libstdc++-v3/testsuite/26_numerics/headers/cmath/117406.cc 2024-11-04 > 11:40:25.793831812 +0100 > @@ -31,9 +31,9 @@ test () >int t0 = std::ilogb(T(4.0)); >VERIFY( t0 == 2 ); >int t1 = std::ilogb(lim::infinity()); > - VERIFY( t1 == INT_MAX ); > + VERIFY( t1 == std::numeric_limits::max() ); >int t2 = std::ilogb(-lim::infinity()); > - VERIFY( t2 == INT_MAX ); > + VERIFY( t2 == std::numeric_limits::max() ); > } > > int > > Jakub >
Re: [PATCH] libstdc++: Fix up std::{, b}float16_t std::{ilogb, l{, l}r{ound, int}} [PR117406]
On Sat, 2 Nov 2024 at 07:11, Jakub Jelinek wrote: > > Hi! > > These overloads incorrectly cast the result of the float __builtin_* > to _Float or __gnu_cxx::__bfloat16_t. For std::ilogb that changes > behavior for the INT_MAX return because that isn't representable in > either of the floating point formats, for the others it is I think > just a very inefficient hop from int/long/long long to std::{,b}float16_t > and back. I mean for the round/rint cases, either the argument is small > and then the return value should be representable in the floating point > format too, or it is too large that the argument is already integral > and then it should just return the argument with the round trips. > Too large value is unspecified unlike ilogb. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? OK for trunk, thanks. I think it's worth backporting too. > > 2024-11-02 Jakub Jelinek > > PR libstdc++/117406 > * include/c_global/cmath (std::ilogb(_Float16), std::llrint(_Float16), > std::llround(_Float16), std::lrint(_Float16), std::lround(_Float16)): > Don't cast __builtin_* return to _Float16. > (std::ilogb(__gnu_cxx::__bfloat16_t), > std::llrint(__gnu_cxx::__bfloat16_t), > std::llround(__gnu_cxx::__bfloat16_t), > std::lrint(__gnu_cxx::__bfloat16_t), > std::lround(__gnu_cxx::__bfloat16_t)): Don't cast __builtin_* return > to > __gnu_cxx::__bfloat16_t. > * testsuite/26_numerics/headers/cmath/117406.cc: New test. > > --- libstdc++-v3/include/c_global/cmath.jj 2024-10-29 11:13:47.741803660 > +0100 > +++ libstdc++-v3/include/c_global/cmath 2024-11-01 21:11:40.367678439 +0100 > @@ -2838,7 +2838,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > >constexpr int >ilogb(_Float16 __x) > - { return _Float16(__builtin_ilogbf(__x)); } > + { return __builtin_ilogbf(__x); } > >constexpr _Float16 >lgamma(_Float16 __x) > @@ -2846,11 +2846,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > >constexpr long long >llrint(_Float16 __x) > - { return _Float16(__builtin_llrintf(__x)); } > + { return __builtin_llrintf(__x); } > >constexpr long long >llround(_Float16 __x) > - { return _Float16(__builtin_llroundf(__x)); } > + { return __builtin_llroundf(__x); } > >constexpr _Float16 >log1p(_Float16 __x) > @@ -2867,11 +2867,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > >constexpr long >lrint(_Float16 __x) > - { return _Float16(__builtin_lrintf(__x)); } > + { return __builtin_lrintf(__x); } > >constexpr long >lround(_Float16 __x) > - { return _Float16(__builtin_lroundf(__x)); } > + { return __builtin_lroundf(__x); } > >constexpr _Float16 >nearbyint(_Float16 __x) > @@ -3560,7 +3560,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > >constexpr int >ilogb(__gnu_cxx::__bfloat16_t __x) > - { return __gnu_cxx::__bfloat16_t(__builtin_ilogbf(__x)); } > + { return __builtin_ilogbf(__x); } > >constexpr __gnu_cxx::__bfloat16_t >lgamma(__gnu_cxx::__bfloat16_t __x) > @@ -3568,11 +3568,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > >constexpr long long >llrint(__gnu_cxx::__bfloat16_t __x) > - { return __gnu_cxx::__bfloat16_t(__builtin_llrintf(__x)); } > + { return __builtin_llrintf(__x); } > >constexpr long long >llround(__gnu_cxx::__bfloat16_t __x) > - { return __gnu_cxx::__bfloat16_t(__builtin_llroundf(__x)); } > + { return __builtin_llroundf(__x); } > >constexpr __gnu_cxx::__bfloat16_t >log1p(__gnu_cxx::__bfloat16_t __x) > @@ -3589,11 +3589,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > >constexpr long >lrint(__gnu_cxx::__bfloat16_t __x) > - { return __gnu_cxx::__bfloat16_t(__builtin_lrintf(__x)); } > + { return __builtin_lrintf(__x); } > >constexpr long >lround(__gnu_cxx::__bfloat16_t __x) > - { return __gnu_cxx::__bfloat16_t(__builtin_lroundf(__x)); } > + { return __builtin_lroundf(__x); } > >constexpr __gnu_cxx::__bfloat16_t >nearbyint(__gnu_cxx::__bfloat16_t __x) > --- libstdc++-v3/testsuite/26_numerics/headers/cmath/117406.cc.jj > 2024-11-02 07:55:07.555121231 +0100 > +++ libstdc++-v3/testsuite/26_numerics/headers/cmath/117406.cc 2024-11-02 > 08:00:14.150679537 +0100 > @@ -0,0 +1,59 @@ > +// Copyright (C) 2024 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > + > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > + > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYI
Re: [PATCH] libstdc++: Deprecate useless compatibility headers for C++17
On 31/10/24 20:09 +, Jonathan Wakely wrote: Tested x86_64-linux. Is the g++ test change OK? Also available for review at: https://forge.sourceware.org/gcc/gcc-TEST/pulls/4 -- >8 -- These headers make no sense for C++ programs, because they either define different content to the corresponding C header, or define nothing at all in namespace std. They were all deprecated in C++17, so add deprecation warnings to them, which can be disabled with -Wno-deprecated. For C++20 and later these headers are no longer in the standard at all, so compiling with _GLIBCXX_USE_DEPRECATED defined to 0 will give an error when they are included. Because #warning is non-standard before C++23 we need to use pragmas to ignore -Wc++23-extensions for the -Wsystem-headers -pedantic case. One g++ test needs adjustment because it includes , but that can be made conditional on the __cplusplus value without any reduction in test coverage. For the library tests, consolidate the std_c++0x_neg.cc XFAIL tests into the macros.cc test, using dg-error with a { target c++98_only } selector. This avoids having two separate test files, one for C++98 and one for everything later. Also add tests for the headers to ensure that they behave as expected and don't give deprecated warnings. libstdc++-v3/ChangeLog: * doc/xml/manual/evolution.xml: Document deprecations. * doc/html/*: Regenerate. * include/c_compatibility/complex.h (_GLIBCXX_COMPLEX_H): Move include guard to start of file. Include directly instead of . * include/c_compatibility/tgmath.h: Include and directly, instead of . * include/c_global/ccomplex: Add deprecated #warning for C++17 and #error for C++20 if _GLIBCXX_USE_DEPRECATED == 0. * include/c_global/ciso646: Likewise. * include/c_global/cstdalign: Likewise. * include/c_global/cstdbool: Likewise. * include/c_global/ctgmath: Likewise. * include/c_std/ciso646: Likewise. * include/precompiled/stdc++.h: Do not include ccomplex, ciso646, cstdalign, cstdbool, or ctgmath in C++17 and later. * testsuite/18_support/headers/cstdalign/macros.cc: Check for warnings and errors for unsupported dialects. * testsuite/18_support/headers/cstdbool/macros.cc: Likewise. * testsuite/26_numerics/headers/ctgmath/complex.cc: Likewise. * testsuite/27_io/objects/char/1.cc: Do not include . * testsuite/27_io/objects/wchar_t/1.cc: Likewise. * testsuite/18_support/headers/cstdbool/std_c++0x_neg.cc: Removed. * testsuite/18_support/headers/cstdalign/std_c++0x_neg.cc: Removed. * testsuite/26_numerics/headers/ccomplex/std_c++0x_neg.cc: Removed. * testsuite/26_numerics/headers/ctgmath/std_c++0x_neg.cc: Removed. * testsuite/18_support/headers/ciso646/macros.cc: New test. * testsuite/18_support/headers/ciso646/macros.h.cc: New test. * testsuite/18_support/headers/cstdbool/macros.h.cc: New test. * testsuite/26_numerics/headers/ccomplex/complex.cc: New test. * testsuite/26_numerics/headers/ccomplex/complex.h.cc: New test. * testsuite/26_numerics/headers/ctgmath/complex.h.cc: New test. gcc/testsuite/ChangeLog: * g++.old-deja/g++.other/headers1.C: Do not include ciso646 for C++17 and later. --- .../g++.old-deja/g++.other/headers1.C | 2 + libstdc++-v3/doc/html/manual/api.html | 8 +++ libstdc++-v3/doc/xml/manual/evolution.xml | 10 .../include/c_compatibility/complex.h | 10 ++-- libstdc++-v3/include/c_compatibility/tgmath.h | 11 ++-- libstdc++-v3/include/c_global/ccomplex| 9 libstdc++-v3/include/c_global/ciso646 | 9 libstdc++-v3/include/c_global/cstdalign | 8 +++ libstdc++-v3/include/c_global/cstdbool| 8 +++ libstdc++-v3/include/c_global/ctgmath | 14 +++-- libstdc++-v3/include/c_std/ciso646| 10 libstdc++-v3/include/precompiled/stdc++.h | 13 +++-- .../18_support/headers/ciso646/macros.cc | 51 +++ .../18_support/headers/ciso646/macros.h.cc| 49 ++ .../18_support/headers/cstdalign/macros.cc| 10 +++- .../18_support/headers/cstdalign/macros.h.cc | 25 + .../headers/cstdalign/std_c++0x_neg.cc| 24 - .../18_support/headers/cstdbool/macros.cc | 9 +++- .../18_support/headers/cstdbool/macros.h.cc | 21 .../headers/cstdbool/std_c++0x_neg.cc | 26 -- .../26_numerics/headers/ccomplex/complex.cc | 10 .../26_numerics/headers/ccomplex/complex.h.cc | 10 .../headers/ccomplex/std_c++0x_neg.cc | 26 -- .../26_numerics/headers/ctgmath/complex.cc| 9 +++- .../26_numerics/headers/ctgmath/complex.h.cc | 10 .../headers/ctgmath/std_c++0x_neg.cc | 26 -- .../testsuite/27_io/objects/char/1.cc | 1 - .../testsuite/27_io/objects/wchar_t/1.cc |
Re: [PATCH] libstdc++: Deprecate useless compatibility headers for C++17
On 01/11/24 20:56 +, Jonathan Wakely wrote: On 31/10/24 20:09 +, Jonathan Wakely wrote: Tested x86_64-linux. Is the g++ test change OK? Also available for review at: https://forge.sourceware.org/gcc/gcc-TEST/pulls/4 -- >8 -- These headers make no sense for C++ programs, because they either define different content to the corresponding C header, or define nothing at all in namespace std. They were all deprecated in C++17, so add deprecation warnings to them, which can be disabled with -Wno-deprecated. For C++20 and later these headers are no longer in the standard at all, so compiling with _GLIBCXX_USE_DEPRECATED defined to 0 will give an error when they are included. Because #warning is non-standard before C++23 we need to use pragmas to ignore -Wc++23-extensions for the -Wsystem-headers -pedantic case. One g++ test needs adjustment because it includes , but that can be made conditional on the __cplusplus value without any reduction in test coverage. For the library tests, consolidate the std_c++0x_neg.cc XFAIL tests into the macros.cc test, using dg-error with a { target c++98_only } selector. This avoids having two separate test files, one for C++98 and one for everything later. Also add tests for the headers to ensure that they behave as expected and don't give deprecated warnings. libstdc++-v3/ChangeLog: * doc/xml/manual/evolution.xml: Document deprecations. * doc/html/*: Regenerate. * include/c_compatibility/complex.h (_GLIBCXX_COMPLEX_H): Move include guard to start of file. Include directly instead of . * include/c_compatibility/tgmath.h: Include and directly, instead of . * include/c_global/ccomplex: Add deprecated #warning for C++17 and #error for C++20 if _GLIBCXX_USE_DEPRECATED == 0. * include/c_global/ciso646: Likewise. * include/c_global/cstdalign: Likewise. * include/c_global/cstdbool: Likewise. * include/c_global/ctgmath: Likewise. * include/c_std/ciso646: Likewise. * include/precompiled/stdc++.h: Do not include ccomplex, ciso646, cstdalign, cstdbool, or ctgmath in C++17 and later. * testsuite/18_support/headers/cstdalign/macros.cc: Check for warnings and errors for unsupported dialects. * testsuite/18_support/headers/cstdbool/macros.cc: Likewise. * testsuite/26_numerics/headers/ctgmath/complex.cc: Likewise. * testsuite/27_io/objects/char/1.cc: Do not include . * testsuite/27_io/objects/wchar_t/1.cc: Likewise. * testsuite/18_support/headers/cstdbool/std_c++0x_neg.cc: Removed. * testsuite/18_support/headers/cstdalign/std_c++0x_neg.cc: Removed. * testsuite/26_numerics/headers/ccomplex/std_c++0x_neg.cc: Removed. * testsuite/26_numerics/headers/ctgmath/std_c++0x_neg.cc: Removed. * testsuite/18_support/headers/ciso646/macros.cc: New test. * testsuite/18_support/headers/ciso646/macros.h.cc: New test. * testsuite/18_support/headers/cstdbool/macros.h.cc: New test. * testsuite/26_numerics/headers/ccomplex/complex.cc: New test. * testsuite/26_numerics/headers/ccomplex/complex.h.cc: New test. * testsuite/26_numerics/headers/ctgmath/complex.h.cc: New test. gcc/testsuite/ChangeLog: * g++.old-deja/g++.other/headers1.C: Do not include ciso646 for C++17 and later. --- .../g++.old-deja/g++.other/headers1.C | 2 + libstdc++-v3/doc/html/manual/api.html | 8 +++ libstdc++-v3/doc/xml/manual/evolution.xml | 10 .../include/c_compatibility/complex.h | 10 ++-- libstdc++-v3/include/c_compatibility/tgmath.h | 11 ++-- libstdc++-v3/include/c_global/ccomplex| 9 libstdc++-v3/include/c_global/ciso646 | 9 libstdc++-v3/include/c_global/cstdalign | 8 +++ libstdc++-v3/include/c_global/cstdbool| 8 +++ libstdc++-v3/include/c_global/ctgmath | 14 +++-- libstdc++-v3/include/c_std/ciso646| 10 libstdc++-v3/include/precompiled/stdc++.h | 13 +++-- .../18_support/headers/ciso646/macros.cc | 51 +++ .../18_support/headers/ciso646/macros.h.cc| 49 ++ .../18_support/headers/cstdalign/macros.cc| 10 +++- .../18_support/headers/cstdalign/macros.h.cc | 25 + .../headers/cstdalign/std_c++0x_neg.cc| 24 - .../18_support/headers/cstdbool/macros.cc | 9 +++- .../18_support/headers/cstdbool/macros.h.cc | 21 .../headers/cstdbool/std_c++0x_neg.cc | 26 -- .../26_numerics/headers/ccomplex/complex.cc | 10 .../26_numerics/headers/ccomplex/complex.h.cc | 10 .../headers/ccomplex/std_c++0x_neg.cc | 26 -- .../26_numerics/headers/ctgmath/complex.cc| 9 +++- .../26_numerics/headers/ctgmath/complex.h.cc | 10 .../headers/ctgmath/std_c++0x_neg.cc | 26 -- .../testsuite/27_io/objects/char/1.cc
[committed] libstdc++: Check feature test macros in unordered containers
Replace some `__cplusplus > 201402L` preprocessor checks with more expressive checks for the appropriate feature test macros. libstdc++-v3/ChangeLog: * include/bits/unordered_map.h: Check __glibcxx_node_extract and __glibcxx_unordered_map_try_emplace instead of __cplusplus. * include/bits/unordered_set.h: Check __glibcxx_node_extract instead of __cplusplus. --- Tested x86_64-linux. Pushed to trunk. libstdc++-v3/include/bits/unordered_map.h | 28 +++ libstdc++-v3/include/bits/unordered_set.h | 24 +-- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/libstdc++-v3/include/bits/unordered_map.h b/libstdc++-v3/include/bits/unordered_map.h index 8607944d565..3b472534c66 100644 --- a/libstdc++-v3/include/bits/unordered_map.h +++ b/libstdc++-v3/include/bits/unordered_map.h @@ -137,7 +137,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef typename _Hashtable::difference_type difference_type; ///@} -#if __cplusplus > 201402L +#ifdef __glibcxx_node_extract // >= C++17 && HOSTED using node_type = typename _Hashtable::node_type; using insert_return_type = typename _Hashtable::insert_return_type; #endif @@ -426,7 +426,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER emplace_hint(const_iterator __pos, _Args&&... __args) { return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); } -#if __cplusplus > 201402L +#ifdef __glibcxx_node_extract // >= C++17 && HOSTED /// Extract a node. node_type extract(const_iterator __pos) @@ -449,7 +449,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER iterator insert(const_iterator, node_type&& __nh) { return _M_h._M_reinsert_node(std::move(__nh)).position; } -#endif // C++17 +#endif // node_extract #ifdef __glibcxx_unordered_map_try_emplace // C++ >= 17 && HOSTED /** @@ -636,7 +636,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER { _M_h.insert(__l); } -#if __cplusplus > 201402L +#ifdef __glibcxx_unordered_map_try_emplace // >= C++17 && HOSTED /** * @brief Attempts to insert a std::pair into the %unordered_map. * @param __kKey to use for finding a possibly existing pair in @@ -728,7 +728,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER __ret.first->second = std::forward<_Obj>(__obj); return __ret.first; } -#endif +#endif // unordered_map_try_emplace ///@{ /** @@ -813,7 +813,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER noexcept( noexcept(_M_h.swap(__x._M_h)) ) { _M_h.swap(__x._M_h); } -#if __cplusplus > 201402L +#ifdef __glibcxx_node_extract // >= C++17 && HOSTED template friend class std::_Hash_merge_helper; @@ -842,7 +842,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>&& __source) { merge(__source); } -#endif // C++17 +#endif // node_extract // observers. @@ -1283,7 +1283,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER typedef typename _Hashtable::difference_type difference_type; ///@} -#if __cplusplus > 201402L +#ifdef __glibcxx_node_extract // >= C++17 && HOSTED using node_type = typename _Hashtable::node_type; #endif @@ -1648,7 +1648,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER insert(initializer_list __l) { _M_h.insert(__l); } -#if __cplusplus > 201402L +#ifdef __glibcxx_node_extract // >= C++17 && HOSTED /// Extract a node. node_type extract(const_iterator __pos) @@ -1671,7 +1671,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER iterator insert(const_iterator __hint, node_type&& __nh) { return _M_h._M_reinsert_node_multi(__hint, std::move(__nh)); } -#endif // C++17 +#endif // node_extract ///@{ /** @@ -1756,7 +1756,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER noexcept( noexcept(_M_h.swap(__x._M_h)) ) { _M_h.swap(__x._M_h); } -#if __cplusplus > 201402L +#ifdef __glibcxx_node_extract // >= C++17 && HOSTED template friend class std::_Hash_merge_helper; @@ -1787,7 +1787,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER void merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>&& __source) { merge(__source); } -#endif // C++17 +#endif // node_extract // observers. @@ -2169,7 +2169,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX_END_NAMESPACE_CONTAINER -#if __cplusplus > 201402L +#ifdef __glibcxx_node_extract // >= C++17 && HOSTED // Allow std::unordered_map access to internals of compatible maps. template @@ -2217,7 +2217,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER _S_get_table(unordered_multimap<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map) { return __map._M_h; } }; -#endif // C++17 +#endif // node_extract _GLIBCXX_END_NAMESPACE_VERSION } // namespace std diff --git a/libstdc++-v3/include/bits/unordered_set.h b/libstdc++-v3/include/bits/unordered_set.h index a2fa2b4a083..08dcfa2a9b9
[committed] libstdc++: Minor comment improvements in
libstdc++-v3/ChangeLog: * include/bits/hashtable.h: Improve comments. --- Tested x86_64-linux. Pushed to trunk. libstdc++-v3/include/bits/hashtable.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h index f1a5490b5ff..47321a9cb13 100644 --- a/libstdc++-v3/include/bits/hashtable.h +++ b/libstdc++-v3/include/bits/hashtable.h @@ -1019,7 +1019,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION iterator erase(const_iterator); - // LWG 2059. + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2059. C++0x ambiguity problem with map::erase iterator erase(iterator __it) { return erase(const_iterator(__it)); } @@ -1041,7 +1042,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // DR 1189. // reserve, if present, comes from _Rehash_base. -#if __glibcxx_node_extract // >= C++17 +#if __glibcxx_node_extract // >= C++17 && HOSTED /// Re-insert an extracted node into a container with unique keys. insert_return_type _M_reinsert_node(node_type&& __nh) -- 2.47.0
[committed] libstdc++: Remove stray whitespace in #endif
This isn't nested within another #if group so shouldn't be indented like this. libstdc++-v3/ChangeLog: * libsupc++/typeinfo: Remove whitespace in #endif --- Pushed as obvious. libstdc++-v3/libsupc++/typeinfo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libstdc++-v3/libsupc++/typeinfo b/libstdc++-v3/libsupc++/typeinfo index 71066eb1e46..721268cb3fa 100644 --- a/libstdc++-v3/libsupc++/typeinfo +++ b/libstdc++-v3/libsupc++/typeinfo @@ -212,7 +212,7 @@ namespace std return false; #endif } -# endif +#endif /** -- 2.47.0
[committed] libstdc++: Add missing header to unordered_set/pr115285.cc test
libstdc++-v3/ChangeLog: * testsuite/23_containers/unordered_set/pr115285.cc: Include missing header for std::vector. --- Pushed as obvious. libstdc++-v3/testsuite/23_containers/unordered_set/pr115285.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/pr115285.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/pr115285.cc index 6c5cc24930c..85954aed74b 100644 --- a/libstdc++-v3/testsuite/23_containers/unordered_set/pr115285.cc +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/pr115285.cc @@ -2,8 +2,9 @@ // libstdc++/115285 -#include #include +#include +#include #include -- 2.47.0
[PATCH] libstdc++: Deprecate useless compatibility headers for C++17
Tested x86_64-linux. Is the g++ test change OK? Also available for review at: https://forge.sourceware.org/gcc/gcc-TEST/pulls/4 -- >8 -- These headers make no sense for C++ programs, because they either define different content to the corresponding C header, or define nothing at all in namespace std. They were all deprecated in C++17, so add deprecation warnings to them, which can be disabled with -Wno-deprecated. For C++20 and later these headers are no longer in the standard at all, so compiling with _GLIBCXX_USE_DEPRECATED defined to 0 will give an error when they are included. Because #warning is non-standard before C++23 we need to use pragmas to ignore -Wc++23-extensions for the -Wsystem-headers -pedantic case. One g++ test needs adjustment because it includes , but that can be made conditional on the __cplusplus value without any reduction in test coverage. For the library tests, consolidate the std_c++0x_neg.cc XFAIL tests into the macros.cc test, using dg-error with a { target c++98_only } selector. This avoids having two separate test files, one for C++98 and one for everything later. Also add tests for the headers to ensure that they behave as expected and don't give deprecated warnings. libstdc++-v3/ChangeLog: * doc/xml/manual/evolution.xml: Document deprecations. * doc/html/*: Regenerate. * include/c_compatibility/complex.h (_GLIBCXX_COMPLEX_H): Move include guard to start of file. Include directly instead of . * include/c_compatibility/tgmath.h: Include and directly, instead of . * include/c_global/ccomplex: Add deprecated #warning for C++17 and #error for C++20 if _GLIBCXX_USE_DEPRECATED == 0. * include/c_global/ciso646: Likewise. * include/c_global/cstdalign: Likewise. * include/c_global/cstdbool: Likewise. * include/c_global/ctgmath: Likewise. * include/c_std/ciso646: Likewise. * include/precompiled/stdc++.h: Do not include ccomplex, ciso646, cstdalign, cstdbool, or ctgmath in C++17 and later. * testsuite/18_support/headers/cstdalign/macros.cc: Check for warnings and errors for unsupported dialects. * testsuite/18_support/headers/cstdbool/macros.cc: Likewise. * testsuite/26_numerics/headers/ctgmath/complex.cc: Likewise. * testsuite/27_io/objects/char/1.cc: Do not include . * testsuite/27_io/objects/wchar_t/1.cc: Likewise. * testsuite/18_support/headers/cstdbool/std_c++0x_neg.cc: Removed. * testsuite/18_support/headers/cstdalign/std_c++0x_neg.cc: Removed. * testsuite/26_numerics/headers/ccomplex/std_c++0x_neg.cc: Removed. * testsuite/26_numerics/headers/ctgmath/std_c++0x_neg.cc: Removed. * testsuite/18_support/headers/ciso646/macros.cc: New test. * testsuite/18_support/headers/ciso646/macros.h.cc: New test. * testsuite/18_support/headers/cstdbool/macros.h.cc: New test. * testsuite/26_numerics/headers/ccomplex/complex.cc: New test. * testsuite/26_numerics/headers/ccomplex/complex.h.cc: New test. * testsuite/26_numerics/headers/ctgmath/complex.h.cc: New test. gcc/testsuite/ChangeLog: * g++.old-deja/g++.other/headers1.C: Do not include ciso646 for C++17 and later. --- .../g++.old-deja/g++.other/headers1.C | 2 + libstdc++-v3/doc/html/manual/api.html | 8 +++ libstdc++-v3/doc/xml/manual/evolution.xml | 10 .../include/c_compatibility/complex.h | 10 ++-- libstdc++-v3/include/c_compatibility/tgmath.h | 11 ++-- libstdc++-v3/include/c_global/ccomplex| 9 libstdc++-v3/include/c_global/ciso646 | 9 libstdc++-v3/include/c_global/cstdalign | 8 +++ libstdc++-v3/include/c_global/cstdbool| 8 +++ libstdc++-v3/include/c_global/ctgmath | 14 +++-- libstdc++-v3/include/c_std/ciso646| 10 libstdc++-v3/include/precompiled/stdc++.h | 13 +++-- .../18_support/headers/ciso646/macros.cc | 51 +++ .../18_support/headers/ciso646/macros.h.cc| 49 ++ .../18_support/headers/cstdalign/macros.cc| 10 +++- .../18_support/headers/cstdalign/macros.h.cc | 25 + .../headers/cstdalign/std_c++0x_neg.cc| 24 - .../18_support/headers/cstdbool/macros.cc | 9 +++- .../18_support/headers/cstdbool/macros.h.cc | 21 .../headers/cstdbool/std_c++0x_neg.cc | 26 -- .../26_numerics/headers/ccomplex/complex.cc | 10 .../26_numerics/headers/ccomplex/complex.h.cc | 10 .../headers/ccomplex/std_c++0x_neg.cc | 26 -- .../26_numerics/headers/ctgmath/complex.cc| 9 +++- .../26_numerics/headers/ctgmath/complex.h.cc | 10 .../headers/ctgmath/std_c++0x_neg.cc | 26 -- .../testsuite/27_io/objects/char/1.cc | 1 - .../testsuite/27_io/objects/wchar_t/1.cc | 1 - 28 files changed, 294 insert
[PATCH 2/2] libstdc++: More user-friendly failed assertions from shared_ptr dereference
Currently dereferencing an empty shared_ptr prints a complicated internal type in the assertion message: include/bits/shared_ptr_base.h:1377: std::__shared_ptr_access<_Tp, _Lp, , >::element_type& std::__shared_ptr_access<_Tp, _Lp, , >::operator*() const [with _Tp = std::filesystem::__cxx11::recursive_directory_iterator::_Dir_stack; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool = false; bool = false; element_type = std::filesystem::__cxx11::recursive_directory_iterator::_Dir_stack]: Assertion '_M_get() != nullptr' failed. Users don't care about any of the _Lp and template parameters, so this is unnecessarily verbose. We can simplify it to something that only mentions "shared_ptr_deref" and the element type: include/bits/shared_ptr_base.h:1371: _Tp* std::__shared_ptr_deref(_Tp*) [with _Tp = filesystem::__cxx11::recursive_directory_iterator::_Dir_stack]: Assertion '__p != nullptr' failed. libstdc++-v3/ChangeLog: * include/bits/shared_ptr_base.h (__shared_ptr_deref): New function template. (__shared_ptr_access, __shared_ptr_access<>): Use it. --- Tested x86_64-linux. Also available for review at: https://forge.sourceware.org/gcc/gcc-TEST/pulls/13 libstdc++-v3/include/bits/shared_ptr_base.h | 28 + 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h index 9a7617e7014..ee01594ce0c 100644 --- a/libstdc++-v3/include/bits/shared_ptr_base.h +++ b/libstdc++-v3/include/bits/shared_ptr_base.h @@ -1337,6 +1337,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { }; + template +[[__gnu__::__always_inline__]] +inline _Tp* +__shared_ptr_deref(_Tp* __p) +{ + __glibcxx_assert(__p != nullptr); + return __p; +} + // Define operator* and operator-> for shared_ptr. template::value, bool = is_void<_Tp>::value> @@ -1347,10 +1356,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION element_type& operator*() const noexcept - { - __glibcxx_assert(_M_get() != nullptr); - return *_M_get(); - } + { return *std::__shared_ptr_deref(_M_get()); } element_type* operator->() const noexcept @@ -1392,10 +1398,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION [[__deprecated__("shared_ptr::operator* is absent from C++17")]] element_type& operator*() const noexcept - { - __glibcxx_assert(_M_get() != nullptr); - return *_M_get(); - } + { return *std::__shared_ptr_deref(_M_get()); } [[__deprecated__("shared_ptr::operator-> is absent from C++17")]] element_type* @@ -1406,13 +1409,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } #endif +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++17-extensions" element_type& operator[](ptrdiff_t __i) const noexcept { - __glibcxx_assert(_M_get() != nullptr); - __glibcxx_assert(!extent<_Tp>::value || __i < extent<_Tp>::value); - return _M_get()[__i]; + if constexpr (extent<_Tp>::value) + __glibcxx_assert(__i < extent<_Tp>::value); + return std::__shared_ptr_deref(_M_get())[__i]; } +#pragma GCC diagnostic pop private: element_type* -- 2.47.0
[PATCH 1/2] libstdc++: Enable debug assertions for filesystem directory iterators
Several member functions of filesystem::directory_iterator and filesystem::recursive_directory_iterator currently dereference their shared_ptr data member without checking for non-null. Because they use operator-> and that function only uses _GLIBCXX_DEBUG_PEDASSERT rather than __glibcxx_assert there is no assertion even when the library is built with _GLIBCXX_ASSERTIONS defined. This means that dereferencing invalid directory iterators gives an unhelpful segfault. By using (*p). instead of p-> we get an assertion when the library is built with _GLIBCXX_ASSERTIONS, with a "_M_get() != nullptr" message. libstdc++-v3/ChangeLog: * src/c++17/fs_dir.cc (fs::directory_iterator::operator*): Use shared_ptr::operator* instead of shared_ptr::operator->. (fs::recursive_directory_iterator::options): Likewise. (fs::recursive_directory_iterator::depth): Likewise. (fs::recursive_directory_iterator::recursion_pending): Likewise. (fs::recursive_directory_iterator::operator*): Likewise. (fs::recursive_directory_iterator::disable_recursion_pending): Likewise. --- Tested x86_64-linux. Also available for review at: https://forge.sourceware.org/gcc/gcc-TEST/pulls/13 libstdc++-v3/src/c++17/fs_dir.cc | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libstdc++-v3/src/c++17/fs_dir.cc b/libstdc++-v3/src/c++17/fs_dir.cc index 28d27f6a9fa..8fe9e5e4cc8 100644 --- a/libstdc++-v3/src/c++17/fs_dir.cc +++ b/libstdc++-v3/src/c++17/fs_dir.cc @@ -230,7 +230,7 @@ directory_iterator(const path& p, directory_options options, error_code* ecptr) const fs::directory_entry& fs::directory_iterator::operator*() const noexcept { - return _M_dir->entry; + return (*_M_dir).entry; } fs::directory_iterator& @@ -327,25 +327,25 @@ fs::recursive_directory_iterator::~recursive_directory_iterator() = default; fs::directory_options fs::recursive_directory_iterator::options() const noexcept { - return _M_dirs->options; + return (*_M_dirs).options; } int fs::recursive_directory_iterator::depth() const noexcept { - return int(_M_dirs->size()) - 1; + return int((*_M_dirs).size()) - 1; } bool fs::recursive_directory_iterator::recursion_pending() const noexcept { - return _M_dirs->pending; + return (*_M_dirs).pending; } const fs::directory_entry& fs::recursive_directory_iterator::operator*() const noexcept { - return _M_dirs->top().entry; + return (*_M_dirs).top().entry; } fs::recursive_directory_iterator& @@ -453,7 +453,7 @@ fs::recursive_directory_iterator::pop() void fs::recursive_directory_iterator::disable_recursion_pending() noexcept { - _M_dirs->pending = false; + (*_M_dirs).pending = false; } // Used to implement filesystem::remove_all. -- 2.47.0
[committed] libstdc++: Fix copy&paste comments in vector range tests
These comments were copied from the std::vector tests, but the value_type is not bool in these ones. libstdc++-v3/ChangeLog: * testsuite/23_containers/vector/cons/from_range.cc: Fix copy & paste error in comment. * testsuite/23_containers/vector/modifiers/append_range.cc: Likewise. * testsuite/23_containers/vector/modifiers/assign/assign_range.cc: Likewise. * testsuite/23_containers/vector/modifiers/insert/insert_range.cc: Likewise. --- Pushed to trunk. libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc | 2 +- .../testsuite/23_containers/vector/modifiers/append_range.cc| 2 +- .../23_containers/vector/modifiers/assign/assign_range.cc | 2 +- .../23_containers/vector/modifiers/insert/insert_range.cc | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc index e91465f5a71..ed2e3ca6ba1 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc @@ -80,7 +80,7 @@ test_ranges() do_test_a>(); do_test_a>(); - // Not lvalue-convertible to bool + // Not lvalue-convertible to int struct C { C(int v) : val(v) { } operator int() && { return val; } diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc index 24a5c7d0e7c..5725cd2ad48 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc @@ -69,7 +69,7 @@ test_ranges() do_test_a>(); do_test_a>(); - // Not lvalue-convertible to bool + // Not lvalue-convertible to int struct C { C(int v) : val(v) { } operator int() && { return val; } diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc index 4e8d8af1614..db3b06cfbc0 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc @@ -90,7 +90,7 @@ test_ranges() do_test_a>(); do_test_a>(); - // Not lvalue-convertible to bool + // Not lvalue-convertible to int struct C { C(int v) : val(v) { } operator int() && { return val; } diff --git a/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc b/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc index 30219f5da02..68218e94f28 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc @@ -80,7 +80,7 @@ test_ranges() do_test_a>(); do_test_a>(); - // Not lvalue-convertible to bool + // Not lvalue-convertible to int struct C { C(int v) : val(v) { } operator int() && { return val; } -- 2.47.0
Re: [PATCH] libstdc++: Add align_alloc attribute to aligned operator new
On Wed, 30 Oct 2024 at 21:54, Jakub Jelinek wrote: > > On Wed, Oct 30, 2024 at 09:24:05PM +, Jonathan Wakely wrote: > > The aligned versions of operator new should use the align_alloc > > attribute to help the compiler. > > > > PR c++/86878 requests that the compiler would use the attribute to warn > > about invalid attributes, so an XFAILed test is added for that. > > > > libstdc++-v3/ChangeLog: > > > > * libsupc++/new (operator new): Add attribute align_alloc(2) to > > overloads taking a std::align_val_t argument. > > * testsuite/18_support/new_aligned_warn.cc: New test. > > --- > > I think this makes sense, but maybe there's some property of the > > attribute that means this isn't a good idea? I think the compiler can > > use the value of align_val_t even though it's a scoped enumeration type. > > We document that alloc_align (and alloc_size etc.) arguments can have > integer or enumerated types, the implemented check is INTEGRAL_TYPE_P (t) > && TREE_CODE (t) != BOOLEAN_TYPE. I suppose the "not implicitly convertible to an integer" rule for scoped enums is just a language constraint, the compiler sees scoped enumerations like any other integral value. > And the meaning of the attribute is exactly what the C++ standard requires > from such operators, so the patch LGTM. Great, thanks, I'll push in the morning.
Re: [PATCH] libstdc++: Add align_alloc attribute to aligned operator new
On Wed, 30 Oct 2024 at 21:26, Jonathan Wakely wrote: > > The aligned versions of operator new should use the align_alloc > attribute to help the compiler. > > PR c++/86878 requests that the compiler would use the attribute to warn > about invalid attributes, so an XFAILed test is added for that. > > libstdc++-v3/ChangeLog: > > * libsupc++/new (operator new): Add attribute align_alloc(2) to > overloads taking a std::align_val_t argument. > * testsuite/18_support/new_aligned_warn.cc: New test. > --- > I think this makes sense, but maybe there's some property of the > attribute that means this isn't a good idea? I think the compiler can > use the value of align_val_t even though it's a scoped enumeration type. > > Tested x86_64-linux. I forgot to say that this is also available for review at: https://forge.sourceware.org/gcc/gcc-TEST/pulls/12 > > libstdc++-v3/libsupc++/new | 6 +++--- > .../testsuite/18_support/new_aligned_warn.cc| 13 + > 2 files changed, 16 insertions(+), 3 deletions(-) > create mode 100644 libstdc++-v3/testsuite/18_support/new_aligned_warn.cc > > diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new > index e9a3d9b49a3..4345030071b 100644 > --- a/libstdc++-v3/libsupc++/new > +++ b/libstdc++-v3/libsupc++/new > @@ -167,7 +167,7 @@ void operator delete[](void*, const std::nothrow_t&) > #if __cpp_aligned_new > _GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t) >_GLIBCXX_TXN_SAFE > - __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__)); > + __attribute__((__externally_visible__, __alloc_size__ (1), __alloc_align__ > (2), __malloc__)); > _GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t, const > std::nothrow_t&) > _GLIBCXX_TXN_SAFE >_GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, > __alloc_size__ (1), __malloc__)); > @@ -178,10 +178,10 @@ void operator delete(void*, std::align_val_t, const > std::nothrow_t&) >_GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); > _GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t) >_GLIBCXX_TXN_SAFE > - __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__)); > + __attribute__((__externally_visible__, __alloc_size__ (1), __alloc_align__ > (2), __malloc__)); > _GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t, const > std::nothrow_t&) >_GLIBCXX_TXN_SAFE > - _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, > __alloc_size__ (1), __malloc__)); > + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, > __alloc_size__ (1), __alloc_align__ (2), __malloc__)); > void operator delete[](void*, std::align_val_t) _GLIBCXX_TXN_SAFE >_GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); > void operator delete[](void*, std::align_val_t, const std::nothrow_t&) > diff --git a/libstdc++-v3/testsuite/18_support/new_aligned_warn.cc > b/libstdc++-v3/testsuite/18_support/new_aligned_warn.cc > new file mode 100644 > index 000..e9d374abe31 > --- /dev/null > +++ b/libstdc++-v3/testsuite/18_support/new_aligned_warn.cc > @@ -0,0 +1,13 @@ > +// { dg-options "-Wattributes" } > +// { dg-do compile { target c++17 } } > + > +#include > + > +int main() > +{ > + // PR c++/86878 has a patch to make these warn. > + (void) operator new(1, std::align_val_t(3)); // { dg-warning "power of > two" "" { xfail *-*-* } } > + (void) operator new[](1, std::align_val_t(10)); // { dg-warning "power of > two" "" { xfail *-*-* } } > + (void) operator new(1, std::align_val_t(0), std::nothrow_t()); // { > dg-warning "power of two" "" { xfail *-*-* } } > + (void) operator new[](1, std::align_val_t(-1), std::nothrow_t()); // { > dg-warning "power of two" "" { xfail *-*-* } } > +} > -- > 2.47.0 >
[PATCH] libstdc++: Add align_alloc attribute to aligned operator new
The aligned versions of operator new should use the align_alloc attribute to help the compiler. PR c++/86878 requests that the compiler would use the attribute to warn about invalid attributes, so an XFAILed test is added for that. libstdc++-v3/ChangeLog: * libsupc++/new (operator new): Add attribute align_alloc(2) to overloads taking a std::align_val_t argument. * testsuite/18_support/new_aligned_warn.cc: New test. --- I think this makes sense, but maybe there's some property of the attribute that means this isn't a good idea? I think the compiler can use the value of align_val_t even though it's a scoped enumeration type. Tested x86_64-linux. libstdc++-v3/libsupc++/new | 6 +++--- .../testsuite/18_support/new_aligned_warn.cc| 13 + 2 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 libstdc++-v3/testsuite/18_support/new_aligned_warn.cc diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new index e9a3d9b49a3..4345030071b 100644 --- a/libstdc++-v3/libsupc++/new +++ b/libstdc++-v3/libsupc++/new @@ -167,7 +167,7 @@ void operator delete[](void*, const std::nothrow_t&) #if __cpp_aligned_new _GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t) _GLIBCXX_TXN_SAFE - __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__)); + __attribute__((__externally_visible__, __alloc_size__ (1), __alloc_align__ (2), __malloc__)); _GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t, const std::nothrow_t&) _GLIBCXX_TXN_SAFE _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__)); @@ -178,10 +178,10 @@ void operator delete(void*, std::align_val_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); _GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t) _GLIBCXX_TXN_SAFE - __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__)); + __attribute__((__externally_visible__, __alloc_size__ (1), __alloc_align__ (2), __malloc__)); _GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t, const std::nothrow_t&) _GLIBCXX_TXN_SAFE - _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__)); + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, __alloc_size__ (1), __alloc_align__ (2), __malloc__)); void operator delete[](void*, std::align_val_t) _GLIBCXX_TXN_SAFE _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); void operator delete[](void*, std::align_val_t, const std::nothrow_t&) diff --git a/libstdc++-v3/testsuite/18_support/new_aligned_warn.cc b/libstdc++-v3/testsuite/18_support/new_aligned_warn.cc new file mode 100644 index 000..e9d374abe31 --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/new_aligned_warn.cc @@ -0,0 +1,13 @@ +// { dg-options "-Wattributes" } +// { dg-do compile { target c++17 } } + +#include + +int main() +{ + // PR c++/86878 has a patch to make these warn. + (void) operator new(1, std::align_val_t(3)); // { dg-warning "power of two" "" { xfail *-*-* } } + (void) operator new[](1, std::align_val_t(10)); // { dg-warning "power of two" "" { xfail *-*-* } } + (void) operator new(1, std::align_val_t(0), std::nothrow_t()); // { dg-warning "power of two" "" { xfail *-*-* } } + (void) operator new[](1, std::align_val_t(-1), std::nothrow_t()); // { dg-warning "power of two" "" { xfail *-*-* } } +} -- 2.47.0
[PATCH] libstdc++: Add P1206R7 from_range members to std::list and std::forward_list [PR111055]
This is another piece of P1206R7, adding new members to std::list and std::forward_list. libstdc++-v3/ChangeLog: PR libstdc++/111055 * include/bits/forward_list.h (forward_list(from_range, R&&, const Alloc&), assign_range) (prepend_range, insert_range_after): Define. * include/bits/stl_list.h: (list(from_range, R&&, const Alloc&)) (assign_range, prepend_range, append_range, insert_range): Define. * testsuite/23_containers/forward_list/cons/from_range.cc: New test. * testsuite/23_containers/forward_list/modifiers/assign_range.cc: New test. * testsuite/23_containers/forward_list/modifiers/insert_range_after.cc: New test. * testsuite/23_containers/forward_list/modifiers/prepend_range.cc: New test. * testsuite/23_containers/list/cons/from_range.cc: New test. * testsuite/23_containers/list/modifiers/append_range.cc: New test. * testsuite/23_containers/list/modifiers/assign/assign_range.cc: New test. * testsuite/23_containers/list/modifiers/insert/insert_range.cc: New test. * testsuite/23_containers/list/modifiers/prepend_range.cc: New test. --- Tested x86_64-linux. This is also available for review at: https://forge.sourceware.org/gcc/gcc-TEST/pulls/11/files libstdc++-v3/include/bits/forward_list.h | 121 + libstdc++-v3/include/bits/stl_list.h | 126 ++ .../forward_list/cons/from_range.cc | 100 ++ .../forward_list/modifiers/assign_range.cc| 97 ++ .../modifiers/insert_range_after.cc | 93 + .../forward_list/modifiers/prepend_range.cc | 86 .../23_containers/list/cons/from_range.cc | 100 ++ .../list/modifiers/append_range.cc| 86 .../list/modifiers/assign/assign_range.cc | 99 ++ .../list/modifiers/insert/insert_range.cc | 98 ++ .../list/modifiers/prepend_range.cc | 86 11 files changed, 1092 insertions(+) create mode 100644 libstdc++-v3/testsuite/23_containers/forward_list/cons/from_range.cc create mode 100644 libstdc++-v3/testsuite/23_containers/forward_list/modifiers/assign_range.cc create mode 100644 libstdc++-v3/testsuite/23_containers/forward_list/modifiers/insert_range_after.cc create mode 100644 libstdc++-v3/testsuite/23_containers/forward_list/modifiers/prepend_range.cc create mode 100644 libstdc++-v3/testsuite/23_containers/list/cons/from_range.cc create mode 100644 libstdc++-v3/testsuite/23_containers/list/modifiers/append_range.cc create mode 100644 libstdc++-v3/testsuite/23_containers/list/modifiers/assign/assign_range.cc create mode 100644 libstdc++-v3/testsuite/23_containers/list/modifiers/insert/insert_range.cc create mode 100644 libstdc++-v3/testsuite/23_containers/list/modifiers/prepend_range.cc diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h index eee773c0212..6ccf2eb2bff 100644 --- a/libstdc++-v3/include/bits/forward_list.h +++ b/libstdc++-v3/include/bits/forward_list.h @@ -42,6 +42,10 @@ #include #include #include +#if __glibcxx_ranges_to_container // C++ >= 23 +# include // ranges::begin, ranges::distance etc. +# include // ranges::subrange +#endif namespace std _GLIBCXX_VISIBILITY(default) { @@ -564,6 +568,30 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER : _Base(_Node_alloc_type(__al)) { _M_range_initialize(__first, __last); } +#if __glibcxx_ranges_to_container // C++ >= 23 + /** + * @brief Construct a forward_list from a range. + * @param __rg An input range with elements that are convertible to + * the forward_list's value_type. + * @param __a An allocator. + * + * @since C++23 + */ + template<__detail::__container_compatible_range<_Tp> _Rg> + forward_list(from_range_t, _Rg&& __rg, const _Alloc& __a = _Alloc()) + : _Base(_Node_alloc_type(__a)) + { + _Node_base* __to = &this->_M_impl._M_head; + auto __first = ranges::begin(__rg); + const auto __last = ranges::end(__rg); + for (; __first != __last; ++__first) + { + __to->_M_next = this->_M_create_node(*__first); + __to = __to->_M_next; + } + } +#endif // ranges_to_container + /** * @brief The %forward_list copy constructor. * @param __list A %forward_list of identical element and allocator @@ -675,6 +703,39 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_assign(__first, __last, __assignable()); } +#if __glibcxx_ranges_to_container // C++ >= 23 + /** + * @brief Assign a range to a forward_list. + * @since C++23 + */ + template<__detail::__container_compatible_range<_Tp> _Rg> + void + assign_range
[committed] libstdc++: Fix some typos and grammatical errors in docs
Also remove some redundant 'void' parameters from code examples. libstdc++-v3/ChangeLog: * doc/xml/manual/using_exceptions.xml: Fix typos and grammatical errors. * doc/html/manual/using_exceptions.html: Regenerate. --- Pushed to trunk. libstdc++-v3/doc/html/manual/using_exceptions.html | 12 ++-- libstdc++-v3/doc/xml/manual/using_exceptions.xml | 12 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libstdc++-v3/doc/html/manual/using_exceptions.html b/libstdc++-v3/doc/html/manual/using_exceptions.html index 706b27e1479..eb4501b1f6b 100644 --- a/libstdc++-v3/doc/html/manual/using_exceptions.html +++ b/libstdc++-v3/doc/html/manual/using_exceptions.html @@ -158,7 +158,7 @@ exception neutrality and exception safety. Doing without C++ is a language that strives to be as efficient as is possible in delivering features. As such, considerable care is used by both -language implementer and designers to make sure unused features +language implementer and designers to make sure unused features do not impose hidden or unexpected costs. The GNU system tries to be as flexible and as configurable as possible. So, it should come as no surprise that GNU C++ provides an optional language extension, @@ -166,7 +166,7 @@ exception neutrality and exception safety. implicitly generated magic necessary to support try and catch blocks and thrown objects. (Language support -for -fno-exceptions is documented in the GCC +for -fno-exceptions is documented in the GCC https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options"; target="_top">manual.) Before detailing the library support for -fno-exceptions, first a passing note on @@ -179,7 +179,7 @@ exception neutrality and exception safety. uses try or catch, you shouldn't use -fno-exceptions. -And what it to be gained, tinkering in the back alleys with a +And what is to be gained, tinkering in the back alleys with a language like this? Exception handling overhead can be measured in the size of the executable binary, and varies with the capabilities of the underlying operating system and specific @@ -216,15 +216,15 @@ exception neutrality and exception safety. # define __throw_exception_again #endif - In addition, for every object derived from + In addition, for most of the classes derived from class exception, there exists a corresponding function with C language linkage. An example: #if __cpp_exceptions - void __throw_bad_exception(void) + void __throw_bad_exception() { throw bad_exception(); } #else - void __throw_bad_exception(void) + void __throw_bad_exception() { abort(); } #endif diff --git a/libstdc++-v3/doc/xml/manual/using_exceptions.xml b/libstdc++-v3/doc/xml/manual/using_exceptions.xml index ab42c809939..ac2ba9dffd4 100644 --- a/libstdc++-v3/doc/xml/manual/using_exceptions.xml +++ b/libstdc++-v3/doc/xml/manual/using_exceptions.xml @@ -274,7 +274,7 @@ exception neutrality and exception safety. C++ is a language that strives to be as efficient as is possible in delivering features. As such, considerable care is used by both -language implementer and designers to make sure unused features +language implementer and designers to make sure unused features do not impose hidden or unexpected costs. The GNU system tries to be as flexible and as configurable as possible. So, it should come as no surprise that GNU C++ provides an optional language extension, @@ -282,7 +282,7 @@ exception neutrality and exception safety. implicitly generated magic necessary to support try and catch blocks and thrown objects. (Language support -for -fno-exceptions is documented in the GCC +for -fno-exceptions is documented in the GCC http://www.w3.org/1999/xlink"; xlink:href="https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options";>manual.) @@ -299,7 +299,7 @@ exception neutrality and exception safety. -And what it to be gained, tinkering in the back alleys with a +And what is to be gained, tinkering in the back alleys with a language like this? Exception handling overhead can be measured in the size of the executable binary, and varies with the capabilities of the underlying operating system and specific @@ -344,17 +344,17 @@ exception neutrality and exception safety. - In addition, for every object derived from + In addition, for most of the classes derived from class exception, there exists a corresponding function with C language linkage. An example: #if __cpp_exceptions - void __throw_bad_exception(void) + void __throw_bad_exception() { throw bad_exception(); } #else - void __throw_bad_exception(void) + void __throw_bad_exception() { abort(); } #endif -- 2.47.0
Re: [pushed: r15-4760] diagnostics: support multiple output formats simultaneously [PR116613]
On 29/10/24 19:19 -0400, David Malcolm wrote: This patch generalizes diagnostic_context so that rather than having a single output format, it has a vector of zero or more. [snip] +/* Class for parsing the arguments of -fdiagnostics-add-output= and + -fdiagnostics-set-output=, and making diagnostic_output_format + instances (or issuing errors). */ + +class output_factory +{ +public: + class handler + { + public: +handler (std::string name) : m_name (name) {} How long are these names? If they don't fit in 15 chars, then this should be std::move(name). So for a name like "sarif:version=2.1" it should be moved, otherwise you make a deep copy and reallocate a new string.
Re: [PATCH] libstdc++: Use if consteval rather than if (std::__is_constant_evaluated()) for {,b}float16_t nextafter [PR117321]
On Tue, 29 Oct 2024, 09:00 Jakub Jelinek, wrote: > Hi! > > The nextafter_c++23.cc testcase fails to link at -O0. > The problem is that eventhough std::__is_constant_evaluated() has > always_inline attribute, that at -O0 just means that we inline the > call, but its result is still assigned to a temporary which is tested > later, nothing at -O0 propagates that false into the if and optimizes > away the if body. And the __builtin_nextafterf16{,b} calls are meant > to be used solely for constant evaluation, the C libraries don't > define nextafterf16 these days. > > As __STDCPP_FLOAT16_T__ and __STDCPP_BFLOAT16_T__ are predefined right > now only by GCC, not by clang which doesn't implement the extended floating > point types paper, and as they are predefined in C++23 and later modes > only, > I think we can just use if consteval which is folded already during the FE > and the body isn't included even at -O0. I've added a feature test for > that just in case clang implements those and implements those in some weird > way. Note, if (__builtin_is_constant_evaluted()) would work correctly too, > that is also folded to false at gimplification time and the corresponding > if block not emitted at all. But for -O0 it can't be wrapped into a helper > inline function. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > OK, thanks > 2024-10-29 Jakub Jelinek > > PR libstdc++/117321 > * include/c_global/cmath (nextafter(_Float16, _Float16)): Use > if consteval rather than if (std::__is_constant_evaluated()) around > the __builtin_nextafterf16 call. > (nextafter(__gnu_cxx::__bfloat16_t, __gnu_cxx::__bfloat16_t)): Use > if consteval rather than if (std::__is_constant_evaluated()) around > the __builtin_nextafterf16b call. > * testsuite/26_numerics/headers/cmath/117321.cc: New test. > > --- libstdc++-v3/include/c_global/cmath.jj 2024-09-25 > 17:25:07.227360607 +0200 > +++ libstdc++-v3/include/c_global/cmath 2024-10-28 13:10:46.348655046 +0100 > @@ -2880,8 +2880,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >constexpr _Float16 >nextafter(_Float16 __x, _Float16 __y) >{ > -if (std::__is_constant_evaluated()) > - return __builtin_nextafterf16(__x, __y); > +#if __cpp_if_consteval >= 202106L > +// Can't use if (std::__is_constant_evaluated()) here, as it > +// doesn't guarantee optimizing the body away at -O0 and > +// nothing defines nextafterf16. > +if consteval { return __builtin_nextafterf16(__x, __y); } > +#endif > #ifdef __INT16_TYPE__ > using __float16_int_type = __INT16_TYPE__; > #else > @@ -3598,8 +3602,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION >constexpr __gnu_cxx::__bfloat16_t >nextafter(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y) >{ > -if (std::__is_constant_evaluated()) > - return __builtin_nextafterf16b(__x, __y); > +#if __cpp_if_consteval >= 202106L > +// Can't use if (std::__is_constant_evaluated()) here, as it > +// doesn't guarantee optimizing the body away at -O0 and > +// nothing defines nextafterf16b. > +if consteval { return __builtin_nextafterf16b(__x, __y); } > +#endif > #ifdef __INT16_TYPE__ > using __bfloat16_int_type = __INT16_TYPE__; > #else > --- libstdc++-v3/testsuite/26_numerics/headers/cmath/117321.cc.jj > 2024-10-28 12:56:10.699876240 +0100 > +++ libstdc++-v3/testsuite/26_numerics/headers/cmath/117321.cc 2024-10-28 > 12:56:59.875189173 +0100 > @@ -0,0 +1,5 @@ > +// { dg-do run { target c++23 } } > +// { dg-require-cmath "" } > +// { dg-additional-options "-O0" } > + > +#include "nextafter_c++23.cc" > > Jakub > >
Re: [PATCH] libstdc++: Fix complexity of drop_view::begin const [PR112641]
On Fri, 25 Oct 2024 at 16:24, Patrick Palka wrote: > > Tested on x86_64-pc-linux-gnu, does this look OK for trunk/backports? OK for all (also approved on the forge). > Also available in PR form at https://forge.sourceware.org/gcc/gcc-TEST/pulls/8 > > -- >8 -- > > Views are required to have a amortized O(1) begin(), but our drop_view's > const begin overload is O(n) for non-common ranges. This patch > reimplements it so that it's O(1) even in that case. See also LWG 4009. > > PR libstdc++/112641 > > libstdc++-v3/ChangeLog: > > * include/std/ranges (drop_view::begin const): Reimplement > so that it's O(1) instead of O(n) even in the non-common > range case. > * testsuite/std/ranges/adaptors/drop.cc (test10): New test. > --- > libstdc++-v3/include/std/ranges| 4 ++-- > libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc | 12 > 2 files changed, 14 insertions(+), 2 deletions(-) > > diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges > index cebe10683f9..743429dbcea 100644 > --- a/libstdc++-v3/include/std/ranges > +++ b/libstdc++-v3/include/std/ranges > @@ -2664,8 +2664,8 @@ namespace views::__adaptor >begin() const > requires random_access_range && sized_range >{ > - return ranges::next(ranges::begin(_M_base), _M_count, > - ranges::end(_M_base)); > + return ranges::begin(_M_base) + ranges::min(ranges::distance(_M_base), > + _M_count); >} > >constexpr auto > diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc > b/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc > index c9987c61e3c..0bd5bebb785 100644 > --- a/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc > +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc > @@ -274,6 +274,17 @@ test09() >static_assert(!requires { views::all | drop; }); > } > > +constexpr bool > +test10() > +{ > + // PR libstdc++/112641 - drop_view::begin const may have O(n) complexity > + const auto s = ranges::subrange(views::iota(size_t(1)), size_t(-1)); > + const auto r = ranges::drop_view(s, s.size() - 1); > + const auto b = r.begin(); // time out > + VERIFY( *b == size_t(-1) ); > + return true; > +} > + > int > main() > { > @@ -286,4 +297,5 @@ main() >test07(); >test08(); >test09(); > + static_assert(test10()); > } > -- > 2.47.0.118.gfd3785337b >
[committed] libstdc++: Fix tests for std::vector range operations
The commit I pushed was not the one I'd tested, so it had older versions of the tests, with bugs that I'd already fixed locally. This commit has the fixed tests that I'd intended to push in the first place. libstdc++-v3/ChangeLog: * testsuite/23_containers/vector/bool/cons/from_range.cc: Use dg-do run instead of compile. (test_ranges): Use do_test instead of do_test_a for rvalue range. (test_constexpr): Call function template instead of just instantiating it. * testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc: Use dg-do run instead of compile. (do_test): Use same test logic for vector as for primary template. (test_constexpr): Call function template instead of just instantiating it. * testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc: Use dg-do run instead of compile. (test_ranges): Use do_test instead of do_test_a for rvalue range. (test_constexpr): Call function template instead of just instantiating it. * testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc: Use dg-do run instead of compile. (do_test): Fix incorrect function arguments to match intended results. (test_ranges): Use do_test instead of do_test_a for rvalue range. (test_constexpr): Call function template instead of just instantiating it. * testsuite/23_containers/vector/cons/from_range.cc: Use dg-do run instead of compile. (test_ranges): Fix ill-formed call to do_test. (test_constexpr): Call function template instead of just instantiating it. * testsuite/23_containers/vector/modifiers/append_range.cc: Use dg-do run instead of compile. (test_constexpr): Likewise. * testsuite/23_containers/vector/modifiers/assign/assign_range.cc: Use dg-do run instead of compile. (do_test): Do not reuse input ranges. (test_constexpr): Call function template instead of just instantiating it. * testsuite/23_containers/vector/modifiers/insert/insert_range.cc: Use dg-do run instead of compile. (do_test): Fix incorrect function arguments to match intended results. (test_constexpr): Call function template instead of just instantiating it. --- Tested x86_64-linux. Pushed to trunk. .../vector/bool/cons/from_range.cc| 6 ++-- .../bool/modifiers/assign/assign_range.cc | 30 --- .../bool/modifiers/insert/append_range.cc | 6 ++-- .../bool/modifiers/insert/insert_range.cc | 10 +++ .../23_containers/vector/cons/from_range.cc | 6 ++-- .../vector/modifiers/append_range.cc | 4 +-- .../vector/modifiers/assign/assign_range.cc | 25 +++- .../vector/modifiers/insert/insert_range.cc | 8 ++--- 8 files changed, 50 insertions(+), 45 deletions(-) diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc index f5180e5a243..f531e7f5039 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc @@ -1,4 +1,4 @@ -// { dg-do compile { target c++23 } } +// { dg-do run { target c++23 } } #include #include @@ -71,7 +71,7 @@ test_ranges() bool val; }; using rvalue_input_range = test_range; - do_test_a(); + do_test(std::allocator()); return true; } @@ -80,7 +80,7 @@ constexpr bool test_constexpr() { // XXX: this doesn't test the non-forward_range code paths are constexpr. - do_test, std::allocator>; + do_test>(std::allocator()); return true; } diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc index a014dfe90de..7e58700ff2b 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc @@ -1,4 +1,4 @@ -// { dg-do compile { target c++23 } } +// { dg-do run { target c++23 } } #include #include @@ -22,29 +22,37 @@ do_test() return true; }; - Range r4(a, a+4); - Range r9(a); - + // assign to empty vector std::vector v; v.assign_range(Range(a, a)); VERIFY( v.empty() ); VERIFY( v.capacity() == 0 ); - v.assign_range(r4); + v.assign_range(Range(a, a+4)); VERIFY( eq(v, {a, 4}) ); v.clear(); - v.assign_range(r9); // larger than v.capacity() + v.assign_range(Range(a)); // larger than v.capacity() VERIFY( eq(v, a) ); - v.assign_range(r9); // equal to size() and equal to capacity() + v.clear(); + v.assign_range(Range(a, a+4)); // smaller than v.capacity() + VERIFY( eq(v, {a, 4}) ); + v.clear(); +
[committed] libstdc++: Fix std::vector::emplace to forward parameter
If the parameter is not lvalue-convertible to bool then the current code will fail to compile. The parameter should be forwarded to restore the original value category. libstdc++-v3/ChangeLog: * include/bits/stl_bvector.h (emplace_back, emplace): Forward parameter pack to preserve value category. * testsuite/23_containers/vector/bool/emplace_rvalue.cc: New test. --- Tested x86_64-linux. Pushed to trunk. libstdc++-v3/include/bits/stl_bvector.h | 4 ++-- .../vector/bool/emplace_rvalue.cc | 24 +++ 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/vector/bool/emplace_rvalue.cc diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h index 42261ac5915..70f69b5b5b5 100644 --- a/libstdc++-v3/include/bits/stl_bvector.h +++ b/libstdc++-v3/include/bits/stl_bvector.h @@ -1343,7 +1343,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER #endif emplace_back(_Args&&... __args) { - push_back(bool(__args...)); + push_back(bool(std::forward<_Args>(__args)...)); #if __cplusplus > 201402L return back(); #endif @@ -1353,7 +1353,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _GLIBCXX20_CONSTEXPR iterator emplace(const_iterator __pos, _Args&&... __args) - { return insert(__pos, bool(__args...)); } + { return insert(__pos, bool(std::forward<_Args>(__args)...)); } #endif protected: diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/emplace_rvalue.cc b/libstdc++-v3/testsuite/23_containers/vector/bool/emplace_rvalue.cc new file mode 100644 index 000..5dea2426d60 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/vector/bool/emplace_rvalue.cc @@ -0,0 +1,24 @@ +// { dg-do compile { target c++11 } } + +#include + +struct S +{ + explicit operator bool() &&; +}; + +void +test_emplace_back() +{ + S s; + std::vector v; + v.emplace_back(std::move(s)); +} + +void +test_emplace() +{ + S s; + std::vector v; + v.emplace(v.begin(), std::move(s)); +} -- 2.47.0
Re: [PATCH] Fix tab after space in leading whitespace
On Fri, 25 Oct 2024 at 12:10, Jakub Jelinek wrote: > > Hi! > > The following patch fixes 2 -Wleading-whitespace=blanks issues in gcc/, > include/, libiberty/, libcpp/, libgcc/ and libstdc++-v3/ > One is the > ../../gcc/c/c-typeck.cc:196:1: warning: whitespace other than spaces and tabs > in leading whitespace [-Wleading-whitespace=] > case (where there was a form-feed immediately followed by a comment > rather than having a new-line separating it) and then tons of > warning: tab after space in leading whitespace [-Wleading-whitespace=] > warnings. For the latter I've used > find -name \*.h -o -name \*.c -o -name \*.cc | grep -v testsuite/ | grep -v > gofrontend/ | xargs grep -l '^[ ]* ' > to find affected files (also left out the m2 'do not edit' files) and in an > editor searched for the same regex and fixed up manually. > > xz compressed patch attached, followed by -ubp diff which shows that > a few changes beyond just space removal or replacement by tab were done > while I was at it, but only very few. > > Ok for trunk if this passes bootstrap/regtest? The libstdc++-v3 parts are all OK, thanks. > libstdc++-v3/ > * config/locale/dragonfly/numeric_members.cc: Fix space after tab > issues in leading whitespace. > * config/locale/dragonfly/time_members.cc: Likewise. > * include/parallel/unique_copy.h: Likewise. > * include/parallel/partition.h: Likewise. > * include/parallel/random_shuffle.h: Likewise. > * include/parallel/losertree.h: Likewise. > * include/parallel/set_operations.h: Likewise. > * include/parallel/multiway_merge.h: Likewise. > * include/parallel/balanced_quicksort.h: Likewise. > * include/bits/streambuf_iterator.h: Likewise. > * include/bits/unordered_set.h: Likewise. > * include/bits/stl_vector.h: Likewise. > * include/bits/uses_allocator.h: Likewise. > * include/tr1/hashtable.h: Likewise. > * include/ext/rc_string_base.h: Likewise. > * src/c++98/mt_allocator.cc: Likewise. > * src/c++11/limits.cc: Likewise.
Re: [PATCH] Replace 8 consecutive spaces in leading whitespace by tab
On Fri, 25 Oct 2024 at 12:17, Jakub Jelinek wrote: > > Hi! > > On top of the previously posted leading whitespace patch, this change > just replaces 8 consecutive spaces in leading whitespace by tab. > The patch is too large (1MB xz -9e compressed), so I'm not even trying to > split it up into 4+ pieces to fit under the mailing list limits. > But the change was done purely by a script, > for i in `find gcc -name \*.h -o -name \*.cc -o -name \*.c | grep -v > testsuite/ | grep -v gofrontend/`; do grep -l '^[ ]*' $i; done > > /tmp/2 > grep -L 'do not edit' `cat /tmp/2` > /tmp/3 > for i in `find include lib{iberty,gcc,cpp,stdc++-v3} -name \*.h -o -name > \*.cc -o -name \*.c | grep -v testsuite/ | grep -v gofrontend/`; do grep -l > '^[]*' $i; done >> /tmp/3 > for j in `seq 32`; do for i in `cat /tmp/3`; do sed -i -e 's/^\(\t*\) > /\1\t/g' $i; done; done > diff -upb yields nothing. > > Ok for trunk if this passes bootstrap/regtest? > > 2024-10-25 Jakub Jelinek > > libstdc++-v3/ > * doc/doxygen/stdheader.cc: Replace 8 spaces with tab in leading > whitespace. > * config/os/aix/ctype_inline.h: Likewise. > * config/locale/newlib/ctype_members.cc: Likewise. > * config/locale/dragonfly/monetary_members.cc: Likewise. > * config/locale/dragonfly/ctype_members.cc: Likewise. > * config/locale/gnu/monetary_members.cc: Likewise. > * config/locale/gnu/ctype_members.cc: Likewise. > * config/locale/generic/ctype_members.cc: Likewise. > * config/locale/darwin/ctype_members.cc: Likewise. > * config/cpu/i486/opt/bits/opt_random.h: Likewise. > * include/debug/functions.h: Likewise. > * include/debug/map.h: Likewise. > * include/debug/formatter.h: Likewise. > * include/debug/safe_iterator.h: Likewise. > * include/parallel/types.h: Likewise. > * include/parallel/sort.h: Likewise. > * include/parallel/algorithmfwd.h: Likewise. > * include/parallel/numericfwd.h: Likewise. > * include/parallel/unique_copy.h: Likewise. > * include/parallel/for_each.h: Likewise. > * include/parallel/partition.h: Likewise. > * include/parallel/multiway_merge.h: Likewise. > * include/parallel/losertree.h: Likewise. > * include/parallel/queue.h: Likewise. > * include/parallel/workstealing.h: Likewise. > * include/parallel/tags.h: Likewise. > * include/parallel/omp_loop_static.h: Likewise. > * include/parallel/partial_sum.h: Likewise. > * include/parallel/list_partition.h: Likewise. > * include/parallel/iterator.h: Likewise. > * include/parallel/set_operations.h: Likewise. > * include/parallel/equally_split.h: Likewise. > * include/parallel/multiway_mergesort.h: Likewise. > * include/parallel/random_shuffle.h: Likewise. > * include/parallel/base.h: Likewise. > * include/parallel/omp_loop.h: Likewise. > * include/parallel/settings.h: Likewise. > * include/parallel/algobase.h: Likewise. > * include/parallel/checkers.h: Likewise. > * include/parallel/find.h: Likewise. > * include/parallel/for_each_selectors.h: Likewise. > * include/parallel/search.h: Likewise. > * include/parallel/multiseq_selection.h: Likewise. > * include/parallel/merge.h: Likewise. > * include/parallel/random_number.h: Likewise. > * include/parallel/quicksort.h: Likewise. > * include/parallel/find_selectors.h: Likewise. > * include/parallel/balanced_quicksort.h: Likewise. > * include/bits/random.h: Likewise. > * include/bits/stl_construct.h: Likewise. > * include/bits/valarray_after.h: Likewise. > * include/bits/stl_uninitialized.h: Likewise. > * include/bits/shared_ptr_base.h: Likewise. > * include/bits/unique_ptr.h: Likewise. > * include/bits/stl_pair.h: Likewise. > * include/bits/stringfwd.h: Likewise. > * include/bits/stl_iterator.h: Likewise. > * include/bits/atomic_base.h: Likewise. > * include/bits/valarray_array.h: Likewise. > * include/bits/stl_vector.h: Likewise. > * include/bits/fs_dir.h: Likewise. > * include/bits/shared_ptr.h: Likewise. > * include/bits/char_traits.h: Likewise. > * include/bits/stream_iterator.h: Likewise. > * include/bits/predefined_ops.h: Likewise. > * include/bits/basic_string.h: Likewise. > * include/bits/concept_check.h: Likewise. > * include/bits/stl_iterator_base_types.h: Likewise. > * include/bits/enable_special_members.h: Likewise. > * include/bits/locale_classes.h: Likewise. > * include/bits/stl_tempbuf.h: Likewise. > * include/bits/ptr_traits.h: Likewise. > * include/bits/stl_algo.h: Likewise. > * include/bits/stl_functio
Re: [PATCH] Replace 8 consecutive spaces in leading whitespace by tab
On Fri, 25 Oct 2024 at 12:54, Jakub Jelinek wrote: > > On Fri, Oct 25, 2024 at 01:25:25PM +0200, Arsen Arsenović wrote: > > Maybe we should go the other way around? Compressing eight spaces into > > a tab leads to strange artifacts in diffs (where lines appear > > misindented because some were aligned by tabs and some by spaces), and > > nowadays editor authors seem to have forgotten tabs are eight spaces and > > instead default to (or, worse, hard-code) four, obviously making the > > codebase quite unreadable. We also don't get the benefit of being able > > to adjust tabstop locally to our preferences when we use two-column > > indentation, so I don't see an advantage to keeping 'indent-tabs-mode > > (or equivalent in other editors) enabled. > > Editors which are worth a dime handle tabs fine, and I think using tabs is > better. And if we put a .editorconfig file at the top level, then most decent editors will be auto-configured as we want. And we can tease people who use bad editors that ignore .editorconfig ;-)
Re: [PATCH v4] libstdc++: implement concatenation of strings and string_views
On Sun, 13 Oct 2024 at 18:59, Giuseppe D'Angelo wrote: > > Hello, > > On 09/10/2024 22:39, Patrick Palka wrote: > >> +#if __glibcxx_string_view >= 202403L > >> + // const string & + string_view > >> + template > >> +[[nodiscard]] > >> +constexpr inline basic_string<_CharT, _Traits, _Alloc> > > > > Redundant 'inline's > > > >> +operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, > >> + type_identity_t> __rhs) > >> +{ > >> + typedef basic_string<_CharT, _Traits, _Alloc> _Str; > > > > These typedefs might as well be usings instead > > > > Besides that LGTM! > > Thank you for the review, updated patch attached to fix both of these. > (Just for the record, these had been C&P from the corresponding > operator+ overloads that deal with const char *.) Those are from C++98 though, so the 'constexpr' is conditional and so the 'inline' is not redundant. I'm going to push your patch in the morning, with one tiny fix for the COW std::string (which isn't usable in constexpr). See attached. Thanks for implementing this. commit 97a03ae904150a65dd2cf41816fed94c283e21b1 Author: Jonathan Wakely Date: Thu Oct 24 20:12:08 2024 libstdc++: Disable parts of new test that depend on constexpr std::string The compile-time assertions don't work with -D_GLIBCXX_USE_CXX11_ABI=0. libstdc++-v3/ChangeLog: * testsuite/21_strings/basic_string/operators/char/op_plus_string_view.cc: Check __cpp_lib_constexpr_string. diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view.cc b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view.cc index 364d5bd5aba..2d474519f60 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view.cc @@ -44,6 +44,7 @@ struct convertible_to_lots constexpr operator std::string() const { return "convertible_to_lots3"; } }; +#if __cpp_lib_constexpr_string >= 201907 // constexpr std::string using namespace std::literals; static_assert( "costa "s + "marbella"sv == "costa marbella"s ); static_assert( "costa "sv + "marbella"s == "costa marbella"s ); @@ -52,6 +53,7 @@ static_assert( "costa "s + convertible_to_string_view2{} == "costa convertible_t static_assert( "costa "s + convertible_to_string_view3{} == "costa convertible_to_sv3 non_const"s ); static_assert( "costa "s + convertible_to_string_view_and_char_star{} == "costa convertible_to_sv_and_charstar1"s ); static_assert( "costa "s + convertible_to_lots{} == "costa convertible_to_lots1"s ); +#endif // __cpp_lib_constexpr_string void test01()
[PATCH 1/3] libstdc++: Fix typos in tests using macros for std::float128_t support
These tests check `_GLIBCXX_DOUBLE_IS_IEEE_BINARY128` but that's never defined, it should be "LDOUBLE" not "DOUBLE". libstdc++-v3/ChangeLog: * testsuite/26_numerics/complex/ext_c++23.cc: Fix typo in macro. * testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc: Likewise. * testsuite/26_numerics/headers/cmath/functions_std_c++23.cc: Likewise. * testsuite/26_numerics/headers/cmath/nextafter_c++23.cc: Likewise. --- This first patch is an obvious fix for a typo, but tests still pass after fixing it, which is reassuring! I'll push it shortly. Tested powerpc64le-linux. libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc | 2 +- .../testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc | 2 +- .../testsuite/26_numerics/headers/cmath/functions_std_c++23.cc | 2 +- .../testsuite/26_numerics/headers/cmath/nextafter_c++23.cc | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc b/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc index 0fc3d6f1a66..5f4ff06448e 100644 --- a/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc +++ b/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc @@ -70,7 +70,7 @@ main() } #endif #if defined(__STDCPP_FLOAT128_T__) \ -&& (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \ +&& (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \ || defined(_GLIBCXX_HAVE_FLOAT128_MATH)) { std::float128_t p[2] = {}; diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc b/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc index 3c2377fd698..983027ff654 100644 --- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc +++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc @@ -119,7 +119,7 @@ main() test_functions(); #endif #if defined(__STDCPP_FLOAT128_T__) \ -&& (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \ +&& (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \ || defined(_GLIBCXX_HAVE_FLOAT128_MATH)) test_functions(); #endif diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc b/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc index ea68ac5da75..bf07493ecd4 100644 --- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc +++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc @@ -131,7 +131,7 @@ main() } #endif #if defined(__STDCPP_FLOAT128_T__) \ -&& (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \ +&& (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \ || defined(_GLIBCXX_HAVE_FLOAT128_MATH)) { std::float128_t p[128] = {}; diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc b/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc index 91767d22cc3..2d0f8017f4a 100644 --- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc +++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc @@ -117,7 +117,7 @@ main () test (); #endif #if defined(__STDCPP_FLOAT128_T__) \ -&& (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \ +&& (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \ || defined(_GLIBCXX_HAVE_FLOAT128_MATH)) test (); #endif -- 2.47.0
Re: [PATCH] libstdc++: Add P1206R7 from_range members to std::vector [PR111055]
On Thu, 24 Oct 2024 at 16:00, Jonathan Wakely wrote: > > This is another piece of P1206R7, adding new members to std::vector and > std::vector. > > The __uninitialized_copy_a extension needs to be enhanced to support > passing non-common ranges (i.e. a sentinel that is a different type from > the iterator) and move-only input iterators. I forgot to say that this patch is also available at https://forge.sourceware.org/gcc/gcc-TEST/pulls/5 > > libstdc++-v3/ChangeLog: > > PR libstdc++/111055 > * include/bits/ranges_base.h (__container_compatible_range): New > concept. > * include/bits/stl_bvector.h (vector(from_range, R&&, const Alloc&)) > (assign_range, insert_range, append_range): Define. > * include/bits/stl_uninitialized.h (__do_uninit_copy): Support > non-common ranges. > (__uninitialized_copy_a): Likewise. > * include/bits/stl_vector.h (_Vector_base::_M_append_range_to): > New function. > (_Vector_base::_M_append_range): Likewise. > (vector(from_range, R&&, const Alloc&), assign_range): Define. > (append_range): Define. > (insert_range): Declare. > * include/debug/vector (vector(from_range, R&&, const Alloc&)) > (assign_range, insert_range, append_range): Define. > * include/bits/vector.tcc (insert_range): Define. > * testsuite/23_containers/vector/bool/cons/from_range.cc: New test. > * > testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc: > New test. > * > testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc: > New test. > * > testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc: > New test. > * testsuite/23_containers/vector/cons/from_range.cc: New test. > * testsuite/23_containers/vector/modifiers/append_range.cc: New test. > * testsuite/23_containers/vector/modifiers/assign/assign_range.cc: > New test. > * testsuite/23_containers/vector/modifiers/insert/insert_range.cc: > New test. > --- > Tested x86_64-linux. > > libstdc++-v3/include/bits/ranges_base.h | 10 ++ > libstdc++-v3/include/bits/stl_bvector.h | 120 + > libstdc++-v3/include/bits/stl_uninitialized.h | 38 +++- > libstdc++-v3/include/bits/stl_vector.h| 166 ++ > libstdc++-v3/include/bits/vector.tcc | 124 + > libstdc++-v3/include/debug/vector | 70 > .../vector/bool/cons/from_range.cc| 81 + > .../bool/modifiers/assign/assign_range.cc | 96 ++ > .../bool/modifiers/insert/append_range.cc | 83 + > .../bool/modifiers/insert/insert_range.cc | 94 ++ > .../23_containers/vector/cons/from_range.cc | 94 ++ > .../vector/modifiers/append_range.cc | 83 + > .../vector/modifiers/assign/assign_range.cc | 107 +++ > .../vector/modifiers/insert/insert_range.cc | 94 ++ > 14 files changed, 1252 insertions(+), 8 deletions(-) > create mode 100644 > libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc > create mode 100644 > libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc > create mode 100644 > libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc > create mode 100644 > libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc > create mode 100644 > libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc > create mode 100644 > libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc > create mode 100644 > libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc > create mode 100644 > libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc > > diff --git a/libstdc++-v3/include/bits/ranges_base.h > b/libstdc++-v3/include/bits/ranges_base.h > index cb2eba1f841..a2c743ff56b 100644 > --- a/libstdc++-v3/include/bits/ranges_base.h > +++ b/libstdc++-v3/include/bits/ranges_base.h > @@ -1079,6 +1079,16 @@ namespace ranges > #if __glibcxx_ranges_to_container // C++ >= 23 >struct from_range_t { explicit from_range_t() = default; }; >inline constexpr from_range_t from_range{}; > + > +/// @cond undocumented > +namespace __detail > +{ > + template > +concept __container_compatible_range > + = ranges::input_range<_Rg> > + && convertible_to, _Tp>; > +} > +/// @endcond > #endif > > _GLIBCXX_END_NAMESPACE_VERSION > diff -
[PATCH 2/3] libstdc++: Define __memcpyable as true
This allows optimizing copying ranges of floating-point types when they have the same size and representation, e.g. between _Float32 and float when we know that float uses the same IEEE binary32 format as _Float32. On some targets double and long double both use IEEE binary64 format so we could enable memcpy between those types, but we don't have existing macros to check for that case. libstdc++-v3/ChangeLog: * include/bits/cpp_type_traits.h (__memcpyable): Add specializations for compatible floating-point types. --- Tested powerpc64le-linux. libstdc++-v3/include/bits/cpp_type_traits.h | 23 + 1 file changed, 23 insertions(+) diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h index 2f9ce75e82c..e412f8d0770 100644 --- a/libstdc++-v3/include/bits/cpp_type_traits.h +++ b/libstdc++-v3/include/bits/cpp_type_traits.h @@ -472,6 +472,8 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3) template struct __memcpyable_integer; // For heterogeneous types, allow memcpy between equal-sized integers. + // N.B. we cannot do the same for equal-sized enums, they're not assignable. + // We cannot do it for pointers, because derived-to-base can adjust offset. template struct __memcpyable<_Tp*, _Up*> { @@ -554,6 +556,27 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3) struct __memcpyable_integer { enum { __width = 128 }; }; #endif +#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) + template<> +struct __memcpyable<_Float32*, float*> { enum { __value = true }; }; + template<> +struct __memcpyable { enum { __value = true }; }; +#endif + +#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64) + template<> +struct __memcpyable<_Float64*, double*> { enum { __value = true }; }; + template<> +struct __memcpyable { enum { __value = true }; }; +#endif + +#if defined(__STDCPP_FLOAT128_T__) && defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) + template<> +struct __memcpyable<_Float128*, long double*> { enum { __value = true }; }; + template<> +struct __memcpyable { enum { __value = true }; }; +#endif + // Whether two iterator types can be used with memcmp. // This trait only says it's well-formed to use memcmp, not that it // gives the right answer for a given algorithm. So for example, std::equal -- 2.47.0
[PATCH 3/3] libstdc++: Define config macros for additional IEEE formats
Some targets use IEEE binary64 for both double and long double, which means we could use memmove to optimize a std::copy from a range of double to a range of long double. We currently have no config macro to detect when long double is binary64, so add that to . This also adds config macros for the case where double and long double both use the same binary32 format as float, which is true for the avr target. No specializations of __memcpyable for that case are added by this patch, but they could be added later. libstdc++-v3/ChangeLog: * include/bits/c++config (_GLIBCXX_DOUBLE_IS_IEEE_BINARY32): Define. (_GLIBCXX_LDOUBLE_IS_IEEE_BINARY64): Define. (_GLIBCXX_LDOUBLE_IS_IEEE_BINARY32): Define. * include/bits/cpp_type_traits.h (__memcpyable): Define specializations when double and long double are compatible. --- Tested powerpc64le-linux. libstdc++-v3/include/bits/c++config | 21 ++--- libstdc++-v3/include/bits/cpp_type_traits.h | 7 +++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index b87a3527f24..1076803a865 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -836,25 +836,40 @@ namespace std # endif #endif -// Define if float has the IEEE binary32 format. #if __FLT_MANT_DIG__ == 24 \ && __FLT_MIN_EXP__ == -125 \ && __FLT_MAX_EXP__ == 128 +// Define if float has the IEEE binary32 format. # define _GLIBCXX_FLOAT_IS_IEEE_BINARY32 1 #endif -// Define if double has the IEEE binary64 format. #if __DBL_MANT_DIG__ == 53 \ && __DBL_MIN_EXP__ == -1021 \ && __DBL_MAX_EXP__ == 1024 +// Define if double has the IEEE binary64 format. # define _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 1 +#elif __FLT_MANT_DIG__ == 24 \ + && __FLT_MIN_EXP__ == -125 \ + && __FLT_MAX_EXP__ == 128 +// Define if double has the IEEE binary32 format. +# define _GLIBCXX_DOUBLE_IS_IEEE_BINARY32 1 #endif -// Define if long double has the IEEE binary128 format. #if __LDBL_MANT_DIG__ == 113 \ && __LDBL_MIN_EXP__ == -16381 \ && __LDBL_MAX_EXP__ == 16384 +// Define if long double has the IEEE binary128 format. # define _GLIBCXX_LDOUBLE_IS_IEEE_BINARY128 1 +#elif __LDBL_MANT_DIG__ == 53 \ + && __LDBL_MIN_EXP__ == -1021 \ + && __LDBL_MAX_EXP__ == 1024 +// Define if long double has the IEEE binary64 format. +# define _GLIBCXX_LDOUBLE_IS_IEEE_BINARY64 1 +#elif __LDBL_MANT_DIG__ == 24 \ + && __LDBL_MIN_EXP__ == -125 \ + && __LDBL_MAX_EXP__ == 128 +// Define if long double has the IEEE binary32 format. +# define _GLIBCXX_LDOUBLE_IS_IEEE_BINARY32 1 #endif #if defined __cplusplus && defined __BFLT16_DIG__ diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h b/libstdc++-v3/include/bits/cpp_type_traits.h index e412f8d0770..e5a5efece42 100644 --- a/libstdc++-v3/include/bits/cpp_type_traits.h +++ b/libstdc++-v3/include/bits/cpp_type_traits.h @@ -556,6 +556,13 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3) struct __memcpyable_integer { enum { __width = 128 }; }; #endif +#if _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 && _GLIBCXX_LDOUBLE_IS_IEEE_BINARY64 + template<> +struct __memcpyable { enum { __value = true }; }; + template<> +struct __memcpyable { enum { __value = true }; }; +#endif + #if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32) template<> struct __memcpyable<_Float32*, float*> { enum { __value = true }; }; -- 2.47.0
Re: [PATCH] libstdc++: Implement P0849R8 auto(x) library changes
On Wed, 9 Oct 2024 at 14:02, Patrick Palka wrote: > > On Mon, 7 Oct 2024, Patrick Palka wrote: > > > Tested on x86_64-pc-linux-gnu, does this look OK for trunk only? > > This doesn't seem worth backporting since there should be no > > behavior change. > > > > -- >8 -- > > > > This implements the library changes in P0849R8 "auto(x): decay-copy > > in the language" which consist of replacing most uses of the > > exposition-only function decay-copy with auto(x) throughout the library > > wording. > > > > Note the main difference between the two is that decay-copy materializes > > its argument whereas auto(x) doesn't, and so the latter is a no-op when > > its argument is a prvalue. Effectively the former could introduce an > > unnecessary move constructor call in some contexts. In C++20 and earlier > > we could emulate auto(x) with decay_t(x). > > I should note this patch is treating this paper as a DR against C++20, > which should be fine since there should be no behavior change in > practice (especially in light of LWG 3724 which constrains decay-copy > to make it SFINAE-friendly). Yes, that seems fine. OK for trunk, thanks. > > > > > After this paper the only remaining uses of decay-copy in the library > > are in the specification of some range adaptors. In our implementation > > of those range adaptors I believe decay-copy is already implied which > > is why we don't mirror the wording and use __decay_copy explicitly. So > > since it's apparently no longer needed this patch goes ahead and removes > > __decay_copy. > > > > libstdc++-v3/ChangeLog: > > > > * c++config (_GLIBCXX_AUTO_CAST): Define. > > * include/bits/iterator_concepts.h (_Decay_copy, __decay_copy): > > Remove. > > (__member_begin, __adl_begin): Use _GLIBCXX_AUTO_CAST instead of > > __decay_copy as per P0849R8. > > * include/bits/ranges_base.h (_Begin): Likewise. > > (__member_end, __adl_end, _End): Likewise. > > (__member_rbegin, __adl_rbegin, _RBegin): Likewise. > > (__member_rend, __adl_rend, _Rend): Likewise. > > (__member_size, __adl_size, _Size): Likewise. > > (_Data): Likewise. > > --- > > libstdc++-v3/include/bits/c++config | 6 +++ > > libstdc++-v3/include/bits/iterator_concepts.h | 13 +- > > libstdc++-v3/include/bits/ranges_base.h | 40 +-- > > 3 files changed, 28 insertions(+), 31 deletions(-) > > > > diff --git a/libstdc++-v3/include/bits/c++config > > b/libstdc++-v3/include/bits/c++config > > index 29d795f687c..fdbf90e28fc 100644 > > --- a/libstdc++-v3/include/bits/c++config > > +++ b/libstdc++-v3/include/bits/c++config > > @@ -265,6 +265,12 @@ > > #define _GLIBCXX_NOEXCEPT_QUAL > > #endif > > > > +#if __cpp_auto_cast > > +# define _GLIBCXX_AUTO_CAST(X) auto(X) > > +#else > > +# define _GLIBCXX_AUTO_CAST(X) ::std::__decay_t(X) > > +#endif > > + > > // Macro for extern template, ie controlling template linkage via use > > // of extern keyword on template declaration. As documented in the g++ > > // manual, it inhibits all implicit instantiations and is used > > diff --git a/libstdc++-v3/include/bits/iterator_concepts.h > > b/libstdc++-v3/include/bits/iterator_concepts.h > > index 490a362cdf1..0fcfed56737 100644 > > --- a/libstdc++-v3/include/bits/iterator_concepts.h > > +++ b/libstdc++-v3/include/bits/iterator_concepts.h > > @@ -1003,19 +1003,10 @@ namespace ranges > >{ > > using std::__detail::__class_or_enum; > > > > -struct _Decay_copy final > > -{ > > - template > > - constexpr decay_t<_Tp> > > - operator()(_Tp&& __t) const > > - noexcept(is_nothrow_convertible_v<_Tp, decay_t<_Tp>>) > > - { return std::forward<_Tp>(__t); } > > -} inline constexpr __decay_copy{}; > > - > > template > >concept __member_begin = requires(_Tp& __t) > > { > > - { __decay_copy(__t.begin()) } -> input_or_output_iterator; > > + { _GLIBCXX_AUTO_CAST(__t.begin()) } -> input_or_output_iterator; > > }; > > > > // Poison pill so that unqualified lookup doesn't find std::begin. > > @@ -1025,7 +1016,7 @@ namespace ranges > >concept __adl_begin = __class_or_enum> > > && requires(_Tp& __t) > > { > > - { __decay_copy(begin(__t)) } -> input_or_output_iterator; > > + { _GLIBCXX_AUTO_CAST(begin(__t)) } -> input_or_output_iterator; > > }; > > > > // Simplified version of std::ranges::begin that only supports lvalues, > > diff --git a/libstdc++-v3/include/bits/ranges_base.h > > b/libstdc++-v3/include/bits/ranges_base.h > > index cb2eba1f841..80ff1e300ce 100644 > > --- a/libstdc++-v3/include/bits/ranges_base.h > > +++ b/libstdc++-v3/include/bits/ranges_base.h > > @@ -115,9 +115,9 @@ namespace ranges > > if constexpr (is_array_v>) > > return true; > > else if constexpr (__member_begin<_Tp>) > > - return noexcept(__decay_copy(std::declval<_Tp&>().begin())); > > + return noexcept(_GLIBCX
Re: [PATCH 1/3] libstdc++: Fix typos in tests using macros for std::float128_t support
On Thu, 24 Oct 2024 at 15:45, Jonathan Wakely wrote: > > These tests check `_GLIBCXX_DOUBLE_IS_IEEE_BINARY128` but that's never > defined, it should be "LDOUBLE" not "DOUBLE". > > libstdc++-v3/ChangeLog: > > * testsuite/26_numerics/complex/ext_c++23.cc: Fix typo in macro. > * testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc: > Likewise. > * testsuite/26_numerics/headers/cmath/functions_std_c++23.cc: > Likewise. > * testsuite/26_numerics/headers/cmath/nextafter_c++23.cc: > Likewise. > --- > This first patch is an obvious fix for a typo, but tests still pass > after fixing it, which is reassuring! > > I'll push it shortly. PATCH 1/3 is now pushed. The patch series is also available at https://forge.sourceware.org/gcc/gcc-TEST/pulls/6/files > > Tested powerpc64le-linux. > > libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc | 2 +- > .../testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc | 2 +- > .../testsuite/26_numerics/headers/cmath/functions_std_c++23.cc | 2 +- > .../testsuite/26_numerics/headers/cmath/nextafter_c++23.cc | 2 +- > 4 files changed, 4 insertions(+), 4 deletions(-) > > diff --git a/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc > b/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc > index 0fc3d6f1a66..5f4ff06448e 100644 > --- a/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc > +++ b/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc > @@ -70,7 +70,7 @@ main() >} > #endif > #if defined(__STDCPP_FLOAT128_T__) \ > -&& (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \ > +&& (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \ > || defined(_GLIBCXX_HAVE_FLOAT128_MATH)) >{ > std::float128_t p[2] = {}; > diff --git > a/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc > b/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc > index 3c2377fd698..983027ff654 100644 > --- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc > +++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc > @@ -119,7 +119,7 @@ main() >test_functions(); > #endif > #if defined(__STDCPP_FLOAT128_T__) \ > -&& (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \ > +&& (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \ > || defined(_GLIBCXX_HAVE_FLOAT128_MATH)) >test_functions(); > #endif > diff --git > a/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc > b/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc > index ea68ac5da75..bf07493ecd4 100644 > --- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc > +++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc > @@ -131,7 +131,7 @@ main() >} > #endif > #if defined(__STDCPP_FLOAT128_T__) \ > -&& (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \ > +&& (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \ > || defined(_GLIBCXX_HAVE_FLOAT128_MATH)) >{ > std::float128_t p[128] = {}; > diff --git > a/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc > b/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc > index 91767d22cc3..2d0f8017f4a 100644 > --- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc > +++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc > @@ -117,7 +117,7 @@ main () >test (); > #endif > #if defined(__STDCPP_FLOAT128_T__) \ > -&& (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \ > +&& (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \ > || defined(_GLIBCXX_HAVE_FLOAT128_MATH)) >test (); > #endif > -- > 2.47.0 >
[committed v2] libstdc++: Simplify std::__throw_bad_variant_access
This removes the overload of __throw_bad_variant_access that must be called with a string literal. This avoids a potential source of undefined behaviour if that function got misused. The other overload that takes a bool parameter can be adjusted to take an integer index selecting one of the four possible string literals to use, ensuring that the std::bad_variant_access constructor is only called with those literals. Passing an index outside the range [0,3] is bogus, but will still select a valid string literal and avoid undefined behaviour. libstdc++-v3/ChangeLog: * include/std/variant (__throw_bad_variant_access(unsigned)): Define new function as inline friend, with namespace-scope declaration using noreturn attribute. (__throw_bad_variant_access(const char*)): Remove. (__throw_bad_variant_access(bool)): Remove. (visit, visit): Adjust calls to __throw_bad_variant_access. Reviewed-by: Patrick Palka --- Patch v2 based on Patrick's review comments at: https://forge.sourceware.org/gcc/gcc-TEST/pulls/3 Changes: - Changed parameter type to unsigned. - Added [[maybe_unused]] to the parameter and array. - Added [[noreturn]] (which required declaring it before the class and then defining it as an inline friend). - Made the array static constexpr. - Added a trailing comma after the last array element. Tested x86_64-linux. Pushed to trunk. libstdc++-v3/include/std/variant | 32 +++- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index cf532126d79..bd0f9c3252a 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -1402,6 +1402,8 @@ namespace __detail::__variant && (is_swappable_v<_Types> && ...))> swap(variant<_Types...>&, variant<_Types...>&) = delete; + [[noreturn]] void __throw_bad_variant_access(unsigned); + class bad_variant_access : public exception { public: @@ -1411,28 +1413,24 @@ namespace __detail::__variant { return _M_reason; } private: +// Must only be called with a string literal bad_variant_access(const char* __reason) noexcept : _M_reason(__reason) { } // Must point to a string with static storage duration: const char* _M_reason = "bad variant access"; -friend void __throw_bad_variant_access(const char* __what); +friend void __throw_bad_variant_access([[maybe_unused]] unsigned __n) +{ + [[maybe_unused]] static constexpr const char* __reasons[] = { + "std::get: wrong index for variant", + "std::get: variant is valueless", + "std::visit: variant is valueless", + "std::visit: variant is valueless", + }; + _GLIBCXX_THROW_OR_ABORT(bad_variant_access(__reasons[__n % 4u])); +} }; - // Must only be called with a string literal - inline void - __throw_bad_variant_access(const char* __what) - { _GLIBCXX_THROW_OR_ABORT(bad_variant_access(__what)); } - - inline void - __throw_bad_variant_access(bool __valueless) - { -if (__valueless) [[__unlikely__]] - __throw_bad_variant_access("std::get: variant is valueless"); -else - __throw_bad_variant_access("std::get: wrong index for variant"); - } - template class variant : private __detail::__variant::_Variant_base<_Types...>, @@ -1941,7 +1939,7 @@ namespace __detail::__variant namespace __variant = std::__detail::__variant; if ((__variant::__as(__variants).valueless_by_exception() || ...)) - __throw_bad_variant_access("std::visit: variant is valueless"); + __throw_bad_variant_access(2); using _Result_type = __detail::__variant::__visit_result_t<_Visitor, _Variants...>; @@ -1981,7 +1979,7 @@ namespace __detail::__variant namespace __variant = std::__detail::__variant; if ((__variant::__as(__variants).valueless_by_exception() || ...)) - __throw_bad_variant_access("std::visit: variant is valueless"); + __throw_bad_variant_access(3); return std::__do_visit<_Res>(std::forward<_Visitor>(__visitor), __variant::__as(std::forward<_Variants>(__variants))...); -- 2.47.0
[PATCH] libstdc++: Add P1206R7 from_range members to std::vector [PR111055]
This is another piece of P1206R7, adding new members to std::vector and std::vector. The __uninitialized_copy_a extension needs to be enhanced to support passing non-common ranges (i.e. a sentinel that is a different type from the iterator) and move-only input iterators. libstdc++-v3/ChangeLog: PR libstdc++/111055 * include/bits/ranges_base.h (__container_compatible_range): New concept. * include/bits/stl_bvector.h (vector(from_range, R&&, const Alloc&)) (assign_range, insert_range, append_range): Define. * include/bits/stl_uninitialized.h (__do_uninit_copy): Support non-common ranges. (__uninitialized_copy_a): Likewise. * include/bits/stl_vector.h (_Vector_base::_M_append_range_to): New function. (_Vector_base::_M_append_range): Likewise. (vector(from_range, R&&, const Alloc&), assign_range): Define. (append_range): Define. (insert_range): Declare. * include/debug/vector (vector(from_range, R&&, const Alloc&)) (assign_range, insert_range, append_range): Define. * include/bits/vector.tcc (insert_range): Define. * testsuite/23_containers/vector/bool/cons/from_range.cc: New test. * testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc: New test. * testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc: New test. * testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc: New test. * testsuite/23_containers/vector/cons/from_range.cc: New test. * testsuite/23_containers/vector/modifiers/append_range.cc: New test. * testsuite/23_containers/vector/modifiers/assign/assign_range.cc: New test. * testsuite/23_containers/vector/modifiers/insert/insert_range.cc: New test. --- Tested x86_64-linux. libstdc++-v3/include/bits/ranges_base.h | 10 ++ libstdc++-v3/include/bits/stl_bvector.h | 120 + libstdc++-v3/include/bits/stl_uninitialized.h | 38 +++- libstdc++-v3/include/bits/stl_vector.h| 166 ++ libstdc++-v3/include/bits/vector.tcc | 124 + libstdc++-v3/include/debug/vector | 70 .../vector/bool/cons/from_range.cc| 81 + .../bool/modifiers/assign/assign_range.cc | 96 ++ .../bool/modifiers/insert/append_range.cc | 83 + .../bool/modifiers/insert/insert_range.cc | 94 ++ .../23_containers/vector/cons/from_range.cc | 94 ++ .../vector/modifiers/append_range.cc | 83 + .../vector/modifiers/assign/assign_range.cc | 107 +++ .../vector/modifiers/insert/insert_range.cc | 94 ++ 14 files changed, 1252 insertions(+), 8 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc create mode 100644 libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc create mode 100644 libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc create mode 100644 libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc create mode 100644 libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc create mode 100644 libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc create mode 100644 libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc create mode 100644 libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc diff --git a/libstdc++-v3/include/bits/ranges_base.h b/libstdc++-v3/include/bits/ranges_base.h index cb2eba1f841..a2c743ff56b 100644 --- a/libstdc++-v3/include/bits/ranges_base.h +++ b/libstdc++-v3/include/bits/ranges_base.h @@ -1079,6 +1079,16 @@ namespace ranges #if __glibcxx_ranges_to_container // C++ >= 23 struct from_range_t { explicit from_range_t() = default; }; inline constexpr from_range_t from_range{}; + +/// @cond undocumented +namespace __detail +{ + template +concept __container_compatible_range + = ranges::input_range<_Rg> + && convertible_to, _Tp>; +} +/// @endcond #endif _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/bits/stl_bvector.h b/libstdc++-v3/include/bits/stl_bvector.h index 42261ac5915..ebb5ff2c594 100644 --- a/libstdc++-v3/include/bits/stl_bvector.h +++ b/libstdc++-v3/include/bits/stl_bvector.h @@ -892,6 +892,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER } #endif +#if __glibcxx_ranges_to_container // C++ >= 23 + /** + * @brief Construct a vector from a range. + * @since C++23 + */ + template<__detail::__container_compatible_range _Rg> + constexpr + vector(from_range_t, _Rg&& __rg, const _Alloc& __a = _Alloc()) + : _Base(__a) + { + if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>) + { +
Re: [PATCH] non-gcc: Remove trailing whitespace
On Thu, 24 Oct 2024 at 10:32, Jonathan Wakely wrote: > > > On Thu, 24 Oct 2024, 09:19 Jakub Jelinek, wrote: > >> Hi! >> >> Here is the non-gcc part of the previous patch, include/, libiberty/, >> libcpp/, libgcc/, libstdc++-v3/. >> >> Is there something that should be left out? >> > > > libstdc++-v3/src/c++17/fast_float/fast_float.h comes from an external > project. Please leave that out, and we can ask upstream to fix it. > Ironically, the line above in my previous email has trailing whitespace ;) These upstream commits already removed the trailing whitespace in the code: https://github.com/jwakely/fast_float/commit/e3fd438c64c973f38c7f4e89790052a67adeba9a https://github.com/fastfloat/fast_float/commit/39e04ea7668b191e748cd294a4942dabdd9ace12 I've submitted https://github.com/fastfloat/fast_float/pull/272 to stop adding it to the licence header. Next time Patrick syncs from upstream we should get rid of the trailing whitespace in that file. > > The other libstdc++ changes are OK, thanks for doing this. > > I don't know whether Doxygen treats two spaces at the end of a line as a > forced line-break, like Markdown does, but I checked that none of the > libstdc++ changes in the patch would be affected by that anyway. > > >
Re: [PATCH] non-gcc: Remove trailing whitespace
On Thu, 24 Oct 2024, 09:19 Jakub Jelinek, wrote: > Hi! > > Here is the non-gcc part of the previous patch, include/, libiberty/, > libcpp/, libgcc/, libstdc++-v3/. > > Is there something that should be left out? > libstdc++-v3/src/c++17/fast_float/fast_float.h comes from an external project. Please leave that out, and we can ask upstream to fix it. The other libstdc++ changes are OK, thanks for doing this. I don't know whether Doxygen treats two spaces at the end of a line as a forced line-break, like Markdown does, but I checked that none of the libstdc++ changes in the patch would be affected by that anyway. > Ok for trunk if it passes bootstrap/regtest? > > 2024-10-24 Jakub Jelinek > > include/ > * dyn-string.h: Remove trailing whitespace. > * libiberty.h: Likewise. > * xregex.h: Likewise. > * splay-tree.h: Likewise. > * partition.h: Likewise. > * plugin-api.h: Likewise. > * demangle.h: Likewise. > * vtv-change-permission.h: Likewise. > * fibheap.h: Likewise. > * hsa_ext_image.h: Likewise. > * hashtab.h: Likewise. > * libcollector.h: Likewise. > * sort.h: Likewise. > * symcat.h: Likewise. > * hsa_ext_amd.h: Likewise. > libcpp/ > * directives.cc: Remove trailing whitespace. > * mkdeps.cc: Likewise. > * line-map.cc: Likewise. > * internal.h: Likewise. > * files.cc: Likewise. > * init.cc: Likewise. > * makeucnid.cc: Likewise. > * system.h: Likewise. > * include/line-map.h: Likewise. > * include/symtab.h: Likewise. > * include/cpplib.h: Likewise. > * expr.cc: Likewise. > * charset.cc: Likewise. > * macro.cc: Likewise. > * errors.cc: Likewise. > * lex.cc: Likewise. > * traditional.cc: Likewise. > libgcc/ > * crtstuff.c: Remove trailing whitespace. > * libgcov.h: Likewise. > * config/alpha/crtfastmath.c: Likewise. > * config/alpha/vms-gcc_shell_handler.c: Likewise. > * config/alpha/vms-unwind.h: Likewise. > * config/pa/linux-atomic.c: Likewise. > * config/pa/linux-unwind.h: Likewise. > * config/pa/quadlib.c: Likewise. > * config/pa/fptr.c: Likewise. > * config/s390/32/_fixsfdi.c: Likewise. > * config/s390/32/_fixunssfdi.c: Likewise. > * config/s390/32/_fixunsdfdi.c: Likewise. > * config/c6x/pr-support.c: Likewise. > * config/lm32/_udivsi3.c: Likewise. > * config/lm32/libgcc_lm32.h: Likewise. > * config/lm32/_udivmodsi4.c: Likewise. > * config/lm32/_mulsi3.c: Likewise. > * config/lm32/_modsi3.c: Likewise. > * config/lm32/_umodsi3.c: Likewise. > * config/lm32/_divsi3.c: Likewise. > * config/darwin-crt3.c: Likewise. > * config/msp430/mpy.c: Likewise. > * config/ia64/tf-signs.c: Likewise. > * config/ia64/fde-vms.c: Likewise. > * config/ia64/unwind-ia64.c: Likewise. > * config/ia64/vms-unwind.h: Likewise. > * config/ia64/sfp-exceptions.c: Likewise. > * config/ia64/quadlib.c: Likewise. > * config/ia64/unwind-ia64.h: Likewise. > * config/avr/libf7/f7-renames.h: Likewise. > * config/rl78/vregs.h: Likewise. > * config/arm/bpabi.c: Likewise. > * config/arm/unwind-arm.c: Likewise. > * config/arm/pr-support.c: Likewise. > * config/arm/linux-atomic.c: Likewise. > * config/arm/bpabi-lib.h: Likewise. > * config/frv/frvend.c: Likewise. > * config/frv/cmovw.c: Likewise. > * config/frv/frvbegin.c: Likewise. > * config/frv/cmovd.c: Likewise. > * config/frv/cmovh.c: Likewise. > * config/aarch64/cpuinfo.c: Likewise. > * config/i386/crtfastmath.c: Likewise. > * config/i386/cygming-crtend.c: Likewise. > * config/i386/32/tf-signs.c: Likewise. > * config/i386/crtprec.c: Likewise. > * config/i386/sfp-exceptions.c: Likewise. > * config/i386/w32-unwind.h: Likewise. > * config/libbid/_le_td.c: Likewise. > * config/libbid/bid128_compare.c: Likewise. > * config/libbid/bid_div_macros.h: Likewise. > * config/libbid/bid64_to_bid128.c: Likewise. > * config/libbid/bid64_to_uint32.c: Likewise. > * config/libbid/bid128_to_uint64.c: Likewise. > * config/libbid/bid64_div.c: Likewise. > * config/libbid/bid128_round_integral.c: Likewise. > * config/libbid/bid_binarydecimal.c: Likewise. > * config/libbid/bid128_string.c: Likewise. > * config/libbid/bid_flag_operations.c: Likewise. > * config/libbid/bid128_to_int64.c: Likewise. > * config/libbid/_mul_sd.c: Likewise. > * config/libbid/bid64_mul.c: Likewise. > * config/libbid/bid128_noncomp.c: Likewise. > * config/libbid/_gt_dd.c: Likewise
Re: [Bug libstdc++/115285] [12/13/14/15 Regression] std::unordered_set can have duplicate value
I'm seeing new FAILs with -D_GLIBCXX_USE_CXX11_ABI=0 /home/test/src/gcc/libstdc++-v3/testsuite/23_containers/unordered_set/96088.cc:247: void test03(): Assertion '__gnu_test::counter::get()._M_increments == in crements + 1' failed. FAIL: 23_containers/unordered_set/96088.cc -std=gnu++17 execution test /home/test/src/gcc/libstdc++-v3/testsuite/23_containers/unordered_map/96088.cc:240: void test03(): Assertion '__gnu_test::counter::count() == origin + incre ments' failed. FAIL: 23_containers/unordered_map/96088.cc -std=gnu++17 execution test On Tue, 22 Oct 2024 at 18:28, François Dumont wrote: > > Hi > > libstdc++: Always instantiate key_type to compute hash code [PR115285] > > Even if it is possible to compute a hash code from the inserted > arguments > we need to instantiate the key_type to guaranty hash code consistency. > > Preserve the lazy instantiation of the mapped_type in the context of > associative containers. > > libstdc++-v3/ChangeLog: > > PR libstdc++/115285 > * include/bits/hashtable.h (_S_forward_key<_Kt>): Always > return a temporary > key_type instance. > * testsuite/23_containers/unordered_map/96088.cc: Adapt to > additional instanciation. > Also check that mapped_type is not instantiated when there > is no insertion. > * testsuite/23_containers/unordered_multimap/96088.cc: > Adapt to additional > instanciation. > * testsuite/23_containers/unordered_multiset/96088.cc: > Likewise. > * testsuite/23_containers/unordered_set/96088.cc: Likewise. > * testsuite/23_containers/unordered_set/pr115285.cc: New > test case. > > > Tested under Linux x64, > > ok to commit ? > > François
[PATCH] libstdc++: Simplify std::__throw_bad_variant_access
This removes the overload of __throw_bad_variant_access that must be called with a string literal. This avoids a potential source of undefined behaviour if that function got misused. The other overload that takes a bool parameter can be adjusted to take an int describing which of the four possible string literals to use, and ensure that the std::bad_variant_access constructor is only called with those. Passing an int outside the range [0,3] is bogus, but will still select a valid string literal and avoid undefined behaviour. libstdc++-v3/ChangeLog: * include/std/variant (bad_variant_access): Adjust friend declaration. (__throw_bad_variant_access(const char*)): Remove. (__throw_bad_variant_access(bool)): Change parameter to int. (visit, visit): Adjust calls to __throw_bad_variant_access. --- Tested x86_64-linux. Also available for review at https://forge.sourceware.org/gcc/gcc-TEST/pulls/3 libstdc++-v3/include/std/variant | 25 - 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index cf532126d79..d79299be634 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -1411,26 +1411,25 @@ namespace __detail::__variant { return _M_reason; } private: +// Must only be called with a string literal bad_variant_access(const char* __reason) noexcept : _M_reason(__reason) { } // Must point to a string with static storage duration: const char* _M_reason = "bad variant access"; -friend void __throw_bad_variant_access(const char* __what); +friend void __throw_bad_variant_access(int); }; - // Must only be called with a string literal inline void - __throw_bad_variant_access(const char* __what) - { _GLIBCXX_THROW_OR_ABORT(bad_variant_access(__what)); } - - inline void - __throw_bad_variant_access(bool __valueless) + __throw_bad_variant_access(int __reason) { -if (__valueless) [[__unlikely__]] - __throw_bad_variant_access("std::get: variant is valueless"); -else - __throw_bad_variant_access("std::get: wrong index for variant"); +const char* __reasons[] = { + "std::get: wrong index for variant", + "std::get: variant is valueless", + "std::visit: variant is valueless", + "std::visit: variant is valueless" +}; +_GLIBCXX_THROW_OR_ABORT(bad_variant_access(__reasons[__reason % 4u])); } template @@ -1941,7 +1940,7 @@ namespace __detail::__variant namespace __variant = std::__detail::__variant; if ((__variant::__as(__variants).valueless_by_exception() || ...)) - __throw_bad_variant_access("std::visit: variant is valueless"); + __throw_bad_variant_access(2); using _Result_type = __detail::__variant::__visit_result_t<_Visitor, _Variants...>; @@ -1981,7 +1980,7 @@ namespace __detail::__variant namespace __variant = std::__detail::__variant; if ((__variant::__as(__variants).valueless_by_exception() || ...)) - __throw_bad_variant_access("std::visit: variant is valueless"); + __throw_bad_variant_access(3); return std::__do_visit<_Res>(std::forward<_Visitor>(__visitor), __variant::__as(std::forward<_Variants>(__variants))...); -- 2.46.2
Re: [PATCH] ginclude: stdalign.h should define __xxx_is_defined macros for C++
On Wed, 23 Oct 2024 at 19:44, Jonathan Wakely wrote: > > On Wed, 23 Oct 2024 at 19:41, Jonathan Wakely wrote: > > > > On Wed, 23 Oct 2024 at 16:02, Jason Merrill wrote: > > > > > > Should there also/instead be a test with ? > > > > We don't usually (or ever?) bother to test the .h versions of headers. > > For these ones that are deprecated it probably makes sense to do so, > > because isn't deprecated, only . So we should > > ensure that the .h forms work fine without diagnostics even in C++17 > > and later. > > I'll add more tests. > > But I think it makes sense to do that as part of a follow-up commit > where I deprecate . Here's a preview of that follow-up, without the new tests I need to add: https://forge.sourceware.org/gcc/gcc-TEST/pulls/4
Re: [PATCH] ginclude: stdalign.h should define __xxx_is_defined macros for C++
On Wed, 23 Oct 2024 at 19:41, Jonathan Wakely wrote: > > On Wed, 23 Oct 2024 at 16:02, Jason Merrill wrote: > > > > Should there also/instead be a test with ? > > We don't usually (or ever?) bother to test the .h versions of headers. > For these ones that are deprecated it probably makes sense to do so, > because isn't deprecated, only . So we should > ensure that the .h forms work fine without diagnostics even in C++17 > and later. > I'll add more tests. But I think it makes sense to do that as part of a follow-up commit where I deprecate .
Re: [PATCH] ginclude: stdalign.h should define __xxx_is_defined macros for C++
On Wed, 23 Oct 2024 at 16:02, Jason Merrill wrote: > > On 10/23/24 10:39 AM, Jonathan Wakely wrote: > > The __alignas_is_defined macro has been required by C++ since C++11, and > > C++ Library DR 4036 clarified that __alignof_is_defined should be > > defined too. > > > > The macros alignas and alignof should not be defined, as they're > > keywords in C++. > > > > Technically it's implementation-defined whether __STDC_VERSION__ is > > defined by a C++ compiler, but G++ does not define it. Adjusting the > > first #if this way works as intended: A C23 compiler will not enter the > > outer if-group and so will not define any of the macros, a C17 compiler > > will enter both if-groups and so define all the macros, and a C++ > > compiler will enter the outer if-group but not the inner if-group. > > > > gcc/ChangeLog: > > > > * ginclude/stdalign.h (__alignas_is_defined): Define for C++. > > (__alignof_is_defined): Likewise. > > Do we want to note somehow that these macros are deprecated since C++17? The header is deprecated in C++17, but the macros aren't if you get them via . They were deprecated for C++23 by my NB comment https://cplusplus.github.io/LWG/issue3827 Would you like it to be noted in the commit message, or in the header itself, something like this? --- a/gcc/ginclude/stdalign.h +++ b/gcc/ginclude/stdalign.h @@ -33,6 +33,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define alignof _Alignof #endif +/* These are defined for C++, but deprecated in C++23. */ #define __alignas_is_defined 1 #define __alignof_is_defined 1 I expect to be removed completely for C++26, if my P3348 is approved. I'm not sure if we want to add deprecation warnings to for C++26, or just make it empty. That's for another day anyway. > > libstdc++-v3/ChangeLog: > > > > * testsuite/18_support/headers/cstdalign/macros.cc: New test. > > --- > > > > The libc++ devs noticed recently that GCC's doesn't conform > > to the C++ requirements. > > > > Tested x86_64-linux. > > > > OK for trunk? > > > > gcc/ginclude/stdalign.h | 5 ++-- > > .../18_support/headers/cstdalign/macros.cc| 24 +++ > > 2 files changed, 27 insertions(+), 2 deletions(-) > > create mode 100644 > > libstdc++-v3/testsuite/18_support/headers/cstdalign/macros.cc > > > > diff --git a/gcc/ginclude/stdalign.h b/gcc/ginclude/stdalign.h > > index 5f82f2d68f2..af73c322624 100644 > > --- a/gcc/ginclude/stdalign.h > > +++ b/gcc/ginclude/stdalign.h > > @@ -26,11 +26,12 @@ see the files COPYING3 and COPYING.RUNTIME > > respectively. If not, see > > #ifndef _STDALIGN_H > > #define _STDALIGN_H > > > > -#if (!defined __cplusplus\ > > - && !(defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L)) > > +#if !(defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L) > > > > +#ifndef __cplusplus > > #define alignas _Alignas > > #define alignof _Alignof > > +#endif > > > > #define __alignas_is_defined 1 > > #define __alignof_is_defined 1 > > diff --git a/libstdc++-v3/testsuite/18_support/headers/cstdalign/macros.cc > > b/libstdc++-v3/testsuite/18_support/headers/cstdalign/macros.cc > > new file mode 100644 > > index 000..c50c921cd59 > > --- /dev/null > > +++ b/libstdc++-v3/testsuite/18_support/headers/cstdalign/macros.cc > > @@ -0,0 +1,24 @@ > > +// { dg-options "-D_GLIBCXX_USE_DEPRECATED=1 -Wno-deprecated" } > > +// { dg-do preprocess { target c++11 } } > > + > > +#include > > Should there also/instead be a test with ? We don't usually (or ever?) bother to test the .h versions of headers. For these ones that are deprecated it probably makes sense to do so, because isn't deprecated, only . So we should ensure that the .h forms work fine without diagnostics even in C++17 and later. I'll add more tests. > > + > > +#ifndef __alignas_is_defined > > +# error "The header fails to define a macro named > > __alignas_is_defined" > > +#elif __alignas_is_defined != 1 > > +# error "__alignas_is_defined is not defined to 1 in " > > +#endif > > + > > +#ifndef __alignof_is_defined > > +# error "The header fails to define a macro named > > __alignof_is_defined" > > +#elif __alignof_is_defined != 1 > > +# error "__alignof_is_defined is not defined to 1 in " > > +#endif > > + > > +#ifdef alignas > > +# error "The header defines a macro named alignas" > > +#endif > > + > > +#ifdef alignof > > +# error "The header defines a macro named alignof" > > +#endif >
Re: [Bug libstdc++/115285] [12/13/14/15 Regression] std::unordered_set can have duplicate value
On Wed, 23 Oct 2024 at 18:37, François Dumont wrote: > > Sorry but I'm not sure, is it also ok for the 3 backports ? Yeah, I should have said - OK for the branches too, thanks. > > On 22/10/2024 22:43, Jonathan Wakely wrote: > > On Tue, 22 Oct 2024 at 18:28, François Dumont wrote: > >> Hi > >> > >> libstdc++: Always instantiate key_type to compute hash code > >> [PR115285] > >> > >> Even if it is possible to compute a hash code from the inserted > >> arguments > >> we need to instantiate the key_type to guaranty hash code > >> consistency. > >> > >> Preserve the lazy instantiation of the mapped_type in the context of > >> associative containers. > >> > >> libstdc++-v3/ChangeLog: > >> > >> PR libstdc++/115285 > >> * include/bits/hashtable.h (_S_forward_key<_Kt>): Always > >> return a temporary > >> key_type instance. > >> * testsuite/23_containers/unordered_map/96088.cc: Adapt to > >> additional instanciation. > >> Also check that mapped_type is not instantiated when there > >> is no insertion. > >> * testsuite/23_containers/unordered_multimap/96088.cc: > >> Adapt to additional > >> instanciation. > >> * testsuite/23_containers/unordered_multiset/96088.cc: > >> Likewise. > >> * testsuite/23_containers/unordered_set/96088.cc: Likewise. > >> * testsuite/23_containers/unordered_set/pr115285.cc: New > >> test case. > >> > >> > >> Tested under Linux x64, > >> > >> ok to commit ? > > OK, thanks > > >
[committed] libstdc++: Add -D_GLIBCXX_ASSERTIONS default for -O0 to API history
Excuse the huge diff, it's because it adds a new section heading so all the TOC pages and section listings change. Pushed to trunk. -- >8 -- libstdc++-v3/ChangeLog: * doc/xml/manual/evolution.xml: Document that assertions are enabled for unoptimized builds. * doc/html/*: Regenerate. --- libstdc++-v3/doc/html/index.html | 2 +- libstdc++-v3/doc/html/manual/api.html | 2 ++ libstdc++-v3/doc/html/manual/appendix.html | 2 +- libstdc++-v3/doc/html/manual/appendix_porting.html | 2 +- libstdc++-v3/doc/html/manual/index.html| 2 +- libstdc++-v3/doc/xml/manual/evolution.xml | 8 6 files changed, 14 insertions(+), 4 deletions(-) diff --git a/libstdc++-v3/doc/html/index.html b/libstdc++-v3/doc/html/index.html index 395908f17a1..e96f2cb2704 100644 --- a/libstdc++-v3/doc/html/index.html +++ b/libstdc++-v3/doc/html/index.html @@ -142,7 +142,7 @@ Existing tests C++11 Requirements Test Sequence Descriptions -ABI Policy and GuidelinesThe C++ InterfaceVersioningGoalsHistoryPrerequisitesConfiguringChecking ActiveAllowed ChangesProhibited ChangesImplementationTestingSingle ABI TestingMultiple ABI TestingOutstanding IssuesAPI Evolution and Deprecation History3.03.13.23.33.44.04.14.24.34.44.54.64.74.84.955.3677.27.38910111212.31313.314Backwards CompatibilityFirstSecondThirdPre-ISO headers removedExtension headers hash_map, hash_set moved to ext or backwardsNo ios::nocreate/ios::noreplace. +ABI Policy and GuidelinesThe C++ InterfaceVersioningGoalsHistoryPrerequisitesConfiguringChecking ActiveAllowed ChangesProhibited ChangesImplementationTestingSingle ABI TestingMultiple ABI TestingOutstanding IssuesAPI Evolution and Deprecation History3.03.13.23.33.44.04.14.24.34.44.54.64.74.84.955.3677.27.38910111212.31313.31415Backwards CompatibilityFirstSecondThirdPre-ISO headers removedExtension headers hash_map, hash_set moved to ext or backwardsNo ios::nocreate/ios::noreplace. No stream::attach(int fd) diff --git a/libstdc++-v3/doc/html/manual/api.html b/libstdc++-v3/doc/html/manual/api.html index 59ed4c88862..799f6eae2a2 100644 --- a/libstdc++-v3/doc/html/manual/api.html +++ b/libstdc++-v3/doc/html/manual/api.html @@ -496,4 +496,6 @@ to be used with std::basic_istream. The extension allowing std::basic_string to be instantiated with an allocator that doesn't match the string's character type is no longer allowed in C++20 mode. +15 +Enabled debug assertions by default for unoptimized builds. Prev Up NextABI Policy and Guidelines Home Backwards Compatibility \ No newline at end of file diff --git a/libstdc++-v3/doc/html/manual/appendix.html b/libstdc++-v3/doc/html/manual/appendix.html index affd5839f43..69a0e0018f3 100644 --- a/libstdc++-v3/doc/html/manual/appendix.html +++ b/libstdc++-v3/doc/html/manual/appendix.html @@ -16,7 +16,7 @@ Existing tests C++11 Requirements Test Sequence Descriptions -ABI Policy and GuidelinesThe C++ InterfaceVersioningGoalsHistoryPrerequisitesConfiguringChecking ActiveAllowed ChangesProhibited ChangesImplementationTestingSingle ABI TestingMultiple ABI TestingOutstanding IssuesAPI Evolution and Deprecation History3.03.13.23.33.44.04.14.24.34.44.54.64.74.84.955.3677.27.38910111212.31313.314Backwards CompatibilityFirstSecondThirdPre-ISO headers removedExtension headers hash_map, hash_set moved to ext or backwardsNo ios::nocreate/ios::noreplace. +ABI Policy and GuidelinesThe C++ InterfaceVersioningGoalsHistoryPrerequisitesConfiguringChecking ActiveAllowed ChangesProhibited ChangesImplementationTestingSingle ABI TestingMultiple ABI TestingOutstanding IssuesAPI Evolution and Deprecation History3.03.13.23.33.44.04.14.24.34.44.54.64.74.84.955.3677.27.38910111212.31313.31415Backwards CompatibilityFirstSecondThirdPre-ISO headers removedExtension headers hash_map, hash_set moved to ext or backwardsNo ios::nocreate/ios::noreplace. No stream::attach(int fd) diff --git a/libstdc++-v3/doc/html/manual/appendix_porting.html b/libstdc++-v3/doc/html/manual/appendix_porting.html index 5d8d5da0bf9..c76ef295e78 100644 --- a/libstdc++-v3/doc/html/manual/appendix_porting.html +++ b/libstdc++-v3/doc/html/manual/appendix_porting.html @@ -14,7 +14,7 @@ Existing tests C++11 Requirements Test Sequence Descriptions -ABI Policy and GuidelinesThe C++ InterfaceVersioningGoalsHistoryPrerequisitesConfiguringChecking ActiveAllowed ChangesProhibited ChangesImplementationTestingSingle ABI TestingMultiple ABI TestingOutstanding IssuesAPI Evolution and Deprecation History3.03.13.23.33.44.04.14.24.34.44.54.64.74.84.955.3677.27.38910111212.31313.314Backwards CompatibilityFirstSecondThirdPre-ISO headers removedExtension headers hash_map, hash_set moved to ext or backwardsNo ios::nocreate/ios::noreplace. +ABI Policy and GuidelinesThe C++ InterfaceVersioningGoalsHistoryPrerequisitesConfiguringChecking ActiveAllowed ChangesProhibited ChangesImpleme
[PATCH] ginclude: stdalign.h should define __xxx_is_defined macros for C++
The __alignas_is_defined macro has been required by C++ since C++11, and C++ Library DR 4036 clarified that __alignof_is_defined should be defined too. The macros alignas and alignof should not be defined, as they're keywords in C++. Technically it's implementation-defined whether __STDC_VERSION__ is defined by a C++ compiler, but G++ does not define it. Adjusting the first #if this way works as intended: A C23 compiler will not enter the outer if-group and so will not define any of the macros, a C17 compiler will enter both if-groups and so define all the macros, and a C++ compiler will enter the outer if-group but not the inner if-group. gcc/ChangeLog: * ginclude/stdalign.h (__alignas_is_defined): Define for C++. (__alignof_is_defined): Likewise. libstdc++-v3/ChangeLog: * testsuite/18_support/headers/cstdalign/macros.cc: New test. --- The libc++ devs noticed recently that GCC's doesn't conform to the C++ requirements. Tested x86_64-linux. OK for trunk? gcc/ginclude/stdalign.h | 5 ++-- .../18_support/headers/cstdalign/macros.cc| 24 +++ 2 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 libstdc++-v3/testsuite/18_support/headers/cstdalign/macros.cc diff --git a/gcc/ginclude/stdalign.h b/gcc/ginclude/stdalign.h index 5f82f2d68f2..af73c322624 100644 --- a/gcc/ginclude/stdalign.h +++ b/gcc/ginclude/stdalign.h @@ -26,11 +26,12 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #ifndef _STDALIGN_H #define _STDALIGN_H -#if (!defined __cplusplus \ - && !(defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L)) +#if !(defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L) +#ifndef __cplusplus #define alignas _Alignas #define alignof _Alignof +#endif #define __alignas_is_defined 1 #define __alignof_is_defined 1 diff --git a/libstdc++-v3/testsuite/18_support/headers/cstdalign/macros.cc b/libstdc++-v3/testsuite/18_support/headers/cstdalign/macros.cc new file mode 100644 index 000..c50c921cd59 --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/headers/cstdalign/macros.cc @@ -0,0 +1,24 @@ +// { dg-options "-D_GLIBCXX_USE_DEPRECATED=1 -Wno-deprecated" } +// { dg-do preprocess { target c++11 } } + +#include + +#ifndef __alignas_is_defined +# error "The header fails to define a macro named __alignas_is_defined" +#elif __alignas_is_defined != 1 +# error "__alignas_is_defined is not defined to 1 in " +#endif + +#ifndef __alignof_is_defined +# error "The header fails to define a macro named __alignof_is_defined" +#elif __alignof_is_defined != 1 +# error "__alignof_is_defined is not defined to 1 in " +#endif + +#ifdef alignas +# error "The header defines a macro named alignas" +#endif + +#ifdef alignof +# error "The header defines a macro named alignof" +#endif -- 2.46.2
[PATCH] top-level: Add pull request template for Forgejo
This complements the existing .github/PULL_REQUEST_TEMPLATE.md file, which is used when somebody opens a pull request for an unofficial mirror/fork of GCC on Github. The text in the existing file is very specific to GitHub and doesn't make much sense to include on every PR created on forge.sourceware.org. I tested it by pushing this file to my own fork and opening a pull request against that fork. This template in .forgejo was used instead of the one in .github, see https://forge.sourceware.org/redi/gcc/pulls/1 OK for trunk? -- >8 -- ChangeLog: * .forgejo/PULL_REQUEST_TEMPLATE.md: New file. --- .forgejo/PULL_REQUEST_TEMPLATE.md | 9 + 1 file changed, 9 insertions(+) create mode 100644 .forgejo/PULL_REQUEST_TEMPLATE.md diff --git a/.forgejo/PULL_REQUEST_TEMPLATE.md b/.forgejo/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000..fc645f11305 --- /dev/null +++ b/.forgejo/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,9 @@ +Thanks for taking the time to contribute to GCC! + +Please be advised that https://forge.sourceware.org/ is currently a trial +that is being used by the GCC community to experiment with a new workflow +based on pull requests. + +Pull requests sent here may be forgotten or ignored. Patches that you want to +propose for inclusion in GCC should use the existing email-based workflow, +see https://gcc.gnu.org/contribute.html -- 2.46.2
Re: [PATCH] libstdc++: Replace std::__to_address in C++20 branch in
On Wed, 23 Oct 2024 at 13:18, Jonathan Wakely wrote: > > As noted by Patrick, r15-4546-g85e5b80ee2de80 should have changed the > usage of std::__to_address to std::to_address in the C++20-specific > branch that works on types satisfying std::contiguous_iterator. > > libstdc++-v3/ChangeLog: > > * include/bits/basic_string.h (assign(Iter, Iter)): Call > std::to_address instead of __to_address. > --- > Tested x86_64-linux. > > This patch is also available as a pull request in the forge: > https://forge.sourceware.org/gcc/gcc-TEST/pulls/2 Patrick approved this on the forge (thanks!), so I've added his Reviewed-by: tag and pushed it now. > > libstdc++-v3/include/bits/basic_string.h | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/libstdc++-v3/include/bits/basic_string.h > b/libstdc++-v3/include/bits/basic_string.h > index 16e356e0678..28b3e536185 100644 > --- a/libstdc++-v3/include/bits/basic_string.h > +++ b/libstdc++-v3/include/bits/basic_string.h > @@ -1748,7 +1748,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 > { > __glibcxx_requires_valid_range(__first, __last); > return _M_replace(size_type(0), size(), > - std::__to_address(__first), __last - __first); > + std::to_address(__first), __last - __first); > } > #endif > else > -- > 2.46.2 >
[PATCH] libstdc++: Add GLIBCXX_TESTSUITE_STDS example to docs
libstdc++-v3/ChangeLog: * doc/xml/manual/test.xml: Add GLIBCXX_TESTSUITE_STDS example. * doc/html/manual/test.html: Regenerate. --- This patch is also available as a pull request in the forge: https://forge.sourceware.org/gcc/gcc-TEST/pulls/1 libstdc++-v3/doc/html/manual/test.html | 5 +++-- libstdc++-v3/doc/xml/manual/test.xml | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libstdc++-v3/doc/html/manual/test.html b/libstdc++-v3/doc/html/manual/test.html index 3657997fad4..1c7af1193da 100644 --- a/libstdc++-v3/doc/html/manual/test.html +++ b/libstdc++-v3/doc/html/manual/test.html @@ -352,12 +352,13 @@ cat 27_io/objects/char/3_xin.in | a.out-std, similar to the G++ tests. Adding set v3_std_list { 11 17 23 } to - ~/.dejagnurc or a file named by the + ~/.dejagnurc or to a file named by the DEJAGNU environment variable will cause every test to be run three times, using a different -std each time. Alternatively, a list of standard versions to test with can be specified as a comma-separated list in the GLIBCXX_TESTSUITE_STDS - environment variable. + environment variable, e.g. GLIBCXX_TESTSUITE_STDS=11,17,23 + is equivalent to the v3_std_list value above. To run the libstdc++ test suite under the debug mode, use diff --git a/libstdc++-v3/doc/xml/manual/test.xml b/libstdc++-v3/doc/xml/manual/test.xml index 40926946fe7..6b7f1b04a2a 100644 --- a/libstdc++-v3/doc/xml/manual/test.xml +++ b/libstdc++-v3/doc/xml/manual/test.xml @@ -600,12 +600,13 @@ cat 27_io/objects/char/3_xin.in | a.out Since GCC 14, the libstdc++ testsuite has built-in support for running tests with more than one -std, similar to the G++ tests. Adding set v3_std_list { 11 17 23 } to - ~/.dejagnurc or a file named by the + ~/.dejagnurc or to a file named by the DEJAGNU environment variable will cause every test to be run three times, using a different -std each time. Alternatively, a list of standard versions to test with can be specified as a comma-separated list in the GLIBCXX_TESTSUITE_STDS - environment variable. + environment variable, e.g. GLIBCXX_TESTSUITE_STDS=11,17,23 + is equivalent to the v3_std_list value above. -- 2.46.2
[PATCH] libstdc++: Replace std::__to_address in C++20 branch in
As noted by Patrick, r15-4546-g85e5b80ee2de80 should have changed the usage of std::__to_address to std::to_address in the C++20-specific branch that works on types satisfying std::contiguous_iterator. libstdc++-v3/ChangeLog: * include/bits/basic_string.h (assign(Iter, Iter)): Call std::to_address instead of __to_address. --- Tested x86_64-linux. This patch is also available as a pull request in the forge: https://forge.sourceware.org/gcc/gcc-TEST/pulls/2 libstdc++-v3/include/bits/basic_string.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 16e356e0678..28b3e536185 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -1748,7 +1748,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { __glibcxx_requires_valid_range(__first, __last); return _M_replace(size_type(0), size(), - std::__to_address(__first), __last - __first); + std::to_address(__first), __last - __first); } #endif else -- 2.46.2
Re: [Bug libstdc++/115285] [12/13/14/15 Regression] std::unordered_set can have duplicate value
On Tue, 22 Oct 2024 at 18:28, François Dumont wrote: > > Hi > > libstdc++: Always instantiate key_type to compute hash code [PR115285] > > Even if it is possible to compute a hash code from the inserted > arguments > we need to instantiate the key_type to guaranty hash code consistency. > > Preserve the lazy instantiation of the mapped_type in the context of > associative containers. > > libstdc++-v3/ChangeLog: > > PR libstdc++/115285 > * include/bits/hashtable.h (_S_forward_key<_Kt>): Always > return a temporary > key_type instance. > * testsuite/23_containers/unordered_map/96088.cc: Adapt to > additional instanciation. > Also check that mapped_type is not instantiated when there > is no insertion. > * testsuite/23_containers/unordered_multimap/96088.cc: > Adapt to additional > instanciation. > * testsuite/23_containers/unordered_multiset/96088.cc: > Likewise. > * testsuite/23_containers/unordered_set/96088.cc: Likewise. > * testsuite/23_containers/unordered_set/pr115285.cc: New > test case. > > > Tested under Linux x64, > > ok to commit ? OK, thanks
Re: [PATCH] libstdc++: Implement LWG 4166 changes to concat_view::end()
On Tue, 22 Oct 2024 at 19:22, Patrick Palka wrote: > > Tested on x86_64-pc-linux-gnu, does this look OK for trunk? OK, thanks. > > -- >8 -- > > This patch proactively implements the proposed resolution for this LWG > issue, which seems straightforward and slated to be approved as-is. > > I opted to not add a _GLIBCXX_RESOLVE_LIB_DEFECTS code comment for this > since concat_view is C++26 and hasn't been shipped in a GCC release yet. Yup, that's fine. The LWG issue isn't a DR against a published standard, so once we get a finished C++26 standard, this issue will already be part of that standard. > > libstdc++-v3/ChangeLog: > > * include/std/ranges (concat_view::begin): Add space after > 'requires' starting a requires-clause. > (concat_view::end): Refine condition for returning an iterator > rather than default_sentinel as per LWG 4166. > * testsuite/std/ranges/concat/1.cc (test03): Verify LWG 4166 > example. > --- > libstdc++-v3/include/std/ranges | 10 > libstdc++-v3/testsuite/std/ranges/concat/1.cc | 23 +++ > 2 files changed, 29 insertions(+), 4 deletions(-) > > diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges > index 5b455888536..a6c4d66520c 100644 > --- a/libstdc++-v3/include/std/ranges > +++ b/libstdc++-v3/include/std/ranges > @@ -9687,7 +9687,7 @@ namespace ranges > { } > > constexpr iterator > -begin() requires(!(__detail::__simple_view<_Vs> && ...)) > +begin() requires (!(__detail::__simple_view<_Vs> && ...)) > { >iterator __it(this, in_place_index<0>, > ranges::begin(std::get<0>(_M_views))); >__it.template _M_satisfy<0>(); > @@ -9703,9 +9703,10 @@ namespace ranges > } > > constexpr auto > -end() requires(!(__detail::__simple_view<_Vs> && ...)) > +end() requires (!(__detail::__simple_view<_Vs> && ...)) > { > - if constexpr (__detail::__last_is_common<_Vs...>::value) > + if constexpr ((semiregular> && ...) > + && __detail::__last_is_common<_Vs...>::value) > { > constexpr auto __n = sizeof...(_Vs); > return iterator(this, in_place_index<__n - 1>, > @@ -9718,7 +9719,8 @@ namespace ranges > constexpr auto > end() const requires (range && ...) && > __detail::__concatable > { > - if constexpr (__detail::__last_is_common::value) > + if constexpr ((semiregular> && ...) > + && __detail::__last_is_common::value) > { > constexpr auto __n = sizeof...(_Vs); > return iterator(this, in_place_index<__n - 1>, > diff --git a/libstdc++-v3/testsuite/std/ranges/concat/1.cc > b/libstdc++-v3/testsuite/std/ranges/concat/1.cc > index 6ffe28ece51..511a7e8a858 100644 > --- a/libstdc++-v3/testsuite/std/ranges/concat/1.cc > +++ b/libstdc++-v3/testsuite/std/ranges/concat/1.cc > @@ -10,6 +10,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -66,9 +67,31 @@ test02() >VERIFY( ranges::equal(v | views::drop(1), x) ); > } > > +void > +test03() > +{ > + // LWG 4166 - concat_view::end() should be more constrained in order to > + // support noncopyable iterators > + auto range_copyable_it = std::vector{1, 2, 3}; > + > + std::stringstream ss{"4 5 6"}; > + auto range_noncopyable_it = views::istream(ss); > + > + auto view1 = views::concat(range_copyable_it, range_noncopyable_it); > + static_assert( ranges::range ); > + VERIFY( ranges::equal(view1, std::vector{1, 2, 3, 4, 5, 6}) ); > + > + ss = std::stringstream{"4 5 6"}; > + range_noncopyable_it = views::istream(ss); > + auto view2 = views::concat(range_noncopyable_it, range_copyable_it); > + static_assert( ranges::range ); > + VERIFY( ranges::equal(view2, std::vector{4, 5, 6, 1, 2, 3}) ); > +} > + > int > main() > { >static_assert(test01()); >test02(); > + test03(); > } > -- > 2.47.0.107.g34b6ce9b30 >
Re: [PATCH] libstdc++: Avoid using std::__to_address with iterators
On Tue, 22 Oct 2024 at 18:43, Patrick Palka wrote: > > On Fri, 18 Oct 2024, Jonathan Wakely wrote: > > > Do others agree with my reasoning below? > > > > The changes to implement the rule "use std::__niter_base before C++20 > > and use std::to_address after C++20" were easier than I expected. There > > weren't many places that were doing it "wrong" and needed to change. > > > > Tested x86_64-linux. > > > > -- >8 -- > > > > In r12-3935-g82626be2d633a9 I added the partial specialization > > std::pointer_traits<__normal_iterator> so that __to_address > > would work with __normal_iterator objects. Soon after that, François > > replaced it in r12-6004-g807ad4bc854cae with an overload of __to_address > > that served the same purpose, but was less complicated and less wrong. > > > > I now think that both commits were mistakes, and that instead of adding > > hacks to make __normal_iterator work with __to_address, we should not be > > using __to_address with iterators at all before C++20. > > > > The pre-C++20 std::__to_address function should only be used with > > pointer-like types, specifically allocator_traits::pointer types. > > Those pointer-like types are guaranteed to be contiguous iterators, so > > that getting a raw memory address from them is OK. > > > > For arbitrary iterators, even random access iterators, we don't know > > that it's safe to lower the iterator to a pointer e.g. for std::deque > > iterators it's not, because (it + n) == (std::to_address(it) + n) only > > holds within the same block of the deque's storage. > > > > For C++20, std::to_address does work correctly for contiguous iterators, > > including __normal_iterator, and __to_address just calls std::to_address > > so also works. But we have to be sure we have an iterator that satisfies > > the std::contiguous_iterator concept for it to be safe, and we can't > > check that before C++20. > > > > So for pre-C++20 code the correct way to handle iterators that might be > > pointers or might be __normal_iterator is to call __niter_base, and if > > necessary use is_pointer to check whether __niter_base returned a real > > pointer. > > > > We currently have some uses of std::__to_address with iterators where > > we've checked that they're either pointers, or __normal_iterator > > wrappers around pointers, or satisfy std::contiguous_iterator. But this > > seems a little fragile, and it would be better to just use > > std::__niter_base for the pointers and __normal_iterator cases, and use > > C++20 std::to_address when the C++20 std::contiguous_iterator concept is > > satisfied. This patch does that. > > > > libstdc++-v3/ChangeLog: > > > > * include/bits/basic_string.h (basic_string::assign): Replace > > use of __to_address with __niter_base or std::to_address as > > appropriate. > > * include/bits/ptr_traits.h (__to_address): Add comment. > > * include/bits/shared_ptr_base.h (__shared_ptr): Qualify calls > > to __to_address. > > * include/bits/stl_algo.h (find): Replace use of __to_address > > with __niter_base or std::to_address as appropriate. Only use > > either of them when the range is not empty. > > * include/bits/stl_iterator.h (__to_address): Remove overload > > for __normal_iterator. > > * include/debug/safe_iterator.h (__to_address): Remove overload > > for _Safe_iterator. > > * include/std/ranges (views::counted): Replace use of > > __to_address with std::to_address. > > * testsuite/24_iterators/normal_iterator/to_address.cc: Removed. > > --- > > libstdc++-v3/include/bits/basic_string.h | 19 +-- > > libstdc++-v3/include/bits/ptr_traits.h| 4 > > libstdc++-v3/include/bits/shared_ptr_base.h | 4 ++-- > > libstdc++-v3/include/bits/stl_algo.h | 16 +++- > > libstdc++-v3/include/bits/stl_iterator.h | 12 > > libstdc++-v3/include/debug/safe_iterator.h| 17 - > > libstdc++-v3/include/std/ranges | 2 +- > > .../normal_iterator/to_address.cc | 19 --- > > 8 files changed, 31 insertions(+), 62 deletions(-) > > delete mode 100644 > > libstdc++-v3/testsuite/24_iterators/normal_iterator/to_address.cc > > > > diff --git a/libstdc++-v3/include/bits/basic_string.h > > b/libstdc++-v3/include/bits/basic_string.h > > index e9b17ea48b5..16e356e0678 1
Re: [WIP RFC] libstdc++: add module std
On Tue, 22 Oct 2024 at 15:03, Jason Merrill wrote: > > On 10/22/24 4:26 AM, Jonathan Wakely wrote: > > On Mon, 21 Oct 2024 at 17:51, Jason Merrill wrote: > >> > >> On 10/18/24 11:21 AM, Patrick Palka wrote: > >>> On Fri, 18 Oct 2024, Jason Merrill wrote: > >>>> > >>>> Is it useful for std.cc to live in a subdirectory of c++23 as in this > >>>> patch, or > >>>> should it be in c++23 itself? Or elsewhere? > >>> > >>> IIUC the src/ subdirectory is for stuff that gets compiled into the .so > >>> which isn't the case here. > >> > >> Sure, though I thought that might change once we consider it ABI-stable. > >> > >>> And if we want to support the std module in > >>> C++20 mode as an extension, a c++23 subdirectory might not be ideal > >>> either. > >> > >> My impression has been that the subdirectories are just for organization? > > > > Yes, and to group all the files which are built with -std=gnu++NN > > together so that the option is set once by the directory's Makefile > > (although we have a couple of cases where we override the directory's > > -std for specific files). > > > >> > >>> Maybe libstdc++-v3/modules/ then? > >> > >> Let's see what Jonathan thinks. > > > > I'm not sure we need a new directory (with Makefile.{in,am} etc.) for > > just two files. If there's a suggestion to install them to > > $(gxx_include_dir)/module then maybe libstdc++-v3/include/module/ > > makes sense? And install them via rules in > > libstdc++-v3/include/Makefile.am? > > > >> > >> On 10/18/24 12:04 PM, Maciej Cencora wrote: > >>> On Fri, 18 Oct 2024, Jason Merrill wrote: > >>>> stdc++.h also doesn't include the eternally deprecated . > >>>> There > >>>> are some other deprecated facilities that I notice are included: > >>>> > >>>> and float_denorm_style, at least. It would be nice for L{E,}WG to > >>>> clarify > >>>> whether module std is intended to include interfaces that were > >>>> deprecated in > >>>> C++23, since ancient code isn't going to be relying on module std. > >>> > >>> Per P2465r3 Standard Library Modules std and std.compat: > >>>> Are deprecated features provided by the Standard Library modules? > >>>> Yes. This is implied by the normative wording. > >> > >> Ah, thanks. > >> > >>> While doing some light testing, one thing that immediately popped up is > >>> that we need to export __normal_iterator related operators from __gnu_cxx > >>> namespace. > >>> Otherwise it is impossible to even use std::vector in range-based for > >>> loops. > >> > >> Ah, good catch. > >> > >>> But I think a better solution (than exporting such impl details) is to > >>> make these operators hidden friends. > >> > >> That sounds right to me, and mechanically duplicating the declarations > >> as friends seems to work (as attached). > > > > I think I'll just move them into the body to be hidden friends. > > > > The operators for __normal_iterator aren't declared explicitly in the > > standard, so we aren't required to declare them at namespace scope. > > Making them hidden friends should be fine. > > > > > >> > >>> Another thing - P2465r3 mentions only lerp, byte and related ops as > >>> special w.r.t skipping export from global namespace in std.compat, but > >>> for some reason Microsoft's impl treats 3-arg hypot as special as well. > >> > >> Curious. By not declaring it at all when building the module? I don't > >> want to mess with that if the standard doesn't require it. > > > > That's https://cplusplus.github.io/LWG/issue3799 > > > > The 3-arg std::hypot did not come from C, so is in exactly the same > > situation as lerp. > > The implementation problem is that 'using' doesn't let you choose > between overloads. > > Well, I suppose we could 'using' the other decls into e.g. namespace > __hypot before declaring the 3-arg version, and then 'using > __hypot::hypot' instead of std::hypot in std.compat. Ah yes, I see. I don't think it's a problem if we export the 3-arg version in the global namespace alongside the 2-arg
Re: [WIP RFC] libstdc++: add module std
On Mon, 21 Oct 2024 at 17:51, Jason Merrill wrote: > > On 10/18/24 11:21 AM, Patrick Palka wrote: > > On Fri, 18 Oct 2024, Jason Merrill wrote: > >> > >> Is it useful for std.cc to live in a subdirectory of c++23 as in this > >> patch, or > >> should it be in c++23 itself? Or elsewhere? > > > > IIUC the src/ subdirectory is for stuff that gets compiled into the .so > > which isn't the case here. > > Sure, though I thought that might change once we consider it ABI-stable. > > > And if we want to support the std module in > > C++20 mode as an extension, a c++23 subdirectory might not be ideal either. > > My impression has been that the subdirectories are just for organization? Yes, and to group all the files which are built with -std=gnu++NN together so that the option is set once by the directory's Makefile (although we have a couple of cases where we override the directory's -std for specific files). > > > Maybe libstdc++-v3/modules/ then? > > Let's see what Jonathan thinks. I'm not sure we need a new directory (with Makefile.{in,am} etc.) for just two files. If there's a suggestion to install them to $(gxx_include_dir)/module then maybe libstdc++-v3/include/module/ makes sense? And install them via rules in libstdc++-v3/include/Makefile.am? > > On 10/18/24 12:04 PM, Maciej Cencora wrote: > > On Fri, 18 Oct 2024, Jason Merrill wrote: > >> stdc++.h also doesn't include the eternally deprecated . There > >> are some other deprecated facilities that I notice are included: > >> and float_denorm_style, at least. It would be nice for L{E,}WG to clarify > >> whether module std is intended to include interfaces that were deprecated > >> in > >> C++23, since ancient code isn't going to be relying on module std. > > > > Per P2465r3 Standard Library Modules std and std.compat: > >> Are deprecated features provided by the Standard Library modules? > >> Yes. This is implied by the normative wording. > > Ah, thanks. > > > While doing some light testing, one thing that immediately popped up is > > that we need to export __normal_iterator related operators from __gnu_cxx > > namespace. > > Otherwise it is impossible to even use std::vector in range-based for loops. > > Ah, good catch. > > > But I think a better solution (than exporting such impl details) is to make > > these operators hidden friends. > > That sounds right to me, and mechanically duplicating the declarations > as friends seems to work (as attached). I think I'll just move them into the body to be hidden friends. The operators for __normal_iterator aren't declared explicitly in the standard, so we aren't required to declare them at namespace scope. Making them hidden friends should be fine. > > > Another thing - P2465r3 mentions only lerp, byte and related ops as special > > w.r.t skipping export from global namespace in std.compat, but for some > > reason Microsoft's impl treats 3-arg hypot as special as well. > > Curious. By not declaring it at all when building the module? I don't > want to mess with that if the standard doesn't require it. That's https://cplusplus.github.io/LWG/issue3799 The 3-arg std::hypot did not come from C, so is in exactly the same situation as lerp. > > On 10/18/24 12:35 PM, Iain Sandoe wrote: > >> Currently this installs the sources under $(pkgdata), i.e. > >> /usr/share/libstdc++/modules. It could also make sense to install them > >> under $(gxx_include_dir), i.e. /usr/include/c++/15/modules. And/or the > >> subdirectory could be "miu" (module interface unit) instead of "modules". > > > I’d think that $(gxx_include_dir)/modules would be a good place, since that > > allows us to tie it to the GCC version in side-by-side installs. > > Presumably that > > might also simplify finding the relevant sources? > > With side-by-side installs presumably $(prefix) would be different > between them as well or the libraries would also clash? > > But I'm certainly not opposed to putting them under the include dir, > that had been my inclination for a while, and with my > -fsearch-include-path patch would make a simple compile easier without > needing to teach the driver to parse the json. > > > I guess it could be just “module”, but my vote would be for an obvious name > > like that or “std-module” > > Indeed singular "module" would be more consistent with "include" and "lib". As long as we're confident there will never be a header that needs to live at $(gxx_include_dir)/module, but I think that's a safe bet. > On 10/19/24 8:08 AM, Florian Weimer wrote: > >> The build system can find this file with > >> gcc -print-file-name=libstdc++.modules.json > > > > Is it possible to use specs file to redirect this to a different file > > based on C++ compiler flags, should that become necessary? > > Well, the compiler looks up a -print-file-name argument on its library > search path, which can be added to with -B. But this is really an > initial interface pending something more stable. > > Jason
Re: [PATCH] aarch64: libstdc++: Use shufflevector instead of shuffle in opt_random.h
On Mon, 21 Oct 2024 at 17:29, Ricardo Jesus wrote: > > On 10/14/24 14:37, Jonathan Wakely wrote: > > > > > > On Mon, 14 Oct 2024 at 14:36, Kyrylo Tkachov wrote: > >> > >> > >> > >>> On 14 Oct 2024, at 15:28, Ricardo Jesus wrote: > >>> > >>> External email: Use caution opening links or attachments > >>> > >>> > >>> This patch modifies the implementation of the vectorized mersenne > >>> twister random number generator to use __builtin_shufflevector instead > >>> of __builtin_shuffle. This makes it (almost) compatible with Clang. > >>> > >>> To make the implementation fully compatible with Clang, Clang will need > >>> to support internal Neon types like __Uint8x16_t and __Uint32x4_t, which > >>> currently it does not. This looks like an oversight in Clang and so will > >>> be addressed separately. > >>> > >>> I see no codegen change with this patch. > >> > >> FWIW the change looks ok to me from an aarch64 perspective. > >> The only potential problem could have been a compile error so as long as > >> the CI buildbots are happy I think this would be safe to take. > > > > OK thanks for looking. I'll wait to see that CI is green (thanks for > > resubmitting it, Ricardo!) and then push it. > > > > Hi Jonathan, > > When you have a chance, could you please check if the CI is looking good? Yes, it's green now: https://patchwork.sourceware.org/project/gcc/patch/20241014132802.506972-1-...@nvidia.com/ With Kyrill's ack for the aarch64 codegen side, I'm happy to approve this and will push it. Thanks! > > Thanks very much! > > Ricardo > > > > >> Thanks, > >> Kyrill > >> > >>> > >>> Bootstrapped and tested on aarch64-none-linux-gnu. > >>> > >>> Signed-off-by: Ricardo Jesus > >>> > >>> 2024-09-05 Ricardo Jesus > >>> > >>>* config/cpu/aarch64/opt/ext/opt_random.h (__VEXT): Replace uses > >>>of __builtin_shuffle with __builtin_shufflevector. > >>>(__aarch64_lsl_128): Move shift amount to a template parameter. > >>>(__aarch64_lsr_128): Move shift amount to a template parameter. > >>>(__aarch64_recursion): Update call sites of __aarch64_lsl_128 > >>>and __aarch64_lsr_128. > >>> --- > >>> .../config/cpu/aarch64/opt/ext/opt_random.h | 28 +++ > >>> 1 file changed, 16 insertions(+), 12 deletions(-) > >>> > >>> diff --git a/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h > >>> b/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h > >>> index 7f756d1572f..7eb816abcd0 100644 > >>> --- a/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h > >>> +++ b/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h > >>> @@ -35,13 +35,13 @@ > >>> #ifdef __ARM_NEON > >>> > >>> #ifdef __ARM_BIG_ENDIAN > >>> -# define __VEXT(_A,_B,_C) __builtin_shuffle (_A, _B, (__Uint8x16_t) \ > >>> -{16-_C, 17-_C, 18-_C, 19-_C, 20-_C, 21-_C, 22-_C, 23-_C, \ > >>> - 24-_C, 25-_C, 26-_C, 27-_C, 28-_C, 29-_C, 30-_C, 31-_C}) > >>> +# define __VEXT(_A,_B,_C) __builtin_shufflevector (_A, _B, \ > >>> +16-_C, 17-_C, 18-_C, 19-_C, 20-_C, 21-_C, 22-_C, 23-_C, \ > >>> +24-_C, 25-_C, 26-_C, 27-_C, 28-_C, 29-_C, 30-_C, 31-_C) > >>> #else > >>> -# define __VEXT(_A,_B,_C) __builtin_shuffle (_B, _A, (__Uint8x16_t) \ > >>> -{_C, _C+1, _C+2, _C+3, _C+4, _C+5, _C+6, _C+7, \ > >>> - _C+8, _C+9, _C+10, _C+11, _C+12, _C+13, _C+14, _C+15}) > >>> +# define __VEXT(_A,_B,_C) __builtin_shufflevector (_B, _A, \ > >>> +_C, _C+1, _C+2, _C+3, _C+4, _C+5, _C+6, _C+7, \ > >>> +_C+8, _C+9, _C+10, _C+11, _C+12, _C+13, _C+14, _C+15) > >>> #endif > >>> > >>> #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ > >>> @@ -52,9 +52,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > >>> namespace { > >>> // Logical Shift right 128-bits by c * 8 bits > >>> > >>> -__extension__ extern __inline __Uint32x4_t > >>> +__extension__ > >>> +template > >>> +extern __inline __Uint32x4_t > >>> __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) > >>> -__aarch64_lsr_128 (__Uint8x16_t
Re: [PATCH] libstdc++: Avoid using std::__to_address with iterators
On Mon, 21 Oct 2024 at 18:02, François Dumont wrote: > > Reasoning is perfectly fine to me. > > It's not a good news for me cause I plan to extend usages of > __niter_base to many algos to limit impact of _GLIBCXX_DEBUG mode at > runtime. If we have random access iterator we can be sure that > __glibcxx_requires_valid_range fully validated the range and so we can > remove the _Safe_iterator layer. Using __niter_base is fine, it's using __to_address with iterators that I want to avoid. > But that's a really minor problem compared to what you are trying to > achieve here. > > François > > > On 18/10/2024 17:13, Jonathan Wakely wrote: > > Do others agree with my reasoning below? > > > > The changes to implement the rule "use std::__niter_base before C++20 > > and use std::to_address after C++20" were easier than I expected. There > > weren't many places that were doing it "wrong" and needed to change. > > > > Tested x86_64-linux. > > > > -- >8 -- > > > > In r12-3935-g82626be2d633a9 I added the partial specialization > > std::pointer_traits<__normal_iterator> so that __to_address > > would work with __normal_iterator objects. Soon after that, François > > replaced it in r12-6004-g807ad4bc854cae with an overload of __to_address > > that served the same purpose, but was less complicated and less wrong. > > > > I now think that both commits were mistakes, and that instead of adding > > hacks to make __normal_iterator work with __to_address, we should not be > > using __to_address with iterators at all before C++20. > > > > The pre-C++20 std::__to_address function should only be used with > > pointer-like types, specifically allocator_traits::pointer types. > > Those pointer-like types are guaranteed to be contiguous iterators, so > > that getting a raw memory address from them is OK. > > > > For arbitrary iterators, even random access iterators, we don't know > > that it's safe to lower the iterator to a pointer e.g. for std::deque > > iterators it's not, because (it + n) == (std::to_address(it) + n) only > > holds within the same block of the deque's storage. > > > > For C++20, std::to_address does work correctly for contiguous iterators, > > including __normal_iterator, and __to_address just calls std::to_address > > so also works. But we have to be sure we have an iterator that satisfies > > the std::contiguous_iterator concept for it to be safe, and we can't > > check that before C++20. > > > > So for pre-C++20 code the correct way to handle iterators that might be > > pointers or might be __normal_iterator is to call __niter_base, and if > > necessary use is_pointer to check whether __niter_base returned a real > > pointer. > > > > We currently have some uses of std::__to_address with iterators where > > we've checked that they're either pointers, or __normal_iterator > > wrappers around pointers, or satisfy std::contiguous_iterator. But this > > seems a little fragile, and it would be better to just use > > std::__niter_base for the pointers and __normal_iterator cases, and use > > C++20 std::to_address when the C++20 std::contiguous_iterator concept is > > satisfied. This patch does that. > > > > libstdc++-v3/ChangeLog: > > > > * include/bits/basic_string.h (basic_string::assign): Replace > > use of __to_address with __niter_base or std::to_address as > > appropriate. > > * include/bits/ptr_traits.h (__to_address): Add comment. > > * include/bits/shared_ptr_base.h (__shared_ptr): Qualify calls > > to __to_address. > > * include/bits/stl_algo.h (find): Replace use of __to_address > > with __niter_base or std::to_address as appropriate. Only use > > either of them when the range is not empty. > > * include/bits/stl_iterator.h (__to_address): Remove overload > > for __normal_iterator. > > * include/debug/safe_iterator.h (__to_address): Remove overload > > for _Safe_iterator. > > * include/std/ranges (views::counted): Replace use of > > __to_address with std::to_address. > > * testsuite/24_iterators/normal_iterator/to_address.cc: Removed. > > --- > > libstdc++-v3/include/bits/basic_string.h | 19 +-- > > libstdc++-v3/include/bits/ptr_traits.h| 4 > > libstdc++-v3/include/bits/shared_ptr_base.h | 4 ++-- > > libstdc++-v3/include/bits/stl_algo.h | 16 +++- > > libstdc++-v3/include/bits/stl_i
[committed] libstdc++: Fix order of [[...]] and __attribute__((...)) attrs [PR117220]
Tested x86_64-linux, and briefly checked with Clang. Pushed to trunk. -- >8 -- GCC allows these in either order, but Clang doesn't like the C++11-style [[__nodiscard__]] coming after __attribute__((__always_inline__)). libstdc++-v3/ChangeLog: PR libstdc++/117220 * include/bits/stl_iterator.h: Move _GLIBCXX_NODISCARD annotations after __attribute__((__always_inline__)). --- libstdc++-v3/include/bits/stl_iterator.h | 46 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index 26c5eab4b4e..1fbc115b116 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -1077,13 +1077,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Forward iterator requirements - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR reference operator*() const _GLIBCXX_NOEXCEPT { return *_M_current; } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR pointer operator->() const _GLIBCXX_NOEXCEPT @@ -1123,7 +1123,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Random access iterator requirements - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR reference operator[](difference_type __n) const _GLIBCXX_NOEXCEPT @@ -1135,7 +1135,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator+=(difference_type __n) _GLIBCXX_NOEXCEPT { _M_current += __n; return *this; } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR __normal_iterator operator+(difference_type __n) const _GLIBCXX_NOEXCEPT @@ -1147,13 +1147,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator-=(difference_type __n) _GLIBCXX_NOEXCEPT { _M_current -= __n; return *this; } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR __normal_iterator operator-(difference_type __n) const _GLIBCXX_NOEXCEPT { return __normal_iterator(_M_current - __n); } - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR const _Iterator& base() const _GLIBCXX_NOEXCEPT @@ -1209,7 +1209,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #else // Forward iterator requirements template -__attribute__((__always_inline__)) _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR +_GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR inline bool operator==(const __normal_iterator<_IteratorL, _Container>& __lhs, const __normal_iterator<_IteratorR, _Container>& __rhs) @@ -1217,7 +1217,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() == __rhs.base(); } template -__attribute__((__always_inline__)) _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR +_GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR inline bool operator==(const __normal_iterator<_Iterator, _Container>& __lhs, const __normal_iterator<_Iterator, _Container>& __rhs) @@ -1225,7 +1225,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() == __rhs.base(); } template -__attribute__((__always_inline__)) _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR +_GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR inline bool operator!=(const __normal_iterator<_IteratorL, _Container>& __lhs, const __normal_iterator<_IteratorR, _Container>& __rhs) @@ -1233,7 +1233,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() != __rhs.base(); } template -__attribute__((__always_inline__)) _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR +_GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR inline bool operator!=(const __normal_iterator<_Iterator, _Container>& __lhs, const __normal_iterator<_Iterator, _Container>& __rhs) @@ -1242,7 +1242,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Random access iterator requirements template -__attribute__((__always_inline__)) _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR +_GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR inline bool operator<(const __normal_iterator<_IteratorL, _Container>& __lhs, const __normal_iterator<_IteratorR, _Container>& __rhs) @@ -1250,7 +1250,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __lhs.base() < __rhs.base(); } template -__attribute__((__always_inline__)) _GLIBCXX_
Re: [PATCH 2/7] libstdc++: Make __normal_iterator constexpr, always_inline, nodiscard
On Mon, 21 Oct 2024, 07:10 Stephan Bergmann, wrote: > Clang appears to be a bit picky wrt the relative order of annotation > notations here, and complains > Yes, this is https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117220 > > > /home/sberg/gcc/inst/lib/gcc/x86_64-pc-linux-gnu/15.0.0/../../../../include/c++/15.0.0/bits/stl_iter > ator.h:1080:42: error: an attribute list cannot appear here > > 1080 | __attribute__((__always_inline__)) _GLIBCXX_NODISCARD > > | ^~ > > > /home/sberg/gcc/inst/lib/gcc/x86_64-pc-linux-gnu/15.0.0/../../../../include/c++/15.0.0/x86_64-pc-linux-gnu/bits/c++config.h:173:29: > note: expanded from macro '_GLIBCXX_NODISCARD' > > 173 | # define _GLIBCXX_NODISCARD [[__nodiscard__]] > > | ^ > > which would be trivially solved by something like > > > diff --git a/libstdc++-v3/include/bits/stl_iterator.h > b/libstdc++-v3/include/bits/stl_iterator.h > > index 26c5eab4b4e..49d03188fda 100644 > > --- a/libstdc++-v3/include/bits/stl_iterator.h > > +++ b/libstdc++-v3/include/bits/stl_iterator.h > > @@ -1077,13 +1077,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > > >// Forward iterator requirements > > > > - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD > > + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) > >_GLIBCXX_CONSTEXPR > >reference > >operator*() const _GLIBCXX_NOEXCEPT > >{ return *_M_current; } > > > > - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD > > + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) > >_GLIBCXX_CONSTEXPR > >pointer > >operator->() const _GLIBCXX_NOEXCEPT > > @@ -1123,7 +1123,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > > >// Random access iterator requirements > > > > - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD > > + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) > >_GLIBCXX_CONSTEXPR > >reference > >operator[](difference_type __n) const _GLIBCXX_NOEXCEPT > > @@ -1135,7 +1135,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > >operator+=(difference_type __n) _GLIBCXX_NOEXCEPT > >{ _M_current += __n; return *this; } > > > > - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD > > + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) > >_GLIBCXX_CONSTEXPR > >__normal_iterator > >operator+(difference_type __n) const _GLIBCXX_NOEXCEPT > > @@ -1147,13 +1147,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > >operator-=(difference_type __n) _GLIBCXX_NOEXCEPT > >{ _M_current -= __n; return *this; } > > > > - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD > > + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) > >_GLIBCXX_CONSTEXPR > >__normal_iterator > >operator-(difference_type __n) const _GLIBCXX_NOEXCEPT > >{ return __normal_iterator(_M_current - __n); } > > > > - __attribute__((__always_inline__)) _GLIBCXX_NODISCARD > > + _GLIBCXX_NODISCARD __attribute__((__always_inline__)) > >_GLIBCXX_CONSTEXPR > >const _Iterator& > >base() const _GLIBCXX_NOEXCEPT > >
[PATCH] libstdc++: Avoid using std::__to_address with iterators
Do others agree with my reasoning below? The changes to implement the rule "use std::__niter_base before C++20 and use std::to_address after C++20" were easier than I expected. There weren't many places that were doing it "wrong" and needed to change. Tested x86_64-linux. -- >8 -- In r12-3935-g82626be2d633a9 I added the partial specialization std::pointer_traits<__normal_iterator> so that __to_address would work with __normal_iterator objects. Soon after that, François replaced it in r12-6004-g807ad4bc854cae with an overload of __to_address that served the same purpose, but was less complicated and less wrong. I now think that both commits were mistakes, and that instead of adding hacks to make __normal_iterator work with __to_address, we should not be using __to_address with iterators at all before C++20. The pre-C++20 std::__to_address function should only be used with pointer-like types, specifically allocator_traits::pointer types. Those pointer-like types are guaranteed to be contiguous iterators, so that getting a raw memory address from them is OK. For arbitrary iterators, even random access iterators, we don't know that it's safe to lower the iterator to a pointer e.g. for std::deque iterators it's not, because (it + n) == (std::to_address(it) + n) only holds within the same block of the deque's storage. For C++20, std::to_address does work correctly for contiguous iterators, including __normal_iterator, and __to_address just calls std::to_address so also works. But we have to be sure we have an iterator that satisfies the std::contiguous_iterator concept for it to be safe, and we can't check that before C++20. So for pre-C++20 code the correct way to handle iterators that might be pointers or might be __normal_iterator is to call __niter_base, and if necessary use is_pointer to check whether __niter_base returned a real pointer. We currently have some uses of std::__to_address with iterators where we've checked that they're either pointers, or __normal_iterator wrappers around pointers, or satisfy std::contiguous_iterator. But this seems a little fragile, and it would be better to just use std::__niter_base for the pointers and __normal_iterator cases, and use C++20 std::to_address when the C++20 std::contiguous_iterator concept is satisfied. This patch does that. libstdc++-v3/ChangeLog: * include/bits/basic_string.h (basic_string::assign): Replace use of __to_address with __niter_base or std::to_address as appropriate. * include/bits/ptr_traits.h (__to_address): Add comment. * include/bits/shared_ptr_base.h (__shared_ptr): Qualify calls to __to_address. * include/bits/stl_algo.h (find): Replace use of __to_address with __niter_base or std::to_address as appropriate. Only use either of them when the range is not empty. * include/bits/stl_iterator.h (__to_address): Remove overload for __normal_iterator. * include/debug/safe_iterator.h (__to_address): Remove overload for _Safe_iterator. * include/std/ranges (views::counted): Replace use of __to_address with std::to_address. * testsuite/24_iterators/normal_iterator/to_address.cc: Removed. --- libstdc++-v3/include/bits/basic_string.h | 19 +-- libstdc++-v3/include/bits/ptr_traits.h| 4 libstdc++-v3/include/bits/shared_ptr_base.h | 4 ++-- libstdc++-v3/include/bits/stl_algo.h | 16 +++- libstdc++-v3/include/bits/stl_iterator.h | 12 libstdc++-v3/include/debug/safe_iterator.h| 17 - libstdc++-v3/include/std/ranges | 2 +- .../normal_iterator/to_address.cc | 19 --- 8 files changed, 31 insertions(+), 62 deletions(-) delete mode 100644 libstdc++-v3/testsuite/24_iterators/normal_iterator/to_address.cc diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index e9b17ea48b5..16e356e0678 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -1732,18 +1732,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 basic_string& assign(_InputIterator __first, _InputIterator __last) { + using _IterTraits = iterator_traits<_InputIterator>; + if constexpr (is_pointer::value + && is_same::value) + { + __glibcxx_requires_valid_range(__first, __last); + return _M_replace(size_type(0), size(), + std::__niter_base(__first), __last - __first); + } #if __cplusplus >= 202002L - if constexpr (contiguous_iterator<_InputIterator> - && is_same_v, _CharT>) -#else - if constexpr (__is_one_of<_InputIterator, const_iterator, iterator, - const _CharT*, _CharT*>::value) -#endif + else if constexpr (contiguous_iterat
Re: [PATCH 1/7] libstdc++: Refactor std::uninitialized_{copy, fill, fill_n} algos [PR68350]
On Fri, 18 Oct 2024 at 15:24, Patrick Palka wrote: > > On Fri, 18 Oct 2024, Jonathan Wakely wrote: > > > On 16/10/24 21:39 -0400, Patrick Palka wrote: > > > On Tue, 15 Oct 2024, Jonathan Wakely wrote: > > > > +#if __cplusplus < 201103L > > > > + > > > > + // True if we can unwrap _Iter to get a pointer by using > > > > std::__niter_base. > > > > + template > > > > +struct __unwrappable_niter > > > > +{ > > > > + template struct __is_ptr { enum { __value = 0 }; }; > > > > + template struct __is_ptr<_Tp*> { enum { __value = 1 > > > > }; }; > > > > + > > > > + typedef __decltype(std::__niter_base(*(_Iter*)0)) _Base; > > > > + > > > > + enum { __value = __is_ptr<_Base>::__value }; > > > > +}; > > > > > > It might be slightly cheaper to define this without the nested class > > > template as: > > > > > > template > > __decltype(std::__niter_base(*(_Iter*)0))> > > > struct __unwrappable_niter > > > { enum { __value = false }; }; > > > > > > template > > > struct __unwrappable_niter<_Iter, _Tp*> > > > { enum { __value = true }; }; > > One minor nit, we might as well use 'value' since it's a reserved name > even in C++98? Huh, I was under the impression it wasn't, but indeed we have binder1st::value and binder2nd::value! Why have we been using __value throughout cpp_type_traits.h then!?! I have indeed pushed it now, but could tweak that, as I'm still working in that file.
[PATCH] libstdc++: Improve 26_numerics/headers/cmath/types_std_c++0x_neg.cc
This test checks that the special functions in are not declared prior to C++17. But we can remove the target selector and allow it to be tested for C++17 and later, and add target selectors to the individual dg-error directives instead. Also rename the test to match what it actually tests. libstdc++-v3/ChangeLog: * testsuite/26_numerics/headers/cmath/types_std_c++0x_neg.cc: Move to ... * testsuite/26_numerics/headers/cmath/specfun_c++17.cc: here and adjust test to be valid for all -std dialects. --- Tested x86_64-linux. ...ypes_std_c++0x_neg.cc => specfun_c++17.cc} | 47 ++- 1 file changed, 24 insertions(+), 23 deletions(-) rename libstdc++-v3/testsuite/26_numerics/headers/cmath/{types_std_c++0x_neg.cc => specfun_c++17.cc} (57%) diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/types_std_c++0x_neg.cc b/libstdc++-v3/testsuite/26_numerics/headers/cmath/specfun_c++17.cc similarity index 57% rename from libstdc++-v3/testsuite/26_numerics/headers/cmath/types_std_c++0x_neg.cc rename to libstdc++-v3/testsuite/26_numerics/headers/cmath/specfun_c++17.cc index 977f800a4b0..efb60ea1fbb 100644 --- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/types_std_c++0x_neg.cc +++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/specfun_c++17.cc @@ -1,4 +1,4 @@ -// { dg-do compile { target { ! c++17 } } } +// { dg-do compile } // Copyright (C) 2007-2024 Free Software Foundation, Inc. // @@ -21,28 +21,29 @@ namespace gnu { - // C++11 changes from TR1. - using std::assoc_laguerre; // { dg-error "has not been declared" } - using std::assoc_legendre; // { dg-error "has not been declared" } - using std::beta; // { dg-error "has not been declared" } - using std::comp_ellint_1;// { dg-error "has not been declared" } - using std::comp_ellint_2;// { dg-error "has not been declared" } - using std::comp_ellint_3;// { dg-error "has not been declared" } + // C++17 additions from TR1. + using std::assoc_laguerre; // { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::assoc_legendre; // { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::beta; // { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::comp_ellint_1;// { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::comp_ellint_2;// { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::comp_ellint_3;// { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::cyl_bessel_i; // { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::cyl_bessel_j; // { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::cyl_bessel_k; // { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::cyl_neumann; // { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::ellint_1; // { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::ellint_2; // { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::ellint_3; // { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::expint; // { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::hermite; // { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::laguerre; // { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::legendre; // { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::riemann_zeta; // { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::sph_bessel; // { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::sph_legendre; // { dg-error "has not been declared" "" { target { ! c++17 } } } + using std::sph_neumann; // { dg-error "has not been declared" "" { target { ! c++17 } } } + // These two were in TR1 but not added to C++17. using std::conf_hyperg; // { dg-error "has not been declared" } - using std::cyl_bessel_i; // { dg-error "has not been declared" } - using std::cyl_bessel_j; // { dg-error "has not been declared" } - using std::cyl_bessel_k; // { dg-error "has not been declared" } - using std::cyl_neumann; // { dg-error "has not been declared" } - using std::ellint_1; // { dg-error "has not been declared" } - using std::ellint_2; // { dg-error "has not been declared" } - using std::ellint_3; // { dg-error "has not been declared" } - using std::expint; // { dg-error "has not been declared" } - using std::hermite; // { dg-error "has not been declared" } using std::hyperg; // { dg-error "has not been declared" } - using std::laguerre; // { dg-error "has not been declared" }
[PATCH] libstdc++: Simplify C++98 std::vector::_M_data_ptr overload set
We don't need separate overloads for returning a const or non-const pointer. We can make the member function const and return a non-const pointer, and let `vector::data() const` convert it to const as needed. libstdc++-v3/ChangeLog: * include/bits/stl_vector.h (vector::_M_data_ptr): Remove non-const overloads. Always return non-const pointer. --- Tested x86_64-linux. libstdc++-v3/include/bits/stl_vector.h | 12 +--- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/libstdc++-v3/include/bits/stl_vector.h b/libstdc++-v3/include/bits/stl_vector.h index e284536ad31..8982ca2b9ee 100644 --- a/libstdc++-v3/include/bits/stl_vector.h +++ b/libstdc++-v3/include/bits/stl_vector.h @@ -2034,20 +2034,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER _M_data_ptr(_Ptr __ptr) const { return empty() ? nullptr : std::__to_address(__ptr); } #else - template - _Up* - _M_data_ptr(_Up* __ptr) _GLIBCXX_NOEXCEPT - { return __ptr; } - template value_type* - _M_data_ptr(_Ptr __ptr) - { return empty() ? (value_type*)0 : __ptr.operator->(); } - - template - const value_type* _M_data_ptr(_Ptr __ptr) const - { return empty() ? (const value_type*)0 : __ptr.operator->(); } + { return empty() ? (value_type*)0 : __ptr.operator->(); } #endif }; -- 2.46.2
Re: [PATCH 1/7] libstdc++: Refactor std::uninitialized_{copy, fill, fill_n} algos [PR68350]
On 18/10/24 10:41 +0100, Jonathan Wakely wrote: On 16/10/24 21:39 -0400, Patrick Palka wrote: On Tue, 15 Oct 2024, Jonathan Wakely wrote: +#if __cplusplus < 201103L + + // True if we can unwrap _Iter to get a pointer by using std::__niter_base. + template +struct __unwrappable_niter +{ + template struct __is_ptr { enum { __value = 0 }; }; + template struct __is_ptr<_Tp*> { enum { __value = 1 }; }; + + typedef __decltype(std::__niter_base(*(_Iter*)0)) _Base; + + enum { __value = __is_ptr<_Base>::__value }; +}; It might be slightly cheaper to define this without the nested class template as: template struct __unwrappable_niter { enum { __value = false }; }; template struct __unwrappable_niter<_Iter, _Tp*> { enum { __value = true }; }; Nice. I think after spending a while failing to make any C++98 metaprogramming work for __memcpyable in cpp_type_traits.h I was not in the mood for fighting C++98 any more :-) But this works well. + + // Use template specialization for C++98 when 'if constexpr' can't be used. + template struct __uninitialized_copy { template @@ -186,53 +172,150 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<> struct __uninitialized_copy { + // Overload for generic iterators. template static _ForwardIterator __uninit_copy(_InputIterator __first, _InputIterator __last, _ForwardIterator __result) -{ return std::copy(__first, __last, __result); } -}; + { + if (__unwrappable_niter<_InputIterator>::__value + && __unwrappable_niter<_ForwardIterator>::__value) + { + __uninit_copy(std::__niter_base(__first), + std::__niter_base(__last), + std::__niter_base(__result)); + std::advance(__result, std::distance(__first, __last)); + return __result; + } + else + return std::__do_uninit_copy(__first, __last, __result); + } + // Overload for pointers. + template + static _Up* + __uninit_copy(_Tp* __first, _Tp* __last, _Up* __result) + { + // Ensure that we don't successfully memcpy in cases that should be + // ill-formed because is_constructible<_Up, _Tp&> is false. + typedef __typeof__(static_cast<_Up>(*__first)) __check + __attribute__((__unused__)); + + if (const ptrdiff_t __n = __last - __first) Do we have to worry about the __n == 1 case here like in the C++11 code path? Actually I think we don't need to worry about it in either case. C++20 had a note in [specialized.algorithms.general]/3 that said: [Note 1: When invoked on ranges of potentially-overlapping subobjects ([intro.object]), the algorithms specified in [specialized.algorithms] result in undefined behavior. — end note] The reason is that the uninitialized algos create new objects at the specified storage locations, and creating new objects reuses storage, which ends the lifetime of any other objects in that storage. That includes any objects that were in tail padding within that storage. See Casey's Feb 2023 comment at https://github.com/cplusplus/draft/issues/6143 That note was removed for C++23 (which is unfortunate IMHO), but the algos still reuse storage by creating new objects, and so still end the lifetime of potentially-overlapping subobjects within that storage. For std::copy there are no new objects created, and the effects are specified in terms of assignment, which does not reuse storage. A compiler-generated trivial copy assignment operator is careful to not overwrite tail padding, so we can't use memmove if it would produce different effects. tl;dr I think I can remove the __n == 1 handling from the C++11 paths. I actually had `if (__n > 0)` in an earlier version, and then looked at it before posting the patch and "fixed" it to check __n > 1 and then handle the __n == 1 case. But that's not nexcessary here, I'd just been spending too much time looking at std::copy and got confused.
Re: [PATCH 1/7] libstdc++: Refactor std::uninitialized_{copy, fill, fill_n} algos [PR68350]
On 16/10/24 21:39 -0400, Patrick Palka wrote: On Tue, 15 Oct 2024, Jonathan Wakely wrote: +#if __cplusplus < 201103L + + // True if we can unwrap _Iter to get a pointer by using std::__niter_base. + template +struct __unwrappable_niter +{ + template struct __is_ptr { enum { __value = 0 }; }; + template struct __is_ptr<_Tp*> { enum { __value = 1 }; }; + + typedef __decltype(std::__niter_base(*(_Iter*)0)) _Base; + + enum { __value = __is_ptr<_Base>::__value }; +}; It might be slightly cheaper to define this without the nested class template as: template struct __unwrappable_niter { enum { __value = false }; }; template struct __unwrappable_niter<_Iter, _Tp*> { enum { __value = true }; }; Nice. I think after spending a while failing to make any C++98 metaprogramming work for __memcpyable in cpp_type_traits.h I was not in the mood for fighting C++98 any more :-) But this works well. + + // Use template specialization for C++98 when 'if constexpr' can't be used. + template struct __uninitialized_copy { template @@ -186,53 +172,150 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<> struct __uninitialized_copy { + // Overload for generic iterators. template static _ForwardIterator __uninit_copy(_InputIterator __first, _InputIterator __last, _ForwardIterator __result) -{ return std::copy(__first, __last, __result); } -}; + { + if (__unwrappable_niter<_InputIterator>::__value + && __unwrappable_niter<_ForwardIterator>::__value) + { + __uninit_copy(std::__niter_base(__first), + std::__niter_base(__last), + std::__niter_base(__result)); + std::advance(__result, std::distance(__first, __last)); + return __result; + } + else + return std::__do_uninit_copy(__first, __last, __result); + } + // Overload for pointers. + template + static _Up* + __uninit_copy(_Tp* __first, _Tp* __last, _Up* __result) + { + // Ensure that we don't successfully memcpy in cases that should be + // ill-formed because is_constructible<_Up, _Tp&> is false. + typedef __typeof__(static_cast<_Up>(*__first)) __check + __attribute__((__unused__)); + + if (const ptrdiff_t __n = __last - __first) Do we have to worry about the __n == 1 case here like in the C++11 code path? Actually I think we don't need to worry about it in either case. C++20 had a note in [specialized.algorithms.general]/3 that said: [Note 1: When invoked on ranges of potentially-overlapping subobjects ([intro.object]), the algorithms specified in [specialized.algorithms] result in undefined behavior. — end note] The reason is that the uninitialized algos create new objects at the specified storage locations, and creating new objects reuses storage, which ends the lifetime of any other objects in that storage. That includes any objects that were in tail padding within that storage. See Casey's Feb 2023 comment at https://github.com/cplusplus/draft/issues/6143 That note was removed for C++23 (which is unfortunate IMHO), but the algos still reuse storage by creating new objects, and so still end the lifetime of potentially-overlapping subobjects within that storage. For std::copy there are no new objects created, and the effects are specified in terms of assignment, which does not reuse storage. A compiler-generated trivial copy assignment operator is careful to not overwrite tail padding, so we can't use memmove if it would produce different effects. tl;dr I think I can remove the __n == 1 handling from the C++11 paths. + { + __builtin_memcpy(__result, __first, __n * sizeof(_Tp)); + __result += __n; + } + return __result; + } +}; +#endif /// @endcond +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++17-extensions" /** * @brief Copies the range [first,last) into result. * @param __first An input iterator. * @param __last An input iterator. - * @param __result An output iterator. - * @return __result + (__first - __last) + * @param __result A forward iterator. + * @return __result + (__last - __first) * - * Like copy(), but does not require an initialized output range. + * Like std::copy, but does not require an initialized output range. */ template inline _ForwardIterator uninitialized_copy(_InputIterator __first, _InputIterator __last, _ForwardIterator __result) { + // We can use memcpy to copy the ranges under these conditions: + // + // _ForwardIterator and _InputIterator are both contiguous iterators
Re: [PATCH] Add fancy pointer support in std::map/set
On Thu, 17 Oct 2024 at 21:39, Jonathan Wakely wrote: > > > On Thu, 17 Oct 2024 at 20:52, François Dumont > wrote: > >> Here is an updated version that compiles, I think, all your feedbacks. >> It's much cleaner indeed. >> > > Thanks, I'll take a look tomorrow. > > >> It's also tested in C++98/17/23. >> >> I'm surprised that we do not need to consider potential >> allocator::const_pointer. >> > Do you mean consider the case where Alloc::const_pointer is not the same > type as rebinding 'pointer' to a const element type? > > We don't need to consider that because we never get a 'const_pointer' from > the allocator, and we never need to pass a 'const_pointer' to the > allocator. The allocator's 'allocate' and 'deallocate' members both work > with the 'pointer' type, so we only need to use that type when interacting > with the allocator. For all the other uses, such as _Const_Node_ptr, what > we need is a pointer-to-const that's compatible with the allocator's > pointer type. It doesn't actually matter if it's the same type as > allocator_traits::const_pointer, because we don't need > Sorry, I sent the email before finishing that thought! ... we don't need to pass a const_pointer to anything, we only need it for the container's own purposes. But thinking about it some more, do we even need a const-pointer for the container? Currently the const_iterator stores a const-pointer, and some members like _M_root() and _M_leftmost() return a const-pointer. But they don't need to. The nodes are all pointed to by a non-const _Base_ptr, none of the storage managed by the container is const. We could just use the non-const pointers everywhere, which would make things much simpler! The const_iterator stores a const_pointer, and returns a const-pointer from operator->(), so maybe _Rb_tree_const_piterator should take the allocator's const_pointer as its template argument, instead of the non-const ValPtr. So the trait would take two pointer types, but the const one would only be used for the const iterator: template struct _Rb_tree_node_traits { using _Node_base = _Rb_tree_pnode_base<_ValPtr>; using _Node_type = _Rb_tree_pnode<_ValPtr>; using _Header_t = _Rb_tree_pheader<_Node_base>; using _Iterator_t = _Rb_tree_piterator<_ValPtr>; using _Const_iterator_t = _Rb_tree_const_piterator<_CValPtr>; }; Would that work? I can experiment with that if you like. > > >> Is there a plan to deprecate it ? >> > > No, although I think that would be possible. Nothing in the allocator > requirements ever uses that type or cares what it is, as long as it's > convertible to 'const_void_pointer', and 'pointer' is convertible to > 'const_pointer'. > > >> And if not, should not alloc traits const_pointer be per default a rebind >> of pointer for const element_type like in the __add_const_to_ptr you made >> me add ? I can try to work on a patch for that if needed. >> > > No, allocator_traits is defined correctly as the standard requires. If an > allocator A defines a 'A::const_pointer' typedef, then that is used. If > not, then 'allocator_traits::const_pointer' defaults to rebinding the > non-const 'allocator_traits::pointer' type. > > >
Re: [PATCH] Add fancy pointer support in std::map/set
On Thu, 17 Oct 2024 at 20:52, François Dumont wrote: > Here is an updated version that compiles, I think, all your feedbacks. > It's much cleaner indeed. > Thanks, I'll take a look tomorrow. > It's also tested in C++98/17/23. > > I'm surprised that we do not need to consider potential > allocator::const_pointer. > Do you mean consider the case where Alloc::const_pointer is not the same type as rebinding 'pointer' to a const element type? We don't need to consider that because we never get a 'const_pointer' from the allocator, and we never need to pass a 'const_pointer' to the allocator. The allocator's 'allocate' and 'deallocate' members both work with the 'pointer' type, so we only need to use that type when interacting with the allocator. For all the other uses, such as _Const_Node_ptr, what we need is a pointer-to-const that's compatible with the allocator's pointer type. It doesn't actually matter if it's the same type as allocator_traits::const_pointer, because we don't need > Is there a plan to deprecate it ? > No, although I think that would be possible. Nothing in the allocator requirements ever uses that type or cares what it is, as long as it's convertible to 'const_void_pointer', and 'pointer' is convertible to 'const_pointer'. > And if not, should not alloc traits const_pointer be per default a rebind > of pointer for const element_type like in the __add_const_to_ptr you made > me add ? I can try to work on a patch for that if needed. > No, allocator_traits is defined correctly as the standard requires. If an allocator A defines a 'A::const_pointer' typedef, then that is used. If not, then 'allocator_traits::const_pointer' defaults to rebinding the non-const 'allocator_traits::pointer' type.
[PATCH] libstdc++: Move std::__niter_base and std::__niter_wrap to stl_iterator.h
I've split this out of "Refactor std::uninitialized_{copy, fill, fill_n}" because this part can be done separately. Call it [PATCH -1/7] if you like :-) This fixes the ordering problem that Patrick noticed in [PATCH 1/7], and adds a test for it. It also updates the comments as was previously done in [PATCH 2/7], which Patrick noted could have been done when moving the functions into stl_iterator.h. Note that the __niter_base overloads for reverse_iterator and move_iterator call __niter_base unqualified, which means that in contrast to all other uses of __niter_base they *do* use ADL to find the next __niter_base to call. I think that's necessary so that it works for both reverse_iterator> and the inverse order, move_iterator>. I haven't changed that here, they still use unqualified calls. As a further change in this area, I think it would be possible (and maybe nice) to remove __miter_base and replace the uses of it in std::move_backward(I,I,O) and std::move(I,I,O). That's left for another day. Tested x86_64-linux. -- >8 -- Move the functions for unwrapping and rewrapping __normal_iterator objects to the same file as the definition of __normal_iterator itself. This will allow a later commit to make use of std::__niter_base in other headers without having to include all of . libstdc++-v3/ChangeLog: * include/bits/stl_algobase.h (__niter_base, __niter_wrap): Move to ... * include/bits/stl_iterator.h: ... here. (__niter_base, __miter_base): Move all overloads to the end of the header. * testsuite/24_iterators/normal_iterator/wrapping.cc: New test. --- libstdc++-v3/include/bits/stl_algobase.h | 45 -- libstdc++-v3/include/bits/stl_iterator.h | 138 +- .../24_iterators/normal_iterator/wrapping.cc | 29 3 files changed, 132 insertions(+), 80 deletions(-) create mode 100644 libstdc++-v3/testsuite/24_iterators/normal_iterator/wrapping.cc diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h index 384e5fdcdc9..751b7ad119b 100644 --- a/libstdc++-v3/include/bits/stl_algobase.h +++ b/libstdc++-v3/include/bits/stl_algobase.h @@ -308,51 +308,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __a; } - // Fallback implementation of the function in bits/stl_iterator.h used to - // remove the __normal_iterator wrapper. See copy, fill, ... - template -_GLIBCXX20_CONSTEXPR -inline _Iterator -__niter_base(_Iterator __it) -_GLIBCXX_NOEXCEPT_IF(std::is_nothrow_copy_constructible<_Iterator>::value) -{ return __it; } - -#if __cplusplus < 201103L - template -_Ite -__niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, -std::random_access_iterator_tag>&); - - template -_Ite -__niter_base(const ::__gnu_debug::_Safe_iterator< -::__gnu_cxx::__normal_iterator<_Ite, _Cont>, _Seq, -std::random_access_iterator_tag>&); -#else - template -_GLIBCXX20_CONSTEXPR -decltype(std::__niter_base(std::declval<_Ite>())) -__niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq, -std::random_access_iterator_tag>&) -noexcept(std::is_nothrow_copy_constructible<_Ite>::value); -#endif - - // Reverse the __niter_base transformation to get a - // __normal_iterator back again (this assumes that __normal_iterator - // is only used to wrap random access iterators, like pointers). - template -_GLIBCXX20_CONSTEXPR -inline _From -__niter_wrap(_From __from, _To __res) -{ return __from + (std::__niter_base(__res) - std::__niter_base(__from)); } - - // No need to wrap, iterator already has the right type. - template -_GLIBCXX20_CONSTEXPR -inline _Iterator -__niter_wrap(const _Iterator&, _Iterator __res) -{ return __res; } - // All of these auxiliary structs serve two purposes. (1) Replace // calls to copy with memmove whenever possible. (Memmove, not memcpy, // because the input and output ranges are permitted to overlap.) diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index 28a600c81cb..be3fa6f7a34 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -654,24 +654,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION # endif // C++20 # endif // __glibcxx_make_reverse_iterator - template -_GLIBCXX20_CONSTEXPR -auto -__niter_base(reverse_iterator<_Iterator> __it) --> decltype(__make_reverse_iterator(__niter_base(__it.base( -{ return __make_reverse_iterator(__niter_base(__it.base())); } - template struct __is_move_iterator > : __is_move_iterator<_Iterator> { }; - - template -_GLIBCXX20_CONSTEXPR -auto -__miter_base(reverse_iterator<_Iterator> __it) --> decltype(__make_reverse_iterator(__miter_base(__it.base( -{ return __make_reverse_iterator(__miter_base(__it.base())); } #endif // C++11
Re: [PATCH 1/7] libstdc++: Refactor std::uninitialized_{copy, fill, fill_n} algos [PR68350]
On Thu, 17 Oct 2024 at 11:12, Jonathan Wakely wrote: > > On Thu, 17 Oct 2024 at 02:39, Patrick Palka wrote: > > > > On Tue, 15 Oct 2024, Jonathan Wakely wrote: > > > > > This is v2 of > > > https://gcc.gnu.org/pipermail/gcc-patches/2024-October/665246.html > > > fixing some thinkos in uninitialized_{fill,fill_n}. We don't need to > > > worry about overwriting tail-padding in those algos, because we only use > > > memset for 1-byte integer types. So they have no tail padding that can > > > be reused anyway! So this changes __n > 1 to __n > 0 in a few places > > > (which fixes the problem that it was not actually filling anything for > > > the n==1 cases). > > > > > > Also simplify std::__to_address(__result++) to just __result++ because > > > we already have a pointer, and use std::to_address(result++) for a C++20 > > > std::contiguous_iterator case, instead of addressof(*result++). > > > > > > Tested x86_64-linux. > > > > > > -- >8 -- > > > > > > This refactors the std::uninitialized_copy, std::uninitialized_fill and > > > std::uninitialized_fill_n algorithms to directly perform memcpy/memset > > > optimizations instead of dispatching to std::copy/std::fill/std::fill_n. > > > > > > The reasons for this are: > > > > > > - Use 'if constexpr' to simplify and optimize compilation throughput, so > > > dispatching to specialized class templates is only needed for C++98 > > > mode. > > > - Relax the conditions for using memcpy/memset, because the C++20 rules > > > on implicit-lifetime types mean that we can rely on memcpy to begin > > > lifetimes of trivially copyable types. We don't need to require > > > trivially default constructible, so don't need to limit the > > > optimization to trivial types. See PR 68350 for more details. > > > - The conditions on non-overlapping ranges are stronger for > > > std::uninitialized_copy than for std::copy so we can use memcpy instead > > > of memmove, which might be a minor optimization. > > > - Avoid including in . > > > It only needs some iterator utilities from that file now, which belong > > > in anyway, so this moves them there. > > > > > > Several tests need changes to the diagnostics matched by dg-error > > > because we no longer use the __constructible() function that had a > > > static assert in. Now we just get straightforward errors for attempting > > > to use a deleted constructor. > > > > > > Two tests needed more signficant changes to the actual expected results > > > of executing the tests, because they were checking for old behaviour > > > which was incorrect according to the standard. > > > 20_util/specialized_algorithms/uninitialized_copy/64476.cc was expecting > > > std::copy to be used for a call to std::uninitialized_copy involving two > > > trivially copyable types. That was incorrect behaviour, because a > > > non-trivial constructor should have been used, but using std::copy used > > > trivial default initialization followed by assignment. > > > 20_util/specialized_algorithms/uninitialized_fill_n/sizes.cc was testing > > > the behaviour with a non-integral Size passed to uninitialized_fill_n, > > > but I wrote the test looking at the requirements of uninitialized_copy_n > > > which are not the same as uninitialized_fill_n. The former uses --n and > > > tests n > 0, but the latter just tests n-- (which will never be false > > > for a floating-point value with a fractional part). > > > > > > libstdc++-v3/ChangeLog: > > > > > > PR libstdc++/68350 > > > PR libstdc++/93059 > > > * include/bits/stl_algobase.h (__niter_base, __niter_wrap): Move > > > to ... > > > * include/bits/stl_iterator.h: ... here. > > > * include/bits/stl_uninitialized.h (__check_constructible) > > > (_GLIBCXX_USE_ASSIGN_FOR_INIT): Remove. > > > [C++98] (__unwrappable_niter): New trait. > > > (__uninitialized_copy): Replace use of std::copy. > > > (uninitialized_copy): Fix Doxygen comments. Open-code memcpy > > > optimization for C++11 and later. > > > (__uninitialized_fill): Replace use of std::fill. > > > (uninitialized_fill): Fix Doxygen comments. Open-code memset > > > optimization for C++11 and later. > > > (__uninitialized_fill_n): Replace us
Re: [PATCH 1/7] libstdc++: Refactor std::uninitialized_{copy, fill, fill_n} algos [PR68350]
On Thu, 17 Oct 2024 at 02:39, Patrick Palka wrote: > > On Tue, 15 Oct 2024, Jonathan Wakely wrote: > > > This is v2 of > > https://gcc.gnu.org/pipermail/gcc-patches/2024-October/665246.html > > fixing some thinkos in uninitialized_{fill,fill_n}. We don't need to > > worry about overwriting tail-padding in those algos, because we only use > > memset for 1-byte integer types. So they have no tail padding that can > > be reused anyway! So this changes __n > 1 to __n > 0 in a few places > > (which fixes the problem that it was not actually filling anything for > > the n==1 cases). > > > > Also simplify std::__to_address(__result++) to just __result++ because > > we already have a pointer, and use std::to_address(result++) for a C++20 > > std::contiguous_iterator case, instead of addressof(*result++). > > > > Tested x86_64-linux. > > > > -- >8 -- > > > > This refactors the std::uninitialized_copy, std::uninitialized_fill and > > std::uninitialized_fill_n algorithms to directly perform memcpy/memset > > optimizations instead of dispatching to std::copy/std::fill/std::fill_n. > > > > The reasons for this are: > > > > - Use 'if constexpr' to simplify and optimize compilation throughput, so > > dispatching to specialized class templates is only needed for C++98 > > mode. > > - Relax the conditions for using memcpy/memset, because the C++20 rules > > on implicit-lifetime types mean that we can rely on memcpy to begin > > lifetimes of trivially copyable types. We don't need to require > > trivially default constructible, so don't need to limit the > > optimization to trivial types. See PR 68350 for more details. > > - The conditions on non-overlapping ranges are stronger for > > std::uninitialized_copy than for std::copy so we can use memcpy instead > > of memmove, which might be a minor optimization. > > - Avoid including in . > > It only needs some iterator utilities from that file now, which belong > > in anyway, so this moves them there. > > > > Several tests need changes to the diagnostics matched by dg-error > > because we no longer use the __constructible() function that had a > > static assert in. Now we just get straightforward errors for attempting > > to use a deleted constructor. > > > > Two tests needed more signficant changes to the actual expected results > > of executing the tests, because they were checking for old behaviour > > which was incorrect according to the standard. > > 20_util/specialized_algorithms/uninitialized_copy/64476.cc was expecting > > std::copy to be used for a call to std::uninitialized_copy involving two > > trivially copyable types. That was incorrect behaviour, because a > > non-trivial constructor should have been used, but using std::copy used > > trivial default initialization followed by assignment. > > 20_util/specialized_algorithms/uninitialized_fill_n/sizes.cc was testing > > the behaviour with a non-integral Size passed to uninitialized_fill_n, > > but I wrote the test looking at the requirements of uninitialized_copy_n > > which are not the same as uninitialized_fill_n. The former uses --n and > > tests n > 0, but the latter just tests n-- (which will never be false > > for a floating-point value with a fractional part). > > > > libstdc++-v3/ChangeLog: > > > > PR libstdc++/68350 > > PR libstdc++/93059 > > * include/bits/stl_algobase.h (__niter_base, __niter_wrap): Move > > to ... > > * include/bits/stl_iterator.h: ... here. > > * include/bits/stl_uninitialized.h (__check_constructible) > > (_GLIBCXX_USE_ASSIGN_FOR_INIT): Remove. > > [C++98] (__unwrappable_niter): New trait. > > (__uninitialized_copy): Replace use of std::copy. > > (uninitialized_copy): Fix Doxygen comments. Open-code memcpy > > optimization for C++11 and later. > > (__uninitialized_fill): Replace use of std::fill. > > (uninitialized_fill): Fix Doxygen comments. Open-code memset > > optimization for C++11 and later. > > (__uninitialized_fill_n): Replace use of std::fill_n. > > (uninitialized_fill_n): Fix Doxygen comments. Open-code memset > > optimization for C++11 and later. > > * > > testsuite/20_util/specialized_algorithms/uninitialized_copy/64476.cc: > > Adjust expected behaviour to match what the standard specifies. > > * > > testsuite/20_util/specialized_algorithms/uninitialized_fill_n/sizes.cc: > > Likewise. &g
Re: [PATCH 3/7] libstdc++: Inline memmove optimizations for std::copy etc. [PR115444]
On Thu, 17 Oct 2024, 03:04 Patrick Palka, wrote: > On Tue, 15 Oct 2024, Jonathan Wakely wrote: > > > This is a slightly different approach to C++98 compatibility than used > > in patch 1/1 of this series for the uninitialized algos. It worked out a > > bit cleaner this way for these algos, I think. > > > > Tested x86_64-linux. > > > > -- >8 -- > > > > This removes all the __copy_move class template specializations that > > decide how to optimize std::copy and std::copy_n. We can inline those > > optimizations into the algorithms, using if-constexpr (and macros for > > C++98 compatibility) and remove the code dispatching to the various > > class template specializations. > > > > Doing this means we implement the optimization directly for std::copy_n > > instead of deferring to std::copy, That avoids the unwanted consequence > > of advancing the iterator in copy_n only to take the difference later to > > get back to the length that we already had in copy_n originally (as > > described in PR 115444). > > > > With the new flattened implementations, we can also lower contiguous > > iterators to pointers in std::copy/std::copy_n/std::copy_backwards, so > > that they benefit from the same memmove optimizations as pointers. > > There's a subtlety though: contiguous iterators can potentially throw > > exceptions to exit the algorithm early. So we can only transform the > > loop to memmove if dereferencing the iterator is noexcept. We don't > > check that incrementing the iterator is noexcept because we advance the > > contiguous iterators before using memmove, so that if incrementing would > > throw, that happens first. I am writing a proposal (P3249R0) which would > > make this unnecessary, so I hope we can drop the nothrow requirements > > later. > > > > This change also solves PR 114817 by checking is_trivially_assignable > > before optimizing copy/copy_n etc. to memmove. It's not enough to check > > that the types are trivially copyable (a precondition for using memmove > > at all), we also need to check that the specific assignment that would > > be performed by the algorithm is also trivial. Replacing a non-trivial > > assignment with memmove would be observable, so not allowed. > > > > libstdc++-v3/ChangeLog: > > > > PR libstdc++/115444 > > PR libstdc++/114817 > > * include/bits/stl_algo.h (__copy_n): Remove generic overload > > and overload for random access iterators. > > (copy_n): Inline generic version of __copy_n here. Do not defer > > to std::copy for random access iterators. > > * include/bits/stl_algobase.h (__copy_move): Remove. > > (__nothrow_contiguous_iterator, __memcpyable_iterators): New > > concepts. > > (__assign_one, _GLIBCXX_TO_ADDR, _GLIBCXX_ADVANCE): New helpers. > > (__copy_move_a2): Inline __copy_move logic and conditional > > memmove optimization into the most generic overload. > > (__copy_n_a): Likewise. > > (__copy_move_backward): Remove. > > (__copy_move_backward_a2): Inline __copy_move_backward logic and > > memmove optimization into the most generic overload. > > * > testsuite/20_util/specialized_algorithms/uninitialized_copy/114817.cc: > > New test. > > * > testsuite/20_util/specialized_algorithms/uninitialized_copy_n/114817.cc: > > New test. > > * testsuite/25_algorithms/copy/114817.cc: New test. > > * testsuite/25_algorithms/copy/115444.cc: New test. > > * testsuite/25_algorithms/copy_n/114817.cc: New test. > > --- > > libstdc++-v3/include/bits/stl_algo.h | 24 +- > > libstdc++-v3/include/bits/stl_algobase.h | 426 +- > > .../uninitialized_copy/114817.cc | 39 ++ > > .../uninitialized_copy_n/114817.cc| 39 ++ > > .../testsuite/25_algorithms/copy/114817.cc| 38 ++ > > .../testsuite/25_algorithms/copy/115444.cc| 93 > > .../testsuite/25_algorithms/copy_n/114817.cc | 38 ++ > > 7 files changed, 469 insertions(+), 228 deletions(-) > > create mode 100644 > libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/114817.cc > > create mode 100644 > libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy_n/114817.cc > > create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy/114817.cc > > create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy/115444.cc > > create mode 100644 libstdc++-v3/testsuite/25
Re: [PATCH 2/7] libstdc++: Make __normal_iterator constexpr, always_inline, nodiscard
On Thu, 17 Oct 2024, 03:33 Patrick Palka, wrote: > On Tue, 15 Oct 2024, Jonathan Wakely wrote: > > > Tested x86_64-linux. > > > > -- >8 -- > > > > The __gnu_cxx::__normal_iterator type we use for std::vector::iterator > > is not specified by the standard, it's an implementation detail. This > > means it's not constrained by the rule that forbids strengthening > > constexpr. We can make it meet the constexpr iterator requirements for > > older standards, not only when it's required to be for C++20. > > > > For the non-const member functions they can't be constexpr in C++11, so > > use _GLIBCXX14_CONSTEXPR for those. For all constructors, const members > > and non-member operator overloads, use _GLIBCXX_CONSTEXPR or just > > constexpr. > > > > We can also liberally add [[nodiscard]] and [[gnu::always_inline]] > > attributes to those functions. > > > > Also change some internal helpers for std::move_iterator which can be > > unconditionally constexpr and marked nodiscard. > > > > libstdc++-v3/ChangeLog: > > > > * include/bits/stl_iterator.h (__normal_iterator): Make all > > members and overloaded operators constexpr before C++20. > > (__niter_base, __niter_wrap, __to_address): Add nodiscard > > and always_inline attributes. > > (__make_move_if_noexcept_iterator, __miter_base): Add nodiscard > > and make unconditionally constexpr. > > --- > > libstdc++-v3/include/bits/stl_iterator.h | 125 ++- > > 1 file changed, 76 insertions(+), 49 deletions(-) > > > > diff --git a/libstdc++-v3/include/bits/stl_iterator.h > b/libstdc++-v3/include/bits/stl_iterator.h > > index 85b9861..3cc10a160bd 100644 > > --- a/libstdc++-v3/include/bits/stl_iterator.h > > +++ b/libstdc++-v3/include/bits/stl_iterator.h > > @@ -656,7 +656,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > > >template > > _GLIBCXX20_CONSTEXPR > > -auto > > +inline auto > > __niter_base(reverse_iterator<_Iterator> __it) > > -> decltype(__make_reverse_iterator(__niter_base(__it.base( > > { return __make_reverse_iterator(__niter_base(__it.base())); } > > @@ -668,7 +668,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > > >template > > _GLIBCXX20_CONSTEXPR > > -auto > > +inline auto > > These 'inline' additions aren't mentioned in the ChangeLog it seems. Good point. Is > the intent of these inlines solely as a compiler hint? > Yes, but they do a little more work than the really trivial ones, and are less important, less frequently used, so I didn't think always_inline was justified. > > __miter_base(reverse_iterator<_Iterator> __it) > > -> decltype(__make_reverse_iterator(__miter_base(__it.base( > > { return __make_reverse_iterator(__miter_base(__it.base())); } > > @@ -1060,23 +1060,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > >using iterator_concept = std::__detail::__iter_concept<_Iterator>; > > #endif > > > > - _GLIBCXX_CONSTEXPR __normal_iterator() _GLIBCXX_NOEXCEPT > > - : _M_current(_Iterator()) { } > > + __attribute__((__always_inline__)) > > + _GLIBCXX_CONSTEXPR > > + __normal_iterator() _GLIBCXX_NOEXCEPT > > + : _M_current() { } > > > > - explicit _GLIBCXX20_CONSTEXPR > > + __attribute__((__always_inline__)) > > + explicit _GLIBCXX_CONSTEXPR > >__normal_iterator(const _Iterator& __i) _GLIBCXX_NOEXCEPT > >: _M_current(__i) { } > > > >// Allow iterator to const_iterator conversion > > #if __cplusplus >= 201103L > >template> > > - _GLIBCXX20_CONSTEXPR > > + [[__gnu__::__always_inline__]] > > + constexpr > > __normal_iterator(const __normal_iterator<_Iter, _Container>& __i) > > noexcept > > #else > >// N.B. _Container::pointer is not actually in container > requirements, > >// but is present in std::vector and std::basic_string. > >template > > + __attribute__((__always_inline__)) > > __normal_iterator(const __normal_iterator<_Iter, > > typename __enable_if< > > (std::__are_same<_Iter, typename > _Container::pointer>::__value), > > @@ -1085,17 +1090,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > : _M_current(__i.base()) { } > > > >// Forward iterator requirements > > -
Re: [committed] libstdc++: Fix Python deprecation warning in printers.py
On Wed, 16 Oct 2024 at 16:58, Tom Tromey wrote: > > >>>>> "Jonathan" == Jonathan Wakely writes: > > Jonathan> Using a keyword argument for count only became possible with Python > 3.1 > Jonathan> so introduce a new function to do the substitution. > > gdb docs are inconsistent on this, but at least one spot says that the > minimum supported Python version is 3.2. Plus, I know we agreed that > the minimum should be 3.4, and I'll be sending a patch to this effect > soon. > > Anyway, I think it would be reasonably safe to just assume 3.1 if you > want to do that. We still have a few places in the printers.py file that check for Python 3 vs Python 2, so I did so here too. For the Python 3 case, I'm assuming 3.1 or later, because I can imagine some people might be stuck on Python 2 for some reason (and also unable to build GDB with Python 3? ... maybe unlikely) but nobody should be stuck on 3.0 and unable to replace that with 3.12 or so. So the condition is Python 2x, or Python 3.1+, and Python 3.0 is unsupported. If we no longer care about Python 2 there are a few places in that file we could clean up.
Re: [PATCH 3/7] libstdc++: Inline memmove optimizations for std::copy etc. [PR115444]
On Tue, 15 Oct 2024 at 15:29, Jonathan Wakely wrote: > > This is a slightly different approach to C++98 compatibility than used > in patch 1/1 of this series for the uninitialized algos. It worked out a > bit cleaner this way for these algos, I think. > > Tested x86_64-linux. > > -- >8 -- > > This removes all the __copy_move class template specializations that > decide how to optimize std::copy and std::copy_n. We can inline those > optimizations into the algorithms, using if-constexpr (and macros for > C++98 compatibility) and remove the code dispatching to the various > class template specializations. > > Doing this means we implement the optimization directly for std::copy_n > instead of deferring to std::copy, That avoids the unwanted consequence > of advancing the iterator in copy_n only to take the difference later to > get back to the length that we already had in copy_n originally (as > described in PR 115444). > > With the new flattened implementations, we can also lower contiguous > iterators to pointers in std::copy/std::copy_n/std::copy_backwards, so > that they benefit from the same memmove optimizations as pointers. > There's a subtlety though: contiguous iterators can potentially throw > exceptions to exit the algorithm early. So we can only transform the > loop to memmove if dereferencing the iterator is noexcept. We don't > check that incrementing the iterator is noexcept because we advance the > contiguous iterators before using memmove, so that if incrementing would > throw, that happens first. I am writing a proposal (P3249R0) which would Oops, got my own paper number wrong, I've fixed that locally. The paper is online now: https://isocpp.org/files/papers/P3349R0.html > make this unnecessary, so I hope we can drop the nothrow requirements > later. > > This change also solves PR 114817 by checking is_trivially_assignable > before optimizing copy/copy_n etc. to memmove. It's not enough to check > that the types are trivially copyable (a precondition for using memmove > at all), we also need to check that the specific assignment that would > be performed by the algorithm is also trivial. Replacing a non-trivial > assignment with memmove would be observable, so not allowed. > > libstdc++-v3/ChangeLog: > > PR libstdc++/115444 > PR libstdc++/114817 > * include/bits/stl_algo.h (__copy_n): Remove generic overload > and overload for random access iterators. > (copy_n): Inline generic version of __copy_n here. Do not defer > to std::copy for random access iterators. > * include/bits/stl_algobase.h (__copy_move): Remove. > (__nothrow_contiguous_iterator, __memcpyable_iterators): New > concepts. > (__assign_one, _GLIBCXX_TO_ADDR, _GLIBCXX_ADVANCE): New helpers. > (__copy_move_a2): Inline __copy_move logic and conditional > memmove optimization into the most generic overload. > (__copy_n_a): Likewise. > (__copy_move_backward): Remove. > (__copy_move_backward_a2): Inline __copy_move_backward logic and > memmove optimization into the most generic overload. > * > testsuite/20_util/specialized_algorithms/uninitialized_copy/114817.cc: > New test. > * > testsuite/20_util/specialized_algorithms/uninitialized_copy_n/114817.cc: > New test. > * testsuite/25_algorithms/copy/114817.cc: New test. > * testsuite/25_algorithms/copy/115444.cc: New test. > * testsuite/25_algorithms/copy_n/114817.cc: New test. > --- > libstdc++-v3/include/bits/stl_algo.h | 24 +- > libstdc++-v3/include/bits/stl_algobase.h | 426 +- > .../uninitialized_copy/114817.cc | 39 ++ > .../uninitialized_copy_n/114817.cc| 39 ++ > .../testsuite/25_algorithms/copy/114817.cc| 38 ++ > .../testsuite/25_algorithms/copy/115444.cc| 93 > .../testsuite/25_algorithms/copy_n/114817.cc | 38 ++ > 7 files changed, 469 insertions(+), 228 deletions(-) > create mode 100644 > libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/114817.cc > create mode 100644 > libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy_n/114817.cc > create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy/114817.cc > create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy/115444.cc > create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy_n/114817.cc > > diff --git a/libstdc++-v3/include/bits/stl_algo.h > b/libstdc++-v3/include/bits/stl_algo.h > index a1ef665506d..489ce7e14d2 100644 > --- a/libstdc++-v3/include/bits/stl_algo.h > +++ b/libstdc++-v3/include/bits/stl_algo.h >
[committed] libstdc++: Fix Python deprecation warning in printers.py
Tested x86_64-linux with gdb-15.1 and Python 3.12. Pushed to trunk, backports to follow. -- >8 -- python/libstdcxx/v6/printers.py:1355: DeprecationWarning: 'count' is passed as positional argument The Python docs say: Deprecated since version 3.13: Passing count and flags as positional arguments is deprecated. In future Python versions they will be keyword-only parameters. Using a keyword argument for count only became possible with Python 3.1 so introduce a new function to do the substitution. libstdc++-v3/ChangeLog: * python/libstdcxx/v6/printers.py (strip_fundts_namespace): New. (StdExpAnyPrinter, StdExpOptionalPrinter): Use it. --- libstdc++-v3/python/libstdcxx/v6/printers.py | 19 +-- 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py index 92104937862..d05b79762fd 100644 --- a/libstdc++-v3/python/libstdcxx/v6/printers.py +++ b/libstdc++-v3/python/libstdcxx/v6/printers.py @@ -220,6 +220,16 @@ def strip_versioned_namespace(typename): return typename.replace(_versioned_namespace, '') +def strip_fundts_namespace(typ): +"""Remove "fundamentals_vN" inline namespace from qualified type name.""" +pattern = r'^std::experimental::fundamentals_v\d::' +repl = 'std::experimental::' +if sys.version_info[0] == 2: +return re.sub(pattern, repl, typ, 1) +else: # Technically this needs Python 3.1 but nobody should be using 3.0 +return re.sub(pattern, repl, typ, count=1) + + def strip_inline_namespaces(type_str): """Remove known inline namespaces from the canonical name of a type.""" type_str = strip_versioned_namespace(type_str) @@ -1355,8 +1365,7 @@ class StdExpAnyPrinter(SingleObjContainerPrinter): def __init__(self, typename, val): self._typename = strip_versioned_namespace(typename) -self._typename = re.sub(r'^std::experimental::fundamentals_v\d::', -'std::experimental::', self._typename, 1) +self._typename = strip_fundts_namespace(self._typename) self._val = val self._contained_type = None contained_value = None @@ -1449,10 +1458,8 @@ class StdExpOptionalPrinter(SingleObjContainerPrinter): """Print a std::optional or std::experimental::optional.""" def __init__(self, typename, val): -typename = strip_versioned_namespace(typename) -self._typename = re.sub( -r'^std::(experimental::|)(fundamentals_v\d::|)(.*)', -r'std::\1\3', typename, 1) +self._typename = strip_versioned_namespace(typename) +self._typename = strip_fundts_namespace(self._typename) payload = val['_M_payload'] if self._typename.startswith('std::experimental'): engaged = val['_M_engaged'] -- 2.46.2
Re: [PATCH 4/7] libstdc++: Remove indirection to __find_if in std::find etc.
On 15/10/24 15:20 +0100, Jonathan Wakely wrote: Tested x86_64-linux. -- >8 -- There doesn't seem to be a lot of benefit in reusing __find_if with __gnu_cxx::__ops predicates, since they aren't going to actually instantiate any less code if we use different predicates every time (e.g. __ops::__negate, or __ops::__iter_equals_val, or __ops::__pred_iter). And now that std::find no longer calls __find_if (because it just does a loop directly), we can make the _Iter_equals_val case of __find_if call std::find, to take advantage of its memchr optimization. This benefits other algos like search_n which use __find_if with _Iter_equals_val. Hmm, I wonder if inverting the relationship below (__find_if calls find, instead of vice versa) can cause an ABI problem if one TU has an instantiation of the old find that calls __find_if, and another TU has an instantiation of the new __find_if that calls find, and they end up calling each other recursively until the stack overflows. We might need to mangle one of them differently. - /** - * @brief Find the first occurrence of a value in a sequence. - * @ingroup non_mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __valThe value to find. - * @return The first iterator @c i in the range @p [__first,__last) - * such that @c *i == @p __val, or @p __last if no such iterator exists. - */ - template -_GLIBCXX20_CONSTEXPR -inline _InputIterator -find(_InputIterator __first, _InputIterator __last, const _Tp& __val) -{ - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_EqualOpConcept< - typename iterator_traits<_InputIterator>::value_type, _Tp>) - __glibcxx_requires_valid_range(__first, __last); - -#if __cpp_if_constexpr && __glibcxx_type_trait_variable_templates - using _ValT = typename iterator_traits<_InputIterator>::value_type; - if constexpr (__can_use_memchr_for_find<_ValT, _Tp>) - if constexpr (is_pointer_v -#if __cpp_lib_concepts - || contiguous_iterator<_InputIterator> -#endif -) - { - // If conversion to the 1-byte value_type alters the value, - // it would not be found by std::find using equality comparison. - // We need to check this here, because otherwise something like - // memchr("a", 'a'+256, 1) would give a false positive match. - if (!(static_cast<_ValT>(__val) == __val)) - return __last; - else if (!__is_constant_evaluated()) - { - const void* __p0 = std::__to_address(__first); - const int __ival = static_cast(__val); - if (auto __n = std::distance(__first, __last); __n > 0) - if (auto __p1 = __builtin_memchr(__p0, __ival, __n)) - return __first + ((const char*)__p1 - (const char*)__p0); - return __last; - } - } -#endif - - return std::__find_if(__first, __last, - __gnu_cxx::__ops::__iter_equals_val(__val)); -} [...] + // When the predicate is just comparing to a value we can use std::find, + // which is optimized to memchr for some types. + template +_GLIBCXX20_CONSTEXPR +inline _Iterator +__find_if(_Iterator __first, _Iterator __last, + __gnu_cxx::__ops::_Iter_equals_val<_Value> __pred) +{ return _GLIBCXX_STD_A::find(__first, __last, __pred._M_value); } + template _GLIBCXX20_CONSTEXPR typename iterator_traits<_InputIterator>::difference_type -- 2.46.2
[PATCH 6/7] libstdc++: Add always_inline to some one-liners in
Tested x86_64-linux. -- >8 -- We implement std::copy, std::fill etc. as a series of calls to other overloads which incrementally peel off layers of iterator wrappers. This adds a high abstraction penalty for -O0 and potentially even -O1. Add the always_inline attribute to several functions that are just a single return statement (and maybe a static_assert, or some concept-checking assertions which are disabled by default). libstdc++-v3/ChangeLog: * include/bits/stl_algobase.h (__copy_move_a1, __copy_move_a) (__copy_move_backward_a1, __copy_move_backward_a, move_backward) (__fill_a1, __fill_a, fill, __fill_n_a, fill_n, __equal_aux): Add always_inline attribute to one-line forwarding functions. --- libstdc++-v3/include/bits/stl_algobase.h | 14 ++ 1 file changed, 14 insertions(+) diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h index d9d1d00b113..b2f5b96d46e 100644 --- a/libstdc++-v3/include/bits/stl_algobase.h +++ b/libstdc++-v3/include/bits/stl_algobase.h @@ -500,12 +500,14 @@ _GLIBCXX_END_NAMESPACE_CONTAINER __copy_move_a1(_II, _II, _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>); template +__attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR inline _OI __copy_move_a1(_II __first, _II __last, _OI __result) { return std::__copy_move_a2<_IsMove>(__first, __last, __result); } template +__attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR inline _OI __copy_move_a(_II __first, _II __last, _OI __result) @@ -757,6 +759,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER #undef _GLIBCXX_ADVANCE template +__attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR inline _BI2 __copy_move_backward_a1(_BI1 __first, _BI1 __last, _BI2 __result) @@ -785,6 +788,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>); template +__attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR inline _OI __copy_move_backward_a(_II __first, _II __last, _OI __result) @@ -840,6 +844,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER * that the start of the output range may overlap [first,last). */ template +__attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR inline _BI2 copy_backward(_BI1 __first, _BI1 __last, _BI2 __result) @@ -875,6 +880,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER * that the start of the output range may overlap [first,last). */ template +__attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR inline _BI2 move_backward(_BI1 __first, _BI1 __last, _BI2 __result) @@ -958,6 +964,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER } template +__attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR inline void __fill_a1(::__gnu_cxx::__normal_iterator<_Ite, _Cont> __first, @@ -977,6 +984,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER const bool&); template +__attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR inline void __fill_a(_FIte __first, _FIte __last, const _Tp& __value) @@ -1002,6 +1010,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER * to @c memset or @c wmemset. */ template +__attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR inline void fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) @@ -1108,6 +1117,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER std::input_iterator_tag); template +__attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR inline _OutputIterator __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value, @@ -1120,6 +1130,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER } template +__attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR inline _OutputIterator __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value, @@ -1132,6 +1143,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER } template +__attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR inline _OutputIterator __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value, @@ -1167,6 +1179,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER // DR 865. More algorithms that throw away information // DR 426. search_n(), fill_n(), and generate_n() with negative n template +__attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR inline _OI fill_n(_OI __first, _Size __n, const _Tp& __value) @@ -1246,6 +1259,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER } template +__attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR inline bool __equal_aux(_II1 __first1, _II1 __last1, _II2 __first2) -- 2.46.2
[PATCH 3/7] libstdc++: Inline memmove optimizations for std::copy etc. [PR115444]
This is a slightly different approach to C++98 compatibility than used in patch 1/1 of this series for the uninitialized algos. It worked out a bit cleaner this way for these algos, I think. Tested x86_64-linux. -- >8 -- This removes all the __copy_move class template specializations that decide how to optimize std::copy and std::copy_n. We can inline those optimizations into the algorithms, using if-constexpr (and macros for C++98 compatibility) and remove the code dispatching to the various class template specializations. Doing this means we implement the optimization directly for std::copy_n instead of deferring to std::copy, That avoids the unwanted consequence of advancing the iterator in copy_n only to take the difference later to get back to the length that we already had in copy_n originally (as described in PR 115444). With the new flattened implementations, we can also lower contiguous iterators to pointers in std::copy/std::copy_n/std::copy_backwards, so that they benefit from the same memmove optimizations as pointers. There's a subtlety though: contiguous iterators can potentially throw exceptions to exit the algorithm early. So we can only transform the loop to memmove if dereferencing the iterator is noexcept. We don't check that incrementing the iterator is noexcept because we advance the contiguous iterators before using memmove, so that if incrementing would throw, that happens first. I am writing a proposal (P3249R0) which would make this unnecessary, so I hope we can drop the nothrow requirements later. This change also solves PR 114817 by checking is_trivially_assignable before optimizing copy/copy_n etc. to memmove. It's not enough to check that the types are trivially copyable (a precondition for using memmove at all), we also need to check that the specific assignment that would be performed by the algorithm is also trivial. Replacing a non-trivial assignment with memmove would be observable, so not allowed. libstdc++-v3/ChangeLog: PR libstdc++/115444 PR libstdc++/114817 * include/bits/stl_algo.h (__copy_n): Remove generic overload and overload for random access iterators. (copy_n): Inline generic version of __copy_n here. Do not defer to std::copy for random access iterators. * include/bits/stl_algobase.h (__copy_move): Remove. (__nothrow_contiguous_iterator, __memcpyable_iterators): New concepts. (__assign_one, _GLIBCXX_TO_ADDR, _GLIBCXX_ADVANCE): New helpers. (__copy_move_a2): Inline __copy_move logic and conditional memmove optimization into the most generic overload. (__copy_n_a): Likewise. (__copy_move_backward): Remove. (__copy_move_backward_a2): Inline __copy_move_backward logic and memmove optimization into the most generic overload. * testsuite/20_util/specialized_algorithms/uninitialized_copy/114817.cc: New test. * testsuite/20_util/specialized_algorithms/uninitialized_copy_n/114817.cc: New test. * testsuite/25_algorithms/copy/114817.cc: New test. * testsuite/25_algorithms/copy/115444.cc: New test. * testsuite/25_algorithms/copy_n/114817.cc: New test. --- libstdc++-v3/include/bits/stl_algo.h | 24 +- libstdc++-v3/include/bits/stl_algobase.h | 426 +- .../uninitialized_copy/114817.cc | 39 ++ .../uninitialized_copy_n/114817.cc| 39 ++ .../testsuite/25_algorithms/copy/114817.cc| 38 ++ .../testsuite/25_algorithms/copy/115444.cc| 93 .../testsuite/25_algorithms/copy_n/114817.cc | 38 ++ 7 files changed, 469 insertions(+), 228 deletions(-) create mode 100644 libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/114817.cc create mode 100644 libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy_n/114817.cc create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy/114817.cc create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy/115444.cc create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy_n/114817.cc diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h index a1ef665506d..489ce7e14d2 100644 --- a/libstdc++-v3/include/bits/stl_algo.h +++ b/libstdc++-v3/include/bits/stl_algo.h @@ -665,25 +665,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __result; } - template -_GLIBCXX20_CONSTEXPR -_OutputIterator -__copy_n(_InputIterator __first, _Size __n, -_OutputIterator __result, input_iterator_tag) -{ - return std::__niter_wrap(__result, - __copy_n_a(__first, __n, - std::__niter_base(__result), true)); -} - - template -_GLIBCXX20_CONSTEXPR -inline _OutputIterator -__copy_n(_RandomAccessIterator __first, _Size __n, -_OutputIterator __result, random_access_iterator_tag) -{ return std
[PATCH 1/7] libstdc++: Refactor std::uninitialized_{copy, fill, fill_n} algos [PR68350]
This is v2 of https://gcc.gnu.org/pipermail/gcc-patches/2024-October/665246.html fixing some thinkos in uninitialized_{fill,fill_n}. We don't need to worry about overwriting tail-padding in those algos, because we only use memset for 1-byte integer types. So they have no tail padding that can be reused anyway! So this changes __n > 1 to __n > 0 in a few places (which fixes the problem that it was not actually filling anything for the n==1 cases). Also simplify std::__to_address(__result++) to just __result++ because we already have a pointer, and use std::to_address(result++) for a C++20 std::contiguous_iterator case, instead of addressof(*result++). Tested x86_64-linux. -- >8 -- This refactors the std::uninitialized_copy, std::uninitialized_fill and std::uninitialized_fill_n algorithms to directly perform memcpy/memset optimizations instead of dispatching to std::copy/std::fill/std::fill_n. The reasons for this are: - Use 'if constexpr' to simplify and optimize compilation throughput, so dispatching to specialized class templates is only needed for C++98 mode. - Relax the conditions for using memcpy/memset, because the C++20 rules on implicit-lifetime types mean that we can rely on memcpy to begin lifetimes of trivially copyable types. We don't need to require trivially default constructible, so don't need to limit the optimization to trivial types. See PR 68350 for more details. - The conditions on non-overlapping ranges are stronger for std::uninitialized_copy than for std::copy so we can use memcpy instead of memmove, which might be a minor optimization. - Avoid including in . It only needs some iterator utilities from that file now, which belong in anyway, so this moves them there. Several tests need changes to the diagnostics matched by dg-error because we no longer use the __constructible() function that had a static assert in. Now we just get straightforward errors for attempting to use a deleted constructor. Two tests needed more signficant changes to the actual expected results of executing the tests, because they were checking for old behaviour which was incorrect according to the standard. 20_util/specialized_algorithms/uninitialized_copy/64476.cc was expecting std::copy to be used for a call to std::uninitialized_copy involving two trivially copyable types. That was incorrect behaviour, because a non-trivial constructor should have been used, but using std::copy used trivial default initialization followed by assignment. 20_util/specialized_algorithms/uninitialized_fill_n/sizes.cc was testing the behaviour with a non-integral Size passed to uninitialized_fill_n, but I wrote the test looking at the requirements of uninitialized_copy_n which are not the same as uninitialized_fill_n. The former uses --n and tests n > 0, but the latter just tests n-- (which will never be false for a floating-point value with a fractional part). libstdc++-v3/ChangeLog: PR libstdc++/68350 PR libstdc++/93059 * include/bits/stl_algobase.h (__niter_base, __niter_wrap): Move to ... * include/bits/stl_iterator.h: ... here. * include/bits/stl_uninitialized.h (__check_constructible) (_GLIBCXX_USE_ASSIGN_FOR_INIT): Remove. [C++98] (__unwrappable_niter): New trait. (__uninitialized_copy): Replace use of std::copy. (uninitialized_copy): Fix Doxygen comments. Open-code memcpy optimization for C++11 and later. (__uninitialized_fill): Replace use of std::fill. (uninitialized_fill): Fix Doxygen comments. Open-code memset optimization for C++11 and later. (__uninitialized_fill_n): Replace use of std::fill_n. (uninitialized_fill_n): Fix Doxygen comments. Open-code memset optimization for C++11 and later. * testsuite/20_util/specialized_algorithms/uninitialized_copy/64476.cc: Adjust expected behaviour to match what the standard specifies. * testsuite/20_util/specialized_algorithms/uninitialized_fill_n/sizes.cc: Likewise. * testsuite/20_util/specialized_algorithms/uninitialized_copy/1.cc: Adjust dg-error directives. * testsuite/20_util/specialized_algorithms/uninitialized_copy/89164.cc: Likewise. * testsuite/20_util/specialized_algorithms/uninitialized_copy_n/89164.cc: Likewise. * testsuite/20_util/specialized_algorithms/uninitialized_fill/89164.cc: Likewise. * testsuite/20_util/specialized_algorithms/uninitialized_fill_n/89164.cc: Likewise. * testsuite/23_containers/vector/cons/89164.cc: Likewise. * testsuite/23_containers/vector/cons/89164_c++17.cc: Likewise. --- libstdc++-v3/include/bits/stl_algobase.h | 45 -- libstdc++-v3/include/bits/stl_iterator.h | 54 +++ libstdc++-v3/include/bits/stl_uninitialized.h | 385 +- .../uninitialized_copy/1.cc | 3 +- .../uninitialized_copy/64476.cc
[PATCH 2/7] libstdc++: Make __normal_iterator constexpr, always_inline, nodiscard
Tested x86_64-linux. -- >8 -- The __gnu_cxx::__normal_iterator type we use for std::vector::iterator is not specified by the standard, it's an implementation detail. This means it's not constrained by the rule that forbids strengthening constexpr. We can make it meet the constexpr iterator requirements for older standards, not only when it's required to be for C++20. For the non-const member functions they can't be constexpr in C++11, so use _GLIBCXX14_CONSTEXPR for those. For all constructors, const members and non-member operator overloads, use _GLIBCXX_CONSTEXPR or just constexpr. We can also liberally add [[nodiscard]] and [[gnu::always_inline]] attributes to those functions. Also change some internal helpers for std::move_iterator which can be unconditionally constexpr and marked nodiscard. libstdc++-v3/ChangeLog: * include/bits/stl_iterator.h (__normal_iterator): Make all members and overloaded operators constexpr before C++20. (__niter_base, __niter_wrap, __to_address): Add nodiscard and always_inline attributes. (__make_move_if_noexcept_iterator, __miter_base): Add nodiscard and make unconditionally constexpr. --- libstdc++-v3/include/bits/stl_iterator.h | 125 ++- 1 file changed, 76 insertions(+), 49 deletions(-) diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h index 85b9861..3cc10a160bd 100644 --- a/libstdc++-v3/include/bits/stl_iterator.h +++ b/libstdc++-v3/include/bits/stl_iterator.h @@ -656,7 +656,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template _GLIBCXX20_CONSTEXPR -auto +inline auto __niter_base(reverse_iterator<_Iterator> __it) -> decltype(__make_reverse_iterator(__niter_base(__it.base( { return __make_reverse_iterator(__niter_base(__it.base())); } @@ -668,7 +668,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template _GLIBCXX20_CONSTEXPR -auto +inline auto __miter_base(reverse_iterator<_Iterator> __it) -> decltype(__make_reverse_iterator(__miter_base(__it.base( { return __make_reverse_iterator(__miter_base(__it.base())); } @@ -1060,23 +1060,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using iterator_concept = std::__detail::__iter_concept<_Iterator>; #endif - _GLIBCXX_CONSTEXPR __normal_iterator() _GLIBCXX_NOEXCEPT - : _M_current(_Iterator()) { } + __attribute__((__always_inline__)) + _GLIBCXX_CONSTEXPR + __normal_iterator() _GLIBCXX_NOEXCEPT + : _M_current() { } - explicit _GLIBCXX20_CONSTEXPR + __attribute__((__always_inline__)) + explicit _GLIBCXX_CONSTEXPR __normal_iterator(const _Iterator& __i) _GLIBCXX_NOEXCEPT : _M_current(__i) { } // Allow iterator to const_iterator conversion #if __cplusplus >= 201103L template> - _GLIBCXX20_CONSTEXPR + [[__gnu__::__always_inline__]] + constexpr __normal_iterator(const __normal_iterator<_Iter, _Container>& __i) noexcept #else // N.B. _Container::pointer is not actually in container requirements, // but is present in std::vector and std::basic_string. template + __attribute__((__always_inline__)) __normal_iterator(const __normal_iterator<_Iter, typename __enable_if< (std::__are_same<_Iter, typename _Container::pointer>::__value), @@ -1085,17 +1090,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_current(__i.base()) { } // Forward iterator requirements - _GLIBCXX20_CONSTEXPR + + __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_CONSTEXPR reference operator*() const _GLIBCXX_NOEXCEPT { return *_M_current; } - _GLIBCXX20_CONSTEXPR + __attribute__((__always_inline__)) _GLIBCXX_NODISCARD + _GLIBCXX_CONSTEXPR pointer operator->() const _GLIBCXX_NOEXCEPT { return _M_current; } - _GLIBCXX20_CONSTEXPR + __attribute__((__always_inline__)) + _GLIBCXX14_CONSTEXPR __normal_iterator& operator++() _GLIBCXX_NOEXCEPT { @@ -1103,13 +1112,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } - _GLIBCXX20_CONSTEXPR + __attribute__((__always_inline__)) + _GLIBCXX14_CONSTEXPR __normal_iterator operator++(int) _GLIBCXX_NOEXCEPT { return __normal_iterator(_M_current++); } // Bidirectional iterator requirements - _GLIBCXX20_CONSTEXPR + + __attribute__((__always_inline__)) + _GLIBCXX14_CONSTEXPR __normal_iterator& operator--() _GLIBCXX_NOEXCEPT { @@ -1117,38 +1129,46 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } - _GLIBCXX20_CONSTEXPR + __attribute__((__always_inline__)) + _GLIBCXX14_CONSTEXPR __normal_iterator operator--(int) _GLIBCXX_NOEXCEPT { return __normal_iterator(_M_current--); } // Ra
[PATCH 4/7] libstdc++: Remove indirection to __find_if in std::find etc.
Tested x86_64-linux. -- >8 -- There doesn't seem to be a lot of benefit in reusing __find_if with __gnu_cxx::__ops predicates, since they aren't going to actually instantiate any less code if we use different predicates every time (e.g. __ops::__negate, or __ops::__iter_equals_val, or __ops::__pred_iter). And now that std::find no longer calls __find_if (because it just does a loop directly), we can make the _Iter_equals_val case of __find_if call std::find, to take advantage of its memchr optimization. This benefits other algos like search_n which use __find_if with _Iter_equals_val. libstdc++-v3/ChangeLog: * include/bits/stl_algo.h (__find_if_not): Do loop here instead of using __find_if with __gnu_cxx::__ops predicate. (find_if): Likewise. (find): Move to ... * include/bits/stl_algobase.h (find): ... here. (__find_if): Overload for _Iter_equals_val predicate. --- libstdc++-v3/include/bits/stl_algo.h | 63 +++- libstdc++-v3/include/bits/stl_algobase.h | 61 +++ 2 files changed, 68 insertions(+), 56 deletions(-) diff --git a/libstdc++-v3/include/bits/stl_algo.h b/libstdc++-v3/include/bits/stl_algo.h index 489ce7e14d2..05c1dbd07b6 100644 --- a/libstdc++-v3/include/bits/stl_algo.h +++ b/libstdc++-v3/include/bits/stl_algo.h @@ -105,15 +105,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::iter_swap(__result, __b); } - /// Provided for stable_partition to use. + // Used by std::find_if_not and __stable_partition. template _GLIBCXX20_CONSTEXPR inline _InputIterator __find_if_not(_InputIterator __first, _InputIterator __last, _Predicate __pred) { - return std::__find_if(__first, __last, - __gnu_cxx::__ops::__negate(__pred)); + while (__first != __last && __pred(__first)) + ++__first; + return __first; } /// Like find_if_not(), but uses and updates a count of the @@ -3810,57 +3811,6 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO } #endif // C++17 - /** - * @brief Find the first occurrence of a value in a sequence. - * @ingroup non_mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __valThe value to find. - * @return The first iterator @c i in the range @p [__first,__last) - * such that @c *i == @p __val, or @p __last if no such iterator exists. - */ - template -_GLIBCXX20_CONSTEXPR -inline _InputIterator -find(_InputIterator __first, _InputIterator __last, const _Tp& __val) -{ - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_EqualOpConcept< - typename iterator_traits<_InputIterator>::value_type, _Tp>) - __glibcxx_requires_valid_range(__first, __last); - -#if __cpp_if_constexpr && __glibcxx_type_trait_variable_templates - using _ValT = typename iterator_traits<_InputIterator>::value_type; - if constexpr (__can_use_memchr_for_find<_ValT, _Tp>) - if constexpr (is_pointer_v -#if __cpp_lib_concepts - || contiguous_iterator<_InputIterator> -#endif -) - { - // If conversion to the 1-byte value_type alters the value, - // it would not be found by std::find using equality comparison. - // We need to check this here, because otherwise something like - // memchr("a", 'a'+256, 1) would give a false positive match. - if (!(static_cast<_ValT>(__val) == __val)) - return __last; - else if (!__is_constant_evaluated()) - { - const void* __p0 = std::__to_address(__first); - const int __ival = static_cast(__val); - if (auto __n = std::distance(__first, __last); __n > 0) - if (auto __p1 = __builtin_memchr(__p0, __ival, __n)) - return __first + ((const char*)__p1 - (const char*)__p0); - return __last; - } - } -#endif - - return std::__find_if(__first, __last, - __gnu_cxx::__ops::__iter_equals_val(__val)); -} - /** * @brief Find the first element in a sequence for which a * predicate is true. @@ -3883,8 +3833,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO typename iterator_traits<_InputIterator>::value_type>) __glibcxx_requires_valid_range(__first, __last); - return std::__find_if(__first, __last, - __gnu_cxx::__ops::__pred_iter(__pred)); + while (__first != __last && !__pred(*__first)) + ++__first; + return __first; } /** diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h index 5f77b00be9b..34e1cf7322f 100644 --- a/libstdc++-v3/include/bits/stl_algobase.h +++ b/libstdc++-v3/include/bits/stl_algobase
[PATCH 7/7] libstdc++: Reuse std::__assign_one in
Tested x86_64-linux. -- >8 -- Use std::__assign_one instead of ranges::__assign_one. Adjust the uses, because std::__assign_one has the arguments in the opposite order (the same order as an assignment expression). libstdc++-v3/ChangeLog: * include/bits/ranges_algobase.h (ranges::__assign_one): Remove. (__copy_or_move, __copy_or_move_backward): Use std::__assign_one instead of ranges::__assign_one. --- libstdc++-v3/include/bits/ranges_algobase.h | 22 ++--- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/libstdc++-v3/include/bits/ranges_algobase.h b/libstdc++-v3/include/bits/ranges_algobase.h index 0345ea850a4..df4e770e7a6 100644 --- a/libstdc++-v3/include/bits/ranges_algobase.h +++ b/libstdc++-v3/include/bits/ranges_algobase.h @@ -225,16 +225,6 @@ namespace ranges copy_backward_result<_Iter, _Out>> __copy_or_move_backward(_Iter __first, _Sent __last, _Out __result); - template -constexpr void -__assign_one(_Iter& __iter, _Out& __result) -{ - if constexpr (_IsMove) - *__result = std::move(*__iter); - else - *__result = *__iter; -} - template _Sent, weakly_incrementable _Out> @@ -294,14 +284,14 @@ namespace ranges __builtin_memmove(__result, __first, sizeof(_ValueTypeI) * __num); else if (__num == 1) - ranges::__assign_one<_IsMove>(__first, __result); + std::__assign_one<_IsMove>(__result, __first); return {__first + __num, __result + __num}; } } for (auto __n = __last - __first; __n > 0; --__n) { - ranges::__assign_one<_IsMove>(__first, __result); + std::__assign_one<_IsMove>(__result, __first); ++__first; ++__result; } @@ -311,7 +301,7 @@ namespace ranges { while (__first != __last) { - ranges::__assign_one<_IsMove>(__first, __result); + std::__assign_one<_IsMove>(__result, __first); ++__first; ++__result; } @@ -423,7 +413,7 @@ namespace ranges __builtin_memmove(__result, __first, sizeof(_ValueTypeI) * __num); else if (__num == 1) - ranges::__assign_one<_IsMove>(__first, __result); + std::__assign_one<_IsMove>(__result, __first); return {__first + __num, __result}; } } @@ -435,7 +425,7 @@ namespace ranges { --__tail; --__result; - ranges::__assign_one<_IsMove>(__tail, __result); + std::__assign_one<_IsMove>(__result, __tail); } return {std::move(__lasti), std::move(__result)}; } @@ -448,7 +438,7 @@ namespace ranges { --__tail; --__result; - ranges::__assign_one<_IsMove>(__tail, __result); + std::__assign_one<_IsMove>(__result, __tail); } return {std::move(__lasti), std::move(__result)}; } -- 2.46.2
[PATCH 5/7] libstdc++: Add nodiscard to std::find
Tested x86_64-linux. -- >8 -- libstdc++-v3/ChangeLog: * include/bits/stl_algobase.h (find): Add nodiscard. --- libstdc++-v3/include/bits/stl_algobase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libstdc++-v3/include/bits/stl_algobase.h b/libstdc++-v3/include/bits/stl_algobase.h index 34e1cf7322f..d9d1d00b113 100644 --- a/libstdc++-v3/include/bits/stl_algobase.h +++ b/libstdc++-v3/include/bits/stl_algobase.h @@ -2087,7 +2087,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO * such that @c *i == @p __val, or @p __last if no such iterator exists. */ template -_GLIBCXX20_CONSTEXPR +_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR inline _InputIterator find(_InputIterator __first, _InputIterator __last, const _Tp& __val) { -- 2.46.2
Re: [PATCH] libstdc++: Implement LWG 3798 for range adaptors [PR106676]
On Tue, 15 Oct 2024 at 14:30, Patrick Palka wrote: > > On Mon, 14 Oct 2024, Jonathan Wakely wrote: > > > Tested x86_64-linux. > > > > -- >8 -- > > > > LWG 3798 modified the iterator_category of the iterator types for > > transform_view, join_with_view, zip_transform_view and > > adjacent_transform_view, to allow the iterator's reference type to be an > > rvalue reference. > > > > libstdc++-v3/ChangeLog: > > > > PR libstdc++/106676 > > * include/bits/iterator_concepts.h (__cpp17_fwd_iterator): Use > > is_reference instead of is_value_reference. > > rvalue references. > > * include/std/ranges (transform_view:__iter_cat::_S_iter_cat): > > Likewise. > > (zip_transform_view::__iter_cat::_S_iter_cat): Likewise. > > (adjacent_transform_view::__iter_cat::_S_iter_cat): Likewise. > > (join_with_view::__iter_cat::_S_iter_cat): Likewise. > > * testsuite/std/ranges/adaptors/transform.cc: Check > > iterator_category when the transformation function returns an > > rvalue reference type. > > --- > > libstdc++-v3/include/bits/iterator_concepts.h| 4 +++- > > libstdc++-v3/include/std/ranges | 16 > > .../testsuite/std/ranges/adaptors/transform.cc | 16 > > 3 files changed, 31 insertions(+), 5 deletions(-) > > > > diff --git a/libstdc++-v3/include/bits/iterator_concepts.h > > b/libstdc++-v3/include/bits/iterator_concepts.h > > index 490a362cdf1..669d3ddfd1e 100644 > > --- a/libstdc++-v3/include/bits/iterator_concepts.h > > +++ b/libstdc++-v3/include/bits/iterator_concepts.h > > @@ -333,10 +333,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > typename incrementable_traits<_Iter>::difference_type>; > > }; > > > > +// _GLIBCXX_RESOLVE_LIB_DEFECTS > > +// 3798. Rvalue reference and iterator_category > > template > >concept __cpp17_fwd_iterator = __cpp17_input_iterator<_Iter> > > && constructible_from<_Iter> > > - && is_lvalue_reference_v> > > + && is_reference_v> > > && same_as>, > > typename indirectly_readable_traits<_Iter>::value_type> > > && requires(_Iter __it) > > diff --git a/libstdc++-v3/include/std/ranges > > b/libstdc++-v3/include/std/ranges > > index f0d81cbea0c..941189d65c3 100644 > > --- a/libstdc++-v3/include/std/ranges > > +++ b/libstdc++-v3/include/std/ranges > > @@ -1892,7 +1892,9 @@ namespace views::__adaptor > > using _Fpc = __detail::__maybe_const_t<_Const, _Fp>; > > using _Base = transform_view::_Base<_Const>; > > using _Res = invoke_result_t<_Fpc&, range_reference_t<_Base>>; > > - if constexpr (is_lvalue_reference_v<_Res>) > > + // _GLIBCXX_RESOLVE_LIB_DEFECTS > > + // 3798. Rvalue reference and iterator_category > > + if constexpr (is_reference_v<_Res>) > > { > > using _Cat > > = typename > > iterator_traits>::iterator_category; > > @@ -5047,7 +5049,9 @@ namespace views::__adaptor > > using __detail::__range_iter_cat; > > using _Res = invoke_result_t<__maybe_const_t<_Const, _Fp>&, > > > > range_reference_t<__maybe_const_t<_Const, _Vs>>...>; > > - if constexpr (!is_lvalue_reference_v<_Res>) > > + // _GLIBCXX_RESOLVE_LIB_DEFECTS > > + // 3798. Rvalue reference and iterator_category > > + if constexpr (!is_reference_v<_Res>) > > return input_iterator_tag{}; > > else if constexpr ((derived_from<__range_iter_cat<_Vs, _Const>, > > random_access_iterator_tag> && > > ...)) > > @@ -5820,7 +5824,9 @@ namespace views::__adaptor > >using _Res = invoke_result_t<__unarize<__maybe_const_t<_Const, > > _Fp>&, _Nm>, > > range_reference_t<_Base>>; > >using _Cat = typename > > iterator_traits>::iterator_category; > > - if constexpr (!is_lvalue_reference_v<_Res>) > > + // _GLIBCXX_RESOLVE_LIB_DEFECTS > > + // 3798. Rvalue reference and iterator_category > > + if constexpr (!is_reference_v<_Res>) > > return input_iterator_tag{}; > >
[committed] libstdc++: Populate generic std::time_get's wide %c format [PR117135]
Tested x86_64-linux. Pushed to trunk. -- >8 -- I missed out the __timepunct specialization for the "generic" implementation when defining the %c format in r15-4016-gc534e37faccf48. libstdc++-v3/ChangeLog: PR libstdc++/117135 * config/locale/generic/time_members.cc (__timepunct::_M_initialize_timepunc): Set _M_date_time_format for C locale. Set %Ex formats to the same values as the %x formats. --- libstdc++-v3/config/locale/generic/time_members.cc | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libstdc++-v3/config/locale/generic/time_members.cc b/libstdc++-v3/config/locale/generic/time_members.cc index 6619f0ca881..5012a270dd1 100644 --- a/libstdc++-v3/config/locale/generic/time_members.cc +++ b/libstdc++-v3/config/locale/generic/time_members.cc @@ -150,11 +150,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_data = new __timepunct_cache; _M_data->_M_date_format = L"%m/%d/%y"; - _M_data->_M_date_era_format = L"%m/%d/%y"; + _M_data->_M_date_era_format = _M_data->_M_date_format; _M_data->_M_time_format = L"%H:%M:%S"; - _M_data->_M_time_era_format = L"%H:%M:%S"; - _M_data->_M_date_time_format = L""; - _M_data->_M_date_time_era_format = L""; + _M_data->_M_time_era_format = _M_data->_M_time_format; + _M_data->_M_date_time_format = L"%a %b %e %T %Y"; + _M_data->_M_date_time_era_format = _M_data->_M_date_time_format; _M_data->_M_am = L"AM"; _M_data->_M_pm = L"PM"; _M_data->_M_am_pm_format = L"%I:%M:%S %p"; -- 2.46.2
[committed] libstdc++: Constrain std::expected comparisons (P3379R0)
Tested x86_64-linux. Pushed to trunk. -- >8 -- This proposal of mine has been approved by LEWG and forwarded to LWG. I expect it to be voted into the draft without significant changes. libstdc++-v3/ChangeLog: * include/bits/version.def (constrained_equality): Bump value. * include/bits/version.h: Regenerate. * include/std/expected (operator==): Add constraints and noexcept specifiers. * testsuite/20_util/optional/relops/constrained.cc: Adjust check for feature test macro. * testsuite/20_util/pair/comparison_operators/constrained.cc: Likewise. * testsuite/20_util/tuple/comparison_operators/constrained.cc: Likewise. * testsuite/20_util/variant/relops/constrained.cc: Likewise. * testsuite/20_util/expected/equality_constrained.cc: New test. --- libstdc++-v3/include/bits/version.def | 2 +- libstdc++-v3/include/bits/version.h | 4 +- libstdc++-v3/include/std/expected | 31 ++- .../20_util/expected/equality_constrained.cc | 181 ++ .../20_util/optional/relops/constrained.cc| 2 +- .../pair/comparison_operators/constrained.cc | 2 +- .../tuple/comparison_operators/constrained.cc | 2 +- .../20_util/variant/relops/constrained.cc | 2 +- 8 files changed, 213 insertions(+), 13 deletions(-) create mode 100644 libstdc++-v3/testsuite/20_util/expected/equality_constrained.cc diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def index 477651f358a..4fa820a5a4a 100644 --- a/libstdc++-v3/include/bits/version.def +++ b/libstdc++-v3/include/bits/version.def @@ -1256,7 +1256,7 @@ ftms = { ftms = { name = constrained_equality; values = { -v = 202403; +v = 202411; // FIXME: 202403 for P2944R3, ??? for P3379R0 cxxmin = 20; extra_cond = "__glibcxx_three_way_comparison"; }; diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h index 342ee6b4c7a..fdbee8161d9 100644 --- a/libstdc++-v3/include/bits/version.h +++ b/libstdc++-v3/include/bits/version.h @@ -1392,9 +1392,9 @@ #if !defined(__cpp_lib_constrained_equality) # if (__cplusplus >= 202002L) && (__glibcxx_three_way_comparison) -# define __glibcxx_constrained_equality 202403L +# define __glibcxx_constrained_equality 202411L # if defined(__glibcxx_want_all) || defined(__glibcxx_want_constrained_equality) -# define __cpp_lib_constrained_equality 202403L +# define __cpp_lib_constrained_equality 202411L # endif # endif #endif /* !defined(__cpp_lib_constrained_equality) && defined(__glibcxx_want_constrained_equality) */ diff --git a/libstdc++-v3/include/std/expected b/libstdc++-v3/include/std/expected index d4a4bc17541..7de2aeffc70 100644 --- a/libstdc++-v3/include/std/expected +++ b/libstdc++-v3/include/std/expected @@ -35,6 +35,7 @@ #define __glibcxx_want_expected #define __glibcxx_want_freestanding_expected +#define __glibcxx_want_constrained_equality #include #ifdef __cpp_lib_expected // C++ >= 23 && __cpp_concepts >= 202002L @@ -1152,10 +1153,15 @@ namespace __expected template requires (!is_void_v<_Up>) + && requires (const _Tp& __t, const _Up& __u, + const _Er& __e, const _Er2& __e2) { + { __t == __u } -> convertible_to; + { __e == __e2 } -> convertible_to; + } friend constexpr bool operator==(const expected& __x, const expected<_Up, _Er2>& __y) - // FIXME: noexcept(noexcept(bool(*__x == *__y)) - // && noexcept(bool(__x.error() == __y.error( + noexcept(noexcept(bool(*__x == *__y)) + && noexcept(bool(__x.error() == __y.error( { if (__x.has_value()) return __y.has_value() && bool(*__x == *__y); @@ -1164,15 +1170,22 @@ namespace __expected } template + requires (!__expected::__is_expected<_Up>) + && requires (const _Tp& __t, const _Up& __u) { + { __t == __u } -> convertible_to; + } friend constexpr bool operator==(const expected& __x, const _Up& __v) - // FIXME: noexcept(noexcept(bool(*__x == __v))) + noexcept(noexcept(bool(*__x == __v))) { return __x.has_value() && bool(*__x == __v); } template + requires requires (const _Er& __e, const _Er2& __e2) { + { __e == __e2 } -> convertible_to; + } friend constexpr bool operator==(const expected& __x, const unexpected<_Er2>& __e) - // FIXME: noexcept(noexcept(bool(__x.error() == __e.error( + noexcept(noexcept(bool(__x.error() == __e.error( { return !__x.has_value() && bool(__x.error() == __e.error()); } friend constexpr void @@ -1819,9 +1832,12 @@ namespace __expected template requires is_void_v<_Up> + && requires (const _Er& __e, const _Er2& __e2) { + { __e == __e2 } -> convert
Re: [PATCH] libstdc++: Refactor std::uninitialized_{copy, fill, fill_n} algos [PR68350]
On Mon, 14 Oct 2024 at 14:59, Jonathan Wakely wrote: > > This causes some codegen regressions on (at least) aarch64 and power64: > > FAIL: g++.dg/pr104547.C -std=gnu++11 scan-tree-dump-not vrp2 > "_M_default_append" > FAIL: g++.dg/pr104547.C -std=gnu++17 scan-tree-dump-not vrp2 > "_M_default_append" > > For some reason the PR 104547 fix to stop the unused _M_default_append > function being emitted in the assembly code no longer works. > > I also see new bogus stringop-overflow warnings for these tests: > > FAIL: 27_io/basic_ios/imbue/14072.cc -std=gnu++17 (test for excess errors) > FAIL: 27_io/basic_istream/extractors_character/char/9826.cc > -std=gnu++17 (test for excess errors) > FAIL: 27_io/basic_stringbuf/requirements/explicit_instantiation/2.cc > -std=gnu++17 (test for excess errors) > FAIL: 27_io/basic_stringstream/requirements/explicit_instantiation.cc > -std=gnu++17 (test for excess errors) Actually the bogus -Wstringop-overflow warnings are due to a different patch I'm testing locally. The FAIL: g++.dg/pr104547.C regression is caused by this one though. > > > > > On Mon, 14 Oct 2024 at 00:53, Jonathan Wakely wrote: > > > > Tested x86_64-linux. > > > > -- >8 -- > > > > This refactors the std::uninitialized_copy, std::uninitialized_fill and > > std::uninitialized_fill_n algorithms to directly perform memcpy/memset > > optimizations instead of dispatching to std::copy/std::fill/std::fill_n. > > > > The reasons for this are: > > > > - Use 'if constexpr' to simplify and optimize compilation throughput, so > > dispatching to specialized class templates is only needed for C++98 > > mode. > > - Relax the conditions for using memcpy/memset, because the C++20 rules > > on implicit-lifetime types mean that we can rely on memcpy to begin > > lifetimes of trivially copyable types. We don't need to require > > trivially default constructible, so don't need to limit the > > optimization to trivial types. See PR 68350 for more details. > > - The conditions on non-overlapping ranges are stronger for > > std::uninitialized_copy than for std::copy so we can use memcpy instead > > of memmove, which might be a minor optimization. > > - Avoid including in . > > It only needs some iterator utilities from that file now, which belong > > in anyway, so this moves them there. > > > > Several tests need changes to the diagnostics matched by dg-error > > because we no longer use the __constructible() function that had a > > static assert in. Now we just get straightforward errors for attempting > > to use a deleted constructor. > > > > Two tests needed more signficant changes to the actual expected results > > of executing the tests, because they were checking for old behaviour > > which was incorrect according to the standard. > > 20_util/specialized_algorithms/uninitialized_copy/64476.cc was expecting > > std::copy to be used for a call to std::uninitialized_copy involving two > > trivially copyable types. That was incorrect behaviour, because a > > non-trivial constructor should have been used, but using std::copy used > > trivial default initialization followed by assignment. > > 20_util/specialized_algorithms/uninitialized_fill_n/sizes.cc was testing > > the behaviour with a non-integral Size passed to uninitialized_fill_n, > > but I wrote the test looking at the requirements of uninitialized_copy_n > > which are not the same as uninitialized_fill_n. The former uses --n and > > tests n > 0, but the latter just tests n-- (which will never be false > > for a floating-point value with a fractional part). > > > > libstdc++-v3/ChangeLog: > > > > PR libstdc++/68350 > > PR libstdc++/93059 > > * include/bits/stl_algobase.h (__niter_base, __niter_wrap): Move > > to ... > > * include/bits/stl_iterator.h: ... here. > > * include/bits/stl_uninitialized.h (__check_constructible) > > (_GLIBCXX_USE_ASSIGN_FOR_INIT): Remove. > > [C++98] (__unwrappable_niter): New trait. > > (__uninitialized_copy): Replace use of std::copy. > > (uninitialized_copy): Fix Doxygen comments. Open-code memcpy > > optimization for C++11 and later. > > (__uninitialized_fill): Replace use of std::fill. > > (uninitialized_fill): Fix Doxygen comments. Open-code memset > > optimization for C++11 and later. > > (__uninitialized_fill_n): Replace use of std::fill_n. > > (uninitialized_fill_n): Fix Doxyg
Re: [PATCH] libstdc++: Refactor std::uninitialized_{copy, fill, fill_n} algos [PR68350]
This causes some codegen regressions on (at least) aarch64 and power64: FAIL: g++.dg/pr104547.C -std=gnu++11 scan-tree-dump-not vrp2 "_M_default_append" FAIL: g++.dg/pr104547.C -std=gnu++17 scan-tree-dump-not vrp2 "_M_default_append" For some reason the PR 104547 fix to stop the unused _M_default_append function being emitted in the assembly code no longer works. I also see new bogus stringop-overflow warnings for these tests: FAIL: 27_io/basic_ios/imbue/14072.cc -std=gnu++17 (test for excess errors) FAIL: 27_io/basic_istream/extractors_character/char/9826.cc -std=gnu++17 (test for excess errors) FAIL: 27_io/basic_stringbuf/requirements/explicit_instantiation/2.cc -std=gnu++17 (test for excess errors) FAIL: 27_io/basic_stringstream/requirements/explicit_instantiation.cc -std=gnu++17 (test for excess errors) On Mon, 14 Oct 2024 at 00:53, Jonathan Wakely wrote: > > Tested x86_64-linux. > > -- >8 -- > > This refactors the std::uninitialized_copy, std::uninitialized_fill and > std::uninitialized_fill_n algorithms to directly perform memcpy/memset > optimizations instead of dispatching to std::copy/std::fill/std::fill_n. > > The reasons for this are: > > - Use 'if constexpr' to simplify and optimize compilation throughput, so > dispatching to specialized class templates is only needed for C++98 > mode. > - Relax the conditions for using memcpy/memset, because the C++20 rules > on implicit-lifetime types mean that we can rely on memcpy to begin > lifetimes of trivially copyable types. We don't need to require > trivially default constructible, so don't need to limit the > optimization to trivial types. See PR 68350 for more details. > - The conditions on non-overlapping ranges are stronger for > std::uninitialized_copy than for std::copy so we can use memcpy instead > of memmove, which might be a minor optimization. > - Avoid including in . > It only needs some iterator utilities from that file now, which belong > in anyway, so this moves them there. > > Several tests need changes to the diagnostics matched by dg-error > because we no longer use the __constructible() function that had a > static assert in. Now we just get straightforward errors for attempting > to use a deleted constructor. > > Two tests needed more signficant changes to the actual expected results > of executing the tests, because they were checking for old behaviour > which was incorrect according to the standard. > 20_util/specialized_algorithms/uninitialized_copy/64476.cc was expecting > std::copy to be used for a call to std::uninitialized_copy involving two > trivially copyable types. That was incorrect behaviour, because a > non-trivial constructor should have been used, but using std::copy used > trivial default initialization followed by assignment. > 20_util/specialized_algorithms/uninitialized_fill_n/sizes.cc was testing > the behaviour with a non-integral Size passed to uninitialized_fill_n, > but I wrote the test looking at the requirements of uninitialized_copy_n > which are not the same as uninitialized_fill_n. The former uses --n and > tests n > 0, but the latter just tests n-- (which will never be false > for a floating-point value with a fractional part). > > libstdc++-v3/ChangeLog: > > PR libstdc++/68350 > PR libstdc++/93059 > * include/bits/stl_algobase.h (__niter_base, __niter_wrap): Move > to ... > * include/bits/stl_iterator.h: ... here. > * include/bits/stl_uninitialized.h (__check_constructible) > (_GLIBCXX_USE_ASSIGN_FOR_INIT): Remove. > [C++98] (__unwrappable_niter): New trait. > (__uninitialized_copy): Replace use of std::copy. > (uninitialized_copy): Fix Doxygen comments. Open-code memcpy > optimization for C++11 and later. > (__uninitialized_fill): Replace use of std::fill. > (uninitialized_fill): Fix Doxygen comments. Open-code memset > optimization for C++11 and later. > (__uninitialized_fill_n): Replace use of std::fill_n. > (uninitialized_fill_n): Fix Doxygen comments. Open-code memset > optimization for C++11 and later. > * > testsuite/20_util/specialized_algorithms/uninitialized_copy/64476.cc: > Adjust expected behaviour to match what the standard specifies. > * > testsuite/20_util/specialized_algorithms/uninitialized_fill_n/sizes.cc: > Likewise. > * testsuite/20_util/specialized_algorithms/uninitialized_copy/1.cc: > Adjust dg-error directives. > * > testsuite/20_util/specialized_algorithms/uninitialized_copy/89164.cc: > Likewise. > * > testsuite/20_util/specialized_algorithms/unin
Re: [PATCH] aarch64: libstdc++: Use shufflevector instead of shuffle in opt_random.h
On Mon, 14 Oct 2024 at 14:36, Kyrylo Tkachov wrote: > > > > > On 14 Oct 2024, at 15:28, Ricardo Jesus wrote: > > > > External email: Use caution opening links or attachments > > > > > > This patch modifies the implementation of the vectorized mersenne > > twister random number generator to use __builtin_shufflevector instead > > of __builtin_shuffle. This makes it (almost) compatible with Clang. > > > > To make the implementation fully compatible with Clang, Clang will need > > to support internal Neon types like __Uint8x16_t and __Uint32x4_t, which > > currently it does not. This looks like an oversight in Clang and so will > > be addressed separately. > > > > I see no codegen change with this patch. > > FWIW the change looks ok to me from an aarch64 perspective. > The only potential problem could have been a compile error so as long as the > CI buildbots are happy I think this would be safe to take. OK thanks for looking. I'll wait to see that CI is green (thanks for resubmitting it, Ricardo!) and then push it. > Thanks, > Kyrill > > > > > Bootstrapped and tested on aarch64-none-linux-gnu. > > > > Signed-off-by: Ricardo Jesus > > > > 2024-09-05 Ricardo Jesus > > > >* config/cpu/aarch64/opt/ext/opt_random.h (__VEXT): Replace uses > >of __builtin_shuffle with __builtin_shufflevector. > >(__aarch64_lsl_128): Move shift amount to a template parameter. > >(__aarch64_lsr_128): Move shift amount to a template parameter. > >(__aarch64_recursion): Update call sites of __aarch64_lsl_128 > >and __aarch64_lsr_128. > > --- > > .../config/cpu/aarch64/opt/ext/opt_random.h | 28 +++ > > 1 file changed, 16 insertions(+), 12 deletions(-) > > > > diff --git a/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h > > b/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h > > index 7f756d1572f..7eb816abcd0 100644 > > --- a/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h > > +++ b/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h > > @@ -35,13 +35,13 @@ > > #ifdef __ARM_NEON > > > > #ifdef __ARM_BIG_ENDIAN > > -# define __VEXT(_A,_B,_C) __builtin_shuffle (_A, _B, (__Uint8x16_t) \ > > -{16-_C, 17-_C, 18-_C, 19-_C, 20-_C, 21-_C, 22-_C, 23-_C, \ > > - 24-_C, 25-_C, 26-_C, 27-_C, 28-_C, 29-_C, 30-_C, 31-_C}) > > +# define __VEXT(_A,_B,_C) __builtin_shufflevector (_A, _B, \ > > +16-_C, 17-_C, 18-_C, 19-_C, 20-_C, 21-_C, 22-_C, 23-_C, \ > > +24-_C, 25-_C, 26-_C, 27-_C, 28-_C, 29-_C, 30-_C, 31-_C) > > #else > > -# define __VEXT(_A,_B,_C) __builtin_shuffle (_B, _A, (__Uint8x16_t) \ > > -{_C, _C+1, _C+2, _C+3, _C+4, _C+5, _C+6, _C+7, \ > > - _C+8, _C+9, _C+10, _C+11, _C+12, _C+13, _C+14, _C+15}) > > +# define __VEXT(_A,_B,_C) __builtin_shufflevector (_B, _A, \ > > +_C, _C+1, _C+2, _C+3, _C+4, _C+5, _C+6, _C+7, \ > > +_C+8, _C+9, _C+10, _C+11, _C+12, _C+13, _C+14, _C+15) > > #endif > > > > #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ > > @@ -52,9 +52,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > namespace { > > // Logical Shift right 128-bits by c * 8 bits > > > > -__extension__ extern __inline __Uint32x4_t > > +__extension__ > > +template > > +extern __inline __Uint32x4_t > > __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) > > -__aarch64_lsr_128 (__Uint8x16_t __a, __const int __c) > > +__aarch64_lsr_128 (__Uint8x16_t __a) > > { > > const __Uint8x16_t __zero = {0, 0, 0, 0, 0, 0, 0, 0, > > 0, 0, 0, 0, 0, 0, 0, 0}; > > @@ -64,9 +66,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > > > // Logical Shift left 128-bits by c * 8 bits > > > > -__extension__ extern __inline __Uint32x4_t > > +__extension__ > > +template > > +extern __inline __Uint32x4_t > > __attribute__ ((__always_inline__, __gnu_inline__, __artificial__)) > > -__aarch64_lsl_128 (__Uint8x16_t __a, __const int __c) > > +__aarch64_lsl_128 (__Uint8x16_t __a) > > { > > const __Uint8x16_t __zero = {0, 0, 0, 0, 0, 0, 0, 0, > > 0, 0, 0, 0, 0, 0, 0, 0}; > > @@ -82,14 +86,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION > > __Uint32x4_t __e) > > { > > __Uint32x4_t __y = (__b >> __sr1); > > - __Uint32x4_t __z = __aarch64_lsr_128 ((__Uint8x16_t) __c, __sr2); > > + __Uint32x4_t __z = __aarch64_lsr_128<__sr2> ((__Uint8x16_t) __c); > > > > __Uint32x4_t __v = __d << __sl1; > > > > __z = __z ^ __a; > > __z = __z ^ __v; > > > > - __Uint32x4_t __x = __aarch64_lsl_128 ((__Uint8x16_t) __a, __sl2); > > + __Uint32x4_t __x = __aarch64_lsl_128<__sl2> ((__Uint8x16_t) __a); > > > > __y = __y & __e; > > __z = __z ^ __x; > > -- > > 2.44.0 > > >
Re: libstdc++ fetch_add & fenv -- ecosystem questions
On Mon, 14 Oct 2024 at 14:35, Jonathan Wakely wrote: > > N.B. please CC the libstdc++ list for libstdc++ topics. > > On Mon, 14 Oct 2024 at 14:00, Matthew Malcomson wrote: > > > > After getting GCC to handle floating point exceptions I'm now noticing that > > the `targetm.atomic_assign_expand_fenv` hook tends to use the library > > function `__atomic_feraiseexcept`. > > This requires adding -latomic to the command line where it wasn't needed > > before. > > I also notice that the inline CAS loop for libstdc++ `atomic::fetch_add` > > on floating point types doesn't handle these floating point exceptions. > > Right, Joseph made the C front-end handle them for _Atomic but I > didn't do that for std::atomic. > > > For context, clang (which has already implemented floating point fetch_add > > for floating point types) is not emitting anything to handle the floating > > point environment. I'm not sure if C++ users really care about fenv. I think most don't. > > > > I expect that the eventual goal should be (please do correct if you > > disagree) > > > > Update the existing libstdc++ CAS loop to handle floating point exceptions. > > Suggest to clang that the fetch_add builtin should handle floating point > > exceptions. > > GCC builtin handles floating point exceptions. > > __atomic_feraiseexcept should be a builtin to avoid previously unnecessary > > requirement to link libatomic. > > > > However I'm uncertain we could sort all that out for GCC 15. > > Would it be reasonable to require linking with libatomic for the GCC 15 > > release? > > That would be a regression for anybody using > std::atomic today. > > > Alternatively is there some other intermediate step that people would > > prefer? > > Similarly — maybe there's something I'm missing — maybe about differences > > between C/C++? > > > > Another option is to aim for implementing the functionality of > > __atomic_feraiseexcept inline in the fetch_add GCC 15 (a bit tight on > > time), to use it in the new fetch_add builtin overload, but not use it in > > the CAS loop. > > That way no compiler & floating point type combination would need linking > > libatomic, current clang would not handle floating point exception > > information, while current gcc would handle that information. > > > > What are your thoughts? > > If making it Just Work without a new libatomic requirement is > possible, I'd prefer that. > > > Regards, > > Matthew > > > > > > From: Joseph Myers > > Sent: 19 September 2024 10:38 PM > > To: Matthew Malcomson > > Cc: gcc-patches@gcc.gnu.org ; Jonathan Wakely > > ; Richard Biener > > Subject: Re: [PATCH 0/8] [RFC] Introduce floating point fetch_add builtins > > > > External email: Use caution opening links or attachments > > > > > > On Thu, 19 Sep 2024, mmalcom...@nvidia.com wrote: > > > > > 6) Anything special about floating point maths that I'm tripping up on? > > > > Correct atomic operations with floating-point operands should ensure that > > exceptions raised exactly correspond to the operands for which the > > operation succeeded, and not to the operands for any previous attempts > > where the compare-exchange failed. There is a lengthy note in the C > > standard (in C11 it's a footnote in 6.5.16.2, in C17 it's a Note in > > 6.5.16.2 and in C23 that subclause has become 6.5.17.3) that discusses > > appropriate code sequences to achieve this. In GCC the implementation of > > this is in c-typeck.cc:build_atomic_assign, which in turn calls > > targetm.atomic_assign_expand_fenv (note that we have the complication for > > C of not introducing libm dependencies in code that only uses standard > > language features and not , or , so direct use > > of functions is inappropriate here). > > > > I would expect such built-in functions to follow the same semantics for > > floating-point exceptions as _Atomic compound assignment does. (Note that > > _Atomic compound assignment is more general in the allowed operands, > > because compound assignment is a heterogeneous operation - for example, > > the special floating-point logic in build_atomic_assign includes the case > > where the LHS of the compound assignment is of atomic integer type but the > > RHS is of floating type. However, built-in functions allow memory orders > > other than seq_cst to be used, whereas _Atomic compound assignment is > > limited
Re: libstdc++ fetch_add & fenv -- ecosystem questions
N.B. please CC the libstdc++ list for libstdc++ topics. On Mon, 14 Oct 2024 at 14:00, Matthew Malcomson wrote: > > After getting GCC to handle floating point exceptions I'm now noticing that > the `targetm.atomic_assign_expand_fenv` hook tends to use the library > function `__atomic_feraiseexcept`. > This requires adding -latomic to the command line where it wasn't needed > before. > I also notice that the inline CAS loop for libstdc++ `atomic::fetch_add` > on floating point types doesn't handle these floating point exceptions. Right, Joseph made the C front-end handle them for _Atomic but I didn't do that for std::atomic. > For context, clang (which has already implemented floating point fetch_add > for floating point types) is not emitting anything to handle the floating > point environment. > > I expect that the eventual goal should be (please do correct if you disagree) > > Update the existing libstdc++ CAS loop to handle floating point exceptions. > Suggest to clang that the fetch_add builtin should handle floating point > exceptions. > GCC builtin handles floating point exceptions. > __atomic_feraiseexcept should be a builtin to avoid previously unnecessary > requirement to link libatomic. > > However I'm uncertain we could sort all that out for GCC 15. > Would it be reasonable to require linking with libatomic for the GCC 15 > release? That would be a regression for anybody using std::atomic today. > Alternatively is there some other intermediate step that people would prefer? > Similarly — maybe there's something I'm missing — maybe about differences > between C/C++? > > Another option is to aim for implementing the functionality of > __atomic_feraiseexcept inline in the fetch_add GCC 15 (a bit tight on time), > to use it in the new fetch_add builtin overload, but not use it in the CAS > loop. > That way no compiler & floating point type combination would need linking > libatomic, current clang would not handle floating point exception > information, while current gcc would handle that information. > > What are your thoughts? If making it Just Work without a new libatomic requirement is possible, I'd prefer that. > Regards, > Matthew > > > From: Joseph Myers > Sent: 19 September 2024 10:38 PM > To: Matthew Malcomson > Cc: gcc-patches@gcc.gnu.org ; Jonathan Wakely > ; Richard Biener > Subject: Re: [PATCH 0/8] [RFC] Introduce floating point fetch_add builtins > > External email: Use caution opening links or attachments > > > On Thu, 19 Sep 2024, mmalcom...@nvidia.com wrote: > > > 6) Anything special about floating point maths that I'm tripping up on? > > Correct atomic operations with floating-point operands should ensure that > exceptions raised exactly correspond to the operands for which the > operation succeeded, and not to the operands for any previous attempts > where the compare-exchange failed. There is a lengthy note in the C > standard (in C11 it's a footnote in 6.5.16.2, in C17 it's a Note in > 6.5.16.2 and in C23 that subclause has become 6.5.17.3) that discusses > appropriate code sequences to achieve this. In GCC the implementation of > this is in c-typeck.cc:build_atomic_assign, which in turn calls > targetm.atomic_assign_expand_fenv (note that we have the complication for > C of not introducing libm dependencies in code that only uses standard > language features and not , or , so direct use > of functions is inappropriate here). > > I would expect such built-in functions to follow the same semantics for > floating-point exceptions as _Atomic compound assignment does. (Note that > _Atomic compound assignment is more general in the allowed operands, > because compound assignment is a heterogeneous operation - for example, > the special floating-point logic in build_atomic_assign includes the case > where the LHS of the compound assignment is of atomic integer type but the > RHS is of floating type. However, built-in functions allow memory orders > other than seq_cst to be used, whereas _Atomic compound assignment is > limited to the seq_cst case.) > > So it would seem appropriate for the implementation of such built-in > functions to make use of targetm.atomic_assign_expand_fenv for > floating-point environment handling, and for testcases to include tests > analogous to c11-atomic-exec-5.c that exceptions are being handled > correctly. > > Cf. N2329 which suggested such operations for C in (but > tried to do to many things in one paper to be accepted into C); it didn't > go into the floating-point exceptions semantics but simple correctness > would indicate avoiding spurious exceptions from discarded computations. > > -- > Joseph S. Myers > josmy...@redhat.com >
[PATCH] libstdc++: debug output in 22_locale/time_get/get/wchar_t/5.cc [PR117135]
This is not going to be committed. This is just for arm-none-eabi CI testing, re PR 117135. libstdc++-v3/ChangeLog: * testsuite/22_locale/time_get/get/wchar_t/5.cc: Dump debugging info. --- .../testsuite/22_locale/time_get/get/wchar_t/5.cc | 13 + 1 file changed, 13 insertions(+) diff --git a/libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/5.cc b/libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/5.cc index 254ae96acd1..79c8a56f04a 100644 --- a/libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/5.cc +++ b/libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/5.cc @@ -11,7 +11,20 @@ int main() std::wistringstream ss(L"Fri Jul 5 14:58:21 2019"); std::ios::iostate err = std::ios::goodbit; std::tm tm = {}; + + const auto& punct = std::use_facet>(std::locale::classic()); + const wchar_t* formats[2]; + punct._M_date_time_formats(formats); + __builtin_printf("Wide D_T_FMT for C locale: "); + std::wstring fmt(formats[0]); + for (wchar_t c : fmt) +__builtin_printf("%c", (char)c); + __builtin_puts(""); + fac.get(ss, Facet::iter_type(), ss, err, &tm, 'c'); + __builtin_printf("eofbit: %d failbit: %d badbit: %d\n", + (int)(err & std::ios::eofbit), (int)(err & std::ios::failbit), + (int)(err & std::ios::badbit)); VERIFY( err == std::ios::eofbit ); VERIFY( tm.tm_year == 119 ); VERIFY( tm.tm_mon == 6 ); -- 2.46.2