Re: [PATCH] Avoid vector -Wfree-nonheap-object warnings

2024-05-25 Thread François Dumont



On 24/05/2024 16:17, Jonathan Wakely wrote:

On Thu, 23 May 2024 at 18:38, François Dumont  wrote:


On 23/05/2024 15:31, Jonathan Wakely wrote:

On 23/05/24 06:55 +0200, François Dumont wrote:

As explained in this email:

https://gcc.gnu.org/pipermail/libstdc++/2024-April/058552.html

I experimented -Wfree-nonheap-object because of my enhancements on
algos.

So here is a patch to extend the usage of the _Guard type to other
parts of vector.

Nice, that fixes the warning you were seeing?

Yes ! I indeed forgot to say so :-)



We recently got a bug report about -Wfree-nonheap-object in
std::vector, but that is coming from _M_realloc_append which already
uses the RAII guard :-(
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115016

Note that I also had to move call to __uninitialized_copy_a before
assigning this->_M_impl._M_start so get rid of the -Wfree-nonheap-object
warn. But _M_realloc_append is already doing potentially throwing
operations before assigning this->_M_impl so it must be something else.

Though it made me notice another occurence of _Guard in this method. Now
replaced too in this new patch.

  libstdc++: Use RAII to replace try/catch blocks

  Move _Guard into std::vector declaration and use it to guard all
calls to
  vector _M_allocate.

  Doing so the compiler has more visibility on what is done with the
pointers
  and do not raise anymore the -Wfree-nonheap-object warning.

  libstdc++-v3/ChangeLog:

  * include/bits/vector.tcc (_Guard): Move all the nested
duplicated class...
  * include/bits/stl_vector.h (_Guard_alloc): ...here.
  (_M_allocate_and_copy): Use latter.
  (_M_initialize_dispatch): Likewise and set _M_finish first
from the result
  of __uninitialize_fill_n_a that can throw.
  (_M_range_initialize): Likewise.


diff --git a/libstdc++-v3/include/bits/stl_vector.h
b/libstdc++-v3/include/bits/stl_vector.h
index 31169711a48..4ea74e3339a 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -1607,6 +1607,39 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   clear() _GLIBCXX_NOEXCEPT
   { _M_erase_at_end(this->_M_impl._M_start); }

+private:
+  // RAII guard for allocated storage.
+  struct _Guard

If it's being defined at class scope instead of locally in a member
function, I think a better name would be good. Maybe _Ptr_guard or
_Dealloc_guard or something.

_Guard_alloc chosen.

+  {
+pointer _M_storage;// Storage to deallocate
+size_type _M_len;
+_Base& _M_vect;
+
+_GLIBCXX20_CONSTEXPR
+_Guard(pointer __s, size_type __l, _Base& __vect)
+: _M_storage(__s), _M_len(__l), _M_vect(__vect)
+{ }
+
+_GLIBCXX20_CONSTEXPR
+~_Guard()
+{
+  if (_M_storage)
+_M_vect._M_deallocate(_M_storage, _M_len);
+}
+
+_GLIBCXX20_CONSTEXPR
+pointer
+_M_release()
+{
+  pointer __res = _M_storage;
+  _M_storage = 0;

I don't think the NullablePointer requirements include assigning 0,
only from nullptr, which isn't valid in C++98.

https://en.cppreference.com/w/cpp/named_req/NullablePointer

Please use _M_storage = pointer() instead.

I forgot about user fancy pointer, fixed.



+  return __res;
+}
+
+  private:
+_Guard(const _Guard&);
+  };
+
 protected:
   /**
*  Memory expansion handler.  Uses the member allocation
function to
@@ -1618,18 +1651,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 _M_allocate_and_copy(size_type __n,
  _ForwardIterator __first, _ForwardIterator __last)
 {
-  pointer __result = this->_M_allocate(__n);
-  __try
-{
-  std::__uninitialized_copy_a(__first, __last, __result,
-  _M_get_Tp_allocator());
-  return __result;
-}
-  __catch(...)
-{
-  _M_deallocate(__result, __n);
-  __throw_exception_again;
-}
+  _Guard __guard(this->_M_allocate(__n), __n, *this);
+  std::__uninitialized_copy_a
+(__first, __last, __guard._M_storage, _M_get_Tp_allocator());
+  return __guard._M_release();
 }


@@ -1642,13 +1667,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   // 438. Ambiguity in the "do the right thing" clause
   template
 void
-_M_initialize_dispatch(_Integer __n, _Integer __value, __true_type)
+_M_initialize_dispatch(_Integer __int_n, _Integer __value,
__true_type)
 {
-  this->_M_impl._M_start = _M_allocate(_S_check_init_len(
-static_cast(__n), _M_get_Tp_allocator()));
-  this->_M_impl._M_end_of_storage =
-this->_M_impl._M_start + static_cast(__n);
-  _M_fill_initialize(static_cast(__n), __value);

Please fix the comment on _M_fill_initialize if you're removing the
use of it here.

Already done in this initial patch proposal, see below.


+  const size_type __n = static_ca

Re: [PATCH] Avoid vector -Wfree-nonheap-object warnings

2024-05-23 Thread François Dumont


On 23/05/2024 15:31, Jonathan Wakely wrote:

On 23/05/24 06:55 +0200, François Dumont wrote:

As explained in this email:

https://gcc.gnu.org/pipermail/libstdc++/2024-April/058552.html

I experimented -Wfree-nonheap-object because of my enhancements on 
algos.


So here is a patch to extend the usage of the _Guard type to other 
parts of vector.


Nice, that fixes the warning you were seeing?


Yes ! I indeed forgot to say so :-)




We recently got a bug report about -Wfree-nonheap-object in
std::vector, but that is coming from _M_realloc_append which already
uses the RAII guard :-(
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115016


Note that I also had to move call to __uninitialized_copy_a before 
assigning this->_M_impl._M_start so get rid of the -Wfree-nonheap-object 
warn. But _M_realloc_append is already doing potentially throwing 
operations before assigning this->_M_impl so it must be something else.


Though it made me notice another occurence of _Guard in this method. Now 
replaced too in this new patch.


    libstdc++: Use RAII to replace try/catch blocks

    Move _Guard into std::vector declaration and use it to guard all 
calls to

    vector _M_allocate.

    Doing so the compiler has more visibility on what is done with the 
pointers

    and do not raise anymore the -Wfree-nonheap-object warning.

    libstdc++-v3/ChangeLog:

    * include/bits/vector.tcc (_Guard): Move all the nested 
duplicated class...

    * include/bits/stl_vector.h (_Guard_alloc): ...here.
    (_M_allocate_and_copy): Use latter.
    (_M_initialize_dispatch): Likewise and set _M_finish first 
from the result

    of __uninitialize_fill_n_a that can throw.
    (_M_range_initialize): Likewise.

diff --git a/libstdc++-v3/include/bits/stl_vector.h 
b/libstdc++-v3/include/bits/stl_vector.h

index 31169711a48..4ea74e3339a 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -1607,6 +1607,39 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
  clear() _GLIBCXX_NOEXCEPT
  { _M_erase_at_end(this->_M_impl._M_start); }

+    private:
+  // RAII guard for allocated storage.
+  struct _Guard


If it's being defined at class scope instead of locally in a member
function, I think a better name would be good. Maybe _Ptr_guard or
_Dealloc_guard or something.

_Guard_alloc chosen.



+  {
+    pointer _M_storage;    // Storage to deallocate
+    size_type _M_len;
+    _Base& _M_vect;
+
+    _GLIBCXX20_CONSTEXPR
+    _Guard(pointer __s, size_type __l, _Base& __vect)
+    : _M_storage(__s), _M_len(__l), _M_vect(__vect)
+    { }
+
+    _GLIBCXX20_CONSTEXPR
+    ~_Guard()
+    {
+  if (_M_storage)
+    _M_vect._M_deallocate(_M_storage, _M_len);
+    }
+
+    _GLIBCXX20_CONSTEXPR
+    pointer
+    _M_release()
+    {
+  pointer __res = _M_storage;
+  _M_storage = 0;


I don't think the NullablePointer requirements include assigning 0,
only from nullptr, which isn't valid in C++98.

https://en.cppreference.com/w/cpp/named_req/NullablePointer

Please use _M_storage = pointer() instead.


I forgot about user fancy pointer, fixed.





+  return __res;
+    }
+
+  private:
+    _Guard(const _Guard&);
+  };
+
    protected:
  /**
   *  Memory expansion handler.  Uses the member allocation 
function to

@@ -1618,18 +1651,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_allocate_and_copy(size_type __n,
 _ForwardIterator __first, _ForwardIterator __last)
{
-  pointer __result = this->_M_allocate(__n);
-  __try
-    {
-  std::__uninitialized_copy_a(__first, __last, __result,
-  _M_get_Tp_allocator());
-  return __result;
-    }
-  __catch(...)
-    {
-  _M_deallocate(__result, __n);
-  __throw_exception_again;
-    }
+  _Guard __guard(this->_M_allocate(__n), __n, *this);
+  std::__uninitialized_copy_a
+    (__first, __last, __guard._M_storage, _M_get_Tp_allocator());
+  return __guard._M_release();
}


@@ -1642,13 +1667,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
  // 438. Ambiguity in the "do the right thing" clause
  template
void
-    _M_initialize_dispatch(_Integer __n, _Integer __value, __true_type)
+    _M_initialize_dispatch(_Integer __int_n, _Integer __value, 
__true_type)

{
-  this->_M_impl._M_start = _M_allocate(_S_check_init_len(
-    static_cast(__n), _M_get_Tp_allocator()));
-  this->_M_impl._M_end_of_storage =
-    this->_M_impl._M_start + static_cast(__n);
-  _M_fill_initialize(static_cast(__n), __value);


Please fix the comment on _M_fill_initialize if you're removing the
use of it here.


Already done in this initial patch proposal, see below.




+  const size_type __n = static_cast(__int_n);
+  _Guard __guard(_M_allocate(_S_check_init_len(
+    __n, _M_get_Tp_allocator())

[PATCH] Avoid vector -Wfree-nonheap-object warnings

2024-05-22 Thread François Dumont

As explained in this email:

https://gcc.gnu.org/pipermail/libstdc++/2024-April/058552.html

I experimented -Wfree-nonheap-object because of my enhancements on algos.

So here is a patch to extend the usage of the _Guard type to other parts 
of vector.


    libstdc++: Use RAII to replace try/catch blocks

    Move _Guard into std::vector declaration and use it to guard all 
calls to

    vector _M_allocate.

    Doing so the compiler has more visibility on what is done with the 
pointers

    and do not raise anymore the -Wfree-nonheap-object warning.

    libstdc++-v3/ChangeLog:

    * include/bits/vector.tcc (_Guard): Move...
    * include/bits/stl_vector.h: ...here.
    (_M_allocate_and_copy): Use latter.
    (_M_initialize_dispatch): Likewise and set _M_finish first 
from the result

    of __uninitialize_fill_n_a that can throw.
    (_M_range_initialize): Likewise.

Tested under Linux x86_64, ok to commit ?

François

diff --git a/libstdc++-v3/include/bits/stl_vector.h 
b/libstdc++-v3/include/bits/stl_vector.h
index 31169711a48..4ea74e3339a 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -1607,6 +1607,39 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   clear() _GLIBCXX_NOEXCEPT
   { _M_erase_at_end(this->_M_impl._M_start); }
 
+private:
+  // RAII guard for allocated storage.
+  struct _Guard
+  {
+   pointer _M_storage; // Storage to deallocate
+   size_type _M_len;
+   _Base& _M_vect;
+
+   _GLIBCXX20_CONSTEXPR
+   _Guard(pointer __s, size_type __l, _Base& __vect)
+   : _M_storage(__s), _M_len(__l), _M_vect(__vect)
+   { }
+
+   _GLIBCXX20_CONSTEXPR
+   ~_Guard()
+   {
+ if (_M_storage)
+   _M_vect._M_deallocate(_M_storage, _M_len);
+   }
+
+   _GLIBCXX20_CONSTEXPR
+   pointer
+   _M_release()
+   {
+ pointer __res = _M_storage;
+ _M_storage = 0;
+ return __res;
+   }
+
+  private:
+   _Guard(const _Guard&);
+  };
+
 protected:
   /**
*  Memory expansion handler.  Uses the member allocation function to
@@ -1618,18 +1651,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_allocate_and_copy(size_type __n,
 _ForwardIterator __first, _ForwardIterator __last)
{
- pointer __result = this->_M_allocate(__n);
- __try
-   {
- std::__uninitialized_copy_a(__first, __last, __result,
- _M_get_Tp_allocator());
- return __result;
-   }
- __catch(...)
-   {
- _M_deallocate(__result, __n);
- __throw_exception_again;
-   }
+ _Guard __guard(this->_M_allocate(__n), __n, *this);
+ std::__uninitialized_copy_a
+   (__first, __last, __guard._M_storage, _M_get_Tp_allocator());
+ return __guard._M_release();
}
 
 
@@ -1642,13 +1667,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   // 438. Ambiguity in the "do the right thing" clause
   template
void
-   _M_initialize_dispatch(_Integer __n, _Integer __value, __true_type)
+   _M_initialize_dispatch(_Integer __int_n, _Integer __value, __true_type)
{
- this->_M_impl._M_start = _M_allocate(_S_check_init_len(
-   static_cast(__n), _M_get_Tp_allocator()));
- this->_M_impl._M_end_of_storage =
-   this->_M_impl._M_start + static_cast(__n);
- _M_fill_initialize(static_cast(__n), __value);
+ const size_type __n = static_cast(__int_n);
+ _Guard __guard(_M_allocate(_S_check_init_len(
+   __n, _M_get_Tp_allocator())), __n, *this);
+ this->_M_impl._M_finish = std::__uninitialized_fill_n_a
+   (__guard._M_storage, __n, __value, _M_get_Tp_allocator());
+ pointer __start = this->_M_impl._M_start = __guard._M_release();
+ this->_M_impl._M_end_of_storage = __start + __n;
}
 
   // Called by the range constructor to implement [23.1.1]/9
@@ -1690,17 +1717,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
std::forward_iterator_tag)
{
  const size_type __n = std::distance(__first, __last);
- this->_M_impl._M_start
-   = this->_M_allocate(_S_check_init_len(__n, _M_get_Tp_allocator()));
- this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n;
- this->_M_impl._M_finish =
-   std::__uninitialized_copy_a(__first, __last,
-   this->_M_impl._M_start,
-   _M_get_Tp_allocator());
+ _Guard __guard(this->_M_allocate(_S_check_init_len(
+   __n, _M_get_Tp_allocator())), __n, *this);
+ this->_M_impl._M_finish = std::__uninitialized_copy_a
+   (__first, __last, __guard._M_storage, _M_get_Tp_allocator());
+ pointer 

Re: [PATCH][_Hashtable] Fix some implementation inconsistencies

2024-05-21 Thread François Dumont

Ping ?

On 13/05/2024 06:33, François Dumont wrote:

libstdc++: [_Hashtable] Fix some implementation inconsistencies

    Get rid of the different usages of the mutable keyword except in
    _Prime_rehash_policy where it is preserved for abi compatibility 
reason.


    Fix comment to explain that we need the computation of bucket 
index noexcept

    to be able to rehash the container when needed.

    For Standard instantiations through std::unordered_xxx containers 
we already
    force caching of hash code when hash functor is not noexcep so it 
is guarantied.


    The static_assert purpose in _Hashtable on _M_bucket_index is thus 
limited

    to usages of _Hashtable with exotic _Hashtable_traits.

    libstdc++-v3/ChangeLog:

    * include/bits/hashtable_policy.h 
(_NodeBuilder<>::_S_build): Remove

    const qualification on _NodeGenerator instance.
(_ReuseOrAllocNode<>::operator()(_Args&&...)): Remove const 
qualification.

    (_ReuseOrAllocNode<>::_M_nodes): Remove mutable.
    (_Insert_base<>::_M_insert_range): Remove _NodeGetter 
const qualification.
    (_Hash_code_base<>::_M_bucket_index(const 
_Hash_node_value<>&, size_t)):
    Simplify noexcept declaration, we already static_assert 
that _RangeHash functor

    is noexcept.
    * include/bits/hashtable.h: Rework comments. Remove const 
qualifier on

    _NodeGenerator& arguments.

Tested under Linux x64, ok to commit ?

François



Re: Fix gnu versioned namespace mode 00/03

2024-05-15 Thread François Dumont


On 13/05/2024 10:34, Jonathan Wakely wrote:



On Mon, 13 May 2024, 07:30 Iain Sandoe,  wrote:



> On 13 May 2024, at 06:06, François Dumont 
wrote:
>
>
> On 07/05/2024 18:15, Iain Sandoe wrote:
>> Hi François
>>
>>> On 4 May 2024, at 22:11, François Dumont
 wrote:
>>>
>>> Here is the list of patches to restore gnu versioned namespace
mode.
>>>
>>> 1/3: Bump gnu version namespace
>>>
>>> This is important to be done first so that once build of gnu
versioned namespace is fixed there is no chance to have another
build of '__8' version with a different abi than last successful
'__8' build.



The versioned namespace build is not expected to be ABI compatible 
though, so nobody should be expecting compatibility with previous 
builds. Especially not on the gcc-15 trunk, a week or two after 
entering stage 1!


Ok, I really thought that we needed to preserve ABI for a given version, 
'__8' at the moment.




>>>
>>> 2/3: Fix build using cxx11 abi for versioned namespace
>>>
>>> 3/3: Proposal to default to "new" abi when dual abi is
disabled and accept any default-libstdcxx-abi either dual abi is
enabled or not.
>>>
>>> All testsuite run for following configs:
>>>
>>> - dual abi
>>>
>>> - gcc4-compatible only abi
>>>
>>> - new only abi
>>>
>>> - versioned namespace abi
>> At the risk of delaying this (a bit) - I think we should also
consider items like once_call that have broken impls.
> Do you have any pointer to this once_call problem, sorry I'm not
aware about it (apart from your messages).

(although this mentions one specific target, it applies more widely).


I've removed the "on ppc64le" part from the summary.

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66146

Thanks for the ref, I'll have a look but I fear that I won't be of any 
help here.





Also, AFAICT, any nested once_call is a problem (not just exceptions).


Could you update the bug with that info please?


>>  in the current library - and at least get proposed
replacements available behind the versioned namespace; rather than
using up a namespace version with the current broken code.
>
> I'm not proposing to fix all library bugs on all platforms with
this patch, just fix the versioned namespace mode.

Sorry, I was not intending to suggest that (although perhaps my
comments read that way).

I was trying to suggest that, in the case where we have proposed
fixes that are blocked because they are ABI breaks, that those
could be put behind the versioned namspace (it was not an
intention to suggest that such additions should be part of this
patch series).

> As to do so I also need to adopt cxx11 abi in versioned mode it
already justify a bump of version.

I see - it’s just a bit strange that we are bumping a version for
a mode that does not currently work; however, i guess someone
might have deployed it even so.


It does work though, doesn't it?
It's known to fail on powerpc64 due to conflicts with the ieee128 
stuff, but it should work elsewhere.
It doesn't work with --with-default-libstdcxx-abi=cxx11 but that's 
just a "this doesn't work and isn't supported" limitation.


The point of the patch series is to change it so the versioned 
namespace always uses the cxx11 ABI, which does seem worth bumping the 
version (even though the versioned namespace is explicitly not a 
stable ABI and not backwards compatible).


So I just need to wait for proper review, right ?

This is what I plan to do on this subject for the moment.


Re: Fix gnu versioned namespace mode 00/03

2024-05-12 Thread François Dumont



On 07/05/2024 18:15, Iain Sandoe wrote:

Hi François


On 4 May 2024, at 22:11, François Dumont  wrote:

Here is the list of patches to restore gnu versioned namespace mode.

1/3: Bump gnu version namespace

This is important to be done first so that once build of gnu versioned 
namespace is fixed there is no chance to have another build of '__8' version 
with a different abi than last successful '__8' build.

2/3: Fix build using cxx11 abi for versioned namespace

3/3: Proposal to default to "new" abi when dual abi is disabled and accept any 
default-libstdcxx-abi either dual abi is enabled or not.

All testsuite run for following configs:

- dual abi

- gcc4-compatible only abi

- new only abi

- versioned namespace abi

At the risk of delaying this (a bit) - I think we should also consider items 
like once_call that have broken impls.
Do you have any pointer to this once_call problem, sorry I'm not aware 
about it (apart from your messages).

  in the current library - and at least get proposed replacements available 
behind the versioned namespace; rather than using up a namespace version with 
the current broken code.


I'm not proposing to fix all library bugs on all platforms with this 
patch, just fix the versioned namespace mode.


As to do so I also need to adopt cxx11 abi in versioned mode it already 
justify a bump of version.




I have a proposed once_call replacement (but I think Jonathan also has one or 
more alternatives there)

Please can we try to identify any other similar blocked fixes?


How ? We can only count on bugzilla bug reports to do so, no ?

If we face another similar problem in the future, after gcc 15 release, 
then we'll just have to bump again. Is it such a problem ?


The reason I'm proposing to integrate this patch this early in gcc 15 
stage is to have time to integrate any other library fix/optimization 
that could make use of it. I already have 1 on my side for the hashtable 
implementation. I hope your once_call fix also have time to be ready for 
gcc 15, no ?


François



[PATCH][_Hashtable] Fix some implementation inconsistencies

2024-05-12 Thread François Dumont

    libstdc++: [_Hashtable] Fix some implementation inconsistencies

    Get rid of the different usages of the mutable keyword except in
    _Prime_rehash_policy where it is preserved for abi compatibility 
reason.


    Fix comment to explain that we need the computation of bucket index 
noexcept

    to be able to rehash the container when needed.

    For Standard instantiations through std::unordered_xxx containers 
we already
    force caching of hash code when hash functor is not noexcep so it 
is guarantied.


    The static_assert purpose in _Hashtable on _M_bucket_index is thus 
limited

    to usages of _Hashtable with exotic _Hashtable_traits.

    libstdc++-v3/ChangeLog:

    * include/bits/hashtable_policy.h 
(_NodeBuilder<>::_S_build): Remove

    const qualification on _NodeGenerator instance.
(_ReuseOrAllocNode<>::operator()(_Args&&...)): Remove const qualification.
    (_ReuseOrAllocNode<>::_M_nodes): Remove mutable.
    (_Insert_base<>::_M_insert_range): Remove _NodeGetter const 
qualification.
    (_Hash_code_base<>::_M_bucket_index(const 
_Hash_node_value<>&, size_t)):
    Simplify noexcept declaration, we already static_assert 
that _RangeHash functor

    is noexcept.
    * include/bits/hashtable.h: Rework comments. Remove const 
qualifier on

    _NodeGenerator& arguments.

Tested under Linux x64, ok to commit ?

François

diff --git a/libstdc++-v3/include/bits/hashtable.h 
b/libstdc++-v3/include/bits/hashtable.h
index cd3e1ac297c..e8e51714d72 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -48,7 +48,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 using __cache_default
   =  __not_<__and_,
-  // Mandatory to have erase not throwing.
+  // Mandatory for the rehash process.
   __is_nothrow_invocable>>;
 
   // Helper to conditionally delete the default constructor.
@@ -481,7 +481,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
void
-   _M_assign(_Ht&&, const _NodeGenerator&);
+   _M_assign(_Ht&&, _NodeGenerator&);
 
   void
   _M_move_assign(_Hashtable&&, true_type);
@@ -919,7 +919,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
std::pair
-   _M_insert_unique(_Kt&&, _Arg&&, const _NodeGenerator&);
+   _M_insert_unique(_Kt&&, _Arg&&, _NodeGenerator&);
 
   template
static __conditional_t<
@@ -939,7 +939,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
std::pair
-   _M_insert_unique_aux(_Arg&& __arg, const _NodeGenerator& __node_gen)
+   _M_insert_unique_aux(_Arg&& __arg, _NodeGenerator& __node_gen)
{
  return _M_insert_unique(
_S_forward_key(_ExtractKey{}(std::forward<_Arg>(__arg))),
@@ -948,7 +948,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
std::pair
-   _M_insert(_Arg&& __arg, const _NodeGenerator& __node_gen,
+   _M_insert(_Arg&& __arg, _NodeGenerator& __node_gen,
  true_type /* __uks */)
{
  using __to_value
@@ -959,7 +959,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
iterator
-   _M_insert(_Arg&& __arg, const _NodeGenerator& __node_gen,
+   _M_insert(_Arg&& __arg, _NodeGenerator& __node_gen,
  false_type __uks)
{
  using __to_value
@@ -972,7 +972,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
iterator
_M_insert(const_iterator, _Arg&& __arg,
- const _NodeGenerator& __node_gen, true_type __uks)
+ _NodeGenerator& __node_gen, true_type __uks)
{
  return
_M_insert(std::forward<_Arg>(__arg), __node_gen, __uks).first;
@@ -982,7 +982,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
iterator
_M_insert(const_iterator, _Arg&&,
- const _NodeGenerator&, false_type __uks);
+ _NodeGenerator&, false_type __uks);
 
   size_type
   _M_erase(true_type __uks, const key_type&);
@@ -1414,7 +1414,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   void
   _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
 _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
-  _M_assign(_Ht&& __ht, const _NodeGenerator& __node_gen)
+  _M_assign(_Ht&& __ht, _NodeGenerator& __node_gen)
   {
__buckets_ptr __buckets = nullptr;
if (!_M_buckets)
@@ -1656,8 +1656,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 ~_Hashtable() noexcept
 {
   // Getting a bucket index from a node shall not throw because it is used
-  // in methods (erase, swap...) that shall not throw. Need a complete
-  // type to check this, so do it in the destructor not at class scope.
+  // during the rehash process. This static_assert purpose is limited to 
usage
+  // of _Hashtable with _Hashtable_traits requesting non-cached hash code.
+  

Fix gnu versioned namespace mode 02/03

2024-05-04 Thread François Dumont

    libstdc++: [_GLIBCXX_INLINE_VERSION] Use cxx11 abi [PR83077]

    Use cxx11 abi when activating versioned namespace mode. To do so 
support a new
    configuration mode where !_GLIBCXX_USE_DUAL_ABI and 
_GLIBCXX_USE_CXX11_ABI.


    The main change is that std::__cow_string is now defined whenever 
_GLIBCXX_USE_DUAL_ABI
    or _GLIBCXX_USE_CXX11_ABI is true. Implementation is using 
available std::string in

    case of dual abi and a subset of it when it's not.

    libstdcxx-v3/ChangeLog:

    PR libstdc++/83077
    * acinclude.m4 [GLIBCXX_ENABLE_LIBSTDCXX_DUAL_ABI]: Default 
to "new" libstdcxx abi

    when enable_symvers is gnu-versioned-namespace.
    * config/locale/dragonfly/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Define money_base

    members.
    * config/locale/generic/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Likewise.
    * config/locale/gnu/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Likewise.

    * config/locale/gnu/numeric_members.cc
    [!_GLIBCXX_USE_DUAL_ABI](__narrow_multibyte_chars): Define.
    * configure: Regenerate.
    * include/bits/c++config
    [_GLIBCXX_INLINE_VERSION](_GLIBCXX_NAMESPACE_CXX11, 
_GLIBCXX_BEGIN_NAMESPACE_CXX11):

    Define empty.
[_GLIBCXX_INLINE_VERSION](_GLIBCXX_END_NAMESPACE_CXX11, 
_GLIBCXX_DEFAULT_ABI_TAG):

    Likewise.
    * include/bits/cow_string.h: Remove _GLIBCXX_USE_CXX11_ABI 
macro condition. Replace
_GLIBCXX_BEGIN_NAMESPACE_VERSION/_GLIBCXX_END_NAMESPACE_VERSION by 
__detail namespace.

    * include/std/stdexcept
    [_GLIBCXX_USE_DUAL_ABI || 
_GLIBCXX_USE_CXX11_ABI](__cow_string): Define.

    (__cow_string::c_str()): New.
    * python/libstdcxx/v6/printers.py 
(StdStringPrinter::__init__): Set self.new_string to True

    when std::__8::basic_string type is found.
    * src/Makefile.am 
[ENABLE_SYMVERS_GNU_NAMESPACE](ldbl_alt128_compat_sources): Define empty.

    * src/Makefile.in: Regenerate.
    * src/c++11/Makefile.am (cxx11_abi_sources): Rename into...
    (dual_abi_sources): ...this. Also move cow-local_init.cc, 
cxx11-hash_tr1.cc,

    cxx11-ios_failure.cc entries to...
    (sources): ...this.
    (extra_string_inst_sources): Move cow-fstream-inst.cc, 
cow-sstream-inst.cc, cow-string-inst.cc,
    cow-string-io-inst.cc, cow-wtring-inst.cc, 
cow-wstring-io-inst.cc, cxx11-locale-inst.cc,

    cxx11-wlocale-inst.cc entries to...
    (inst_sources): ...this.
    * src/c++11/Makefile.in: Regenerate.
    * src/c++11/cow-fstream-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip content.
    * src/c++11/cow-locale_init.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip content.

    [!_GLIBCXX_USE_DUAL_ABI](locale::name()): Skip definition.
    * src/c++11/cow-sstream-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip content.
    * src/c++11/cow-stdexcept.cc [_GLIBCXX_USE_CXX11_ABI]: 
Include .
    [_GLIBCXX_USE_DUAL_ABI || 
_GLIBCXX_USE_CXX11_ABI](__cow_string): Redefine before
    including . Define 
_GLIBCXX_DEFINE_STDEXCEPT_INSTANTIATIONS so that

    __cow_string definition in  is skipped.
    (__cow_string::c_str()): Define.
    [_GLIBCXX_USE_CXX11_ABI]: Skip Transaction Memory TS 
definitions.

    * src/c++11/cow-string-inst.cc
    [!_GLIBCXX_USE_DUAL_ABI || _GLIBCXX_USE_CXX11_ABI]: Skip 
content.
    * src/c++11/cow-string-io-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip content.
    * src/c++11/cow-wstring-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip content.
    * src/c++11/cow-wstring-io-inst.cc 
[_GLIBCXX_USE_CXX11_ABI]: Skip content.
    * src/c++11/cxx11-hash_tr1.cc [!_GLIBCXX_USE_CXX11_ABI]: 
Skip content.
    * src/c++11/cxx11-ios_failure.cc [!_GLIBCXX_USE_CXX11_ABI]: 
Skip content.

    [!_GLIBCXX_USE_DUAL_ABI] (__ios_failure): Remove.
    * src/c++11/cxx11-locale-inst.cc: Cleanup, just include 
locale-inst.cc.
    * src/c++11/cxx11-stdexcept.cc [!_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cxx11-wlocale-inst.cc 
[!_GLIBCXX_USE_CXX11_ABI]: Skip definitions.

    * src/c++11/locale-inst-numeric.h
[!_GLIBCXX_USE_DUAL_ABI](std::use_facet>, 
std::use_facet>): Instantiate.
[!_GLIBCXX_USE_DUAL_ABI](std::has_facet>, 
std::has_facet>): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](std::num_getistreambuf_iterator>): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](std::num_putostreambuf_iterator>): Instantiate.
    * src/c++11/locale-inst.cc [!_GLIBCXX_USE_DUAL_ABI]: Build 
only when configured

    _GLIBCXX_USE_CXX11_ABI is equal to currently built abi.
    [!_GLIBCXX_USE_DUAL_ABI](__moneypunct_cache): 
Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](__moneypunct_cache): 
Instantiate.

    

Fix gnu versioned namespace mode 03/03

2024-05-04 Thread François Dumont

    libstdc++: Review configuration options to control abi

    --disable-libstdcxx-dual-abi default to 'new' abi mode.

    --with-default-libstdcxx-abi consider the requested abi mode regardless
    of --disable-libstdcxx-dual-abi usage.

    libstdc++-v3/ChangeLog

    * acinclude.m4 (GLIBCXX_ENABLE_LIBSTDCXX_DUAL_ABI): Set
    default_libstdcxx_abi to "new" when not using versioned 
namespace.
    (GLIBCXX_DEFAULT_ABI): Remove enable_libstdcxx_dual_abi=yes 
check.

    * configure: Regenerate.

Ok to commit ?

François

diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 3da1d5f1a01..0ba755b08d2 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -4867,7 +4867,7 @@ dnl
 dnl Control whether the library should define symbols for old and new ABIs.
 dnl This affects definitions of strings, stringstreams and locale facets.
 dnl
-dnl --disable-libstdcxx-dual-abi will use old ABI for all types.
+dnl --disable-libstdcxx-dual-abi will use new ABI for all types.
 dnl
 dnl Defines:
 dnl  _GLIBCXX_USE_DUAL_ABI (always defined, either to 1 or 0)
@@ -4883,7 +4883,7 @@ AC_DEFUN([GLIBCXX_ENABLE_LIBSTDCXX_DUAL_ABI], [
   else
 if test x"$enable_libstdcxx_dual_abi" != xyes; then
   AC_MSG_NOTICE([dual ABI is disabled])
-  default_libstdcxx_abi="gcc4-compatible"
+  default_libstdcxx_abi="new"
 fi
   fi
   GLIBCXX_CONDITIONAL(ENABLE_DUAL_ABI, test $enable_libstdcxx_dual_abi = yes)
@@ -4898,7 +4898,6 @@ dnl Defines:
 dnl  _GLIBCXX_USE_CXX11_ABI (always defined, either to 1 or 0)
 dnl
 AC_DEFUN([GLIBCXX_DEFAULT_ABI], [
-  if test x$enable_libstdcxx_dual_abi = xyes; then
   AC_MSG_CHECKING([for default std::string ABI to use])
   AC_ARG_WITH([default-libstdcxx-abi],
 AS_HELP_STRING([--with-default-libstdcxx-abi],
@@ -4912,7 +4911,6 @@ AC_DEFUN([GLIBCXX_DEFAULT_ABI], [
  ],
 [default_libstdcxx_abi="new"])
   AC_MSG_RESULT(${default_libstdcxx_abi})
-  fi
   if test $default_libstdcxx_abi = "new"; then
 glibcxx_cxx11_abi=1
 glibcxx_cxx98_abi=0
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index 341a8b2cb25..89201086507 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -51276,13 +51276,12 @@ $as_echo "$as_me: dual ABI is disabled" >&6;}
 if test x"$enable_libstdcxx_dual_abi" != xyes; then
   { $as_echo "$as_me:${as_lineno-$LINENO}: dual ABI is disabled" >&5
 $as_echo "$as_me: dual ABI is disabled" >&6;}
-  default_libstdcxx_abi="gcc4-compatible"
+  default_libstdcxx_abi="new"
 fi
   fi
 
 
 
-  if test x$enable_libstdcxx_dual_abi = xyes; then
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default std::string 
ABI to use" >&5
 $as_echo_n "checking for default std::string ABI to use... " >&6; }
 
@@ -51301,7 +51300,6 @@ fi
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${default_libstdcxx_abi}" 
>&5
 $as_echo "${default_libstdcxx_abi}" >&6; }
-  fi
   if test $default_libstdcxx_abi = "new"; then
 glibcxx_cxx11_abi=1
 glibcxx_cxx98_abi=0


Fix gnu versioned namespace mode 01/03

2024-05-04 Thread François Dumont

libstdc++: Bump gnu versioned namespace to __9

libstdc++-v3/ChangeLog:

    * acinclude.m4 (libtool_VERSION): Bump to 9:0:0.
    * config/abi/pre/gnu-versioned-namespace.ver (GLIBCXX_8.0): 
Replace by GLIBCXX_9.0.

    Adapt all references to __8 namespace.
    * configure: Regenerate.
    * include/bits/c++config 
(_GLIBCXX_BEGIN_NAMESPACE_VERSION): Define as 'namespace __9{'.

    (_GLIBCXX_STD_V): Adapt.
    * include/std/format (to_chars): Update namespace version 
in symbols alias definitions.
    (__format::_Arg_store): Update namespace version in 
make_format_args friend

    declaration.
    * python/libstdcxx/v6/printers.py (_versioned_namespace): 
Assign '__9::'.

    * python/libstdcxx/v6/xmethods.py: Likewise.
    * testsuite/23_containers/map/48101_neg.cc: Adapt dg-error.
    * testsuite/23_containers/multimap/48101_neg.cc: Likewise.
    * testsuite/20_util/function/cons/70692.cc: Likewise.
    * testsuite/20_util/function_objects/bind_back/111327.cc: 
Likewise.
    * testsuite/20_util/function_objects/bind_front/111327.cc: 
Likewise.
    * testsuite/lib/prune.exp (libstdc++-dg-prune): Bump 
version namespace.


Ok to commit ?

François
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 51a08bcc8b1..8978355a6d3 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -4243,7 +4243,7 @@ case $enable_symvers in
  [Define to use GNU versioning in the shared library.])
 ;;
   gnu-versioned-namespace)
-libtool_VERSION=8:0:0
+libtool_VERSION=9:0:0
 SYMVER_FILE=config/abi/pre/gnu-versioned-namespace.ver
 AC_DEFINE(_GLIBCXX_SYMVER_GNU_NAMESPACE, 1,
  [Define to use GNU namespace versioning in the shared library.])
diff --git a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver 
b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
index bdf8f40f1f6..d3d30b5bafa 100644
--- a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
+++ b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
@@ -19,7 +19,7 @@
 ## with this library; see the file COPYING3.  If not see
 ## .
 
-GLIBCXX_8.0 {
+GLIBCXX_9.0 {
 
   global:
 
@@ -27,7 +27,7 @@ GLIBCXX_8.0 {
 extern "C++"
 {
   std::*;
-  std::__8::*;
+  std::__9::*;
 };
 
 # operator new(size_t)
@@ -59,7 +59,7 @@ GLIBCXX_8.0 {
 # vtable
 _ZTVSt*;
 _ZTVNSt*;
-_ZTVN9__gnu_cxx3__818stdio_sync_filebufI[cw]NSt3__811char_traitsI[cw];
+_ZTVN9__gnu_cxx3__918stdio_sync_filebufI[cw]NSt3__911char_traitsI[cw];
 
 # thunk
 _ZTv0_n12_NS*;
@@ -74,7 +74,7 @@ GLIBCXX_8.0 {
 _ZTSNSt*;
 
 # locale
-_ZNSt3__89has_facetINS_*;
+_ZNSt3__99has_facetINS_*;
 
 # thread/mutex/condition_variable/future
 __once_proxy;
@@ -84,37 +84,37 @@ GLIBCXX_8.0 {
 __emutls_v._ZSt3__815__once_callable;
 
 # std::__convert_to_v
-_ZNSt3__814__convert_to_v*;
+_ZNSt3__914__convert_to_v*;
 
 # std::__copy_streambufs
-_ZNSt3__817__copy_streambufsI*;
-_ZNSt3__821__copy_streambufs_eofI*;
+_ZNSt3__917__copy_streambufsI*;
+_ZNSt3__921__copy_streambufs_eofI*;
 
 # std::__istream_extract(wistream&, wchar_t*, streamsize)
-
_ZNSt3__817__istream_extractIwNS_11char_traitsIwvRNS_13basic_istreamIT_T0_EEPS4_[ilx];
+
_ZNSt3__917__istream_extractIwNS_11char_traitsIwvRNS_13basic_istreamIT_T0_EEPS4_[ilx];
 
 # __gnu_cxx::__atomic_add
 # __gnu_cxx::__exchange_and_add
-_ZN9__gnu_cxx3__812__atomic_addEPV[il][il];
-_ZN9__gnu_cxx3__818__exchange_and_addEPV[li][il];
+_ZN9__gnu_cxx3__912__atomic_addEPV[il][il];
+_ZN9__gnu_cxx3__918__exchange_and_addEPV[li][il];
 
 # __gnu_cxx::__pool
-_ZN9__gnu_cxx3__86__poolILb[01]EE13_M_initializeEv;
-_ZN9__gnu_cxx3__86__poolILb[01]EE16_M_reserve_blockE[jmy][jmy];
-_ZN9__gnu_cxx3__86__poolILb[01]EE16_M_reclaim_blockEPc[jmy];
-_ZN9__gnu_cxx3__86__poolILb[01]EE10_M_destroyEv;
-_ZN9__gnu_cxx3__86__poolILb1EE16_M_get_thread_idEv;
+_ZN9__gnu_cxx3__96__poolILb[01]EE13_M_initializeEv;
+_ZN9__gnu_cxx3__96__poolILb[01]EE16_M_reserve_blockE[jmy][jmy];
+_ZN9__gnu_cxx3__96__poolILb[01]EE16_M_reclaim_blockEPc[jmy];
+_ZN9__gnu_cxx3__96__poolILb[01]EE10_M_destroyEv;
+_ZN9__gnu_cxx3__96__poolILb1EE16_M_get_thread_idEv;
 
-_ZN9__gnu_cxx3__817__pool_alloc_base9_M_refillE[jmy];
-_ZN9__gnu_cxx3__817__pool_alloc_base16_M_get_free_listE[jmy];
-_ZN9__gnu_cxx3__817__pool_alloc_base12_M_get_mutexEv;
+_ZN9__gnu_cxx3__917__pool_alloc_base9_M_refillE[jmy];
+_ZN9__gnu_cxx3__917__pool_alloc_base16_M_get_free_listE[jmy];
+_ZN9__gnu_cxx3__917__pool_alloc_base12_M_get_mutexEv;
 
-_ZN9__gnu_cxx3__89free_list6_M_getE[jmy];
-_ZN9__gnu_cxx3__89free_list8_M_clearEv;
+_ZN9__gnu_cxx3__99free_list6_M_getE[jmy];
+

Fix gnu versioned namespace mode 00/03

2024-05-04 Thread François Dumont

Here is the list of patches to restore gnu versioned namespace mode.

1/3: Bump gnu version namespace

This is important to be done first so that once build of gnu versioned 
namespace is fixed there is no chance to have another build of '__8' 
version with a different abi than last successful '__8' build.


2/3: Fix build using cxx11 abi for versioned namespace

3/3: Proposal to default to "new" abi when dual abi is disabled and 
accept any default-libstdcxx-abi either dual abi is enabled or not.


All testsuite run for following configs:

- dual abi

- gcc4-compatible only abi

- new only abi

- versioned namespace abi

François




Re: _LIBCXX_DEBUG value initialized singular iterators assert failures in std algorithms [PR104316]

2024-03-20 Thread François Dumont

As proposed below I also updated gcc-13 branch.

    libstdc++: [_GLIBCXX_DEBUG] Define __cpp_lib_null_iterators

    _GLIBCXX_DEBUG has now fully N3344 compliant iterator checks, we 
can define

    __cpp_lib_null_iterators macros like the normal mode.

    libstdc++-v3/ChangeLog:

    * include/std/iterator (__cpp_lib_null_iterators): Define 
regardless of

    _GLIBCXX_DEBUG.
    * include/std/version (__cpp_lib_null_iterators): Likewise.

François


On 20/03/2024 10:02, Jonathan Wakely wrote:

On Wed, 20 Mar 2024 at 05:59, François Dumont wrote:

Thanks to you doc:

  libstdc++: [_GLIBCXX_DEBUG] Define __[glibcxx,cpp_lib]_null_iterators

  _GLIBCXX_DEBUG has now fully N3344 compliant iterator checks, we
can define
  __glibcxx_null_iterators and __cpp_lib_null_iterators macros like
the normal
  mode.

  libstdc++-v3/ChangeLog:

  * version.def (null_iterators): Remove extra_cond.
  * version.h: Regenerate.

Ok to commit ?

Please don't bother talking about __glibcxx_null_iterators in the
commit message, that's an implementation detail that always mirrors
the standard-defined __cpp_lib_null_iterators one. The first line of
the commit will be much easier to read without that.

OK with that change, thanks.


I already noticed that GCC 13 has no version.h file so no backport question.

It has no version.h but it still has the macros:

include/std/iterator:# define __cpp_lib_null_iterators 201304L
include/std/version:# define __cpp_lib_null_iterators 201304L

Those definitions can be made to not depend on _GLIBCXX_DEBUG.
diff --git a/libstdc++-v3/include/std/iterator 
b/libstdc++-v3/include/std/iterator
index 695e18e2c47..a0a8eac570b 100644
--- a/libstdc++-v3/include/std/iterator
+++ b/libstdc++-v3/include/std/iterator
@@ -67,7 +67,7 @@
 #endif
 #include 
 
-#if __cplusplus >= 201402L && ! defined _GLIBCXX_DEBUG // PR libstdc++/70303
+#if __cplusplus >= 201402L
 # define __cpp_lib_null_iterators 201304L
 #endif
 
diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
index bd1bee0190d..ee515c4e66c 100644
--- a/libstdc++-v3/include/std/version
+++ b/libstdc++-v3/include/std/version
@@ -81,9 +81,7 @@
 #define __cpp_lib_integral_constant_callable 201304L
 #define __cpp_lib_is_final 201402L
 #define __cpp_lib_make_reverse_iterator 201402L
-#ifndef _GLIBCXX_DEBUG // PR libstdc++/70303
-# define __cpp_lib_null_iterators 201304L
-#endif
+#define __cpp_lib_null_iterators 201304L
 #define __cpp_lib_robust_nonmodifying_seq_ops 201304L
 #define __cpp_lib_transformation_trait_aliases 201304L
 #define __cpp_lib_transparent_operators 201510L


Re: _LIBCXX_DEBUG value initialized singular iterators assert failures in std algorithms [PR104316]

2024-03-19 Thread François Dumont

Thanks to you doc:

    libstdc++: [_GLIBCXX_DEBUG] Define __[glibcxx,cpp_lib]_null_iterators

    _GLIBCXX_DEBUG has now fully N3344 compliant iterator checks, we 
can define
    __glibcxx_null_iterators and __cpp_lib_null_iterators macros like 
the normal

    mode.

    libstdc++-v3/ChangeLog:

    * version.def (null_iterators): Remove extra_cond.
    * version.h: Regenerate.

Ok to commit ?

I already noticed that GCC 13 has no version.h file so no backport question.

François

On 19/03/2024 16:41, Jonathan Wakely wrote:

On Tue, 19 Mar 2024 at 09:31, Jonathan Wakely wrote:

On Mon, 18 Mar 2024 at 21:38, François Dumont wrote:

Both committed now.

Just to confirm, those 2 last patches should be backported to gcc-13
branch, right ?

Yes please.


I might have a try to update version.h but if you want to do it before
don't hesitate.

You'll need to have 'autogen' installed to do it (I'm going to update
the docs to describe that today).

I've documented it in a new "Generated files" section at the end of
https://gcc.gnu.org/onlinedocs/libstdc++/manual/appendix_porting.html#build_hacking.generated
diff --git a/libstdc++-v3/include/bits/version.def 
b/libstdc++-v3/include/bits/version.def
index be5af18e818..26e62c6a9b2 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -209,7 +209,6 @@ ftms = {
   values = {
 v = 201304;
 cxxmin = 14;
-extra_cond = "!defined(_GLIBCXX_DEBUG)";
   };
 };
 
diff --git a/libstdc++-v3/include/bits/version.h 
b/libstdc++-v3/include/bits/version.h
index 9107b45a484..23c8c09ab4b 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -214,7 +214,7 @@
 #undef __glibcxx_want_make_reverse_iterator
 
 #if !defined(__cpp_lib_null_iterators)
-# if (__cplusplus >= 201402L) && (!defined(_GLIBCXX_DEBUG))
+# if (__cplusplus >= 201402L)
 #  define __glibcxx_null_iterators 201304L
 #  if defined(__glibcxx_want_all) || defined(__glibcxx_want_null_iterators)
 #   define __cpp_lib_null_iterators 201304L


Re: _LIBCXX_DEBUG value initialized singular iterators assert failures in std algorithms [PR104316]

2024-03-18 Thread François Dumont

Both committed now.

Just to confirm, those 2 last patches should be backported to gcc-13 
branch, right ?


I might have a try to update version.h but if you want to do it before 
don't hesitate.


François

On 18/03/2024 08:45, Jonathan Wakely wrote:

On Sun, 17 Mar 2024 at 18:14, François Dumont  wrote:

I was a little bit too confident below. After review of all _M_singular
usages I found another necessary fix.

After this one for sure we will be able to define
__cpp_lib_null_iterators even in Debug mode.

  libstdc++: Fix N3344 behavior on _Safe_iterator::_M_can_advance

  We shall be able to advance from a 0 offset a value-initialized
iterator.

  libstdc++-v3/ChangeLog:

  * include/debug/safe_iterator.tcc
(_Safe_iterator<>::_M_can_advance):
  Accept 0 offset advance on value-initialized iterator.
  * testsuite/23_containers/vector/debug/n3644.cc: New test case.

Ok to commit ?


OK, thanks.



François


On 17/03/2024 17:52, François Dumont wrote:

OK for trunk, thanks!

I think this is OK to backport to 13 too.

Maybe after this we can define the __cpp_lib_null_itetators macro for
debug mode?


After this fix of local_iterator I think we can indeed.

In fact the added 11316.cc was already passing for
unordered_set<>::local_iterator but simply because we were missing the
singular check. Both issues solved with this patch.

I found the version.def file to cleanup but no idea how to regenerate
version.h from it so I'll let you do it, ok ?

 libstdc++: Fix _Safe_local_iterator<>::_M_valid_range

 Unordered container local_iterator range shall not contain any
singular
 iterator unless both iterators are value-initialized.

 libstdc++-v3/ChangeLog:

 * include/debug/safe_local_iterator.tcc
 (_Safe_local_iterator::_M_valid_range): Add
_M_value_initialized and
 _M_singular checks.
 * testsuite/23_containers/unordered_set/debug/114316.cc:
New test case.


Ok to commit ?

François


Re: _LIBCXX_DEBUG value initialized singular iterators assert failures in std algorithms [PR104316]

2024-03-17 Thread François Dumont
I was a little bit too confident below. After review of all _M_singular 
usages I found another necessary fix.


After this one for sure we will be able to define 
__cpp_lib_null_iterators even in Debug mode.


    libstdc++: Fix N3344 behavior on _Safe_iterator::_M_can_advance

    We shall be able to advance from a 0 offset a value-initialized 
iterator.


    libstdc++-v3/ChangeLog:

    * include/debug/safe_iterator.tcc 
(_Safe_iterator<>::_M_can_advance):

    Accept 0 offset advance on value-initialized iterator.
    * testsuite/23_containers/vector/debug/n3644.cc: New test case.

Ok to commit ?

François


On 17/03/2024 17:52, François Dumont wrote:




OK for trunk, thanks!

I think this is OK to backport to 13 too.

Maybe after this we can define the __cpp_lib_null_itetators macro for 
debug mode?



After this fix of local_iterator I think we can indeed.

In fact the added 11316.cc was already passing for 
unordered_set<>::local_iterator but simply because we were missing the 
singular check. Both issues solved with this patch.


I found the version.def file to cleanup but no idea how to regenerate 
version.h from it so I'll let you do it, ok ?


    libstdc++: Fix _Safe_local_iterator<>::_M_valid_range

    Unordered container local_iterator range shall not contain any 
singular

    iterator unless both iterators are value-initialized.

    libstdc++-v3/ChangeLog:

    * include/debug/safe_local_iterator.tcc
    (_Safe_local_iterator::_M_valid_range): Add 
_M_value_initialized and

    _M_singular checks.
    * testsuite/23_containers/unordered_set/debug/114316.cc: 
New test case.



Ok to commit ?

Françoisdiff --git a/libstdc++-v3/include/debug/safe_iterator.tcc 
b/libstdc++-v3/include/debug/safe_iterator.tcc
index 4b2baf2980e..deaa84d0a1f 100644
--- a/libstdc++-v3/include/debug/safe_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_iterator.tcc
@@ -86,6 +86,9 @@ namespace __gnu_debug
 _Safe_iterator<_Iterator, _Sequence, _Category>::
 _M_can_advance(difference_type __n, bool __strict) const
 {
+  if (this->_M_value_initialized() && __n == 0)
+   return true;
+
   if (this->_M_singular())
return false;
 
diff --git a/libstdc++-v3/testsuite/23_containers/vector/debug/n3644.cc 
b/libstdc++-v3/testsuite/23_containers/vector/debug/n3644.cc
new file mode 100644
index 000..052c52f26b7
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/debug/n3644.cc
@@ -0,0 +1,16 @@
+// { dg-do run { target c++11 } }
+// { dg-require-debug-mode "" }
+
+#include 
+#include 
+
+#include 
+
+int main()
+{
+  std::vector::iterator it{};
+  auto cpy = it;
+  std::advance(it, 0);
+  VERIFY( it == cpy );
+  return 0;
+}


Re: _LIBCXX_DEBUG value initialized singular iterators assert failures in std algorithms [PR104316]

2024-03-17 Thread François Dumont




OK for trunk, thanks!

I think this is OK to backport to 13 too.

Maybe after this we can define the __cpp_lib_null_itetators macro for 
debug mode?



After this fix of local_iterator I think we can indeed.

In fact the added 11316.cc was already passing for 
unordered_set<>::local_iterator but simply because we were missing the 
singular check. Both issues solved with this patch.


I found the version.def file to cleanup but no idea how to regenerate 
version.h from it so I'll let you do it, ok ?


    libstdc++: Fix _Safe_local_iterator<>::_M_valid_range

    Unordered container local_iterator range shall not contain any singular
    iterator unless both iterators are value-initialized.

    libstdc++-v3/ChangeLog:

    * include/debug/safe_local_iterator.tcc
    (_Safe_local_iterator::_M_valid_range): Add 
_M_value_initialized and

    _M_singular checks.
    * testsuite/23_containers/unordered_set/debug/114316.cc: 
New test case.



Ok to commit ?

François
diff --git a/libstdc++-v3/include/debug/safe_local_iterator.tcc 
b/libstdc++-v3/include/debug/safe_local_iterator.tcc
index 90e60e37c32..6d546ec040c 100644
--- a/libstdc++-v3/include/debug/safe_local_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_local_iterator.tcc
@@ -78,7 +78,13 @@ namespace __gnu_debug
 _M_valid_range(const _Safe_local_iterator& __rhs,
std::pair& __dist) const
 {
-  if (!_M_can_compare(__rhs))
+  if (_M_value_initialized() && __rhs._M_value_initialized())
+   {
+ __dist = { 0, __dp_exact };
+ return true;
+   }
+
+  if (_M_singular() || __rhs._M_singular() || !_M_can_compare(__rhs))
return false;
 
   if (bucket() != __rhs.bucket())
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/debug/114316.cc 
b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/114316.cc
new file mode 100644
index 000..41b649a9cbd
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/debug/114316.cc
@@ -0,0 +1,28 @@
+// { dg-do run { target c++11 } }
+// { dg-require-debug-mode "" }
+
+// PR libstdc++/114316
+
+#include 
+#include 
+
+#include 
+
+void test01()
+{
+  std::unordered_set::iterator it{};
+  VERIFY( std::find(it, it, 0) == it );
+}
+
+void test02()
+{
+  std::unordered_set::local_iterator it{};
+  VERIFY( std::find(it, it, 0) == it );
+}
+
+int main()
+{
+  test01();
+  test02();
+  return 0;
+}


Re: _LIBCXX_DEBUG value initialized singular iterators assert failures in std algorithms [PR104316]

2024-03-16 Thread François Dumont

With the patch, sorry.

On 14/03/2024 22:49, François Dumont wrote:

Hi

This is what I started to do.

For now I haven't touch to __cpp_lib_null_iterators definition as 
_Safe_local_iterator still need some work.


libstdc++: Implement N3644 on _Safe_iterator<> [PR114316]

Consider range of value-initialized iterators as valid and empty.

libstdc++-v3/ChangeLog:

    PR libstdc++/114316
    * include/debug/safe_iterator.tcc 
(_Safe_iterator<>::_M_valid_range):
    First check if both iterators are value-initialized before 
checking if

    singular.
    * testsuite/23_containers/set/debug/114316.cc: New test case.
    * testsuite/23_containers/vector/debug/114316.cc: New test case.

Tested under Linux x86_64, ok to commit ?

François


On 12/03/2024 10:52, Jonathan Wakely wrote:
On Tue, 12 Mar 2024 at 01:03, Jonathan Wakely  
wrote:
On Tue, 12 Mar 2024 at 00:55, Maciej Miera  
wrote:



Wiadomość napisana przez Jonathan Wakely  w 
dniu 11.03.2024, o godz. 21:40:


On Mon, 11 Mar 2024 at 20:07, Maciej Miera  
wrote:



Hello,

I have tried to introduce an extra level of safety to my codebase 
and utilize _GLIBCXX_DEBUG in my test builds in order to catch 
faulty iterators.
However, I have encountered the following problem: I would like to 
utilize singular, value-initialized iterators as an arbitrary "null 
range”.
However, this leads to failed assertions in std:: algorithms taking 
such range.


Consider the following code sample with find_if:

#include 
#include 
#include 

#ifndef __cpp_lib_null_iterators
#warning "Not standard compliant"
#endif

int main()
{
    std::multimap::iterator it1{};
    std::multimap::iterator it2{};

    (void) (it1==it2); // OK
    (void) std::find_if(
    it1, it2, [](const auto& el) { return el.second == 8;});
}

Compiled with -std=c++20 and -D_GLIBCXX_DEBUG it produces the 
warning "Not standard compliant"

and the execution results in the following assert failure:

/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/stl_algo.h:3875: 


In function:
    constexpr _IIter std::find_if(_IIter, _IIter, _Predicate) [with 
_IIter =

gnu_debug::_Safe_iterator<_Rb_tree_iterator >,
    debug::multimap, bidirectional_iterator_tag>; 
_Predicate =

    main()::]

The question is though: is it by design, or is it just a mere 
oversight? The warning actually suggest the first option.
If it is an intentional design choice, could you provide some 
rationale behind it, please?



The macro was not defined because the C++14 rule wasn't implemented
for debug mode, but that should have been fixed for GCC 11, according
to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98466 and
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70303
So we should be able to define macro now, except maybe it wasn't fixed
for the RB tree containers.



Just to make sure there are no misunderstandings: comparison via == 
works fine. The feature check macro without _GLIBCXX_DEBUG and with 
 included is also fine. Maybe the need to include a 
header is the issue, but that’s not the core of the problem anyway.

No, it has nothing to do with the headers included. The feature test
macro is defined like so:

# if (__cplusplus >= 201402L) && (!defined(_GLIBCXX_DEBUG))
#  define __glibcxx_null_iterators 201304L

It's a very deliberate choice to not define it when _GLIBCXX_DEBUG is
defined. But as I said, I think we should have changed that.

The actual question is though, whether passing singular iterators 
to std algorithms (like find_if) should make the asserts at the 
beginning of the algo function fail when compiled with 
_GLIBCXX_DEBUG. IMHO, intuitively it should not, as comparing 
iterators equal would just ensure early exit and return of the same 
singular iterator.

This seems not to be the case though. The actual message is this:
Error: the function requires a valid iterator range [first, last).
What bothers me is whether the empty virtual range limited by two 
same singular iterators is actually valid or not.
Yes, it's valid. So the bug is in the __glibcxx_requires_valid_range 
macro.

Thanks for the bugzilla report:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114316
We'll get it fixed!
diff --git a/libstdc++-v3/include/debug/safe_iterator.tcc 
b/libstdc++-v3/include/debug/safe_iterator.tcc
index a8b24233e85..4b2baf2980e 100644
--- a/libstdc++-v3/include/debug/safe_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_iterator.tcc
@@ -194,6 +194,12 @@ namespace __gnu_debug
   std::pair& __dist,
   bool __check_dereferenceable) const
 {
+  if (_M_value_initialized() && __rhs._M_value_initialized())
+   {
+ __dist = std::make_pair(0, __dp_exact);
+ return true;
+   }
+
   if (_M_singular() || __rhs._M_singular() || !_M_can_compare(__rhs))
return false;
 
@@ -218,6 +224,12 @@ namespace __gnu_debug
   std::pa

Re: _LIBCXX_DEBUG value initialized singular iterators assert failures in std algorithms [PR104316]

2024-03-14 Thread François Dumont

Hi

This is what I started to do.

For now I haven't touch to __cpp_lib_null_iterators definition as 
_Safe_local_iterator still need some work.


libstdc++: Implement N3644 on _Safe_iterator<> [PR114316]

Consider range of value-initialized iterators as valid and empty.

libstdc++-v3/ChangeLog:

    PR libstdc++/114316
    * include/debug/safe_iterator.tcc 
(_Safe_iterator<>::_M_valid_range):
    First check if both iterators are value-initialized before 
checking if

    singular.
    * testsuite/23_containers/set/debug/114316.cc: New test case.
    * testsuite/23_containers/vector/debug/114316.cc: New test case.

Tested under Linux x86_64, ok to commit ?

François


On 12/03/2024 10:52, Jonathan Wakely wrote:

On Tue, 12 Mar 2024 at 01:03, Jonathan Wakely  wrote:

On Tue, 12 Mar 2024 at 00:55, Maciej Miera  wrote:



Wiadomość napisana przez Jonathan Wakely  w dniu 
11.03.2024, o godz. 21:40:

On Mon, 11 Mar 2024 at 20:07, Maciej Miera  wrote:


Hello,

I have tried to introduce an extra level of safety to my codebase and utilize 
_GLIBCXX_DEBUG in my test builds in order to catch faulty iterators.
However, I have encountered the following problem: I would like to utilize singular, 
value-initialized iterators as an arbitrary "null range”.
However, this leads to failed assertions in std:: algorithms taking such range.

Consider the following code sample with find_if:

#include 
#include 
#include 

#ifndef __cpp_lib_null_iterators
#warning "Not standard compliant"
#endif

int main()
{
std::multimap::iterator it1{};
std::multimap::iterator it2{};

(void) (it1==it2); // OK
(void) std::find_if(
it1, it2, [](const auto& el) { return el.second == 8;});
}

Compiled with -std=c++20 and -D_GLIBCXX_DEBUG it produces the warning "Not standard 
compliant"
and the execution results in the following assert failure:

/opt/compiler-explorer/gcc-12.2.0/include/c++/12.2.0/bits/stl_algo.h:3875:
In function:
constexpr _IIter std::find_if(_IIter, _IIter, _Predicate) [with _IIter =
gnu_debug::_Safe_iterator<_Rb_tree_iterator >,
debug::multimap, bidirectional_iterator_tag>; _Predicate =
main()::]

The question is though: is it by design, or is it just a mere oversight? The 
warning actually suggest the first option.
If it is an intentional design choice, could you provide some rationale behind 
it, please?


The macro was not defined because the C++14 rule wasn't implemented
for debug mode, but that should have been fixed for GCC 11, according
to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98466 and
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70303
So we should be able to define macro now, except maybe it wasn't fixed
for the RB tree containers.



Just to make sure there are no misunderstandings: comparison via == works fine. The 
feature check macro without _GLIBCXX_DEBUG and with  included is also 
fine. Maybe the need to include a header is the issue, but that’s not the core of the 
problem anyway.

No, it has nothing to do with the headers included. The feature test
macro is defined like so:

# if (__cplusplus >= 201402L) && (!defined(_GLIBCXX_DEBUG))
#  define __glibcxx_null_iterators 201304L

It's a very deliberate choice to not define it when _GLIBCXX_DEBUG is
defined. But as I said, I think we should have changed that.


The actual question is though, whether passing singular iterators to std 
algorithms (like find_if) should make the asserts at the beginning of the algo 
function fail when compiled with _GLIBCXX_DEBUG. IMHO, intuitively it should 
not, as comparing iterators equal would just ensure early exit and return of 
the same singular iterator.
This seems not to be the case though. The actual message is this:
Error: the function requires a valid iterator range [first, last).
What bothers me is whether the empty virtual range limited by two same singular 
iterators is actually valid or not.

Yes, it's valid. So the bug is in the __glibcxx_requires_valid_range macro.

Thanks for the bugzilla report:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114316
We'll get it fixed!



[PATCH][_GLIBCXX_INLINE_VERSION] Adapt dg-error messages

2024-02-21 Thread François Dumont
For those using my patch to build in gnu-versioned-namespace mode it 
would be preferable not to have any failures when running testsuite.


    libstdc++: [_GLIBCXX_INLINE_VERSION] Adapt dg-error message

    libstdc++-v3/ChangeLog:

    * testsuite/20_util/function_objects/bind_back/111327.cc: 
Adapt dg-error message

    for __8 namespace.
    * testsuite/20_util/function_objects/bind_front/111327.cc: 
Likewise.


Ok to commit ?

François
diff --git 
a/libstdc++-v3/testsuite/20_util/function_objects/bind_back/111327.cc 
b/libstdc++-v3/testsuite/20_util/function_objects/bind_back/111327.cc
index d634db9dc1d..f8a65127ccf 100644
--- a/libstdc++-v3/testsuite/20_util/function_objects/bind_back/111327.cc
+++ b/libstdc++-v3/testsuite/20_util/function_objects/bind_back/111327.cc
@@ -39,4 +39,4 @@ int main() {
   std::move(std::as_const(g1))();
 }
 
-// { dg-error "no type named 'type' in 'struct std::invoke_result" "" { target 
c++23 } 0 }
+// { dg-error "no type named 'type' in 'struct std::(__8::)?invoke_result" "" 
{ target c++23 } 0 }
diff --git 
a/libstdc++-v3/testsuite/20_util/function_objects/bind_front/111327.cc 
b/libstdc++-v3/testsuite/20_util/function_objects/bind_front/111327.cc
index 5fe0a83baec..896492b3d74 100644
--- a/libstdc++-v3/testsuite/20_util/function_objects/bind_front/111327.cc
+++ b/libstdc++-v3/testsuite/20_util/function_objects/bind_front/111327.cc
@@ -39,4 +39,4 @@ int main() {
   std::move(std::as_const(g1))();
 }
 
-// { dg-error "no type named 'type' in 'struct std::invoke_result" "" { target 
c++23 } 0 }
+// { dg-error "no type named 'type' in 'struct std::(__8::)?invoke_result" "" 
{ target c++23 } 0 }


Re: [PATCH][_GLIBCXX_DEBUG] Fix std::__niter_base behavior

2024-02-20 Thread François Dumont

   libstdc++: [_GLIBCXX_DEBUG] Fix std::__niter_wrap behavior

    In _GLIBCXX_DEBUG mode the std::__niter_base can remove 2 layers, the
    __gnu_debug::_Safe_iterator<> and the __gnu_cxx::__normal_iterator<>.
    When std::__niter_wrap is called to build a 
__gnu_debug::_Safe_iterator<>

    from a __gnu_cxx::__normal_iterator<> we then have a consistency issue
    as the difference between the 2 iterators will done on a 
__normal_iterator

    on one side and a C pointer on the other. To avoid this problem call
    std::__niter_base on both input iterators.

    libstdc++-v3/ChangeLog:

    * include/bits/stl_algobase.h (std::__niter_wrap): Add a 
call to

    std::__niter_base on res iterator.

Tested under Linux x86_64 normal and _GLIBCXX_DEBUG modes in c++98, 
c++11, c++17.


Ok to commit ?

François


On 19/02/2024 09:21, Jonathan Wakely wrote:



On Mon, 19 Feb 2024, 08:12 Jonathan Wakely,  wrote:



On Mon, 19 Feb 2024, 07:08 Stephan Bergmann, 
wrote:

    On 2/17/24 15:14, François Dumont wrote:
> Thanks for the link, tested and committed.

I assume this is the cause for the below failure now,


Yes, the new >= C++11 overload of __niter_base recursively unwraps
multiple layers of wrapping, so that a safe iterator wrapping a
normal iterator wrapping a pointer is unwrapped to just a pointer.
But then __niter_wrap doesn't restore both layers.



Actually that's not the problem. __niter_wrap would restore both 
layers, except that it uses __niter_base itself:


>   347 |     { return __from + (__res - std::__niter_base(__from)); }
>       |  ~~~^~~~

And it seems to be getting called with the wrong types. Maybe that's 
just a bug in std:: erase or maybe niter_wrap needs adjusting.


I'll check in a couple of hours if François doesn't get to it first.

I have to wonder how this wasn't caught by existing tests though.


diff --git a/libstdc++-v3/include/bits/stl_algobase.h 
b/libstdc++-v3/include/bits/stl_algobase.h
index 0f73da13172..d534e02871f 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -344,7 +344,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 _GLIBCXX20_CONSTEXPR
 inline _From
 __niter_wrap(_From __from, _To __res)
-{ return __from + (__res - std::__niter_base(__from)); }
+{ return __from + (std::__niter_base(__res) - std::__niter_base(__from)); }
 
   // No need to wrap, iterator already has the right type.
   template


Re: [PATCH][_GLIBCXX_DEBUG] Fix std::__niter_base behavior

2024-02-19 Thread François Dumont
Turns out that 23_containers/vector/erasure.cc was showing the problem 
in _GLIBCXX_DEBUG mode.


I had only run 25_algorithms tests in _GLIBCXX_DEBUG mode.

This is what I'm testing, I 'll let you know tomorrow morning if all 
successful.


Of course feel free to do or ask for a revert instead.

François


On 19/02/2024 09:21, Jonathan Wakely wrote:



On Mon, 19 Feb 2024, 08:12 Jonathan Wakely,  wrote:



On Mon, 19 Feb 2024, 07:08 Stephan Bergmann, 
wrote:

On 2/17/24 15:14, François Dumont wrote:
> Thanks for the link, tested and committed.

I assume this is the cause for the below failure now,


Yes, the new >= C++11 overload of __niter_base recursively unwraps
multiple layers of wrapping, so that a safe iterator wrapping a
normal iterator wrapping a pointer is unwrapped to just a pointer.
But then __niter_wrap doesn't restore both layers.



Actually that's not the problem. __niter_wrap would restore both 
layers, except that it uses __niter_base itself:


>   347 |     { return __from + (__res - std::__niter_base(__from)); }
>       |  ~~~^~~~

And it seems to be getting called with the wrong types. Maybe that's 
just a bug in std:: erase or maybe niter_wrap needs adjusting.


I'll check in a couple of hours if François doesn't get to it first.

I have to wonder how this wasn't caught by existing tests though.


diff --git a/libstdc++-v3/include/bits/stl_algobase.h 
b/libstdc++-v3/include/bits/stl_algobase.h
index 0f73da13172..d534e02871f 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -344,7 +344,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 _GLIBCXX20_CONSTEXPR
 inline _From
 __niter_wrap(_From __from, _To __res)
-{ return __from + (__res - std::__niter_base(__from)); }
+{ return __from + (std::__niter_base(__res) - std::__niter_base(__from)); }
 
   // No need to wrap, iterator already has the right type.
   template


Re: [PATCH][_GLIBCXX_DEBUG] Fix std::__niter_base behavior

2024-02-17 Thread François Dumont

Thanks for the link, tested and committed.

On 15/02/2024 19:40, Jonathan Wakely wrote:



On Thu, 15 Feb 2024 at 18:38, François Dumont  
wrote:



On 15/02/2024 14:17, Jonathan Wakely wrote:



On Wed, 14 Feb 2024 at 21:48, François Dumont
 wrote:


On 14/02/2024 20:44, Jonathan Wakely wrote:



On Wed, 14 Feb 2024 at 18:39, François Dumont
 wrote:

libstdc++: [_GLIBCXX_DEBUG] Fix std::__niter_base behavior

std::__niter_base is used in _GLIBCXX_DEBUG mode to
remove _Safe_iterator<>
wrapper on random access iterators. But doing so it
should also preserve
original
behavior to remove __normal_iterator wrapper.

libstdc++-v3/ChangeLog:

 * include/bits/stl_algobase.h (std::__niter_base):
Redefine the
overload
 definitions for __gnu_debug::_Safe_iterator.
 * include/debug/safe_iterator.tcc
(std::__niter_base): Adapt
declarations.

Ok to commit once all tests completed (still need to
check pre-c++11) ?



The declaration in include/bits/stl_algobase.h has a
noexcept-specifier but the definition in
include/debug/safe_iterator.tcc does not have one - that
seems wrong (I'm surprised it even compiles).


It does !


The diagnostic is suppressed without -Wsystem-headers:


/home/jwakely/gcc/14/include/c++/14.0.1/debug/safe_iterator.tcc:255:5:warning:
declaration of 'template constexpr
decltype (std::__
niter_base(declval<_Ite>())) std::__niter_base(const
__gnu_debug::_Safe_iterator<_Iterator, _Sequence,
random_access_iterator_tag>&)' has a different except
ion specifier [-Wsystem-headers]
 255 | __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq,
 | ^~~~
/home/jwakely/gcc/14/include/c++/14.0.1/bits/stl_algobase.h:335:5:note:
from previous declaration 'template
constexpr decltype (std
::__niter_base(declval<_Ite>())) std::__niter_base(const
__gnu_debug::_Safe_iterator<_Iterator, _Sequence,
random_access_iterator_tag>&) noexcept (noexcept
(is_nothrow_copy_constructible()))>::value))'
 335 | __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq,
 | ^~~~


It's a hard error with Clang though:

deb.cc:7:10: error: call to '__niter_base' is ambiguous



Yes, I eventually got the error too, I hadn't run enough tests yet.





I thought it was only necessary at declaration, and I also
had troubles doing it right at definition because of the
interaction with the auto and ->.


The trailing-return-type has to come after the noexcept-specifier.

Now simplified and consistent in this new proposal.



Just using std::is_nothrow_copy_constructible<_Ite> seems
simpler, that will be true for __normal_iterator if
is_nothrow_copy_constructible is true.


Ok



The definition in include/debug/safe_iterator.tcc should use
std::declval<_Ite>() not declval<_Ite>(). Is there any
reason why the definition uses a late-specified-return-type
(i.e. auto and ->) when the declaration doesn't?



I initially plan to use '->
std::decltype(std::__niter_base(__it.base()))' but this did
not compile, ambiguity issue. So I resort to using
std::declval and I could have then done it the same way as
declaration, done now.

Attached is what I'm testing, ok to commit once fully tested ?


OK, thanks.


Thanks for validation but I have a problem to test for c++98.

When I do:

make CXXFLAGS=-std=c++98 check-debug


That doesn't work any more, see 
https://gcc.gnu.org/onlinedocs/libstdc++/manual/test.html#test.run.permutations


I see in debug/libstdc++.log for example:

Executing on host: /home/fdumont/dev/gcc/build/./gcc/xg++
-shared-libgcc ... -mshstk -std=c++98 -g -O2 -DLOCALEDIR="."
-nostdinc++ -I/home/fdumont/dev/gcc/...
/home/fdumont/dev/gcc/git/libstdc++-v3/testsuite/25_algorithms/copy/3.cc
-D_GLIBCXX_DEBUG   -std=gnu++17  -include bits/stdc++.h ...  -lm 
-o ./3.exe    (timeout = 360)

The -std=c++98 is there but later comes the -std=gnu++17 so I
think it runs in C++17, no ?

I also tried the documented alternative:

make check 
'RUNTESTFLAGS=--target_board=unix/-O3\"{-std=gnu++98,-std=gnu++11,-std=gnu++14}\"'

but same problem, -std=gnu++17 comes last.

I'll try to rebuild all from scratch but I won't commit soon then.



Re: [PATCH][_GLIBCXX_DEBUG] Fix std::__niter_base behavior

2024-02-15 Thread François Dumont


On 15/02/2024 14:17, Jonathan Wakely wrote:



On Wed, 14 Feb 2024 at 21:48, François Dumont  
wrote:



On 14/02/2024 20:44, Jonathan Wakely wrote:



On Wed, 14 Feb 2024 at 18:39, François Dumont
 wrote:

libstdc++: [_GLIBCXX_DEBUG] Fix std::__niter_base behavior

std::__niter_base is used in _GLIBCXX_DEBUG mode to remove
_Safe_iterator<>
wrapper on random access iterators. But doing so it should
also preserve
original
behavior to remove __normal_iterator wrapper.

libstdc++-v3/ChangeLog:

 * include/bits/stl_algobase.h (std::__niter_base):
Redefine the
overload
 definitions for __gnu_debug::_Safe_iterator.
 * include/debug/safe_iterator.tcc (std::__niter_base):
Adapt
declarations.

Ok to commit once all tests completed (still need to check
pre-c++11) ?



The declaration in  include/bits/stl_algobase.h has a
noexcept-specifier but the definition in
include/debug/safe_iterator.tcc does not have one - that seems
wrong (I'm surprised it even compiles).


It does !


The diagnostic is suppressed without -Wsystem-headers:

/home/jwakely/gcc/14/include/c++/14.0.1/debug/safe_iterator.tcc:255:5:warning: 
declaration of 'template constexpr decltype 
(std::__
niter_base(declval<_Ite>())) std::__niter_base(const 
__gnu_debug::_Safe_iterator<_Iterator, _Sequence, 
random_access_iterator_tag>&)' has a different except

ion specifier [-Wsystem-headers]
 255 | __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq,
 | ^~~~
/home/jwakely/gcc/14/include/c++/14.0.1/bits/stl_algobase.h:335:5:note: 
from previous declaration 'template constexpr 
decltype (std
::__niter_base(declval<_Ite>())) std::__niter_base(const 
__gnu_debug::_Safe_iterator<_Iterator, _Sequence, 
random_access_iterator_tag>&) noexcept (noexcept
(is_nothrow_copy_constructible(std::__niter_base(declval<_Ite>()))>::value))'

 335 | __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq,
 | ^~~~


It's a hard error with Clang though:

deb.cc:7:10: error: call to '__niter_base' is ambiguous



Yes, I eventually got the error too, I hadn't run enough tests yet.





I thought it was only necessary at declaration, and I also had
troubles doing it right at definition because of the interaction
with the auto and ->.


The trailing-return-type has to come after the noexcept-specifier.

Now simplified and consistent in this new proposal.



Just using std::is_nothrow_copy_constructible<_Ite> seems
simpler, that will be true for __normal_iterator if
is_nothrow_copy_constructible is true.


Ok



The definition in include/debug/safe_iterator.tcc should use
std::declval<_Ite>() not declval<_Ite>(). Is there any reason why
the definition uses a late-specified-return-type (i.e. auto and
->) when the declaration doesn't?



I initially plan to use '->
std::decltype(std::__niter_base(__it.base()))' but this did not
compile, ambiguity issue. So I resort to using std::declval and I
could have then done it the same way as declaration, done now.

Attached is what I'm testing, ok to commit once fully tested ?


OK, thanks.


Thanks for validation but I have a problem to test for c++98.

When I do:

make CXXFLAGS=-std=c++98 check-debug

I see in debug/libstdc++.log for example:

Executing on host: /home/fdumont/dev/gcc/build/./gcc/xg++ -shared-libgcc 
... -mshstk -std=c++98 -g -O2 -DLOCALEDIR="." -nostdinc++ 
-I/home/fdumont/dev/gcc/... 
/home/fdumont/dev/gcc/git/libstdc++-v3/testsuite/25_algorithms/copy/3.cc 
-D_GLIBCXX_DEBUG   -std=gnu++17  -include bits/stdc++.h ...  -lm -o 
./3.exe    (timeout = 360)


The -std=c++98 is there but later comes the -std=gnu++17 so I think it 
runs in C++17, no ?


I also tried the documented alternative:

make check 
'RUNTESTFLAGS=--target_board=unix/-O3\"{-std=gnu++98,-std=gnu++11,-std=gnu++14}\"'

but same problem, -std=gnu++17 comes last.

I'll try to rebuild all from scratch but I won't commit soon then.



Re: [PATCH][_GLIBCXX_DEBUG] Fix std::__niter_base behavior

2024-02-14 Thread François Dumont


On 14/02/2024 20:44, Jonathan Wakely wrote:



On Wed, 14 Feb 2024 at 18:39, François Dumont  
wrote:


libstdc++: [_GLIBCXX_DEBUG] Fix std::__niter_base behavior

std::__niter_base is used in _GLIBCXX_DEBUG mode to remove
_Safe_iterator<>
wrapper on random access iterators. But doing so it should also
preserve
original
behavior to remove __normal_iterator wrapper.

libstdc++-v3/ChangeLog:

 * include/bits/stl_algobase.h (std::__niter_base): Redefine the
overload
 definitions for __gnu_debug::_Safe_iterator.
 * include/debug/safe_iterator.tcc (std::__niter_base): Adapt
declarations.

Ok to commit once all tests completed (still need to check
pre-c++11) ?



The declaration in  include/bits/stl_algobase.h has a 
noexcept-specifier but the definition in 
include/debug/safe_iterator.tcc does not have one - that seems wrong 
(I'm surprised it even compiles).


It does ! I thought it was only necessary at declaration, and I also had 
troubles doing it right at definition because of the interaction with 
the auto and ->. Now simplified and consistent in this new proposal.



Just using std::is_nothrow_copy_constructible<_Ite> seems simpler, 
that will be true for __normal_iterator if 
is_nothrow_copy_constructible is true.



Ok


The definition in include/debug/safe_iterator.tcc should use 
std::declval<_Ite>() not declval<_Ite>(). Is there any reason why the 
definition uses a late-specified-return-type (i.e. auto and ->) when 
the declaration doesn't?



I initially plan to use '-> 
std::decltype(std::__niter_base(__it.base()))' but this did not compile, 
ambiguity issue. So I resort to using std::declval and I could have then 
done it the same way as declaration, done now.


Attached is what I'm testing, ok to commit once fully tested ?

François

diff --git a/libstdc++-v3/include/bits/stl_algobase.h 
b/libstdc++-v3/include/bits/stl_algobase.h
index e7207f67266..0f73da13172 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -317,12 +317,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 _GLIBCXX_NOEXCEPT_IF(std::is_nothrow_copy_constructible<_Iterator>::value)
 { return __it; }
 
+#if __cplusplus < 201103L
   template
-_GLIBCXX20_CONSTEXPR
 _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).
diff --git a/libstdc++-v3/include/debug/safe_iterator.tcc 
b/libstdc++-v3/include/debug/safe_iterator.tcc
index 6eb70cbda04..a8b24233e85 100644
--- a/libstdc++-v3/include/debug/safe_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_iterator.tcc
@@ -235,13 +235,29 @@ namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
+#if __cplusplus < 201103L
   template
-_GLIBCXX20_CONSTEXPR
 _Ite
 __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq,
 std::random_access_iterator_tag>& __it)
 { return __it.base(); }
 
+  template
+_Ite
+__niter_base(const ::__gnu_debug::_Safe_iterator<
+::__gnu_cxx::__normal_iterator<_Ite, _Cont>, _DbgSeq,
+std::random_access_iterator_tag>& __it)
+{ return __it.base().base(); }
+#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>& __it)
+noexcept(std::is_nothrow_copy_constructible<_Ite>::value)
+{ return std::__niter_base(__it.base()); }
+#endif
+
   template
 _GLIBCXX20_CONSTEXPR


[PATCH][_GLIBCXX_DEBUG] Fix std::__niter_base behavior

2024-02-14 Thread François Dumont

libstdc++: [_GLIBCXX_DEBUG] Fix std::__niter_base behavior

std::__niter_base is used in _GLIBCXX_DEBUG mode to remove _Safe_iterator<>
wrapper on random access iterators. But doing so it should also preserve 
original

behavior to remove __normal_iterator wrapper.

libstdc++-v3/ChangeLog:

    * include/bits/stl_algobase.h (std::__niter_base): Redefine the 
overload

    definitions for __gnu_debug::_Safe_iterator.
    * include/debug/safe_iterator.tcc (std::__niter_base): Adapt 
declarations.


Ok to commit once all tests completed (still need to check pre-c++11) ?

François
diff --git a/libstdc++-v3/include/bits/stl_algobase.h 
b/libstdc++-v3/include/bits/stl_algobase.h
index e7207f67266..056fa0c4173 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -317,12 +317,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 _GLIBCXX_NOEXCEPT_IF(std::is_nothrow_copy_constructible<_Iterator>::value)
 { return __it; }
 
+#if __cplusplus < 201103L
   template
-_GLIBCXX20_CONSTEXPR
 _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( noexcept(std::is_nothrow_copy_constructible<
+   decltype(std::__niter_base(std::declval<_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).
diff --git a/libstdc++-v3/include/debug/safe_iterator.tcc 
b/libstdc++-v3/include/debug/safe_iterator.tcc
index 6eb70cbda04..d6cfe24cc83 100644
--- a/libstdc++-v3/include/debug/safe_iterator.tcc
+++ b/libstdc++-v3/include/debug/safe_iterator.tcc
@@ -235,13 +235,29 @@ namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
+#if __cplusplus < 201103L
   template
-_GLIBCXX20_CONSTEXPR
 _Ite
 __niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq,
 std::random_access_iterator_tag>& __it)
 { return __it.base(); }
 
+  template
+_Ite
+__niter_base(const ::__gnu_debug::_Safe_iterator<
+::__gnu_cxx::__normal_iterator<_Ite, _Cont>, _DbgSeq,
+std::random_access_iterator_tag>& __it)
+{ return __it.base().base(); }
+#else
+  template
+_GLIBCXX20_CONSTEXPR
+auto
+__niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq,
+std::random_access_iterator_tag>& __it)
+-> decltype(std::__niter_base(declval<_Ite>()))
+{ return std::__niter_base(__it.base()); }
+#endif
+
   template
 _GLIBCXX20_CONSTEXPR


Fwd: [Bug libstdc++/90276] PSTL tests fail in Debug Mode

2024-01-31 Thread François Dumont

I replied to bugzilla rather than sending to proper mailing list !

At the same time it looks like you also found the root cause of the 
problem Jonathan. Just let me know if you want to deal with it eventually.


François


 Forwarded Message 
Subject:Re: [Bug libstdc++/90276] PSTL tests fail in Debug Mode
Date:   Wed, 31 Jan 2024 19:09:02 +0100
From:   François Dumont 
To: 	redi at gcc dot gnu.org , 
fdum...@gcc.gnu.org




Here is the reason of the 
20_util/specialized_algorithms/pstl/uninitialized_copy_move.cc FAIL.


Maybe it fixes some other tests too, I need to run all of them.

    libstdc++: Do not forward arguments several times [PR90276]

    Forwarding several times the same arguments results in UB. It is 
detected
    by the _GLIBCXX_DEBUG mode as an attempt to use a singular iterator 
which has

    been moved.

    libstdc++-v3/ChangeLog

    PR libstdc++/90276
    * testsuite/util/pstl/test_utils.h: Remove std::forward<> 
calls when

    done several times on the same arguments.

Ok to commit ?

François


On 31/01/2024 14:11, redi at gcc dot gnu.org wrote:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90276

Jonathan Wakely  changed:

What |Removed |Added

See Also| |https://github.com/llvm/llv
| |m-project/issues/80136
diff --git a/libstdc++-v3/testsuite/util/pstl/test_utils.h b/libstdc++-v3/testsuite/util/pstl/test_utils.h
index ed6d48b9471..fc3de6ae24b 100644
--- a/libstdc++-v3/testsuite/util/pstl/test_utils.h
+++ b/libstdc++-v3/testsuite/util/pstl/test_utils.h
@@ -1088,13 +1088,14 @@ struct reverse_invoker
 operator()(Rest&&... rest)
 {
 // Random-access iterator
-iterator_invoker()(std::forward(rest)...);
+iterator_invoker()(rest...);
 
 // Forward iterator
-iterator_invoker()(std::forward(rest)...);
+
+iterator_invoker()(rest...);
 
 // Bidirectional iterator
-iterator_invoker()(std::forward(rest)...);
+iterator_invoker()(rest...);
 }
 };
 
@@ -1104,8 +1105,8 @@ struct invoke_on_all_iterator_types
 void
 operator()(Rest&&... rest)
 {
-reverse_invoker()(std::forward(rest)...);
-reverse_invoker()(std::forward(rest)...);
+reverse_invoker()(rest...);
+reverse_invoker()(rest...);
 }
 };
 //
@@ -1118,10 +1119,10 @@ invoke_on_all_policies(Op op, T&&... rest)
 using namespace __pstl::execution;
 
 // Try static execution policies
-invoke_on_all_iterator_types()(seq, op, std::forward(rest)...);
-invoke_on_all_iterator_types()(unseq, op, std::forward(rest)...);
-invoke_on_all_iterator_types()(par, op, std::forward(rest)...);
-invoke_on_all_iterator_types()(par_unseq, op, std::forward(rest)...);
+invoke_on_all_iterator_types()(seq, op, rest...);
+invoke_on_all_iterator_types()(unseq, op, rest...);
+invoke_on_all_iterator_types()(par, op, rest...);
+invoke_on_all_iterator_types()(par_unseq, op, rest...);
 }
 
 template 


Re: _GLIBCXX_DEBUG_BACKTRACE broken

2024-01-29 Thread François Dumont

I had missed it, thanks.

Here is a patch to fix debug mode doc then.

libstdc++: Fix _GLIBCXX_DEBUG_BACKTRACE macro documentation

libstdc++-v3/ChangeLog:

    * doc/xml/manual/debug_mode.xml: Link against libstdc++exp.a to use
    _GLIBCXX_DEBUG_BACKTRACE macro.

Ok to commit ?

François

On 29/01/2024 11:10, Jonathan Wakely wrote:

On Mon, 29 Jan 2024 at 06:13, François Dumont  wrote:

Hi

I'm trying to use _GLIBCXX_DEBUG_BACKTRACE to debug some crash in debug
mode.

So I buit library with --enable-libstdcxx-backtrace=yes

But when I build any test I have:

/usr/bin/ld: /tmp/cctvPvlb.o: in function
`__gnu_debug::_Error_formatter::_Error_formatter(char const*, unsigned
int, char const*)':
/home/fdumont/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/debug/formatter.h:597:
undefined reference to `__glibcxx_backtrace_create_state'
/usr/bin/ld:
/home/fdumont/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/debug/formatter.h:598:
undefined reference to `__glibcxx_backtrace_full'

-lstdc++_libbacktrace does not help as it cannot find it.

You need to use -lstdc++exp.a instead, as documented at
https://gcc.gnu.org/gcc-14/changes.html#libstdcxx

I changed this with
https://gcc.gnu.org/g:b96b554592c5cbb6a2c1797ffcb5706fd295f4fd
diff --git a/libstdc++-v3/doc/xml/manual/debug_mode.xml 
b/libstdc++-v3/doc/xml/manual/debug_mode.xml
index dadc0cd1bb4..ac15ef6f6d0 100644
--- a/libstdc++-v3/doc/xml/manual/debug_mode.xml
+++ b/libstdc++-v3/doc/xml/manual/debug_mode.xml
@@ -165,8 +165,8 @@ which always works correctly.
   It requires that you configure libstdc++ build with
   --enable-libstdcxx-backtrace=yes.
   Use -D_GLIBCXX_DEBUG_BACKTRACE to activate it.
-  You'll then have to link with libstdc++_libbacktrace static library
-  (-lstdc++_libbacktrace) to build your application.
+  You'll then have to link against libstdc++exp static library
+  (-lstdc++exp) to build your application.
 
 
 Using a Specific Debug Container


Re: [PATCH] libstdc++: hashtable: No need to update before begin node in _M_remove_bucket_begin

2024-01-21 Thread François Dumont
Thanks, nice result, I'll try to run the performance benchmarks that are 
coming with libstdc++ to see if they spot anything.


That's tests in testsuite/performance folder in case you want to have a 
try yourself.


François


On 18/01/2024 10:26, Huanghui Nie wrote:


Yes, I have. I did a benchmark today.

The conclusion is: the time consumption can be reduced by 0.4% ~ 1.2% 
when unordered_set erase(begin()), and 1.2% ~ 2.4% when erase(begin(), 
end()).



My test environment:

CPU: Intel(R) Xeon(R) CPU E5-2680 v4 @ 2.40GHz, 2393.365 MHz, 56 CPUs

MEM: 256G

OS: CentOS-8.2

g++: gcc version 8.3.1 20191121 (Red Hat 8.3.1-5) (GCC)

Compile flags: -O3 -std=c++17


Test conclusion data (time taken to delete every 100 million elements):

erase(begin()):

|size of unordered_set |100 |1,000 |10,000|100,000 |1,000,000|10,000,000|

|base time consuming (ms)|3827.736|3807.725|3830.168|3807.373|3798.713 
|3854.168|


|test time consuming (ms)|3783.406|3789.460|3791.146|3778.033|3783.494 
|3808.137|


|Time-consuming reduction|1.16% |0.48% |1.02% |0.77% |0.40%|1.19% |

erase(begin(),end()):

|size of unordered_set |100 |1,000 |10,000|100,000 |1,000,000|10,000,000|

|base time consuming (ms)|2779.229|2768.550|2795.778|2767.385|2761.521 
|2804.099|


|test time consuming (ms)|2712.759|2726.578|2752.224|2732.140|2718.953 
|2739.727|


|Time-consuming reduction|2.39% |1.52% |1.56% |1.27% |1.54%|2.30% |


Please see the attachment for test code and detailed test result.


2024年1月18日(木) 4:04 François Dumont :

Hi

Looks like a great finding to me, this is indeed a useless check,
thanks!

Have you any figures on the performance enhancement ? It might
help to get proper approval as gcc is currently in dev stage 4
that is to say only bug fixes normally.

François

On 17/01/2024 09:11, Huanghui Nie wrote:


Hi.

When I implemented a hash table with reference to the C++ STL, I
found that when the hash table in the C++ STL deletes elements,
if the first element deleted is the begin element, the before
begin node is repeatedly assigned. This creates unnecessary
performance overhead.


First, let’s see the code implementation:

In _M_remove_bucket_begin, _M_before_begin._M_nxt is assigned
when &_M_before_begin == _M_buckets[__bkt]. That also means
_M_buckets[__bkt]->_M_nxt is assigned under some conditions.

_M_remove_bucket_begin is called by _M_erase and _M_extract_node:

 1. Case _M_erase a range: _M_remove_bucket_begin is called in a
for loop when __is_bucket_begin is true. And if
__is_bucket_begin is true and &_M_before_begin ==
_M_buckets[__bkt], __prev_n must be &_M_before_begin.
__prev_n->_M_nxt is always assigned in _M_erase. That means
_M_before_begin._M_nxt is always assigned, if
_M_remove_bucket_begin is called and &_M_before_begin ==
_M_buckets[__bkt]. So there’s no need to assign
_M_before_begin._M_nxt in _M_remove_bucket_begin.
 2. Other cases: _M_remove_bucket_begin is called when __prev_n
== _M_buckets[__bkt]. And __prev_n->_M_nxt is always assigned
in _M_erase and _M_before_begin. That means
_M_buckets[__bkt]->_M_nxt is always assigned. So there's no
need to assign _M_buckets[__bkt]->_M_nxt in
_M_remove_bucket_begin.

In summary, there’s no need to check &_M_before_begin ==
_M_buckets[__bkt] and assign _M_before_begin._M_nxt in
_M_remove_bucket_begin.


Then let’s see the responsibility of each method:

The hash table in the C++ STL is composed of hash buckets and a
node list. The update of the node list is responsible for
_M_erase and _M_extract_node method. _M_remove_bucket_begin
method only needs to update the hash buckets. The update of
_M_before_begin belongs to the update of the node list. So
_M_remove_bucket_begin doesn’t need to update _M_before_begin.


Existing tests listed below cover this change:

23_containers/unordered_set/allocator/copy.cc

23_containers/unordered_set/allocator/copy_assign.cc

23_containers/unordered_set/allocator/move.cc

23_containers/unordered_set/allocator/move_assign.cc

23_containers/unordered_set/allocator/swap.cc

23_containers/unordered_set/erase/1.cc

23_containers/unordered_set/erase/24061-set.cc

23_containers/unordered_set/modifiers/extract.cc

23_containers/unordered_set/operations/count.cc

23_containers/unordered_set/requirements/exception/basic.cc

23_containers/unordered_map/allocator/copy.cc

23_containers/unordered_map/allocator/copy_assign.cc

23_containers/unordered_map/allocator/move.cc

23_containers/unordered_map/allocator/move_assign.cc

23_containers/unordered_map/allocator/swap.cc

23_containers/unordered_map/erase/1.cc

23_containers/unordered_map/erase/24061-map.cc

23_containers/unordered_map/modifiers/extract.

Re: [PATCH] libstdc++: hashtable: No need to update before begin node in _M_remove_bucket_begin

2024-01-17 Thread François Dumont

Hi

Looks like a great finding to me, this is indeed a useless check, thanks!

Have you any figures on the performance enhancement ? It might help to 
get proper approval as gcc is currently in dev stage 4 that is to say 
only bug fixes normally.


François

On 17/01/2024 09:11, Huanghui Nie wrote:


Hi.

When I implemented a hash table with reference to the C++ STL, I found 
that when the hash table in the C++ STL deletes elements, if the first 
element deleted is the begin element, the before begin node is 
repeatedly assigned. This creates unnecessary performance overhead.



First, let’s see the code implementation:

In _M_remove_bucket_begin, _M_before_begin._M_nxt is assigned when 
&_M_before_begin == _M_buckets[__bkt]. That also means 
_M_buckets[__bkt]->_M_nxt is assigned under some conditions.


_M_remove_bucket_begin is called by _M_erase and _M_extract_node:

 1. Case _M_erase a range: _M_remove_bucket_begin is called in a for
loop when __is_bucket_begin is true. And if __is_bucket_begin is
true and &_M_before_begin == _M_buckets[__bkt], __prev_n must be
&_M_before_begin. __prev_n->_M_nxt is always assigned in _M_erase.
That means _M_before_begin._M_nxt is always assigned, if
_M_remove_bucket_begin is called and &_M_before_begin ==
_M_buckets[__bkt]. So there’s no need to assign
_M_before_begin._M_nxt in _M_remove_bucket_begin.
 2. Other cases: _M_remove_bucket_begin is called when __prev_n ==
_M_buckets[__bkt]. And __prev_n->_M_nxt is always assigned in
_M_erase and _M_before_begin. That means _M_buckets[__bkt]->_M_nxt
is always assigned. So there's no need to assign
_M_buckets[__bkt]->_M_nxt in _M_remove_bucket_begin.

In summary, there’s no need to check &_M_before_begin == 
_M_buckets[__bkt] and assign _M_before_begin._M_nxt in 
_M_remove_bucket_begin.



Then let’s see the responsibility of each method:

The hash table in the C++ STL is composed of hash buckets and a node 
list. The update of the node list is responsible for _M_erase and 
_M_extract_node method. _M_remove_bucket_begin method only needs to 
update the hash buckets. The update of _M_before_begin belongs to the 
update of the node list. So _M_remove_bucket_begin doesn’t need to 
update _M_before_begin.



Existing tests listed below cover this change:

23_containers/unordered_set/allocator/copy.cc

23_containers/unordered_set/allocator/copy_assign.cc

23_containers/unordered_set/allocator/move.cc

23_containers/unordered_set/allocator/move_assign.cc

23_containers/unordered_set/allocator/swap.cc

23_containers/unordered_set/erase/1.cc

23_containers/unordered_set/erase/24061-set.cc

23_containers/unordered_set/modifiers/extract.cc

23_containers/unordered_set/operations/count.cc

23_containers/unordered_set/requirements/exception/basic.cc

23_containers/unordered_map/allocator/copy.cc

23_containers/unordered_map/allocator/copy_assign.cc

23_containers/unordered_map/allocator/move.cc

23_containers/unordered_map/allocator/move_assign.cc

23_containers/unordered_map/allocator/swap.cc

23_containers/unordered_map/erase/1.cc

23_containers/unordered_map/erase/24061-map.cc

23_containers/unordered_map/modifiers/extract.cc

23_containers/unordered_map/modifiers/move_assign.cc

23_containers/unordered_map/operations/count.cc

23_containers/unordered_map/requirements/exception/basic.cc


Regression tested on x86_64-pc-linux-gnu. Is it OK to commit?


---

ChangeLog:


libstdc++: hashtable: No need to update before begin node in 
_M_remove_bucket_begin



2024-01-16Huanghui Nie


gcc/

* libstdc++-v3/include/bits/hashtable.h


---


diff --git a/libstdc++-v3/include/bits/hashtable.h 
b/libstdc++-v3/include/bits/hashtable.h


index b48610036fa..6056639e663 100644

--- a/libstdc++-v3/include/bits/hashtable.h

+++ b/libstdc++-v3/include/bits/hashtable.h

@@ -872,13 +872,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION

      if (!__next_n || __next_bkt != __bkt)

        {

          // Bucket is now empty

-         // First update next bucket if any

+         // Update next bucket if any

          if (__next_n)

            _M_buckets[__next_bkt] = _M_buckets[__bkt];

-         // Second update before begin node if necessary

-         if (&_M_before_begin == _M_buckets[__bkt])

-           _M_before_begin._M_nxt = __next_n;

          _M_buckets[__bkt] = nullptr;

        }

    }



Re: [Bug libstdc++/112477] [13/14 Regression] Assignment of value-initialized iterators differs from value-initialization

2024-01-10 Thread François Dumont
libstdc++: [_GLIBCXX_DEBUG] Fix assignment of value-initialized iterator 
[PR112477]


Now that _M_Detach do not reset iterator _M_version value we need to 
reset it when
the iterator is attached to a new sequence. Even if this sequencer is 
null like when
assigning a value-initialized iterator. In this case _M_version shall be 
reset to 0.


libstdc++-v3/ChangeLog:

    PR libstdc++/112477
    * src/c++11/debug.cc
    (_Safe_iterator_base::_M_attach): Reset _M_version to 0 if 
attaching to null

    sequence.
    (_Safe_iterator_base::_M_attach_single): Likewise.
    (_Safe_local_iterator_base::_M_attach): Likewise.
    (_Safe_local_iterator_base::_M_attach_single): Likewise.
    * testsuite/23_containers/map/debug/112477.cc: New test case.

Tested under Linux x64 _GLIBCXX_DEBUG mode.

Ok to commit and backport to gcc 13 ?

François

On 09/01/2024 22:47, fdumont at gcc dot gnu.org wrote:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112477

François Dumont  changed:

What|Removed |Added

Assignee|unassigned at gcc dot gnu.org  |fdumont at gcc dot 
gnu.org

--- Comment #8 from François Dumont  ---
Hi
I'm going to have a look but if you wish to contribute do not hesitate.
Thanks for the report.
diff --git a/libstdc++-v3/src/c++11/debug.cc b/libstdc++-v3/src/c++11/debug.cc
index bb0d0db6679..cb2cbf9d312 100644
--- a/libstdc++-v3/src/c++11/debug.cc
+++ b/libstdc++-v3/src/c++11/debug.cc
@@ -437,6 +437,8 @@ namespace __gnu_debug
_M_version = _M_sequence->_M_version;
_M_sequence->_M_attach(this, __constant);
   }
+else
+  _M_version = 0;
   }
 
   void
@@ -452,6 +454,8 @@ namespace __gnu_debug
_M_version = _M_sequence->_M_version;
_M_sequence->_M_attach_single(this, __constant);
   }
+else
+  _M_version = 0;
   }
 
   void
@@ -528,6 +532,8 @@ namespace __gnu_debug
_M_version = _M_sequence->_M_version;
_M_get_container()->_M_attach_local(this, __constant);
   }
+else
+  _M_version = 0;
   }
 
   void
@@ -543,6 +549,8 @@ namespace __gnu_debug
_M_version = _M_sequence->_M_version;
_M_get_container()->_M_attach_local_single(this, __constant);
   }
+else
+  _M_version = 0;
   }
 
   void
diff --git a/libstdc++-v3/testsuite/23_containers/map/debug/112477.cc 
b/libstdc++-v3/testsuite/23_containers/map/debug/112477.cc
new file mode 100644
index 000..bde613b8905
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/map/debug/112477.cc
@@ -0,0 +1,20 @@
+// { dg-do run { target c++11 } }
+// { dg-require-debug-mode "" }
+
+// PR libstdc++/112477
+
+#include 
+
+int main()
+{
+  using M = std::map;
+  using I = M::iterator;
+
+  M map{ {1, 1}, {2, 2} };
+
+  I it1 = map.begin();
+  it1 = I{};
+
+  I it2{};
+  (void)(it1 == it2);
+}


Re: [PATCH] Add __cow_string C string constructor

2024-01-07 Thread François Dumont



On 07/01/2024 21:53, Jonathan Wakely wrote:

On Sun, 7 Jan 2024 at 18:50, François Dumont  wrote:


On 07/01/2024 17:34, Jonathan Wakely wrote:

On Sun, 7 Jan 2024 at 12:57, François Dumont  wrote:

Hi

While working on the patch to use the cxx11 abi in gnu version namespace
mode I got a small problem with this missing constructor. I'm not sure
that the main patch will be integrated in gcc 14 so I think it is better
if I propose this patch independently.

   libstdc++: Add __cow_string constructor from C string

   The __cow_string is instantiated from a C string in
cow-stdexcept.cc. At the moment
   the constructor from std::string is being used with the drawback of
an intermediate
   potential allocation/deallocation and copy. With the C string
constructor we bypass
   all those operations.

But in that file, the std::string is the COW string, which means that
when we construct a std::string and copy it, it's cheap. It's just a
reference count increment/decrement. There should be no additional
allocation or deallocation.

Good remark but AFAI understand in this case std::string is the cxx11
one. I'll take a second look.

Clearly in my gnu version namespace patch it is the cxx11 implementation.

I hope not! The whole point of that type is to always be a COW string,
which it does by storing a COW std::basic_string in the union, but
wrapping it in a class with a different name, __cow_string.

If your patch to use the SSO string in the versioned namespace doesn't
change that file to guarantee that __cow_string is still a
copy-on-write type then the patch is wrong and must be fixed.


Don't worry, __cow_string is indeed wrapping a COW string.

What I meant is that in this constructor in :

__cow_string(const std::string&);

The std::string parameter is the SSO string.

However, as you said, in cow-stdexcept.cc the similar constructor is in 
fact taking a COW string so it has less importance. It's just a ODR issue.


In my gnu version namespace patch however this type is still the SSO 
string in cow-stdexcept.cc so I'll keep it in this context.




Even if so, why do we want to do those additional operations ? Adding
this C string constructor will make sure that no useless operations will
be done.

Yes, we could avoid an atomic increment and decrement, but that type
is only used when throwing an exception so the overhead of allocating
memory and calling __cxa_throw etc. is far higher than an atomic
inc/dec pair.

I was going to say that the new constructor would need to be exported
from the shared lib, but I think the new constructor is only ever used
in these two places, both defined in that same file:

   logic_error::logic_error(const char* __arg)
   : exception(), _M_msg(__arg) { }

   runtime_error::runtime_error(const char* __arg)
   : exception(), _M_msg(__arg) { }

So I think the change is safe, but I don't think it's urgent, and
certainly not needed for the reasons claimed in the patch description.

The ODR violation has no side effect, it confirms your statement, looks 
like the __cow_string(const std::string&) could be removed from .





Re: [PATCH] Add __cow_string C string constructor

2024-01-07 Thread François Dumont



On 07/01/2024 17:34, Jonathan Wakely wrote:

On Sun, 7 Jan 2024 at 12:57, François Dumont  wrote:

Hi

While working on the patch to use the cxx11 abi in gnu version namespace
mode I got a small problem with this missing constructor. I'm not sure
that the main patch will be integrated in gcc 14 so I think it is better
if I propose this patch independently.

  libstdc++: Add __cow_string constructor from C string

  The __cow_string is instantiated from a C string in
cow-stdexcept.cc. At the moment
  the constructor from std::string is being used with the drawback of
an intermediate
  potential allocation/deallocation and copy. With the C string
constructor we bypass
  all those operations.

But in that file, the std::string is the COW string, which means that
when we construct a std::string and copy it, it's cheap. It's just a
reference count increment/decrement. There should be no additional
allocation or deallocation.


Good remark but AFAI understand in this case std::string is the cxx11 
one. I'll take a second look.


Clearly in my gnu version namespace patch it is the cxx11 implementation.

Even if so, why do we want to do those additional operations ? Adding 
this C string constructor will make sure that no useless operations will 
be done.




Am I missing something?



  libstdc++-v3/ChangeLog:

  * include/std/stdexcept (__cow_string(const char*)): New
definition.
  * src/c++11/cow-stdexcept.cc (__cow_string(const char*)):
New definition and
  declaration.

Tested under Linux x64, ok to commit ?

François



[PATCH] Add __cow_string C string constructor

2024-01-07 Thread François Dumont

Hi

While working on the patch to use the cxx11 abi in gnu version namespace 
mode I got a small problem with this missing constructor. I'm not sure 
that the main patch will be integrated in gcc 14 so I think it is better 
if I propose this patch independently.


    libstdc++: Add __cow_string constructor from C string

    The __cow_string is instantiated from a C string in 
cow-stdexcept.cc. At the moment
    the constructor from std::string is being used with the drawback of 
an intermediate
    potential allocation/deallocation and copy. With the C string 
constructor we bypass

    all those operations.

    libstdc++-v3/ChangeLog:

    * include/std/stdexcept (__cow_string(const char*)): New 
definition.
    * src/c++11/cow-stdexcept.cc (__cow_string(const char*)): 
New definition and

    declaration.

Tested under Linux x64, ok to commit ?

François

diff --git a/libstdc++-v3/include/std/stdexcept 
b/libstdc++-v3/include/std/stdexcept
index 66c8572d0cd..2e3c9f3bf71 100644
--- a/libstdc++-v3/include/std/stdexcept
+++ b/libstdc++-v3/include/std/stdexcept
@@ -54,6 +54,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 __cow_string();
 __cow_string(const std::string&);
+__cow_string(const char*);
 __cow_string(const char*, size_t);
 __cow_string(const __cow_string&) _GLIBCXX_NOTHROW;
 __cow_string& operator=(const __cow_string&) _GLIBCXX_NOTHROW;
diff --git a/libstdc++-v3/src/c++11/cow-stdexcept.cc 
b/libstdc++-v3/src/c++11/cow-stdexcept.cc
index 8d1cc4605d4..12b189b43b5 100644
--- a/libstdc++-v3/src/c++11/cow-stdexcept.cc
+++ b/libstdc++-v3/src/c++11/cow-stdexcept.cc
@@ -127,6 +127,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 __cow_string();
 __cow_string(const std::string& s);
+__cow_string(const char*);
 __cow_string(const char*, size_t n);
 __cow_string(const __cow_string&) noexcept;
 __cow_string& operator=(const __cow_string&) noexcept;
@@ -139,6 +140,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   __cow_string::__cow_string(const std::string& s) : _M_str(s) { }
 
+  __cow_string::__cow_string(const char* s) : _M_str(s) { }
+
   __cow_string::__cow_string(const char* s, size_t n) : _M_str(s, n) { }
 
   __cow_string::__cow_string(const __cow_string& s) noexcept


Re: [PATCH 3/5][_Hashtable] Avoid redundant usage of rehash policy

2024-01-03 Thread François Dumont

Here is an updated version.

    libstdc++: [_Hashtable] Avoid redundant usage of rehash policy

    Bypass call to __detail::__distance_fwd and the check if rehash is 
needed when
    instantiating from an iterator range or assigning an 
initializer_list to an

    unordered_multimap or unordered_multiset.

    libstdc++-v3/ChangeLog:

    * include/bits/hashtable.h
    (_Hashtable<>::_M_insert_range(_InputIte, _InputIte, 
_NodeGen&)): New.

(_Hashtable<>::operator=(initializer_list)): Use latter.
    (_Hashtable<>::_Hashtable(_InputIte, _InputIte, size_type, 
const _Hash&, const _Equal&,

    const allocator_type&, false_type)): Use latter.
    * include/bits/hashtable_policy.h
    (_Insert_base<>::_M_insert_range): Rename in...
    (_Insert_base<>::_M_insert): ...this and private.

Ok to commit ?

François


On 21/12/2023 23:17, Jonathan Wakely wrote:

On Thu, 23 Nov 2023 at 21:59, François Dumont  wrote:

  libstdc++: [_Hashtable] Avoid redundant usage of rehash policy

  Bypass call to __detail::__distance_fwd and the check if rehash is
needed when
  assigning an initializer_list to an unordered_multimap or
unordered_multiset.

I find this patch and the description a bit confusing. It would help
if the new _Hashtable::_M_insert_range function had a comment (or a
different name!) explaining how it's different from the existing
_Insert_base::_M_insert_range functions.



  libstdc++-v3/ChangeLog:

  * include/bits/hashtable.h
  (_Hashtable<>::_M_insert_range(_InputIte, _InputIte,
_NodeGen&)): New.
(_Hashtable<>::operator=(initializer_list)): Use latter.
  (_Hashtable<>::_Hashtable(_InputIte, _InputIte, size_type,
const _Hash&, const _Equal&,
  const allocator_type&, false_type)): Use latter.
  * include/bits/hashtable_policy.h
  (_Insert_base<>::_M_insert_range(_InputIte, _InputIte,
true_type)): Use latter.
  (_Insert_base<>::_M_insert_range(_InputIte, _InputIte,
false_type)): Likewise.

Tested under Linux x64

Ok to commit ?

Françoisdiff --git a/libstdc++-v3/include/bits/hashtable.h 
b/libstdc++-v3/include/bits/hashtable.h
index adf77f25d41..aec77c34a58 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -616,7 +616,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (_M_bucket_count < __l_bkt_count)
  rehash(__l_bkt_count);
 
-   this->_M_insert_range(__l.begin(), __l.end(), __roan, __unique_keys{});
+   _M_insert_range(__l.begin(), __l.end(), __roan);
return *this;
   }
 
@@ -989,6 +989,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_insert(const_iterator, _Arg&&,
  _NodeGenerator&, false_type __uks);
 
+  template
+   void
+   _M_insert_range(_InputIterator __first, _InputIterator __last,
+   _NodeGenerator&);
+
   size_type
   _M_erase(true_type __uks, const key_type&);
 
@@ -1304,8 +1309,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  }
 
__alloc_node_gen_t __node_gen(*this);
-   for (; __f != __l; ++__f)
- _M_insert(*__f, __node_gen, __uks);
+   _M_insert_range(__f, __l, __node_gen);
   }
 
   template
+template
+  void
+  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
+_Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
+  _M_insert_range(_InputIterator __first, _InputIterator __last,
+ _NodeGenerator& __node_gen)
+  {
+   for (; __first != __last; ++__first)
+ _M_insert(*__first, __node_gen, __unique_keys{});
+  }
+
   template(this)); }
 
-  template
+private:
+  template
void
-   _M_insert_range(_InputIterator __first, _InputIterator __last,
-   _NodeGetter&, true_type __uks);
+   _M_insert(_InputIterator __first, _InputIterator __last,
+ true_type __uks);
 
-  template
+  template
void
-   _M_insert_range(_InputIterator __first, _InputIterator __last,
-   _NodeGetter&, false_type __uks);
+   _M_insert(_InputIterator __first, _InputIterator __last,
+ false_type __uks);
 
 public:
   using iterator = _Node_iterator<_Value, __constant_iterators::value,
@@ -999,41 +1000,37 @@ namespace __detail
   template
void
insert(_InputIterator __first, _InputIterator __last)
-   {
- __hashtable& __h = _M_conjure_hashtable();
- __node_gen_type __node_gen(__h);
- return _M_insert_range(__first, __last, __node_gen, __unique_keys{});
-   }
+   { _M_insert(__first, __last, __unique_keys{}); }
 };
 
   template
-template
+template
   void
   _Insert_base<_Key, _Valu

Re: [PATCH 2/5][_Hashtable] Fix implementation inconsistencies

2024-01-03 Thread François Dumont


On 21/12/2023 23:07, Jonathan Wakely wrote:

On Thu, 23 Nov 2023 at 21:59, François Dumont  wrote:

  libstdc++: [_Hashtable] Fix some implementation inconsistencies

  Get rid of the different usages of the mutable keyword. For
  _Prime_rehash_policy methods are exported from the library, we need to
  keep their const qualifier, so adapt implementation to update
previously
  mutable member.

If anybody ever declares a const _Prime_rehash_policy and then calls
its _M_next_bkt member or _M_need_rehash member they'll get undefined
behaviour, which seems bad. Probably nobody will ever do that, but if
we just leave the mutable member then that problem doesn't exist.

It would be possible to add non-const overlaods of _M_next_bkt and
_M_need_rehash, and then make the const ones do:

return const_cast<_Prime_rehash_policy*>(this)->_M_next_bkt(n);

or even just define the const symbol as an alias of the non-const
symbol, on targets that support that.  That would still be undefined
if somebody uses a const Prime_rehash_policy object somewhere, but it
would mean the definition of the member functions don't contain nasty
surprises, and new code would call the non-const version, which
doesn't use the unsafe const_cast.
Ok, nevermind for this part, I just commented that the 'const' or 
'mutable' in this implementation are just here for abi compatibility reason.



  Remove useless noexcept qualification on _Hashtable _M_bucket_index
overload.
  Fix comment to explain that we need the computation of bucket index
to be
  noexcept to be able to rehash the container when needed. For Standard
  instantiations through std::unordered_xxx containers we already force
  usage of hash code cache when hash functor is not noexcep so it is
guarantied.
  The static_assert purpose in _Hashtable on _M_bucket_index is thus
limited
  to usages of _Hashtable with exotic _Hashtable_traits.

  libstdc++-v3/ChangeLog:

  * include/bits/hashtable_policy.h
(_NodeBuilder<>::_S_build): Remove
  const qualification on _NodeGenerator instance.
(_ReuseOrAllocNode<>::operator()(_Args&&...)): Remove const qualification.
  (_ReuseOrAllocNode<>::_M_nodes): Remove mutable.
  (_Prime_rehash_policy::max_load_factor()): Remove noexcept.

Why?


  (_Prime_rehash_policy::_M_reset()): Remove noexcept.

Why?

Those functions really are noexcept, right? We should remove noexcept
where it's incorrect or misleading, but here it's OK, isn't it? Or am
I forgetting the problem being solved here?


I just try to answer your remarks in:

https://gcc.gnu.org/pipermail/libstdc++/2023-October/057531.html

AFAI understand 'noexcept' purpose is just to implement some 
optimizations in meta-programmation or have static_assert. As all this 
code is an implementation detail and I'm not using those qualifiers and 
as it seems to raise some concerns to you I just preferred to remove those.


Is the compiler behavior changing w/o it ?

diff --git a/libstdc++-v3/include/bits/hashtable.h 
b/libstdc++-v3/include/bits/hashtable.h
index 9441fe1f91c..adf77f25d41 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -48,7 +48,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 using __cache_default
   =  __not_<__and_,
-  // Mandatory to have erase not throwing.
+  // Mandatory for the rehash process.
   __is_nothrow_invocable>>;
 
   // Helper to conditionally delete the default constructor.
@@ -481,7 +481,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
void
-   _M_assign(_Ht&&, const _NodeGenerator&);
+   _M_assign(_Ht&&, _NodeGenerator&);
 
   void
   _M_move_assign(_Hashtable&&, true_type);
@@ -796,7 +796,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 private:
   // Bucket index computation helpers.
   size_type
-  _M_bucket_index(const __node_value_type& __n) const noexcept
+  _M_bucket_index(const __node_value_type& __n) const
   { return __hash_code_base::_M_bucket_index(__n, _M_bucket_count); }
 
   size_type
@@ -924,7 +924,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
std::pair
-   _M_insert_unique(_Kt&&, _Arg&&, const _NodeGenerator&);
+   _M_insert_unique(_Kt&&, _Arg&&, _NodeGenerator&);
 
   template
static __conditional_t<
@@ -944,7 +944,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
std::pair
-   _M_insert_unique_aux(_Arg&& __arg, const _NodeGenerator& __node_gen)
+   _M_insert_unique_aux(_Arg&& __arg, _NodeGenerator& __node_gen)
{
  return _M_insert_unique(
_S_forward_key(_ExtractKey{}(std::forward<_Arg>(__arg))),
@@ -953,7 +953,7 @@ _GLIBCXX_BEGIN_NAMESPACE

Re: [PATCH 5/5][_Hashtable] Prefer to insert after last node

2024-01-02 Thread François Dumont



On 21/12/2023 22:55, Jonathan Wakely wrote:

I think this should wait for the next stage 1. It's a big patch
affecting the default -std mode (not just experimental C++20/23/26
material), and was first posted after the end of stage 1.
The idea of this patch was in the air far before it but I agree that its 
form has changed a lot.


Do we really need the changes for versioned namespace? How much
difference does that extra member make to performance, compared with
the version for the default config?


It is huge and demonstrated by the bench results below. You can see that 
the number of calls to the hash functor is divided by 2. With such a 
member you only need to compute 1 hash code when inserting in an empty 
bucket (the perfect hasher case) whereas we currently need 2 to properly 
maintained the bucket pointing to the before-begin base node.


This is also why I proposed it now as I still hope that the patch to 
move to cxx11 abi in gnu versioned namespace will be integrated so with 
its implied version bump.





On Wed, 20 Dec 2023 at 06:10, François Dumont  wrote:

Here is a new version of this patch.

The previous one had some flaws that were unnoticed by testsuite tests,
only the performance tests were spotting it. So I'm adding checks on the
consistency of the unordered containers in this patch.

I also forget to signal that after this patch gnu versioned namespace
version is supposed to be bump. But I hope it's already the plan because
of the move to the cxx11 abi in this mode.

Note for reviewer, after application of the patch, a 'git diff -b' is
much more readable.

And some benches results:

before:

unordered_set_range_insert.cc-threadhash code NOT cached 2 X 100
inserts individually 1990 calls  44r   44u0s 95999760mem0pf
unordered_set_range_insert.cc-threadhash code NOT cached 2 X 100
inserts in range 2000 calls  43r   43u0s 95999760mem0pf
unordered_set_range_insert.cc-threadhash code NOT cached 100 X
inserts individually 1990 calls  44r   44u 0s  95999760mem0pf
unordered_set_range_insert.cc-threadhash code NOT cached 100 X
inserts in range 2000 calls  43r   43u0s 95999760mem0pf
unordered_set_range_insert.cc-threadhash code cached 2 X 100
inserts individually 1000 calls  30r   30u0s 111999328mem
0pf
unordered_set_range_insert.cc-threadhash code cached 2 X 100
inserts in range 1010 calls  33r   32u0s 111999328mem0pf
unordered_set_range_insert.cc-threadhash code cached 100 X
inserts individually 1000 calls  30r   31u0s 111999328mem
0pf
unordered_set_range_insert.cc-threadhash code cached 100 X
inserts in range 1010 calls  32r   32u0s 111999328mem0pf

after:

unordered_set_range_insert.cc-threadhash code NOT cached 2 X 100
inserts individually 1990 calls  44r   44u0s 95999760mem0pf
unordered_set_range_insert.cc-threadhash code NOT cached 2 X 100
inserts in range 1020 calls  26r   25u0s 95999760mem0pf
unordered_set_range_insert.cc-threadhash code NOT cached 100 X
inserts individually 1990 calls  43r   44u 0s  95999760mem0pf
unordered_set_range_insert.cc-threadhash code NOT cached 100 X
inserts in range 1020 calls  26r   26u0s 95999760mem0pf
unordered_set_range_insert.cc-threadhash code cached 2 X 100
inserts individually 1000 calls  35r   35u0s 111999328mem
0pf
unordered_set_range_insert.cc-threadhash code cached 2 X 100
inserts in range 1010 calls  32r   33u0s 111999328mem0pf
unordered_set_range_insert.cc-threadhash code cached 100 X
inserts individually 1000 calls  31r   32u0s 111999328mem
0pf
unordered_set_range_insert.cc-threadhash code cached 100 X
inserts in range 1010 calls  31r   31u0s 111999328mem0pf


  libstdc++: [_Hashtable] Prefer to insert after last node

  When inserting an element into an empty bucket we currently insert
the new node
  after the before-begin node so in first position. The drawback of
doing this is
  that we are forced to update the bucket that was containing this
before-begin
  node to point to the newly inserted node. To do so we need at best
to do a modulo
  to find this bucket and at worst, when hash code is not cached,
also compute it.

  To avoid this side effect it is better to insert after the last
node. To do so
  we are introducing a helper type _HintPolicy that has 3
resposibilities.

  1. When the gnu versioned namespace is used we add a _M_last member
to _Hashtable,
  _HintPolicy is then in charge of maintaining it. For this purpose
_HintPolicy is
  using the RAII pattern, it resets the _M_last at destruction level.
It also maintain
  its own _M_last, all mutable operations are updating it when needed.

  2. When the gnu versioned namespace

Re: [PATCH 5/5][_Hashtable] Prefer to insert after last node

2023-12-19 Thread François Dumont

Here is a new version of this patch.

The previous one had some flaws that were unnoticed by testsuite tests, 
only the performance tests were spotting it. So I'm adding checks on the 
consistency of the unordered containers in this patch.


I also forget to signal that after this patch gnu versioned namespace 
version is supposed to be bump. But I hope it's already the plan because 
of the move to the cxx11 abi in this mode.


Note for reviewer, after application of the patch, a 'git diff -b' is 
much more readable.


And some benches results:

before:

unordered_set_range_insert.cc-thread    hash code NOT cached 2 X 100 
inserts individually 1990 calls      44r   44u    0s 95999760mem    0pf
unordered_set_range_insert.cc-thread    hash code NOT cached 2 X 100 
inserts in range 2000 calls      43r   43u    0s 95999760mem    0pf
unordered_set_range_insert.cc-thread    hash code NOT cached 100 X 
inserts individually 1990 calls      44r   44u 0s  95999760mem    0pf
unordered_set_range_insert.cc-thread    hash code NOT cached 100 X 
inserts in range 2000 calls      43r   43u    0s 95999760mem    0pf
unordered_set_range_insert.cc-thread    hash code cached 2 X 100 
inserts individually 1000 calls      30r   30u    0s 111999328mem    
0pf
unordered_set_range_insert.cc-thread    hash code cached 2 X 100 
inserts in range 1010 calls      33r   32u    0s 111999328mem    0pf
unordered_set_range_insert.cc-thread    hash code cached 100 X 
inserts individually 1000 calls      30r   31u    0s 111999328mem    
0pf
unordered_set_range_insert.cc-thread    hash code cached 100 X 
inserts in range 1010 calls      32r   32u    0s 111999328mem    0pf


after:

unordered_set_range_insert.cc-thread    hash code NOT cached 2 X 100 
inserts individually 1990 calls      44r   44u    0s 95999760mem    0pf
unordered_set_range_insert.cc-thread    hash code NOT cached 2 X 100 
inserts in range 1020 calls      26r   25u    0s 95999760mem    0pf
unordered_set_range_insert.cc-thread    hash code NOT cached 100 X 
inserts individually 1990 calls      43r   44u 0s  95999760mem    0pf
unordered_set_range_insert.cc-thread    hash code NOT cached 100 X 
inserts in range 1020 calls      26r   26u    0s 95999760mem    0pf
unordered_set_range_insert.cc-thread    hash code cached 2 X 100 
inserts individually 1000 calls      35r   35u    0s 111999328mem    
0pf
unordered_set_range_insert.cc-thread    hash code cached 2 X 100 
inserts in range 1010 calls      32r   33u    0s 111999328mem    0pf
unordered_set_range_insert.cc-thread    hash code cached 100 X 
inserts individually 1000 calls      31r   32u    0s 111999328mem    
0pf
unordered_set_range_insert.cc-thread    hash code cached 100 X 
inserts in range 1010 calls      31r   31u    0s 111999328mem    0pf



    libstdc++: [_Hashtable] Prefer to insert after last node

    When inserting an element into an empty bucket we currently insert 
the new node
    after the before-begin node so in first position. The drawback of 
doing this is
    that we are forced to update the bucket that was containing this 
before-begin
    node to point to the newly inserted node. To do so we need at best 
to do a modulo
    to find this bucket and at worst, when hash code is not cached, 
also compute it.


    To avoid this side effect it is better to insert after the last 
node. To do so
    we are introducing a helper type _HintPolicy that has 3 
resposibilities.


    1. When the gnu versioned namespace is used we add a _M_last member 
to _Hashtable,
    _HintPolicy is then in charge of maintaining it. For this purpose 
_HintPolicy is
    using the RAII pattern, it resets the _M_last at destruction level. 
It also maintain

    its own _M_last, all mutable operations are updating it when needed.

    2. When the gnu versioned namespace is not used _HintPolicy will 
still maintain its
    _M_last member using initially the user provided hint if any and if 
it is actually
    the container last node that is to say a dereferenceable node with 
its next node being
    null. All mutable operations can also update the contextual 
_HintPolicy instance

    whenever they detect the last node during their process.

    3. As long as we haven't been able to detect the container last 
node, _HintPolicy
    is used to keep a cache of the before-begin bucket index so that we 
do not need to

    compute it afterward for example in the context of range insertion.

    libstdc++-v3/ChangeLog:

    * include/bits/hashtable.h
[_GLIBCXX_INLINE_VERSION](_Hashtable<>::_M_last): New, the container 
last node.

    (_Hashtable<>::_LastNodeManager): New.
    (_Hashtable<>::_M_get_last(__node_ptr)): New.
(_Hashtable<>::_M_get_last_node_mgr(__node_ptr)): New.
(_Hashtable<>::_M_check_for_last(__node_base_ptr)): New.
    (_Hashtable<>::_M_set_last(__node_ptr)): New.
   

Re: [PATCH] Reimplement __gnu_cxx::__ops operators

2023-12-09 Thread François Dumont



On 07/12/2023 14:41, Jonathan Wakely wrote:

On Wed, 6 Dec 2023 at 20:55, François Dumont  wrote:

I think I still got no feedback about this cleanup proposal.

Can you remind me why we have all those different functions in
predefined_ops.h in the first place? I think it was to avoid having
two versions of every algorithm, one that does *l < *r and one that
does pred(*l, *r), right?

Yes, that was the purpose.


One property of the current code is that _Iter_less_iter will compare
exactly *lhs < *rhs and so works even with this type, where its
operator< only accepts non-const arguments:

struct X { bool operator<(X&); };

Doesn't your simplification break that, because the _Less function
only accepts const references now?


Indeed, I thought more about the problem of const qualification on the 
operator(). This is why _Comp_val is mimicking what _Not_fn does.


To be honnest I even thought that this kind of operator above was more a 
user code issue than a real use case we need to handle. But it looks 
like you, I guess the C++ Standard then, impose to support it.


I'll rework it then, thanks for the proposal below and in your other email.




Re: [PATCH] Reimplement __gnu_cxx::__ops operators

2023-12-06 Thread François Dumont

I think I still got no feedback about this cleanup proposal.

Here is a new version.

François

On 15/06/2023 07:07, François Dumont wrote:
I think we all agree that __gnu_cxx::__ops needed to be reimplemented, 
here it is.


Note that I kept the usage of std::ref in ,  and .

    libstdc++: Reimplement __gnu_cxx::__ops operators

    Replace functors using iterators as input to adopt functors that
    are matching the same Standard expectations as the ones imposed on
    predicates used in predicates-aware algos. Doing so we need far less
    functors. It impose that iterators are dereference at algo level and
    not in the functors anymore.

    libstdc++-v3/ChangeLog:

    * include/std/functional (_Not_fn): Move to...
    * include/bits/predefined_ops.h: ...here, and expose a 
version

    in pre-C++14 mode.
    (__not_fn): New, use latter.
    (_Iter_less_iter, _Iter_less_val, _Val_less_iter, 
_Iter_equal_to_iter)
    (_Iter_equal_to_val, _Iter_comp_iter, _Iter_comp_val, 
_Val_comp_iter)
    (_Iter_equals_val, _Iter_equals_iter, _Iter_pred, 
_Iter_comp_val)
    (_Iter_comp_to_val, _Iter_comp_to_iter, _Iter_negate): 
Remove.
    (__iter_less_iter, __iter_less_val, __iter_comp_val, 
__val_less_iter)
    (__val_comp_iter, __iter_equal_to_iter, 
__iter_equal_to_val, __iter_comp_iter)
    (__val_comp_iter, __iter_equals_val, __iter_comp_iter, 
__pred_iter): Remove.

    (_Less, _Equal_to, _Equal_to_val, _Comp_val): New.
    (__less, __equal_to, __comp_val): New.
    * include/bits/stl_algo.h: Adapt all algos to use new 
__gnu_cxx::__ops operators.
    When possible use std::move to pass predicates between 
routines.

    * include/bits/stl_algobase.h: Likewise.
    * include/bits/stl_heap.h: Likewise.
    * include/std/deque: Cleanup usage of __gnu_cxx::__ops 
operators.

    * include/std/string: Likewise.
    * include/std/vector: Likewise.

Tested under Linux x86_64 normal and _GLIBCXX_DEBUG modes.

Ok to commit ?

François
diff --git a/libstdc++-v3/include/bits/predefined_ops.h 
b/libstdc++-v3/include/bits/predefined_ops.h
index e9933373ed9..8753e6f64cd 100644
--- a/libstdc++-v3/include/bits/predefined_ops.h
+++ b/libstdc++-v3/include/bits/predefined_ops.h
@@ -32,376 +32,229 @@
 
 #include 
 
+#if __cplusplus >= 201103L
+# include 
+#endif
+
 namespace __gnu_cxx
 {
 namespace __ops
 {
-  struct _Iter_less_iter
+  struct _Less
   {
-template
+template
   _GLIBCXX14_CONSTEXPR
   bool
-  operator()(_Iterator1 __it1, _Iterator2 __it2) const
-  { return *__it1 < *__it2; }
+  operator()(const _Lhs& __lhs, const _Rhs& __rhs) const
+  { return __lhs < __rhs; }
   };
 
   _GLIBCXX14_CONSTEXPR
-  inline _Iter_less_iter
-  __iter_less_iter()
-  { return _Iter_less_iter(); }
-
-  struct _Iter_less_val
-  {
-#if __cplusplus >= 201103L
-constexpr _Iter_less_val() = default;
-#else
-_Iter_less_val() { }
-#endif
-
-_GLIBCXX20_CONSTEXPR
-explicit
-_Iter_less_val(_Iter_less_iter) { }
-
-template
-  _GLIBCXX20_CONSTEXPR
-  bool
-  operator()(_Iterator __it, _Value& __val) const
-  { return *__it < __val; }
-  };
-
-  _GLIBCXX20_CONSTEXPR
-  inline _Iter_less_val
-  __iter_less_val()
-  { return _Iter_less_val(); }
-
-  _GLIBCXX20_CONSTEXPR
-  inline _Iter_less_val
-  __iter_comp_val(_Iter_less_iter)
-  { return _Iter_less_val(); }
-
-  struct _Val_less_iter
-  {
-#if __cplusplus >= 201103L
-constexpr _Val_less_iter() = default;
-#else
-_Val_less_iter() { }
-#endif
-
-_GLIBCXX20_CONSTEXPR
-explicit
-_Val_less_iter(_Iter_less_iter) { }
-
-template
-  _GLIBCXX20_CONSTEXPR
-  bool
-  operator()(_Value& __val, _Iterator __it) const
-  { return __val < *__it; }
-  };
+  inline _Less
+  __less()
+  { return _Less(); }
 
-  _GLIBCXX20_CONSTEXPR
-  inline _Val_less_iter
-  __val_less_iter()
-  { return _Val_less_iter(); }
-
-  _GLIBCXX20_CONSTEXPR
-  inline _Val_less_iter
-  __val_comp_iter(_Iter_less_iter)
-  { return _Val_less_iter(); }
-
-  struct _Iter_equal_to_iter
+  struct _Equal_to
   {
-template
+template
   _GLIBCXX20_CONSTEXPR
   bool
-  operator()(_Iterator1 __it1, _Iterator2 __it2) const
-  { return *__it1 == *__it2; }
+  operator()(const _Lhs& __lhs, const _Rhs& __rhs) const
+  { return __lhs == __rhs; }
   };
 
   _GLIBCXX20_CONSTEXPR
-  inline _Iter_equal_to_iter
-  __iter_equal_to_iter()
-  { return _Iter_equal_to_iter(); }
-
-  struct _Iter_equal_to_val
-  {
-template
-  _GLIBCXX20_CONSTEXPR
-  bool
-  operator()(_Iterator __it, _Value& __val) const
-  { return *__it == __val; }
-  };
+  inline _Equal_to
+  __equal_to()
+  { return _Equal_to(); }
 
-  _GLIBCXX20_CONSTEXPR
-  inline _Iter_equal_to_val
-  __iter_equal_to_val()
-  { return 

[PATCH 4/5][_Hashtable] Generalize the small size optimization

2023-11-23 Thread François Dumont

    libstdc++: [_Hashtable] Extend the small size optimization

    A number of methods were still not using the small size 
optimization which
    is to prefer an O(N) research to a hash computation as long as N is 
small.


    libstdc++-v3/ChangeLog:

    * include/bits/hashtable.h: Move comment about all 
equivalent values

    being next to each other in the class documentation header.
    (_M_reinsert_node, _M_merge_unique): Implement small size 
optimization.

    (_M_find_tr, _M_count_tr, _M_equal_range_tr): Likewise.

Tested under Linux x64

Ok to commit ?

François
diff --git a/libstdc++-v3/include/bits/hashtable.h 
b/libstdc++-v3/include/bits/hashtable.h
index 771ed9968f7..aec77c34a58 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -152,6 +152,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*  _M_before_begin, if any, is updated to point to its new before
*  begin node.
*
+   *  Note that all equivalent values, if any, are next to each other, if
+   *  we find a non-equivalent value after an equivalent one it means that
+   *  we won't find any new equivalent value.
+   *
*  On erase, the simple iterator design requires using the hash
*  functor to get the index of the bucket to update. For this
*  reason, when __cache_hash_code is set to false the hash functor must
@@ -1054,10 +1058,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  {
__glibcxx_assert(get_allocator() == __nh.get_allocator());
 
+   __node_ptr __n = nullptr;
const key_type& __k = __nh._M_key();
-   __hash_code __code = this->_M_hash_code(__k);
-   size_type __bkt = _M_bucket_index(__code);
-   if (__node_ptr __n = _M_find_node(__bkt, __k, __code))
+   const size_type __size = size();
+   if (__size <= __small_size_threshold())
+ {
+   for (__n = _M_begin(); __n; __n = __n->_M_next())
+ if (this->_M_key_equals(__k, *__n))
+   break;
+ }
+
+   __hash_code __code;
+   size_type __bkt;
+   if (!__n)
+ {
+   __code = this->_M_hash_code(__k);
+   __bkt = _M_bucket_index(__code);
+   if (__size > __small_size_threshold())
+ __n = _M_find_node(__bkt, __k, __code);
+ }
+
+   if (__n)
  {
__ret.node = std::move(__nh);
__ret.position = iterator(__n);
@@ -1161,11 +1182,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  for (auto __i = __src.cbegin(), __end = __src.cend(); __i != __end;)
{
  auto __pos = __i++;
+ const size_type __size = size();
  const key_type& __k = _ExtractKey{}(*__pos);
+ if (__size <= __small_size_threshold())
+   {
+ bool __found = false;
+ for (auto __n = _M_begin(); __n; __n = __n->_M_next())
+   if (this->_M_key_equals(__k, *__n))
+ {
+   __found = true;
+   break;
+ }
+
+ if (__found)
+   {
+ if (__n_elt != 1)
+   --__n_elt;
+ continue;
+   }
+   }
+
  __hash_code __code
= _M_src_hash_code(__src.hash_function(), __k, *__pos._M_cur);
  size_type __bkt = _M_bucket_index(__code);
- if (_M_find_node(__bkt, __k, __code) == nullptr)
+ if (__size <= __small_size_threshold()
+ || _M_find_node(__bkt, __k, __code) == nullptr)
{
  auto __nh = __src.extract(__pos);
  _M_insert_unique_node(__bkt, __code, __nh._M_ptr, __n_elt);
@@ -1743,6 +1784,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   _M_find_tr(const _Kt& __k)
   -> iterator
   {
+   if (size() <= __small_size_threshold())
+ {
+   for (auto __n = _M_begin(); __n; __n = __n->_M_next())
+ if (this->_M_key_equals_tr(__k, *__n))
+   return iterator(__n);
+   return end();
+ }
+
__hash_code __code = this->_M_hash_code_tr(__k);
std::size_t __bkt = _M_bucket_index(__code);
return iterator(_M_find_node_tr(__bkt, __k, __code));
@@ -1759,6 +1808,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   _M_find_tr(const _Kt& __k) const
   -> const_iterator
   {
+   if (size() <= __small_size_threshold())
+ {
+   for (auto __n = _M_begin(); __n; __n = __n->_M_next())
+ if (this->_M_key_equals_tr(__k, *__n))
+   return const_iterator(__n);
+   return end();
+ }
+
__hash_code __code = this->_M_hash_code_tr(__k);
std::size_t __bkt = _M_bucket_index(__code);
return 

[PATCH 5/5][_Hashtable] Prefer to insert after last node

2023-11-23 Thread François Dumont

    libstdc++: [_Hashtable] Prefer to insert after last node

    When inserting an element into an empty bucket we currently insert 
the new node
    after the before-begin node so in first position. The drawback of 
doing this is
    that we are forced to update the bucket that was containing this 
before-begin
    node to point to the newly inserted node. To do so we need at best 
to do a modulo
    to find this bucket and at worst, when hash code is not cached, 
also compute it.


    To avoid this side effect it is better to insert after the last 
node. To do so
    we are introducing a helper type _HintPolicy that have 3 
resposibilities.


    1. When the gnu versioned namespace is used we add a _M_last member 
to _Hashtable,
    _HintPolicy is then in charge of maintaining it. For this purpose 
_HintPolicy is
    using the RAII pattern, it resets the _M_last at destruction level. 
It also maintain

    its own _M_last, all mutable operations are updating it when needed.

    2. When the gnu versioned namespace is not used _HintPolicy will 
still maintain its
    _M_last member using initially the user provided hint if any and if 
it is actually
    the container last node that is to say a dereferenceable node with 
its next node being
    null. All mutable operations can also update the contextual 
_HintPolicy instance

    whenever they detect the last node during their process.

    3. As long as we haven't been able to detect the container last 
node _HintPolicy
    is used to keep a cache of the before-begin bucket index so that we 
do not need to

    compute it afterward for example in the context of range insertion.

    libstdc++-v3/ChangeLog:

    * include/bits/hashtable.h
[_GLIBCXX_INLINE_VERSION](_Hashtable<>::_M_last): New, the container 
last node.

    (_Hashtable<>::_HintPolicy): New.
    (_Hashtable<>::_M_get_hint(__node_ptr)): New.
    (_Hashtable<>::_M_get_hint_policy(__node_ptr)): New.
(_Hashtable<>::_M_check_for_last(__node_base_ptr)): New.
    (_Hashtable<>::_M_set_last(__node_ptr)): New.
    (_Hashtable<>::_M_get_last()): New.
    (_Hashtable<>::_M_compute_hash_code(__node_ptr, const 
key_type&)): Remove.

    (_Hashtable<>::_InsertInfo): New struct.
    (_Hashtable<>::_M_get_insert_info): New, return latter.
(_Hashtable<>::operator=(initializer_list<>)): Adapt to instantiate a 
_HintPolicy.
    (_Hashtable<>::_M_insert_bucket_begin): Add _HintPolicy& 
parameter and use it

    to optimize insertion in an empty bucket.
    (_Hashtable<>::_M_insert_unique_node): Add _HintPolicy& 
parameter.
    (_Hashtable<>::_M_insert_multi_node): Likewise and add 
_InsertInfo parameter.

(_Hashtable<>::_M_emplace_unique(_HintPolicy&, _Args&&...)): New.
(_Hashtable<>::_M_emplace_multi(_HintPolicy&, _Args&&...)): New.
    (_Hashtable<>::_M_emplace): Adapt to use latters.
    (_Hashtable<>::_M_insert_unique): Add _HintPolicy& parameter.
    (_Hashtable<>::_M_insert_unique_aux): Add _HintPolicy& 
parameter.

    (_Hashtable<>::_M_insert): Adapt to use latter.
    (_Hashtable<>::emplace_hint(const_iterator, _Args&&...)): 
Adapt.

    (_hashtable<>::rehash(size_type)): Adapt.
    (_Hashtable<>::_M_reinsert_node(const_iterator, node_type&&)):
    Add hint parameter, adapt to use it for _HintPolicy 
instantiation.

    (_Hashtable<>::_M_reinsert_node_multi): Likewise.
    (_Hashtable<>::_M_merge_unique): Adapt.
    (_Hashtable<>::_M_rehash): Add _HintPolicy& parameter.
    (_Hashtable<>::_Hashtable<_InputIte>()): Adapt.
    (_Hashtable<>::_M_assign): Call _M_set_last.
    (_Hashtable<>::_M_reset()): Reset _M_last.
(_Hashtable<>::_M_move_assign(_Hashtable&&, true_type)): Move _M_last.
    (_Hashtable<>(_Hashtable&&, __node_alloc_type&&, 
true_type)): Copy _M_last.
    (_Hashtable<>(_Hashtable&&, __node_alloc_type&&, 
false_type)): Copy _M_last.

    (_Hashtable<>::_M_insert_range): Adapt.
    (_Hashtable<>::_M_erase): Call _M_check_for_last.
    (_Hashtable<>::erase): Likewise.
    * include/bits/hashtable_policy.h:
    (_Map_base<>::operator[](const key_type&)): Use hint policy.
    (_Map_base<>::operator[](key_type&&)): Likewise.
    (_Insert_base<>::insert(const_iterator, const 
value_type&)): Likewise using hint.

    (_Insert_base<>::try_emplace): Likewise.
(_Insert_base<>::_M_insert_range<>(_InputIte, _InputIte, true_type)): 
Use hint policy.
(_Insert_base<>::_M_insert_range<>(_InputIte, _InputIte, false_type)): 
Use hint policy.

    (_Insert<>::insert(const_iterator, value_type&&)): Likewise.
    * include/bits/unordered_map.h 
(unordered_map<>::insert(node_type&&)): Pass cend as

    hint.
    (unordered_map<>::insert(const_iterator, node_type&&)): 
Adapt to use hint.

[PATCH 3/5][_Hashtable] Avoid redundant usage of rehash policy

2023-11-23 Thread François Dumont

    libstdc++: [_Hashtable] Avoid redundant usage of rehash policy

    Bypass call to __detail::__distance_fwd and the check if rehash is 
needed when
    assigning an initializer_list to an unordered_multimap or 
unordered_multiset.


    libstdc++-v3/ChangeLog:

    * include/bits/hashtable.h
    (_Hashtable<>::_M_insert_range(_InputIte, _InputIte, 
_NodeGen&)): New.

(_Hashtable<>::operator=(initializer_list)): Use latter.
    (_Hashtable<>::_Hashtable(_InputIte, _InputIte, size_type, 
const _Hash&, const _Equal&,

    const allocator_type&, false_type)): Use latter.
    * include/bits/hashtable_policy.h
    (_Insert_base<>::_M_insert_range(_InputIte, _InputIte, 
true_type)): Use latter.
    (_Insert_base<>::_M_insert_range(_InputIte, _InputIte, 
false_type)): Likewise.


Tested under Linux x64

Ok to commit ?

François
diff --git a/libstdc++-v3/include/bits/hashtable.h 
b/libstdc++-v3/include/bits/hashtable.h
index 8329d32e68e..771ed9968f7 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -612,7 +612,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
if (_M_bucket_count < __l_bkt_count)
  rehash(__l_bkt_count);
 
-   this->_M_insert_range(__l.begin(), __l.end(), __roan, __unique_keys{});
+   _M_insert_range(__l.begin(), __l.end(), __roan);
return *this;
   }
 
@@ -985,6 +985,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_insert(const_iterator, _Arg&&,
  _NodeGenerator&, false_type __uks);
 
+  template
+   void
+   _M_insert_range(_InputIterator __first, _InputIterator __last,
+   _NodeGenerator&);
+
   size_type
   _M_erase(true_type __uks, const key_type&);
 
@@ -1263,8 +1268,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  }
 
__alloc_node_gen_t __node_gen(*this);
-   for (; __f != __l; ++__f)
- _M_insert(*__f, __node_gen, __uks);
+   _M_insert_range(__f, __l, __node_gen);
   }
 
   template
+template
+  void
+  _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal,
+_Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
+  _M_insert_range(_InputIterator __first, _InputIterator __last,
+ _NodeGenerator& __node_gen)
+  {
+   for (; __first != __last; ++__first)
+ _M_insert(*__first, __node_gen, __unique_keys{});
+  }
+
   template(this)); }
 
-  template
+  template
void
_M_insert_range(_InputIterator __first, _InputIterator __last,
-   _NodeGetter&, true_type __uks);
+   true_type __uks);
 
-  template
+  template
void
_M_insert_range(_InputIterator __first, _InputIterator __last,
-   _NodeGetter&, false_type __uks);
+   false_type __uks);
 
 public:
   using iterator = _Node_iterator<_Value, __constant_iterators::value,
@@ -997,41 +997,37 @@ namespace __detail
   template
void
insert(_InputIterator __first, _InputIterator __last)
-   {
- __hashtable& __h = _M_conjure_hashtable();
- __node_gen_type __node_gen(__h);
- return _M_insert_range(__first, __last, __node_gen, __unique_keys{});
-   }
+   { _M_insert_range(__first, __last, __unique_keys{}); }
 };
 
   template
-template
+template
   void
   _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
   _Hash, _RangeHash, _Unused,
   _RehashPolicy, _Traits>::
   _M_insert_range(_InputIterator __first, _InputIterator __last,
- _NodeGetter& __node_gen, true_type __uks)
+ true_type /* __uks */)
   {
__hashtable& __h = _M_conjure_hashtable();
-   for (; __first != __last; ++__first)
- __h._M_insert(*__first, __node_gen, __uks);
+   __node_gen_type __node_gen(__h);
+   __h._M_insert_range(__first, __last, __node_gen);
   }
 
   template
-template
+template
   void
   _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
   _Hash, _RangeHash, _Unused,
   _RehashPolicy, _Traits>::
   _M_insert_range(_InputIterator __first, _InputIterator __last,
- _NodeGetter& __node_gen, false_type __uks)
+ false_type __uks)
   {
using __rehash_guard_t = typename __hashtable::__rehash_guard_t;
using __pair_type = std::pair;
@@ -1051,8 +1047,8 @@ namespace __detail
  __h._M_rehash(__do_rehash.second, __uks);
 
__rehash_guard._M_guarded_obj = nullptr;
-   for (; __first != __last; ++__first)
- __h._M_insert(*__first, __node_gen, __uks);
+   __node_gen_type __node_gen(__h);
+   __h._M_insert_range(__first, __last, __node_gen);
   }
 
   /**


[PATCH 2/5][_Hashtable] Fix implementation inconsistencies

2023-11-23 Thread François Dumont

    libstdc++: [_Hashtable] Fix some implementation inconsistencies

    Get rid of the different usages of the mutable keyword. For
    _Prime_rehash_policy methods are exported from the library, we need to
    keep their const qualifier, so adapt implementation to update 
previously

    mutable member.

    Remove useless noexcept qualification on _Hashtable _M_bucket_index 
overload.
    Fix comment to explain that we need the computation of bucket index 
to be

    noexcept to be able to rehash the container when needed. For Standard
    instantiations through std::unordered_xxx containers we already force
    usage of hash code cache when hash functor is not noexcep so it is 
guarantied.
    The static_assert purpose in _Hashtable on _M_bucket_index is thus 
limited

    to usages of _Hashtable with exotic _Hashtable_traits.

    libstdc++-v3/ChangeLog:

    * include/bits/hashtable_policy.h 
(_NodeBuilder<>::_S_build): Remove

    const qualification on _NodeGenerator instance.
(_ReuseOrAllocNode<>::operator()(_Args&&...)): Remove const qualification.
    (_ReuseOrAllocNode<>::_M_nodes): Remove mutable.
    (_Prime_rehash_policy::max_load_factor()): Remove noexcept.
    (_Prime_rehash_policy::_M_reset()): Remove noexcept.
    (_Prime_rehash_policy::_M_next_resize): Remove mutable.
    (_Power2_rehash_policy::_M_next_bkt(size_t)): Remove noexcept.
    (_Power2_rehash_policy::_M_bkt_for_elements(size_t)): 
Remove noexcept.

    (_Power2_rehash_policy::_M_neeed_rehash): Remove noexcept.
    (_Power2_rehash_policy::_M_reset): Remove noexcept.
    (_Insert_base<>::_M_insert_range): Remove _NodeGetter const 
qualification.
    (_Hash_code_base<>::_M_bucket_index(const 
_Hash_node_value<>&, size_t)):
    Simplify noexcept declaration, we already static_assert 
that _RangeHash functor

    is noexcept.
    * include/bits/hashtable.h: Rework comments. Remove const 
qualifier on

    _NodeGenerator& arguments.
    (_Hashtable<>::_M_bucket_index(const __node_value_type&)): 
Remove useless

    noexcept qualification.
    * src/c++11/hashtable_c++0x.cc (_Prime_rehash_policy): 
Workaround

    _M_next_resize not being mutable anymore.

Tested under Linux x86_64,

ok to commit ?

François
diff --git a/libstdc++-v3/include/bits/hashtable.h 
b/libstdc++-v3/include/bits/hashtable.h
index 9ff9104a2ab..8329d32e68e 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -48,7 +48,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 using __cache_default
   =  __not_<__and_,
-  // Mandatory to have erase not throwing.
+  // Mandatory for the rehash process.
   __is_nothrow_invocable>>;
 
   // Helper to conditionally delete the default constructor.
@@ -477,7 +477,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
void
-   _M_assign(_Ht&&, const _NodeGenerator&);
+   _M_assign(_Ht&&, _NodeGenerator&);
 
   void
   _M_move_assign(_Hashtable&&, true_type);
@@ -792,7 +792,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 private:
   // Bucket index computation helpers.
   size_type
-  _M_bucket_index(const __node_value_type& __n) const noexcept
+  _M_bucket_index(const __node_value_type& __n) const
   { return __hash_code_base::_M_bucket_index(__n, _M_bucket_count); }
 
   size_type
@@ -920,7 +920,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
std::pair
-   _M_insert_unique(_Kt&&, _Arg&&, const _NodeGenerator&);
+   _M_insert_unique(_Kt&&, _Arg&&, _NodeGenerator&);
 
   template
static __conditional_t<
@@ -940,7 +940,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
std::pair
-   _M_insert_unique_aux(_Arg&& __arg, const _NodeGenerator& __node_gen)
+   _M_insert_unique_aux(_Arg&& __arg, _NodeGenerator& __node_gen)
{
  return _M_insert_unique(
_S_forward_key(_ExtractKey{}(std::forward<_Arg>(__arg))),
@@ -949,7 +949,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
std::pair
-   _M_insert(_Arg&& __arg, const _NodeGenerator& __node_gen,
+   _M_insert(_Arg&& __arg, _NodeGenerator& __node_gen,
  true_type /* __uks */)
{
  using __to_value
@@ -960,7 +960,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
iterator
-   _M_insert(_Arg&& __arg, const _NodeGenerator& __node_gen,
+   _M_insert(_Arg&& __arg, _NodeGenerator& __node_gen,
  false_type __uks)
{
  using __to_value
@@ -973,7 +973,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
iterator
_M_insert(const_iterator, _Arg&& __arg,
- const _NodeGenerator& __node_gen, true_type __uks)
+ _NodeGenerator& __node_gen, true_type __uks)
{
   

[PATCH 1/5][_Hashtable] Add benches

2023-11-23 Thread François Dumont

libstdc++: [_Hashtable] Enhance/Add performance benches

diff --git a/libstdc++-v3/testsuite/performance/23_containers/insert/54075.cc 
b/libstdc++-v3/testsuite/performance/23_containers/insert/54075.cc
index f8fcce31609..f2d975ecdaf 100644
--- a/libstdc++-v3/testsuite/performance/23_containers/insert/54075.cc
+++ b/libstdc++-v3/testsuite/performance/23_containers/insert/54075.cc
@@ -17,12 +17,14 @@
 
 // { dg-do run { target c++11 } }
 
-#include 
+#include 
 #include 
 #include 
 #include 
 #include 
 
+#include 
+
 #define USE_MY_FOO 1
 
 struct Foo
@@ -71,10 +73,13 @@ struct HashFunction
 };
 
 const int sz = 30;
+const int usz = sz / 2;
 
 template
   void
-  bench(const char* container_desc, const typename _ContType::value_type* foos)
+  bench(const char* container_desc,
+   const typename _ContType::value_type* foos,
+   const typename _ContType::value_type* ufoos)
   {
 using namespace __gnu_test;
 
@@ -106,6 +111,51 @@ template
 ostr << container_desc << nb_loop << " times insertion of "
 << sz << " elements";
 report_performance(__FILE__, ostr.str().c_str(), time, resource);
+
+// Try to lookup for mostly unknown entries.
+start_counters(time, resource);
+
+int fcount = 0;
+for (int j = 0; j != nb_loop; ++j)
+  for (int i = 0; i != usz; ++i)
+   fcount += s.find(ufoos[i]) != s.end() ? 1 : 0;
+
+stop_counters(time, resource);
+ostr.str("");
+ostr << container_desc << nb_loop << " times lookup of "
+<< usz << " elements " << fcount / nb_loop << " found";
+report_performance(__FILE__, ostr.str().c_str(), time, resource);
+
+// Try again the previous operations but on a copy with potentially
+// less memory fragmentation.
+_ContType scopy(s);
+
+// Try to insert again to check performance of collision detection
+start_counters(time, resource);
+
+for (int j = 0; j != nb_loop; ++j)
+  for (int i = 0; i != sz; ++i)
+   scopy.insert(foos[i]);
+
+stop_counters(time, resource);
+ostr.str("");
+ostr << container_desc << nb_loop << " times insertion of "
+<< sz << " elements in copy";
+report_performance(__FILE__, ostr.str().c_str(), time, resource);
+
+// Try to lookup for mostly unknown entries.
+start_counters(time, resource);
+
+fcount = 0;
+for (int j = 0; j != nb_loop; ++j)
+  for (int i = 0; i != usz; ++i)
+   fcount += scopy.find(ufoos[i]) != scopy.end() ? 1 : 0;
+
+stop_counters(time, resource);
+ostr.str("");
+ostr << container_desc << nb_loop << " times lookup of "
+<< usz << " elements " << fcount / nb_loop << " found";
+report_performance(__FILE__, ostr.str().c_str(), time, resource);
   }
 
 template
@@ -155,67 +205,78 @@ int main()
 
   {
 int bars[sz];
+int ubars[usz];
 for (int i = 0; i != sz; ++i)
   bars[i] = i;
+for (int i = 0; i != usz; ++i)
+  ubars[i] = sz + i;
 bench>(
-   "std::tr1::unordered_set ", bars);
+  "std::tr1::unordered_set ", bars, ubars);
 bench>(
-   "std::unordered_set ", bars);
+  "std::unordered_set ", bars, ubars);
   }
 
-  Foo foos[sz];
-#if USE_MY_FOO
   {
-std::random_device randev;
-for (int i = 0; i != sz; ++i)
-  foos[i].init(randev);
-  }
+Foo foos[sz];
+Foo ufoos[usz];
+#if USE_MY_FOO
+{
+  std::random_device randev;
+  for (int i = 0; i != sz; ++i)
+   foos[i].init(randev);
+  for (int i = 0; i != usz; ++i)
+   ufoos[i].init(randev);
+}
 #endif
 
-  time_counter time;
-  resource_counter resource;
-  start_counters(time, resource);
-
-  bench<__tr1_uset>(
-   "std::tr1::unordered_set without hash code cached ", foos);
-  bench<__tr1_uset>(
-   "std::tr1::unordered_set with hash code cached ", foos);
-  bench<__tr1_umset>(
-   "std::tr1::unordered_multiset without hash code cached ", foos);
-  bench<__tr1_umset>(
-   "std::tr1::unordered_multiset with hash code cached ", foos);
-
-  stop_counters(time, resource);
-  report_performance(__FILE__, "tr1 benches", time, resource);
-
-  start_counters(time, resource);
-  bench<__uset>(
-   "std::unordered_set without hash code cached ", foos);
-  bench<__uset>(
-   "std::unordered_set with hash code cached ", foos);
-  bench<__umset>(
-   "std::unordered_multiset without hash code cached ", foos);
-  bench<__umset>(
-   "std::unordered_multiset with hash code cached ", foos);
-
-  stop_counters(time, resource);
-  report_performance(__FILE__, "std benches", time, resource);
-
-  start_counters(time, resource);
-  bench<__uset2>(
-   "std::unordered_set2 without hash code cached ", foos);
-  bench<__uset2>(
-   "std::unordered_set2 with hash code cached ", foos);
-  bench<__umset2>(
-   "std::unordered_multiset2 without hash code cached ", foos);
-  bench<__umset2>(
-   "std::unordered_multiset2 with hash code cached ", foos);
-
-  stop_counters(time, resource);
-  

[PATCH 0/5][_Hashtable] Optimize insertions

2023-11-23 Thread François Dumont
This is a series of patch to enhance _Hashtable insertion operations 
that I'd like to see in gcc 14. I've already submitted something similar 
a couple of months ago but it is quite a revisited version.


1/5 Is adding benches to show the impact of the different optimizations

2/5 Implementation inconsistencies fixes already submitted individually.

3/5 Avoid redundant rehash check on unordered_multi[map/set]

4/5 Extend the small size optimization to all methods

5/5 Insert node for empty bucket after last rather than before-begin

The last patch of the series will require to bump version namespace but 
it is already plan for the cxx11 abi adoption in this mode.


I still need to run the benches that I've already run previously on this 
new version of the patches.


Successfully tested in normal and gnu-versioned namespace modes.

François



[PATCH] Fix some _Hashtable implementation inconsistencies

2023-11-14 Thread François Dumont
Following several remarks on a previous patch of _Hashtable I considered 
clarifying its implementation.


    libstdc++: [_Hashtable] Fix some implementation inconsistencies

    Get rid of the different usages of the mutable keyword. For
    _Prime_rehash_policy methods are exported from the library, we need to
    keep their const qualifier, so adapt implementation to update 
previously

    mutable member.

    Remove useless noexcept qualification on _Hashtable _M_bucket_index 
overload.
    Fix comment to explain that we need the computation of bucket index 
to be

    noexcept to be able to rehash the container when needed. For Standard
    instantiations through std::unordered_xxx containers we already force
    usage of hash code cache when hash functor is not noexcep so it is 
guarantied.
    The static_assert purpose in _Hashtable on _M_bucket_index is thus 
limited

    to usages of _Hashtable with exotic _Hashtable_traits.

    libstdc++-v3/ChangeLog:

    * include/bits/hashtable_policy.h 
(_NodeBuilder<>::_S_build): Remove

    const qualification on _NodeGenerator instance.
(_ReuseOrAllocNode<>::operator()(_Args&&...)): Remove const qualification.
    (_ReuseOrAllocNode<>::_M_nodes): Remove mutable.
    (_Prime_rehash_policy::max_load_factor()): Remove noexcept.
    (_Prime_rehash_policy::_M_reset()): Remove noexcept.
    (_Prime_rehash_policy::_M_next_resize): Remove mutable.
    (_Power2_rehash_policy::_M_next_bkt(size_t)): Remove noexcept.
    (_Power2_rehash_policy::_M_bkt_for_elements(size_t)): 
Remove noexcept.

    (_Power2_rehash_policy::_M_neeed_rehash): Remove noexcept.
    (_Power2_rehash_policy::_M_reset): Remove noexcept.
    (_Insert_base<>::_M_insert_range): Remove _NodeGetter const 
qualification.
    (_Hash_code_base<>::_M_bucket_index(const 
_Hash_node_value<>&, size_t)):
    Simplify noexcept declaration, we already static_assert 
that _RangeHash functor

    is noexcept.
    * include/bits/hashtable.h: Rework comments. Remove const 
qualifier on

    _NodeGenerator& arguments.
    (_Hashtable<>::_M_bucket_index(const __node_value_type&)): 
Remove useless

    noexcept qualification.
    * src/c++11/hashtable_c++0x.cc (_Prime_rehash_policy): 
Workaround

    _M_next_resize not being mutable anymore.

Tested under Linux x86_64,

ok to commit ?

François
diff --git a/libstdc++-v3/include/bits/hashtable.h 
b/libstdc++-v3/include/bits/hashtable.h
index 89132430f3e..8d462ce7bd5 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -51,7 +51,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 using __cache_default
   =  __not_<__and_,
-  // Mandatory to have erase not throwing.
+  // Mandatory for the rehash process.
   __is_nothrow_invocable>>;
 
   // Helper to conditionally delete the default constructor.
@@ -480,7 +480,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
void
-   _M_assign(_Ht&&, const _NodeGenerator&);
+   _M_assign(_Ht&&, _NodeGenerator&);
 
   void
   _M_move_assign(_Hashtable&&, true_type);
@@ -795,7 +795,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 private:
   // Bucket index computation helpers.
   size_type
-  _M_bucket_index(const __node_value_type& __n) const noexcept
+  _M_bucket_index(const __node_value_type& __n) const
   { return __hash_code_base::_M_bucket_index(__n, _M_bucket_count); }
 
   size_type
@@ -923,7 +923,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
std::pair
-   _M_insert_unique(_Kt&&, _Arg&&, const _NodeGenerator&);
+   _M_insert_unique(_Kt&&, _Arg&&, _NodeGenerator&);
 
   template
static __conditional_t<
@@ -943,7 +943,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
std::pair
-   _M_insert_unique_aux(_Arg&& __arg, const _NodeGenerator& __node_gen)
+   _M_insert_unique_aux(_Arg&& __arg, _NodeGenerator& __node_gen)
{
  return _M_insert_unique(
_S_forward_key(_ExtractKey{}(std::forward<_Arg>(__arg))),
@@ -952,7 +952,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
std::pair
-   _M_insert(_Arg&& __arg, const _NodeGenerator& __node_gen,
+   _M_insert(_Arg&& __arg, _NodeGenerator& __node_gen,
  true_type /* __uks */)
{
  using __to_value
@@ -963,7 +963,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
iterator
-   _M_insert(_Arg&& __arg, const _NodeGenerator& __node_gen,
+   _M_insert(_Arg&& __arg, _NodeGenerator& __node_gen,
  false_type __uks)
{
  using __to_value
@@ -976,7 +976,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template
iterator
_M_insert(const_iterator, _Arg&& __arg,
- const 

[PATCH][_Hahstable] Use RAII to guard node pointer while constructing

2023-11-08 Thread François Dumont

Another proposal to use RAII rather than __try/__catch block.

libstdc++: [_Hashtable] Use RAII type to guard node while constructing value

libstdc++-v3/ChangeLog:

    * include/bits/hashtable_policy.h
    (struct _NodePtrGuard<_HashtableAlloc, _NodePtr>): New.
    (_ReuseAllocNode::operator()(_Args&&...)): Use latter to guard 
allocated node

    pointer while constructing in place the value_type instance.

Tested under Linux x64, ok to commit ?

François
diff --git a/libstdc++-v3/include/bits/hashtable_policy.h 
b/libstdc++-v3/include/bits/hashtable_policy.h
index cd8943d8d05..c67eebd3b2b 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -173,6 +173,19 @@ namespace __detail
{ return __node_gen(std::forward<_Kt>(__k)); }
 };
 
+  template
+struct _NodePtrGuard
+{
+  _HashtableAlloc& _M_h;
+  _NodePtr _M_ptr;
+
+  ~_NodePtrGuard()
+  {
+   if (_M_ptr)
+ _M_h._M_deallocate_node_ptr(_M_ptr);
+  }
+};
+
   template
 struct _Hashtable_alloc;
 
@@ -201,27 +214,20 @@ namespace __detail
__node_ptr
operator()(_Args&&... __args) const
{
- if (_M_nodes)
-   {
+ if (!_M_nodes)
+   return _M_h._M_allocate_node(std::forward<_Args>(__args)...);
+
  __node_ptr __node = _M_nodes;
  _M_nodes = _M_nodes->_M_next();
  __node->_M_nxt = nullptr;
  auto& __a = _M_h._M_node_allocator();
  __node_alloc_traits::destroy(__a, __node->_M_valptr());
- __try
-   {
+ _NodePtrGuard<__hashtable_alloc, __node_ptr> __guard { _M_h, __node };
  __node_alloc_traits::construct(__a, __node->_M_valptr(),
 std::forward<_Args>(__args)...);
-   }
- __catch(...)
-   {
- _M_h._M_deallocate_node_ptr(__node);
- __throw_exception_again;
-   }
+ __guard._M_ptr = nullptr;
  return __node;
}
- return _M_h._M_allocate_node(std::forward<_Args>(__args)...);
-   }
 
 private:
   mutable __node_ptr _M_nodes;


Re: [PATCH][_Hashtable] Add missing destructor call

2023-11-07 Thread François Dumont



On 07/11/2023 00:28, Jonathan Wakely wrote:

On Mon, 6 Nov 2023 at 21:39, François Dumont  wrote:

Noticed looking for other occasion to replace __try/__catch with RAII
helper.

  libstdc++: [_Hashtable] Add missing node destructor call

  libstdc++-v3/ChangeLog:

  * include/bits/hashtable_policy.h
  (_Hashtable_alloc<>::_M_allocate_node): Add missing call to
node destructor
  on construct exception.

Tested under Linux x64, ok to commit ?

OK.

Is this missing on any branches too?

Clearly all maintained branches.

I don't think it's actually a problem, since it's a trivial destructor anyway.


Yes, me neither, I was only thinking about sanity checker tools when 
doing this so no plan for backports.




[PATCH][_Hashtable] Add missing destructor call

2023-11-06 Thread François Dumont
Noticed looking for other occasion to replace __try/__catch with RAII 
helper.


    libstdc++: [_Hashtable] Add missing node destructor call

    libstdc++-v3/ChangeLog:

    * include/bits/hashtable_policy.h
    (_Hashtable_alloc<>::_M_allocate_node): Add missing call to 
node destructor

    on construct exception.

Tested under Linux x64, ok to commit ?

I hope gmail appli will appreciate .diff instead of .patch. .txt are not 
in .gitignore so annoying to use for patches.


François
diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h
index 2d13bda6ae0..ed2b2c02a4a 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -2020,19 +2020,20 @@ namespace __detail
   _Hashtable_alloc<_NodeAlloc>::_M_allocate_node(_Args&&... __args)
   -> __node_ptr
   {
-	auto __nptr = __node_alloc_traits::allocate(_M_node_allocator(), 1);
+	auto& __alloc = _M_node_allocator();
+	auto __nptr = __node_alloc_traits::allocate(__alloc, 1);
 	__node_ptr __n = std::__to_address(__nptr);
 	__try
 	  {
 	::new ((void*)__n) __node_type;
-	__node_alloc_traits::construct(_M_node_allocator(),
-	   __n->_M_valptr(),
+	__node_alloc_traits::construct(__alloc, __n->_M_valptr(),
 	   std::forward<_Args>(__args)...);
 	return __n;
 	  }
 	__catch(...)
 	  {
-	__node_alloc_traits::deallocate(_M_node_allocator(), __nptr, 1);
+	__n->~__node_type();
+	__node_alloc_traits::deallocate(__alloc, __nptr, 1);
 	__throw_exception_again;
 	  }
   }


Re: [committed][_GLIBCXX_INLINE_VERSION] Fix constract violation

2023-10-30 Thread François Dumont



On 30/10/2023 14:45, Jonathan Wakely wrote:

On Sun, 29 Oct 2023 at 21:11, François Dumont  wrote:

This fixes handle_contract_violation under versioned namespace mode.

Tested under Linux x64 and confirmed to also fix Darwin build.

libstdc++: [_GLIBCXX_INLINE_VERSION] Provide handle_contract_violation
symbol

libstdc++-v3/ChangeLog:

  * src/experimental/contract.cc
  [_GLIBCXX_INLINE_VERSION](handle_contract_violation): Provide
symbol
  without version namespace decoration for gcc.
+#if _GLIBCXX_INLINE_VERSION
+// Provide symbol without version namespace decoration for gcc.

For the comment in the code, I think this would be better:

// The compiler expects the contract_violation class to be in an unversioned
// namespace, so provide a forwarding function with the expected symbol name.

Sure, I'll update it.

Do we want the forwarding function to be a weak symbol? The main
handler function is weak because we want users to be able to override
it with their own handler. But for this new forwarding function, they
can't even declare it (because it has a reserved name that doesn't
demangle to a valid type for the versioned namespace build).


Good point, I see no reason neither so I'll remove it.



Re: [committed][_GLIBCXX_INLINE_VERSION] Add emul TLS symbol exports

2023-10-30 Thread François Dumont



On 30/10/2023 14:58, Jonathan Wakely wrote:

On Sun, 29 Oct 2023 at 21:25, François Dumont  wrote:

libstdc++: [_GLIBCXX_INLINE_VERSION] Add emul TLS symbols

libstdc++-v3/ChangeLog:

  * config/abi/pre/gnu-versioned-namespace.ver: Add missing emul TLS
  symbols.


Please put a comment above the two new lines, the same as in gnu.ver:

# targets using emutls

OK with that change, thanks.


It's already committed as it was a trivial change limited to the 
versioned namespace special mode for which I'm maintainer.


Can you confirm you want a new commit just to add this comment ?




[committed][_GLIBCXX_INLINE_VERSION] Add emul TLS symbol exports

2023-10-29 Thread François Dumont

libstdc++: [_GLIBCXX_INLINE_VERSION] Add emul TLS symbols

libstdc++-v3/ChangeLog:

    * config/abi/pre/gnu-versioned-namespace.ver: Add missing emul TLS
    symbols.

François
diff --git a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
index 9fab8bead15..3140a9628d8 100644
--- a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
+++ b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
@@ -78,6 +78,8 @@ GLIBCXX_8.0 {
 
 # thread/mutex/condition_variable/future
 __once_proxy;
+__emutls_v._ZSt3__811__once_call;
+__emutls_v._ZSt3__815__once_callable;
 
 # std::__convert_to_v
 _ZNSt3__814__convert_to_v*;


[committed][_GLIBCXX_INLINE_VERSION] Fix constract violation

2023-10-29 Thread François Dumont

This fixes handle_contract_violation under versioned namespace mode.

Tested under Linux x64 and confirmed to also fix Darwin build.

libstdc++: [_GLIBCXX_INLINE_VERSION] Provide handle_contract_violation 
symbol


libstdc++-v3/ChangeLog:

    * src/experimental/contract.cc
    [_GLIBCXX_INLINE_VERSION](handle_contract_violation): Provide 
symbol

    without version namespace decoration for gcc.

François
diff --git a/libstdc++-v3/src/experimental/contract.cc b/libstdc++-v3/src/experimental/contract.cc
index 504a6c041f1..d550b49c4eb 100644
--- a/libstdc++-v3/src/experimental/contract.cc
+++ b/libstdc++-v3/src/experimental/contract.cc
@@ -67,3 +67,11 @@ handle_contract_violation (const std::experimental::contract_violation 
   std::cerr << std::endl;
 #endif
 }
+
+#if _GLIBCXX_INLINE_VERSION
+// Provide symbol without version namespace decoration for gcc.
+extern "C" __attribute__ ((weak)) void
+_Z25handle_contract_violationRKNSt12experimental18contract_violationE
+(const std::experimental::contract_violation )
+{ handle_contract_violation(violation); }
+#endif


Re: [PATCH][_Hashtable] Use RAII to restore Rehash state

2023-10-26 Thread François Dumont


On 26/10/2023 12:43, Jonathan Wakely wrote:

On 26/10/23 07:18 +0200, François Dumont wrote:

    libstdc++: [_Hashtable] Use RAII type to manage rehash functor state

    Replace usage of __try/__catch with a RAII type to restore rehash 
functor

    state when needed.


Generally I really like replacing try-catch with RAII but I have some
questions below.


    libstdc++-v3/ChangeLog:

    * include/bits/hashtable_policy.h (_RehashStateGuard): New.
    (_Insert_base<>::_M_insert_range(_IIt, _IIt, const 
_NodeGet&, false_type)):

    Adapt.
    * include/bits/hashtable.h (__rehash_guard_t): New.
    (__rehash_state): Remove.
    (_M_rehash): Remove.
    (_M_rehash_aux): Rename into _M_rehash.
    (_M_assign_elements, _M_insert_unique_node, 
_M_insert_multi_node): Adapt.

    (rehash): Adapt.


Tested under Linux x64.

Ok to commit ?

François


diff --git a/libstdc++-v3/include/bits/hashtable.h 
b/libstdc++-v3/include/bits/hashtable.h

index 0857448f7ed..64071ac1fb2 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -234,6 +234,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  _RehashPolicy, _Traits>;
  using __enable_default_ctor
= _Hashtable_enable_default_ctor<_Equal, _Hash, _Alloc>;
+  using __rehash_guard_t
+    = __detail::_RehashStateGuard<_RehashPolicy>;

    public:
  typedef _Key    key_type;
@@ -264,7 +266,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION

    private:
  using __rehash_type = _RehashPolicy;
-  using __rehash_state = typename __rehash_type::_State;

  using __unique_keys = typename __traits_type::__unique_keys;

@@ -1200,14 +1201,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION

    private:
  // Helper rehash method used when keys are unique.
-  void _M_rehash_aux(size_type __bkt_count, true_type __uks);
+  void _M_rehash(size_type __bkt_count, true_type __uks);

  // Helper rehash method used when keys can be non-unique.
-  void _M_rehash_aux(size_type __bkt_count, false_type __uks);
-
-  // Unconditionally change size of bucket array to n, restore
-  // hash policy state to __state on exception.
-  void _M_rehash(size_type __bkt_count, const __rehash_state& 
__state);

+  void _M_rehash(size_type __bkt_count, false_type __uks);
    };

  // Definitions of class template _Hashtable's out-of-line member 
functions.

@@ -1337,7 +1334,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  {
__buckets_ptr __former_buckets = nullptr;
std::size_t __former_bucket_count = _M_bucket_count;
-    const __rehash_state& __former_state = _M_rehash_policy._M_state();
+    __rehash_guard_t __rehash_guard(_M_rehash_policy);

if (_M_bucket_count != __ht._M_bucket_count)
  {
@@ -1359,6 +1356,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    _M_assign(std::forward<_Ht>(__ht), __roan);
    if (__former_buckets)
  _M_deallocate_buckets(__former_buckets, 
__former_bucket_count);

+    __rehash_guard._M_reset = false;


I find this confusing. Usually "reset" means that something is
cleared, so won't take an action in the destructor. e.g. if you use
std::unique_ptr::reset() then the object is destroyed immediately, and
then nothing happens in the destructor. Here it's the opposite,
_M_reset=true means that it _sould_ do something in the destructor.

The problem is the ambiguity between "reset the state in the
destructor later" and "reset the object to an empty state now".

If the member was called _M_guarded then it might be clearer.
_M_guarded=true means the guard is active, and will restore the state
later. Or _M_active, or _M_armed, or even _M_reset_in_dtor. Any of
those names avoids the confusion with the semantics of
std::unique_ptr::reset() and similar well-known APIs.

Or what I usually do is store a pointer to the guarded object in the
RAII guard type, and then just null the pointer to disarm the guard.
That means you don't need a separate bool member variable. If
_RehashStateGuard::_M_rehash_policy was called _M_guarded_obj and was
a _RehashPolicy* instead of _RehashPolicy& then disarming it would be:

   __rehash_guard._M_guarded_obj = nullptr;

This seems clear to me, as it says that the guard no longer has
anything to guard, so won't do anything in the destructor.


Looks clearer to me too.

I started with a _RehashStateScope and a _M_commit() method, it could 
have been worst :-)






  }
__catch(...)
  {
@@ -1366,7 +1364,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  {
    // Restore previous buckets.
    _M_deallocate_buckets();
-    _M_rehash_policy._M_reset(__former_state);
    _M_buckets = __former_buckets;
    _M_bucket_count = __former_bucket_count;
  }
@@ -2142,17 +2139,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  __node_ptr __node, size_type 

[PATCH][_Hashtable] Use RAII to restore Rehash state

2023-10-25 Thread François Dumont

    libstdc++: [_Hashtable] Use RAII type to manage rehash functor state

    Replace usage of __try/__catch with a RAII type to restore rehash 
functor

    state when needed.

    libstdc++-v3/ChangeLog:

    * include/bits/hashtable_policy.h (_RehashStateGuard): New.
    (_Insert_base<>::_M_insert_range(_IIt, _IIt, const 
_NodeGet&, false_type)):

    Adapt.
    * include/bits/hashtable.h (__rehash_guard_t): New.
    (__rehash_state): Remove.
    (_M_rehash): Remove.
    (_M_rehash_aux): Rename into _M_rehash.
    (_M_assign_elements, _M_insert_unique_node, 
_M_insert_multi_node): Adapt.

    (rehash): Adapt.


Tested under Linux x64.

Ok to commit ?

François
diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index 0857448f7ed..64071ac1fb2 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -234,6 +234,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  _RehashPolicy, _Traits>;
   using __enable_default_ctor
 	= _Hashtable_enable_default_ctor<_Equal, _Hash, _Alloc>;
+  using __rehash_guard_t
+	= __detail::_RehashStateGuard<_RehashPolicy>;
 
 public:
   typedef _Key		key_type;
@@ -264,7 +266,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 private:
   using __rehash_type = _RehashPolicy;
-  using __rehash_state = typename __rehash_type::_State;
 
   using __unique_keys = typename __traits_type::__unique_keys;
 
@@ -1200,14 +1201,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 private:
   // Helper rehash method used when keys are unique.
-  void _M_rehash_aux(size_type __bkt_count, true_type __uks);
+  void _M_rehash(size_type __bkt_count, true_type __uks);
 
   // Helper rehash method used when keys can be non-unique.
-  void _M_rehash_aux(size_type __bkt_count, false_type __uks);
-
-  // Unconditionally change size of bucket array to n, restore
-  // hash policy state to __state on exception.
-  void _M_rehash(size_type __bkt_count, const __rehash_state& __state);
+  void _M_rehash(size_type __bkt_count, false_type __uks);
 };
 
   // Definitions of class template _Hashtable's out-of-line member functions.
@@ -1337,7 +1334,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   {
 	__buckets_ptr __former_buckets = nullptr;
 	std::size_t __former_bucket_count = _M_bucket_count;
-	const __rehash_state& __former_state = _M_rehash_policy._M_state();
+	__rehash_guard_t __rehash_guard(_M_rehash_policy);
 
 	if (_M_bucket_count != __ht._M_bucket_count)
 	  {
@@ -1359,6 +1356,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	_M_assign(std::forward<_Ht>(__ht), __roan);
 	if (__former_buckets)
 	  _M_deallocate_buckets(__former_buckets, __former_bucket_count);
+	__rehash_guard._M_reset = false;
 	  }
 	__catch(...)
 	  {
@@ -1366,7 +1364,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  {
 		// Restore previous buckets.
 		_M_deallocate_buckets();
-		_M_rehash_policy._M_reset(__former_state);
 		_M_buckets = __former_buckets;
 		_M_bucket_count = __former_bucket_count;
 	  }
@@ -2142,17 +2139,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 			  __node_ptr __node, size_type __n_elt)
 -> iterator
 {
-  const __rehash_state& __saved_state = _M_rehash_policy._M_state();
+  __rehash_guard_t __rehash_guard(_M_rehash_policy);
   std::pair __do_rehash
 	= _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count,
 	  __n_elt);
 
   if (__do_rehash.first)
 	{
-	  _M_rehash(__do_rehash.second, __saved_state);
+	  _M_rehash(__do_rehash.second, true_type{});
 	  __bkt = _M_bucket_index(__code);
 	}
 
+  __rehash_guard._M_reset = false;
   this->_M_store_code(*__node, __code);
 
   // Always insert at the beginning of the bucket.
@@ -2172,13 +2170,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 			 __hash_code __code, __node_ptr __node)
 -> iterator
 {
-  const __rehash_state& __saved_state = _M_rehash_policy._M_state();
+  __rehash_guard_t __rehash_guard(_M_rehash_policy);
   std::pair __do_rehash
 	= _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1);
 
   if (__do_rehash.first)
-	_M_rehash(__do_rehash.second, __saved_state);
+	_M_rehash(__do_rehash.second, false_type{});
 
+  __rehash_guard._M_reset = false;
   this->_M_store_code(*__node, __code);
   const key_type& __k = _ExtractKey{}(__node->_M_v());
   size_type __bkt = _M_bucket_index(__code);
@@ -2509,39 +2508,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	   _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::
 rehash(size_type __bkt_count)
 {
-  const __rehash_state& __saved_state = _M_rehash_policy._M_state();
+  __rehash_guard_t __rehash_guard(_M_rehash_policy);
   __bkt_count
 	= std::max(_M_rehash_policy._M_bkt_for_elements(_M_element_count + 1),
 		   __bkt_count);
   __bkt_count = _M_rehash_policy._M_next_bkt(__bkt_count);
 
  

Re: [PATCH] sso-string@gnu-versioned-namespace [PR83077]

2023-10-23 Thread François Dumont

Hi

Still no one to complete this review ?

Thanks


On 07/10/2023 21:32, François Dumont wrote:
I've been told that previous patch generated with 'git diff -b' was 
not applying properly so here is the same patch again with a simple 
'git diff'.



On 07/10/2023 14:25, François Dumont wrote:

Hi

Here is a rebased version of this patch.

There are few test failures when running 'make check-c++' but nothing 
new.


Still, there are 2 patches awaiting validation to fix some of them, 
PR c++/111524 to fix another bunch and I fear that we will have to 
live with the others.


    libstdc++: [_GLIBCXX_INLINE_VERSION] Use cxx11 abi [PR83077]

    Use cxx11 abi when activating versioned namespace mode. To do 
support
    a new configuration mode where !_GLIBCXX_USE_DUAL_ABI and 
_GLIBCXX_USE_CXX11_ABI.


    The main change is that std::__cow_string is now defined whenever 
_GLIBCXX_USE_DUAL_ABI
    or _GLIBCXX_USE_CXX11_ABI is true. Implementation is using 
available std::string in

    case of dual abi and a subset of it when it's not.

    On the other side std::__sso_string is defined only when 
_GLIBCXX_USE_DUAL_ABI is true
    and _GLIBCXX_USE_CXX11_ABI is false. Meaning that 
std::__sso_string is a typedef for the
    cow std::string implementation when dual abi is disabled and cow 
string is being used.


    libstdcxx-v3/ChangeLog:

    PR libstdc++/83077
    * acinclude.m4 [GLIBCXX_ENABLE_LIBSTDCXX_DUAL_ABI]: 
Default to "new" libstdcxx abi

    when enable_symvers is gnu-versioned-namespace.
    * config/locale/dragonfly/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Define money_base

    members.
    * config/locale/generic/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Likewise.
    * config/locale/gnu/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Likewise.

    * config/locale/gnu/numeric_members.cc
    [!_GLIBCXX_USE_DUAL_ABI](__narrow_multibyte_chars): Define.
    * configure: Regenerate.
    * include/bits/c++config
    [_GLIBCXX_INLINE_VERSION](_GLIBCXX_NAMESPACE_CXX11, 
_GLIBCXX_BEGIN_NAMESPACE_CXX11):

    Define empty.
[_GLIBCXX_INLINE_VERSION](_GLIBCXX_END_NAMESPACE_CXX11, 
_GLIBCXX_DEFAULT_ABI_TAG):

    Likewise.
    * include/bits/cow_string.h [!_GLIBCXX_USE_CXX11_ABI]: 
Define a light version of COW

    basic_string as __std_cow_string for use in stdexcept.
    * include/std/stdexcept [_GLIBCXX_USE_CXX11_ABI]: Define 
__cow_string.

    (__cow_string(const char*)): New.
    (__cow_string::c_str()): New.
    * python/libstdcxx/v6/printers.py 
(StdStringPrinter::__init__): Set self.new_string to True

    when std::__8::basic_string type is found.
    * src/Makefile.am 
[ENABLE_SYMVERS_GNU_NAMESPACE](ldbl_alt128_compat_sources): Define 
empty.

    * src/Makefile.in: Regenerate.
    * src/c++11/Makefile.am (cxx11_abi_sources): Rename into...
    (dual_abi_sources): ...this. Also move cow-local_init.cc, 
cxx11-hash_tr1.cc,

    cxx11-ios_failure.cc entries to...
    (sources): ...this.
    (extra_string_inst_sources): Move cow-fstream-inst.cc, 
cow-sstream-inst.cc, cow-string-inst.cc,
    cow-string-io-inst.cc, cow-wtring-inst.cc, 
cow-wstring-io-inst.cc, cxx11-locale-inst.cc,

    cxx11-wlocale-inst.cc entries to...
    (inst_sources): ...this.
    * src/c++11/Makefile.in: Regenerate.
    * src/c++11/cow-fstream-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-locale_init.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-sstream-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-stdexcept.cc [_GLIBCXX_USE_CXX11_ABI]: 
Include .
    [_GLIBCXX_USE_DUAL_ABI || 
_GLIBCXX_USE_CXX11_ABI](__cow_string): Redefine before
    including . Define 
_GLIBCXX_DEFINE_STDEXCEPT_INSTANTIATIONS so that

    __cow_string definition in  is skipped.
    [_GLIBCXX_USE_CXX11_ABI]: Skip Transaction Memory TS 
definitions.
    * src/c++11/string-inst.cc: Add sizeof/alignof 
static_assert on stdexcept

    __cow_string definition.
    (_GLIBCXX_DEFINING_CXX11_ABI_INSTANTIATIONS): Define 
following _GLIBCXX_USE_CXX11_ABI

    value.
    [_GLIBCXX_USE_CXX11_ABI && 
!_GLIBCXX_DEFINING_CXX11_ABI_INSTANTIATIONS]:
    Define _GLIBCXX_DEFINING_COW_STRING_INSTANTIATIONS. 
Include .
    Define basic_string as __std_cow_string for the current 
translation unit.
    * src/c++11/cow-string-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-string-io-inst.cc 
[_GLIBCXX_USE_CXX11_ABI]: Skip definitions.
    * src/c++11/cow-wstring-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-

Re: [PATCH][_Hashtable] Fix merge

2023-10-19 Thread François Dumont

Committed with the advised changes.

Ok, I'll backport next week.

Thanks

On 19/10/2023 10:05, Jonathan Wakely wrote:



On Thursday, 19 October 2023, François Dumont  
wrote:

> libstdc++: [_Hashtable] Do not reuse untrusted cached hash code
>
> On merge reuse merged node cached hash code only if we are on the 
same type of
> hash and this hash is stateless. Usage of function pointers or 
std::function as

> hash functor will prevent this optimization.

I found this first sentence a little hard to parse. How about:

On merge, reuse a merged node's cached hash code only if we are on the 
same

type of
hash and this hash is stateless.


And for the second sentence, would it be clearer to say "will prevent 
reusing cached hash codes" instead of "will prevent this optimization"?



And for the comment on the new function, I think this reads better:

"Only use the node's (possibly cached) hash code if its hash function 
_H2 matches _Hash. Otherwise recompute it using _Hash."


The code and tests look good, so if you're happy with the 
comment+changelog suggestions, this is ok for trunk.


This seems like a bug fix that should be backported too, after some 
time on trunk.



>
> libstdc++-v3/ChangeLog
>
>     * include/bits/hashtable_policy.h
>     (_Hash_code_base::_M_hash_code(const _Hash&, const 
_Hash_node_value<>&)): Remove.
>     (_Hash_code_base::_M_hash_code<_H2>(const _H2&, const 
_Hash_node_value<>&)): Remove.

>     * include/bits/hashtable.h
>     (_M_src_hash_code<_H2>(const _H2&, const key_type&, const 
__node_value_type&)): New.

>     (_M_merge_unique<>, _M_merge_multi<>): Use latter.
>     * testsuite/23_containers/unordered_map/modifiers/merge.cc
>     (test04, test05, test06): New test cases.
>
> Tested under Linux x86_64, ok to commit ?
>
> François
>
> 

[PATCH][_Hashtable] Fix merge

2023-10-18 Thread François Dumont

libstdc++: [_Hashtable] Do not reuse untrusted cached hash code

On merge reuse merged node cached hash code only if we are on the same 
type of
hash and this hash is stateless. Usage of function pointers or 
std::function as

hash functor will prevent this optimization.

libstdc++-v3/ChangeLog

    * include/bits/hashtable_policy.h
    (_Hash_code_base::_M_hash_code(const _Hash&, const 
_Hash_node_value<>&)): Remove.
    (_Hash_code_base::_M_hash_code<_H2>(const _H2&, const 
_Hash_node_value<>&)): Remove.

    * include/bits/hashtable.h
    (_M_src_hash_code<_H2>(const _H2&, const key_type&, const 
__node_value_type&)): New.

    (_M_merge_unique<>, _M_merge_multi<>): Use latter.
    * testsuite/23_containers/unordered_map/modifiers/merge.cc
    (test04, test05, test06): New test cases.

Tested under Linux x86_64, ok to commit ?

François

diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index 4c12dc895b2..f69acfe5213 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -1109,6 +1109,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	return { __n, this->_M_node_allocator() };
   }
 
+  // Check and if needed compute hash code using _Hash as __n _M_hash_code,
+  // if present, was computed using _H2.
+  template
+	__hash_code
+	_M_src_hash_code(const _H2&, const key_type& __k,
+			 const __node_value_type& __src_n) const
+	{
+	  if constexpr (std::is_same_v<_H2, _Hash>)
+	if constexpr (std::is_empty_v<_Hash>)
+	  return this->_M_hash_code(__src_n);
+
+	  return this->_M_hash_code(__k);
+	}
+
 public:
   // Extract a node.
   node_type
@@ -1146,7 +1160,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  auto __pos = __i++;
 	  const key_type& __k = _ExtractKey{}(*__pos);
 	  __hash_code __code
-		= this->_M_hash_code(__src.hash_function(), *__pos._M_cur);
+		= _M_src_hash_code(__src.hash_function(), __k, *__pos._M_cur);
 	  size_type __bkt = _M_bucket_index(__code);
 	  if (_M_find_node(__bkt, __k, __code) == nullptr)
 		{
@@ -1174,8 +1188,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  for (auto __i = __src.cbegin(), __end = __src.cend(); __i != __end;)
 	{
 	  auto __pos = __i++;
+	  const key_type& __k = _ExtractKey{}(*__pos);
 	  __hash_code __code
-		= this->_M_hash_code(__src.hash_function(), *__pos._M_cur);
+		= _M_src_hash_code(__src.hash_function(), __k, *__pos._M_cur);
 	  auto __nh = __src.extract(__pos);
 	  __hint = _M_insert_multi_node(__hint, __code, __nh._M_ptr)._M_cur;
 	  __nh._M_ptr = nullptr;
diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h
index 86b32fb15f2..5d162463dc3 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -1319,19 +1319,6 @@ namespace __detail
 	  return _M_hash()(__k);
 	}
 
-  __hash_code
-  _M_hash_code(const _Hash&,
-		   const _Hash_node_value<_Value, true>& __n) const
-  { return __n._M_hash_code; }
-
-  // Compute hash code using _Hash as __n _M_hash_code, if present, was
-  // computed using _H2.
-  template
-	__hash_code
-	_M_hash_code(const _H2&,
-		const _Hash_node_value<_Value, __cache_hash_code>& __n) const
-	{ return _M_hash_code(_ExtractKey{}(__n._M_v())); }
-
   __hash_code
   _M_hash_code(const _Hash_node_value<_Value, false>& __n) const
   { return _M_hash_code(_ExtractKey{}(__n._M_v())); }
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/modifiers/merge.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/modifiers/merge.cc
index b140ce452aa..c051b58137a 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_map/modifiers/merge.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/modifiers/merge.cc
@@ -17,15 +17,29 @@
 
 // { dg-do run { target c++17 } }
 
+#include 
+#include 
 #include 
 #include 
 #include 
 
 using test_type = std::unordered_map;
 
-struct hash {
-  auto operator()(int i) const noexcept { return ~std::hash()(i); }
-};
+template
+  struct xhash
+  {
+auto operator()(const T& i) const noexcept
+{ return ~std::hash()(i); }
+  };
+
+
+namespace std
+{
+  template
+struct __is_fast_hash> : __is_fast_hash>
+{ };
+}
+
 struct equal : std::equal_to<> { };
 
 template
@@ -64,7 +78,7 @@ test02()
 {
   const test_type c0{ {1, 10}, {2, 20}, {3, 30} };
   test_type c1 = c0;
-  std::unordered_map c2( c0.begin(), c0.end() );
+  std::unordered_map, equal> c2( c0.begin(), c0.end() );
 
   c1.merge(c2);
   VERIFY( c1 == c0 );
@@ -89,7 +103,7 @@ test03()
 {
   const test_type c0{ {1, 10}, {2, 20}, {3, 30} };
   test_type c1 = c0;
-  std::unordered_multimap c2( c0.begin(), c0.end() );
+  std::unordered_multimap, equal> c2( c0.begin(), c0.end() );
   c1.merge(c2);
   VERIFY( c1 == c0 );
   VERIFY( equal_elements(c2, c0) );
@@ -125,10 +139,164 @@ test03()
   VERIFY( c2.empty() );
 }
 
+void
+test04()
+{
+  const 

Re: [PATCH][_Hashtable] Avoid redundant usage of rehash policy

2023-10-12 Thread François Dumont

Now that abi breakage is fixed and hoping that Friday is review day :-)

Ping !

On 17/09/2023 22:41, François Dumont wrote:

libstdc++: [_Hashtable] Avoid redundant usage of rehash policy

Bypass usage of __detail::__distance_fwd and check for need to rehash 
when assigning an initializer_list to

an unordered_multimap or unordered_multiset.

libstdc++-v3/ChangeLog:

    * include/bits/hashtable_policy.h
    (_Insert_base<>::_M_insert_range(_InputIte, _InputIte, 
_NodeGen&)): New.
    (_Insert_base<>::_M_insert_range(_InputIte, _InputIte, 
true_type)): Use latter.
    (_Insert_base<>::_M_insert_range(_InputIte, _InputIte, 
false_type)): Likewise.

    * include/bits/hashtable.h
(_Hashtable<>::operator=(initializer_list)): Likewise.
    (_Hashtable<>::_Hashtable(_InputIte, _InputIte, size_type, const 
_Hash&, const _Equal&,

    const allocator_type&, false_type)): Likewise.

Ok to commit ?

François



Re: [PATCH] Fix coroutine tests for libstdc++ gnu-version-namespace mode

2023-10-11 Thread François Dumont

Hi Iain

On 11/10/2023 09:30, Iain Sandoe wrote:

Hi François,


On 11 Oct 2023, at 05:49, François Dumont  wrote:
On 08/10/2023 15:59, Iain Sandoe wrote:

On 23 Sep 2023, at 21:10, François Dumont  wrote:

I'm eventually fixing those tests the same way we manage this problem in 
libstdc++ testsuite.

testsuite: Add optional libstdc++ version namespace in expected diagnostic

 When libstdc++ is build with --enable-symvers=gnu-versioned-namespace 
diagnostics are
 showing this namespace, currently __8.

 gcc/testsuite/ChangeLog:

 * testsuite/g++.dg/coroutines/coro-bad-alloc-00-bad-op-new.C: Add 
optional
 '__8' version namespace in expected diagnostic.
 * testsuite/g++.dg/coroutines/coro-bad-alloc-01-bad-op-del.C: 
Likewise.
 * testsuite/g++.dg/coroutines/coro-bad-alloc-02-no-op-new-nt.C: 
Likewise.
 * 
testsuite/g++.dg/coroutines/coro-bad-grooaf-01-grooaf-expected.C: Likewise.
 * testsuite/g++.dg/coroutines/pr97438.C: Likewise.
 * testsuite/g++.dg/coroutines/ramp-return-b.C: Likewise.

Tested under Linux x86_64.

I'm contributing to libstdc++ so I already have write access.

Ok to commit ?

As author of the tests, this LGTM as a suitable fix for now (at least, once the 
main
patch to fix versioned namespaces lands).

I just realized it was a "go", no ? Then why after the main patch ?

The "main patch" do not fix the versioned namespace. It just makes it adopt the 
cxx11 abi.

This patch fixes a problem that is as old as the tests and that is totally 
unrelated with the main one. I just wanted to improve the situation so that 
versioned namespace mode do not look more buggy than necessary when someone 
(like you) run those.

Maybe a misunderstanding on my part.  I was under the impression that 
versioned-namespace was currently unusable because it forces the old string 
ABI.  If that is not the case, then I guess the changes are OK now.


Said this way it sure makes this mode usability quite limited.

It's only functional to (almost) pass make check-c++ :-)



I am pretty concerned about the maintainability of this tho, hence this …


However, IMO, this could become quite painful as more g++ tests make use of std 
headers
(which is not really optional for facilities like this that are tightly-coupled 
between the FE and
the library).

For the future, it does seem that a more complete solution might be to 
introduce a
testsuite-wide definition for the C++ versioned std:: introducer, so that we 
can update it in one
place as the version changes.

So (as a thought experiment):
  - we’d have something of the form “CXX_STD” as a tcl global
  - we’d add the presence/absence of versioning to the relevant site.exp (which
means recognising the versioning choice also in the GCC configure)
  - we’d migrate tests to using ${CXX_STD} instead of "std::__N”  in matches

… I guess an alternative could be to cook up some alternate warning/error/etc
match functions that cater for arbitrary inline namespaces but that seems 
like a much
more tricky and invasive testsuite change.

thoughts?

I considered amending gcc/testsuite/lib/prune.exp to simply remove the version 
from the diagnostic. But the reply on why it was not working scared me, so this 
patch.

https://gcc.gnu.org/pipermail/gcc/2023-September/242526.html

Ah, I didn’t see that mail - will try to take a look at the weekend.


Ok, I'll instead chase for the patches on libstdc++ side then.

Moreover adopting cxx11 abi in versioned-namespace mode will imply a 
version bump which would force to patch those files again if we do not 
find another approach before.


Thanks,

François




Re: [PATCH] Fix coroutine tests for libstdc++ gnu-version-namespace mode

2023-10-10 Thread François Dumont



On 08/10/2023 15:59, Iain Sandoe wrote:

Hi François,


On 23 Sep 2023, at 21:10, François Dumont  wrote:

I'm eventually fixing those tests the same way we manage this problem in 
libstdc++ testsuite.

testsuite: Add optional libstdc++ version namespace in expected diagnostic

 When libstdc++ is build with --enable-symvers=gnu-versioned-namespace 
diagnostics are
 showing this namespace, currently __8.

 gcc/testsuite/ChangeLog:

 * testsuite/g++.dg/coroutines/coro-bad-alloc-00-bad-op-new.C: Add 
optional
 '__8' version namespace in expected diagnostic.
 * testsuite/g++.dg/coroutines/coro-bad-alloc-01-bad-op-del.C: 
Likewise.
 * testsuite/g++.dg/coroutines/coro-bad-alloc-02-no-op-new-nt.C: 
Likewise.
 * 
testsuite/g++.dg/coroutines/coro-bad-grooaf-01-grooaf-expected.C: Likewise.
 * testsuite/g++.dg/coroutines/pr97438.C: Likewise.
 * testsuite/g++.dg/coroutines/ramp-return-b.C: Likewise.

Tested under Linux x86_64.

I'm contributing to libstdc++ so I already have write access.

Ok to commit ?

As author of the tests, this LGTM as a suitable fix for now (at least, once the 
main
patch to fix versioned namespaces lands).


I just realized it was a "go", no ? Then why after the main patch ?

The "main patch" do not fix the versioned namespace. It just makes it 
adopt the cxx11 abi.


This patch fixes a problem that is as old as the tests and that is 
totally unrelated with the main one. I just wanted to improve the 
situation so that versioned namespace mode do not look more buggy than 
necessary when someone (like you) run those.




However, IMO, this could become quite painful as more g++ tests make use of std 
headers
(which is not really optional for facilities like this that are tightly-coupled 
between the FE and
the library).

For the future, it does seem that a more complete solution might be to 
introduce a
testsuite-wide definition for the C++ versioned std:: introducer, so that we 
can update it in one
place as the version changes.

So (as a thought experiment):
  - we’d have something of the form “CXX_STD” as a tcl global
  - we’d add the presence/absence of versioning to the relevant site.exp (which
means recognising the versioning choice also in the GCC configure)
  - we’d migrate tests to using ${CXX_STD} instead of "std::__N”  in matches

… I guess an alternative could be to cook up some alternate warning/error/etc
match functions that cater for arbitrary inline namespaces but that seems 
like a much
more tricky and invasive testsuite change.

thoughts?


I considered amending gcc/testsuite/lib/prune.exp to simply remove the 
version from the diagnostic. But the reply on why it was not working 
scared me, so this patch.


https://gcc.gnu.org/pipermail/gcc/2023-September/242526.html



Re: [PATCH] sso-string@gnu-versioned-namespace [PR83077]

2023-10-09 Thread François Dumont



On 09/10/2023 16:42, Iain Sandoe wrote:

Hi François,


On 7 Oct 2023, at 20:32, François Dumont  wrote:

I've been told that previous patch generated with 'git diff -b' was not 
applying properly so here is the same patch again with a simple 'git diff'.

Thanks, that did fix it - There are some training whitespaces in the config 
files, but I suspect that they need to be there since those have values 
appended during the configuration.


You're talking about the ones coming from regenerated Makefile.in and 
configure I guess. I prefer not to edit those, those trailing 
whitespaces are already in.





Anyway, with this + the coroutines and contract v2 (weak def) fix, plus a local 
patch to enable versioned namespace on Darwin, I get results comparable with 
the non-versioned case - but one more patchlet is needed on  yours (to allow 
for targets using emultated TLS):

diff --git a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver 
b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
index 9fab8bead15..b7167fc0c2f 100644
--- a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
+++ b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
@@ -78,6 +78,7 @@ GLIBCXX_8.0 {
  
  # thread/mutex/condition_variable/future

  __once_proxy;
+__emutls_v._ZNSt3__81?__once_call*;


I can add this one, sure, even if it could be part of a dedicated patch. 
I'm surprised that we do not need the __once_callable emul symbol too, 
it would be more consistent with the non-versioned mode.


I'm pretty sure there are a bunch of other symbols missing, but this 
mode is seldomly tested...


  
  # std::__convert_to_v

  _ZNSt3__814__convert_to_v*;


thanks
Iain



On 07/10/2023 14:25, François Dumont wrote:

Hi

Here is a rebased version of this patch.

There are few test failures when running 'make check-c++' but nothing new.

Still, there are 2 patches awaiting validation to fix some of them, PR 
c++/111524 to fix another bunch and I fear that we will have to live with the 
others.

 libstdc++: [_GLIBCXX_INLINE_VERSION] Use cxx11 abi [PR83077]

 Use cxx11 abi when activating versioned namespace mode. To do support
 a new configuration mode where !_GLIBCXX_USE_DUAL_ABI and 
_GLIBCXX_USE_CXX11_ABI.

 The main change is that std::__cow_string is now defined whenever 
_GLIBCXX_USE_DUAL_ABI
 or _GLIBCXX_USE_CXX11_ABI is true. Implementation is using available 
std::string in
 case of dual abi and a subset of it when it's not.

 On the other side std::__sso_string is defined only when 
_GLIBCXX_USE_DUAL_ABI is true
 and _GLIBCXX_USE_CXX11_ABI is false. Meaning that std::__sso_string is a 
typedef for the
 cow std::string implementation when dual abi is disabled and cow string is 
being used.

 libstdcxx-v3/ChangeLog:

 PR libstdc++/83077
 * acinclude.m4 [GLIBCXX_ENABLE_LIBSTDCXX_DUAL_ABI]: Default to 
"new" libstdcxx abi
 when enable_symvers is gnu-versioned-namespace.
 * config/locale/dragonfly/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Define money_base
 members.
 * config/locale/generic/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Likewise.
 * config/locale/gnu/monetary_members.cc [!_GLIBCXX_USE_DUAL_ABI]: 
Likewise.
 * config/locale/gnu/numeric_members.cc
 [!_GLIBCXX_USE_DUAL_ABI](__narrow_multibyte_chars): Define.
 * configure: Regenerate.
 * include/bits/c++config
 [_GLIBCXX_INLINE_VERSION](_GLIBCXX_NAMESPACE_CXX11, 
_GLIBCXX_BEGIN_NAMESPACE_CXX11):
 Define empty.
[_GLIBCXX_INLINE_VERSION](_GLIBCXX_END_NAMESPACE_CXX11, 
_GLIBCXX_DEFAULT_ABI_TAG):
 Likewise.
 * include/bits/cow_string.h [!_GLIBCXX_USE_CXX11_ABI]: Define a 
light version of COW
 basic_string as __std_cow_string for use in stdexcept.
 * include/std/stdexcept [_GLIBCXX_USE_CXX11_ABI]: Define 
__cow_string.
 (__cow_string(const char*)): New.
 (__cow_string::c_str()): New.
 * python/libstdcxx/v6/printers.py (StdStringPrinter::__init__): 
Set self.new_string to True
 when std::__8::basic_string type is found.
 * src/Makefile.am 
[ENABLE_SYMVERS_GNU_NAMESPACE](ldbl_alt128_compat_sources): Define empty.
 * src/Makefile.in: Regenerate.
 * src/c++11/Makefile.am (cxx11_abi_sources): Rename into...
 (dual_abi_sources): ...this. Also move cow-local_init.cc, 
cxx11-hash_tr1.cc,
 cxx11-ios_failure.cc entries to...
 (sources): ...this.
 (extra_string_inst_sources): Move cow-fstream-inst.cc, 
cow-sstream-inst.cc, cow-string-inst.cc,
 cow-string-io-inst.cc, cow-wtring-inst.cc, cow-wstring-io-inst.cc, 
cxx11-locale-inst.cc,
 cxx11-wlocale-inst.cc entries to...
 (inst_sources): ...this.
 * src/c++11/M

Re: [PATCH][_GLIBCXX_INLINE_VERSION] Fix

2023-10-08 Thread François Dumont
I think we can do the same without the symbol alias feature. It's even 
simpler cause do not require any maintenance when version symbol bump.


Here is what I'm testing, at least exported symbol is fine.

François


On 08/10/2023 16:06, Iain Sandoe wrote:

Hi François,


On 21 Sep 2023, at 05:41, François Dumont  wrote:

Tests were successful, ok to commit ?

On 20/09/2023 19:51, François Dumont wrote:

libstdc++: [_GLIBCXX_INLINE_VERSION] Add handle_contract_violation symbol alias

libstdc++-v3/ChangeLog:

 * src/experimental/contract.cc
 [_GLIBCXX_INLINE_VERSION](handle_contract_violation): Provide symbol alias
 without version namespace decoration for gcc.

This does not work in the source on targets without support for symbol aliases 
(Darwin is one)
“../experimental/contract.cc:79:8: warning: alias definitions not supported in 
Mach-O; ignored”

- there might be a way to do it at link-time (for one symbol not too bad); I 
will have to poke at
   it a bit.
Iain


Here is what I'm testing eventually, ok to commit if successful ?

François

On 20/09/2023 11:32, Jonathan Wakely wrote:

On Wed, 20 Sept 2023 at 05:51, François Dumont via Libstdc++
 wrote:

libstdc++: Remove std::constract_violation from versioned namespace

Spelling mistake in contract_violation, and it's not
std::contract_violation, it's std::experimental::contract_violation


GCC expects this type to be in std namespace directly.

Again, it's in std::experimental not in std directly.

Will this change cause problems when including another experimental
header, which does put experimental below std::__8?

I think std::__8::experimental and std::experimental will become ambiguous.

Maybe we do want to remove the inline __8 namespace from all
experimental headers. That needs a bit more thought though.


libstdc++-v3/ChangeLog:

   * include/experimental/contract:
   Remove _GLIBCXX_BEGIN_NAMESPACE_VERSION/_GLIBCXX_END_NAMESPACE_VERSION.

This line is too long for the changelog.


It does fix 29 g++.dg/contracts in gcc testsuite.

Ok to commit ?

Françoisdiff --git a/libstdc++-v3/src/experimental/contract.cc b/libstdc++-v3/src/experimental/contract.cc
index 504a6c041f1..7918e5ae53a 100644
--- a/libstdc++-v3/src/experimental/contract.cc
+++ b/libstdc++-v3/src/experimental/contract.cc
@@ -67,3 +67,12 @@ handle_contract_violation (const std::experimental::contract_violation 
   std::cerr << std::endl;
 #endif
 }
+
+#if _GLIBCXX_INLINE_VERSION
+// Provide symbol without version namespace decoration for gcc.
+extern "C"
+__attribute__ ((weak)) void
+_Z25handle_contract_violationRKNSt12experimental18contract_violationE
+(const std::experimental::contract_violation )
+{ handle_contract_violation(violation); }
+#endif


Re: [PATCH] sso-string@gnu-versioned-namespace [PR83077]

2023-10-07 Thread François Dumont
I've been told that previous patch generated with 'git diff -b' was not 
applying properly so here is the same patch again with a simple 'git diff'.



On 07/10/2023 14:25, François Dumont wrote:

Hi

Here is a rebased version of this patch.

There are few test failures when running 'make check-c++' but nothing 
new.


Still, there are 2 patches awaiting validation to fix some of them, PR 
c++/111524 to fix another bunch and I fear that we will have to live 
with the others.


    libstdc++: [_GLIBCXX_INLINE_VERSION] Use cxx11 abi [PR83077]

    Use cxx11 abi when activating versioned namespace mode. To do support
    a new configuration mode where !_GLIBCXX_USE_DUAL_ABI and 
_GLIBCXX_USE_CXX11_ABI.


    The main change is that std::__cow_string is now defined whenever 
_GLIBCXX_USE_DUAL_ABI
    or _GLIBCXX_USE_CXX11_ABI is true. Implementation is using 
available std::string in

    case of dual abi and a subset of it when it's not.

    On the other side std::__sso_string is defined only when 
_GLIBCXX_USE_DUAL_ABI is true
    and _GLIBCXX_USE_CXX11_ABI is false. Meaning that 
std::__sso_string is a typedef for the
    cow std::string implementation when dual abi is disabled and cow 
string is being used.


    libstdcxx-v3/ChangeLog:

    PR libstdc++/83077
    * acinclude.m4 [GLIBCXX_ENABLE_LIBSTDCXX_DUAL_ABI]: 
Default to "new" libstdcxx abi

    when enable_symvers is gnu-versioned-namespace.
    * config/locale/dragonfly/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Define money_base

    members.
    * config/locale/generic/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Likewise.
    * config/locale/gnu/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Likewise.

    * config/locale/gnu/numeric_members.cc
    [!_GLIBCXX_USE_DUAL_ABI](__narrow_multibyte_chars): Define.
    * configure: Regenerate.
    * include/bits/c++config
    [_GLIBCXX_INLINE_VERSION](_GLIBCXX_NAMESPACE_CXX11, 
_GLIBCXX_BEGIN_NAMESPACE_CXX11):

    Define empty.
[_GLIBCXX_INLINE_VERSION](_GLIBCXX_END_NAMESPACE_CXX11, 
_GLIBCXX_DEFAULT_ABI_TAG):

    Likewise.
    * include/bits/cow_string.h [!_GLIBCXX_USE_CXX11_ABI]: 
Define a light version of COW

    basic_string as __std_cow_string for use in stdexcept.
    * include/std/stdexcept [_GLIBCXX_USE_CXX11_ABI]: Define 
__cow_string.

    (__cow_string(const char*)): New.
    (__cow_string::c_str()): New.
    * python/libstdcxx/v6/printers.py 
(StdStringPrinter::__init__): Set self.new_string to True

    when std::__8::basic_string type is found.
    * src/Makefile.am 
[ENABLE_SYMVERS_GNU_NAMESPACE](ldbl_alt128_compat_sources): Define empty.

    * src/Makefile.in: Regenerate.
    * src/c++11/Makefile.am (cxx11_abi_sources): Rename into...
    (dual_abi_sources): ...this. Also move cow-local_init.cc, 
cxx11-hash_tr1.cc,

    cxx11-ios_failure.cc entries to...
    (sources): ...this.
    (extra_string_inst_sources): Move cow-fstream-inst.cc, 
cow-sstream-inst.cc, cow-string-inst.cc,
    cow-string-io-inst.cc, cow-wtring-inst.cc, 
cow-wstring-io-inst.cc, cxx11-locale-inst.cc,

    cxx11-wlocale-inst.cc entries to...
    (inst_sources): ...this.
    * src/c++11/Makefile.in: Regenerate.
    * src/c++11/cow-fstream-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-locale_init.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-sstream-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-stdexcept.cc [_GLIBCXX_USE_CXX11_ABI]: 
Include .
    [_GLIBCXX_USE_DUAL_ABI || 
_GLIBCXX_USE_CXX11_ABI](__cow_string): Redefine before
    including . Define 
_GLIBCXX_DEFINE_STDEXCEPT_INSTANTIATIONS so that

    __cow_string definition in  is skipped.
    [_GLIBCXX_USE_CXX11_ABI]: Skip Transaction Memory TS 
definitions.
    * src/c++11/string-inst.cc: Add sizeof/alignof 
static_assert on stdexcept

    __cow_string definition.
    (_GLIBCXX_DEFINING_CXX11_ABI_INSTANTIATIONS): Define 
following _GLIBCXX_USE_CXX11_ABI

    value.
    [_GLIBCXX_USE_CXX11_ABI && 
!_GLIBCXX_DEFINING_CXX11_ABI_INSTANTIATIONS]:
    Define _GLIBCXX_DEFINING_COW_STRING_INSTANTIATIONS. 
Include .
    Define basic_string as __std_cow_string for the current 
translation unit.
    * src/c++11/cow-string-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-string-io-inst.cc 
[_GLIBCXX_USE_CXX11_ABI]: Skip definitions.
    * src/c++11/cow-wstring-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-wstring-io-inst.cc 
[_GLIBCXX_USE_CXX11_ABI]: Skip definitions.
    * src/c++11/cxx11-hash_tr1.cc [!_GLIBCXX_USE

Re: [PATCH] sso-string@gnu-versioned-namespace [PR83077]

2023-10-07 Thread François Dumont
 * src/c++11/cxx11-locale-inst.cc: Cleanup, just include 
locale-inst.cc.
    * src/c++11/cxx11-stdexcept.cc [!_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cxx11-wlocale-inst.cc 
[!_GLIBCXX_USE_CXX11_ABI]: Skip definitions.

    * src/c++11/locale-inst-numeric.h
[!_GLIBCXX_USE_DUAL_ABI](std::use_facet>, 
std::use_facet>): Instantiate.
[!_GLIBCXX_USE_DUAL_ABI](std::has_facet>, 
std::has_facet>): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](std::num_getistreambuf_iterator>): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](std::num_putostreambuf_iterator>): Instantiate.
    * src/c++11/locale-inst.cc [!_GLIBCXX_USE_DUAL_ABI]: Build 
only when configured

    _GLIBCXX_USE_CXX11_ABI is equal to currently built abi.
    [!_GLIBCXX_USE_DUAL_ABI](__moneypunct_cache): 
Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](__moneypunct_cache): 
Instantiate.

    [!_GLIBCXX_USE_DUAL_ABI](__numpunct_cache): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](__timepunct): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](__timepunct_cache): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](time_putostreambuf_iterator>): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](time_put_bynameostreambuf_iterator>): Instantiate.

[!_GLIBCXX_USE_DUAL_ABI](__ctype_abstract_base): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](ctype_byname): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](__codecvt_abstract_basembstate_t>): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](codecvt_bynamembstate_t>): Instantiate.

[!_GLIBCXX_USE_DUAL_ABI](use_facet>(const locale&)): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](use_facetmbstate_t>>(const locale&)): Instantiate.
[!_GLIBCXX_USE_DUAL_ABI](use_facet<__timepunct>(const locale&)): 
Instantiate.
[!_GLIBCXX_USE_DUAL_ABI](use_facet>(const locale&)): 
Instantiate.

[!_GLIBCXX_USE_DUAL_ABI](has_facet>(const locale&)): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](has_facetmbstate_t>>(const locale&)): Instantiate.
[!_GLIBCXX_USE_DUAL_ABI](has_facet<__timepunct>(const locale&)): 
Instantiate.
[!_GLIBCXX_USE_DUAL_ABI](has_facet>(const locale&)): 
Instantiate.

    [!_GLIBCXX_USE_DUAL_ABI](__add_grouping): Define.
    [!_GLIBCXX_USE_DUAL_ABI](__pad>): 
Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](__int_to_char(C*, unsigned long, 
const C*,

    ios_base::fmtflags, bool)): Define.
    [!_GLIBCXX_USE_DUAL_ABI](__int_to_char(C*, unsigned long 
long, const C*,

    ios_base::fmtflags, bool)): Define.
    * src/c++11/wlocale-inst.cc [!_GLIBCXX_USE_CXX11_ABI]: Skip 
definitions.
    * src/c++98/Makefile.am (cxx11_abi_sources): Remove, unique 
cow-istream-string.cc entry

    move to...
    (inst_sources): ...this.
    * src/c++98/Makefile.in: Regenerate.
    * src/c++98/cow-istream-string.cc: Include .
    [_GLIBCXX_USE_CXX11_ABI]: Skip definitions.
    * src/c++98/hash_tr1.cc [_GLIBCXX_USE_CXX11_ABI]: Skip 
definitions.
    * src/c++98/ios_failure.cc 
[_GLIBCXX_USE_CXX11_ABI][_GLIBCXX_USE_DUAL_ABI]: Skip definitions.
    * src/c++98/istream-string.cc [!_GLIBCXX_USE_DUAL_ABI]: 
Build only when configured

    _GLIBCXX_USE_CXX11_ABI is equal to currently built abi.
    * src/c++98/locale_facets.cc 
[_GLIBCXX_USE_CXX11_ABI](__verify_grouping): Remove.

    * src/c++98/stdexcept.cc
    [_GLIBCXX_USE_CXX11_ABI](logic_error(const string&): Remove.
    [_GLIBCXX_USE_CXX11_ABI](domain_error(const string&): Remove.
    [_GLIBCXX_USE_CXX11_ABI](invalid_argument(const string&): 
Remove.

    [_GLIBCXX_USE_CXX11_ABI](length_error(const string&): Remove.
    [_GLIBCXX_USE_CXX11_ABI](out_of_range(const string&): Remove.
    [_GLIBCXX_USE_CXX11_ABI](runtime_error(const string&): Remove.
    [_GLIBCXX_USE_CXX11_ABI](range_error(const string&): Remove.
    [_GLIBCXX_USE_CXX11_ABI](overflow_error(const string&): Remove.
    [_GLIBCXX_USE_CXX11_ABI](underflow_error(const string&): 
Remove.
    * src/c++98/compatibility.cc [_GLIBCXX_USE_CXX11_ABI]: Skip 
all definitions appart from

    istream::ignore(streamsize).

Tested under Linux x64_86, ok to commit ?

François


On 17/08/2023 19:22, Jonathan Wakely wrote:

On Sun, 13 Aug 2023 at 14:27, François Dumont via Libstdc++
 wrote:

Here is the fixed patch tested in all 3 modes:

- _GLIBCXX_USE_DUAL_ABI

- !_GLIBCXX_USE_DUAL_ABI && !_GLIBCXX_USE_CXX11_ABI

- !_GLIBCXX_USE_DUAL_ABI && _GLIBCXX_USE_CXX11_ABI

I don't know what you have in mind for the change below but I wanted to
let you know that I tried to put COW std::basic_string into a nested
__cow namespace when _GLIBCXX_USE_CXX11_ABI. But it had more im

[PATCH][_GLIBCXX_INLINE_VERSION] Add missing symbols

2023-10-05 Thread François Dumont

Here is a patch to fix following test case in gcc:

gcc/testsuite/g++.dg/cpp23/ext-floating13.C

    libstdc++: [_GLIBCXX_INLINE_VERSION] Add missing float symbols

    libstdc++-v3/ChangeLog:

    * config/abi/pre/gnu-versioned-namespace.ver: Add missing 
symbols

    for _Float{16,32,64,128,32x,64x,128x}.

Ok to commit ?

François

diff --git a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
index 267ab8fc719..9fab8bead15 100644
--- a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
+++ b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
@@ -318,6 +318,15 @@ CXXABI_2.0 {
 _ZTIPD[fde];
 _ZTIPKD[fde];
 
+# typeinfo for _Float{16,32,64,128,32x,64x,128x} and
+# __bf16
+_ZTIDF[0-9]*[_bx];
+_ZTIPDF[0-9]*[_bx];
+_ZTIPKDF[0-9]*[_bx];
+_ZTIu6__bf16;
+_ZTIPu6__bf16;
+_ZTIPKu6__bf16;
+
 # typeinfo for decltype(nullptr)
 _ZTIDn;
 _ZTIPDn;


Re: [PATCH] Fix coroutine tests for libstdc++ gnu-version-namespace mode

2023-10-03 Thread François Dumont

Indeed ! Here is the right one.

On 03/10/2023 11:52, Jonathan Wakely wrote:

On Mon, 2 Oct 2023 at 18:07, François Dumont  wrote:

Hi

Gentle reminder for this minor patch.

It looks like you attached the wrong patch.



Thanks

On 23/09/2023 22:10, François Dumont wrote:

I'm eventually fixing those tests the same way we manage this problem
in libstdc++ testsuite.

testsuite: Add optional libstdc++ version namespace in expected
diagnostic

 When libstdc++ is build with
--enable-symvers=gnu-versioned-namespace diagnostics are
 showing this namespace, currently __8.

 gcc/testsuite/ChangeLog:

 *
testsuite/g++.dg/coroutines/coro-bad-alloc-00-bad-op-new.C: Add optional
 '__8' version namespace in expected diagnostic.
 *
testsuite/g++.dg/coroutines/coro-bad-alloc-01-bad-op-del.C: Likewise.
 *
testsuite/g++.dg/coroutines/coro-bad-alloc-02-no-op-new-nt.C: Likewise.
 *
testsuite/g++.dg/coroutines/coro-bad-grooaf-01-grooaf-expected.C:
Likewise.
 * testsuite/g++.dg/coroutines/pr97438.C: Likewise.
 * testsuite/g++.dg/coroutines/ramp-return-b.C: Likewise.

Tested under Linux x86_64.

I'm contributing to libstdc++ so I already have write access.

Ok to commit ?

Françoisdiff --git a/gcc/testsuite/g++.dg/coroutines/coro-bad-alloc-00-bad-op-new.C b/gcc/testsuite/g++.dg/coroutines/coro-bad-alloc-00-bad-op-new.C
index 4706deebf4e..928e0c974e1 100644
--- a/gcc/testsuite/g++.dg/coroutines/coro-bad-alloc-00-bad-op-new.C
+++ b/gcc/testsuite/g++.dg/coroutines/coro-bad-alloc-00-bad-op-new.C
@@ -6,7 +6,7 @@
 #include "coro1-allocators.h"
 
 struct coro1
-f ()  /* { dg-error {'operator new' is provided by 'std::__n4861::__coroutine_traits_impl::promise_type' \{aka 'coro1::promise_type'\} but is not usable with the function signature 'coro1 f\(\)'} } */
+f ()  /* { dg-error {'operator new' is provided by 'std::(__8::)?__n4861::__coroutine_traits_impl::promise_type' \{aka 'coro1::promise_type'\} but is not usable with the function signature 'coro1 f\(\)'} } */
 {
   co_return;
 }
diff --git a/gcc/testsuite/g++.dg/coroutines/coro-bad-alloc-01-bad-op-del.C b/gcc/testsuite/g++.dg/coroutines/coro-bad-alloc-01-bad-op-del.C
index 252cb5e442c..6bed524aa0a 100644
--- a/gcc/testsuite/g++.dg/coroutines/coro-bad-alloc-01-bad-op-del.C
+++ b/gcc/testsuite/g++.dg/coroutines/coro-bad-alloc-01-bad-op-del.C
@@ -6,7 +6,7 @@
 #include "coro1-allocators.h"
 
 struct coro1
-f ()  /* { dg-error {'operator delete' is provided by 'std::__n4861::__coroutine_traits_impl::promise_type' \{aka 'coro1::promise_type'\} but is not usable with the function signature 'coro1 f\(\)'} } */
+f ()  /* { dg-error {'operator delete' is provided by 'std::(__8::)?__n4861::__coroutine_traits_impl::promise_type' \{aka 'coro1::promise_type'\} but is not usable with the function signature 'coro1 f\(\)'} } */
 {
   co_return;
 }
diff --git a/gcc/testsuite/g++.dg/coroutines/coro-bad-alloc-02-no-op-new-nt.C b/gcc/testsuite/g++.dg/coroutines/coro-bad-alloc-02-no-op-new-nt.C
index 89972b60945..0a545fed0e3 100644
--- a/gcc/testsuite/g++.dg/coroutines/coro-bad-alloc-02-no-op-new-nt.C
+++ b/gcc/testsuite/g++.dg/coroutines/coro-bad-alloc-02-no-op-new-nt.C
@@ -9,7 +9,7 @@
 #include "coro1-allocators.h"
 
 struct coro1
-f () /* { dg-error {'coro1::promise_type::get_return_object_on_allocation_failure\(\)\(\)' is provided by 'std::__n4861::__coroutine_traits_impl::promise_type' \{aka 'coro1::promise_type'\} but 'operator new' is not marked 'throw\(\)' or 'noexcept'} } */
+f () /* { dg-error {'coro1::promise_type::get_return_object_on_allocation_failure\(\)\(\)' is provided by 'std::(__8::)?__n4861::__coroutine_traits_impl::promise_type' \{aka 'coro1::promise_type'\} but 'operator new' is not marked 'throw\(\)' or 'noexcept'} } */
 {
   co_return;
 }
diff --git a/gcc/testsuite/g++.dg/coroutines/coro-bad-grooaf-01-grooaf-expected.C b/gcc/testsuite/g++.dg/coroutines/coro-bad-grooaf-01-grooaf-expected.C
index 9fa3d64a9f2..b36e88f871a 100644
--- a/gcc/testsuite/g++.dg/coroutines/coro-bad-grooaf-01-grooaf-expected.C
+++ b/gcc/testsuite/g++.dg/coroutines/coro-bad-grooaf-01-grooaf-expected.C
@@ -6,7 +6,7 @@
 int used_grooaf = 0;
 
 struct coro1
-f () noexcept // { dg-warning {'operator new' is marked 'throw\(\)' or 'noexcept' but no usable 'get_return_object_on_allocation_failure' is provided by 'std::__n4861::__coroutine_traits_impl::promise_type' \{aka 'coro1::promise_type'\}} }
+f () noexcept // { dg-warning {'operator new' is marked 'throw\(\)' or 'noexcept' but no usable 'get_return_object_on_allocation_failure' is provided by 'std::(__8::)?__n4861::__coroutine_traits_impl::promise_type' \{aka 'coro1::promise_type'\}} }
 {
   PRINT ("coro1: about to return");
   co_return;
diff --git a/gcc/testsuite/g++.dg/coroutines/pr97438.C b/gcc/testsuite/g++.dg/coroutines/pr97438.C
index 95376648ed7..ac37118eae7 100644
--- a/gcc/testsuite/g++.dg/corouti

Re: [PATCH] [11/12/13/14 Regression] ABI break in _Hash_node_value_base since GCC 11 [PR 111050]

2023-10-02 Thread François Dumont

Now backport to gcc-11/12/13 branches.

On 29/09/2023 11:53, Jonathan Wakely wrote:

On Thu, 28 Sept 2023 at 18:25, François Dumont  wrote:


On 28/09/2023 18:18, Jonathan Wakely wrote:

On Wed, 27 Sept 2023 at 05:44, François Dumont  wrote:

Still no chance to get feedback from TC ? Maybe I can commit the below
then ?

I've heard back from Tim now. Please use "Tim Song
" as the author.

You can change the commit again using git commit --amend --author "Tim
Song "

Sure :-)


OK for trunk with that change - thanks for waiting.

Committed to trunk, let me know for backports.

Please wait a few days in case of problems on the trunk (although I
don't expect any) and then OK for 11/12/13 too - thanks!



AFAICS on gcc mailing list several gcc releases were done recently, too
late.

There have been no releases this month, so the delay hasn't caused any problems.

I was confused by emails like this one:

https://gcc.gnu.org/pipermail/gcc/2023-September/242429.html

I just subscribed to gcc mailing list, I had no idea there were regular
snapshots like this.



Re: [PATCH] Fix coroutine tests for libstdc++ gnu-version-namespace mode

2023-10-02 Thread François Dumont

Hi

Gentle reminder for this minor patch.

Thanks

On 23/09/2023 22:10, François Dumont wrote:
I'm eventually fixing those tests the same way we manage this problem 
in libstdc++ testsuite.


   testsuite: Add optional libstdc++ version namespace in expected 
diagnostic


    When libstdc++ is build with 
--enable-symvers=gnu-versioned-namespace diagnostics are

    showing this namespace, currently __8.

    gcc/testsuite/ChangeLog:

    * 
testsuite/g++.dg/coroutines/coro-bad-alloc-00-bad-op-new.C: Add optional

    '__8' version namespace in expected diagnostic.
    * 
testsuite/g++.dg/coroutines/coro-bad-alloc-01-bad-op-del.C: Likewise.
    * 
testsuite/g++.dg/coroutines/coro-bad-alloc-02-no-op-new-nt.C: Likewise.
    * 
testsuite/g++.dg/coroutines/coro-bad-grooaf-01-grooaf-expected.C: 
Likewise.

    * testsuite/g++.dg/coroutines/pr97438.C: Likewise.
    * testsuite/g++.dg/coroutines/ramp-return-b.C: Likewise.

Tested under Linux x86_64.

I'm contributing to libstdc++ so I already have write access.

Ok to commit ?

François


Re: [PATCH] [11/12/13/14 Regression] ABI break in _Hash_node_value_base since GCC 11 [PR 111050]

2023-09-28 Thread François Dumont



On 28/09/2023 18:18, Jonathan Wakely wrote:

On Wed, 27 Sept 2023 at 05:44, François Dumont  wrote:

Still no chance to get feedback from TC ? Maybe I can commit the below
then ?

I've heard back from Tim now. Please use "Tim Song
" as the author.

You can change the commit again using git commit --amend --author "Tim
Song "


Sure :-)



OK for trunk with that change - thanks for waiting.


Committed to trunk, let me know for backports.


AFAICS on gcc mailing list several gcc releases were done recently, too
late.

There have been no releases this month, so the delay hasn't caused any problems.


I was confused by emails like this one:

https://gcc.gnu.org/pipermail/gcc/2023-September/242429.html

I just subscribed to gcc mailing list, I had no idea there were regular 
snapshots like this.




Re: [PATCH] [11/12/13/14 Regression] ABI break in _Hash_node_value_base since GCC 11 [PR 111050]

2023-09-26 Thread François Dumont
Still no chance to get feedback from TC ? Maybe I can commit the below 
then ?


AFAICS on gcc mailing list several gcc releases were done recently, too 
late.



On 14/09/2023 06:46, François Dumont wrote:

Author: TC 
Date:   Wed Sep 6 19:31:55 2023 +0200

    libstdc++: Force _Hash_node_value_base methods inline to fix abi 
(PR111050)


https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=1b6f0476837205932613ddb2b3429a55c26c409d 

    changed _Hash_node_value_base to no longer derive from 
_Hash_node_base, which means
    that its member functions expect _M_storage to be at a different 
offset. So explosions
    result if an out-of-line definition is emitted for any of the 
member functions (say,
    in a non-optimized build) and the resulting object file is then 
linked with code built

    using older version of GCC/libstdc++.

    libstdc++-v3/ChangeLog:

    PR libstdc++/111050
    * include/bits/hashtable_policy.h
    (_Hash_node_value_base<>::_M_valptr(), 
_Hash_node_value_base<>::_M_v())

    Add [[__gnu__::__always_inline__]].

Ok to commit ?

On 12/09/2023 18:09, Jonathan Wakely wrote:
On Mon, 11 Sept 2023 at 18:19, François Dumont  
wrote:


On 11/09/2023 13:51, Jonathan Wakely wrote:

On Sun, 10 Sept 2023 at 14:57, François Dumont via Libstdc++
 wrote:

Following confirmation of the fix by TC here is the patch where I'm
simply adding a 'constexpr' on _M_next().

Please let me know this ChangeLog entry is correct. I would prefer 
this
patch to be assigned to 'TC' with me as co-author but I don't know 
how
to do such a thing. Unless I need to change my user git identity 
to do so ?

Sam already explained that, but please check with Tim how he wants to
be credited, if at all. He doesn't have a copyright assignment, and
hasn't added a DCO sign-off to the patch, but it's small enough to not
need it as this is the first contribution credited to him.


   libstdc++: Add constexpr qualification to 
_Hash_node::_M_next()

What has this constexpr addition got to do with the ABI change and the
always_inline attributes?

It certainly doesn't seem like it should be the summary line of the
git commit message.
Oops, sorry, that's what I had started to do before Tim submitted 
anything.


Here is latest version:

No patch attached, and the ChangeLog below still mentions the constexpr.

I've pinged Tim via another channel to ask him about the author 
attribution.




Author: TC 
Date:   Wed Sep 6 19:31:55 2023 +0200

  libstdc++: Force inline on _Hash_node_value_base methods to 
fix abi

(PR111050)

https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=1b6f0476837205932613ddb2b3429a55c26c409d 


  changed _Hash_node_value_base to no longer derive from
_Hash_node_base, which means
  that its member functions expect _M_storage to be at a different
offset. So explosions
  result if an out-of-line definition is emitted for any of the
member functions (say,
  in a non-optimized build) and the resulting object file is then
linked with code built
  using older version of GCC/libstdc++.

  libstdc++-v3/ChangeLog:

  PR libstdc++/111050
  * include/bits/hashtable_policy.h
  (_Hash_node_value_base<>::_M_valptr(),
_Hash_node_value_base<>::_M_v())
  Add [[__gnu__::__always_inline__]].
  (_Hash_node<>::_M_next()): Add constexpr.

  Co-authored-by: François Dumont 

Ok for you TC (Tim ?) ?




[PATCH] Fix coroutine tests for libstdc++ gnu-version-namespace mode

2023-09-23 Thread François Dumont
I'm eventually fixing those tests the same way we manage this problem in 
libstdc++ testsuite.


   testsuite: Add optional libstdc++ version namespace in expected 
diagnostic


    When libstdc++ is build with 
--enable-symvers=gnu-versioned-namespace diagnostics are

    showing this namespace, currently __8.

    gcc/testsuite/ChangeLog:

    * 
testsuite/g++.dg/coroutines/coro-bad-alloc-00-bad-op-new.C: Add optional

    '__8' version namespace in expected diagnostic.
    * 
testsuite/g++.dg/coroutines/coro-bad-alloc-01-bad-op-del.C: Likewise.
    * 
testsuite/g++.dg/coroutines/coro-bad-alloc-02-no-op-new-nt.C: Likewise.
    * 
testsuite/g++.dg/coroutines/coro-bad-grooaf-01-grooaf-expected.C: Likewise.

    * testsuite/g++.dg/coroutines/pr97438.C: Likewise.
    * testsuite/g++.dg/coroutines/ramp-return-b.C: Likewise.

Tested under Linux x86_64.

I'm contributing to libstdc++ so I already have write access.

Ok to commit ?

François
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 73e7f381020..c44b71a04cb 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -4867,7 +4867,7 @@ dnl
 dnl Control whether the library should define symbols for old and new ABIs.
 dnl This affects definitions of strings, stringstreams and locale facets.
 dnl
-dnl --disable-libstdcxx-dual-abi will use old ABI for all types.
+dnl --disable-libstdcxx-dual-abi will use new ABI for all types.
 dnl
 dnl Defines:
 dnl  _GLIBCXX_USE_DUAL_ABI (always defined, either to 1 or 0)
@@ -4883,7 +4883,7 @@ AC_DEFUN([GLIBCXX_ENABLE_LIBSTDCXX_DUAL_ABI], [
   else
 if test x"$enable_libstdcxx_dual_abi" != xyes; then
   AC_MSG_NOTICE([dual ABI is disabled])
-  default_libstdcxx_abi="gcc4-compatible"
+  default_libstdcxx_abi="new"
 fi
   fi
   GLIBCXX_CONDITIONAL(ENABLE_DUAL_ABI, test $enable_libstdcxx_dual_abi = yes)
@@ -4898,7 +4898,6 @@ dnl Defines:
 dnl  _GLIBCXX_USE_CXX11_ABI (always defined, either to 1 or 0)
 dnl
 AC_DEFUN([GLIBCXX_DEFAULT_ABI], [
-  if test x$enable_libstdcxx_dual_abi = xyes; then
   AC_MSG_CHECKING([for default std::string ABI to use])
   AC_ARG_WITH([default-libstdcxx-abi],
 AS_HELP_STRING([--with-default-libstdcxx-abi],
@@ -4912,7 +4911,6 @@ AC_DEFUN([GLIBCXX_DEFAULT_ABI], [
  ],
 [default_libstdcxx_abi="new"])
   AC_MSG_RESULT(${default_libstdcxx_abi})
-  fi
   if test $default_libstdcxx_abi = "new"; then
 glibcxx_cxx11_abi=1
 glibcxx_cxx98_abi=0
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index 6e9a532a359..14f9569597a 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -70712,13 +70712,12 @@ $as_echo "$as_me: dual ABI is disabled" >&6;}
 if test x"$enable_libstdcxx_dual_abi" != xyes; then
   { $as_echo "$as_me:${as_lineno-$LINENO}: dual ABI is disabled" >&5
 $as_echo "$as_me: dual ABI is disabled" >&6;}
-  default_libstdcxx_abi="gcc4-compatible"
+  default_libstdcxx_abi="new"
 fi
   fi
 
 
 
-  if test x$enable_libstdcxx_dual_abi = xyes; then
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking for default std::string ABI to use" >&5
 $as_echo_n "checking for default std::string ABI to use... " >&6; }
 
@@ -70737,7 +70736,6 @@ fi
 
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${default_libstdcxx_abi}" >&5
 $as_echo "${default_libstdcxx_abi}" >&6; }
-  fi
   if test $default_libstdcxx_abi = "new"; then
 glibcxx_cxx11_abi=1
 glibcxx_cxx98_abi=0


Re: [PATCH][_GLIBCXX_INLINE_VERSION] Fix

2023-09-20 Thread François Dumont

Tests were successful, ok to commit ?

On 20/09/2023 19:51, François Dumont wrote:
libstdc++: [_GLIBCXX_INLINE_VERSION] Add handle_contract_violation 
symbol alias


libstdc++-v3/ChangeLog:

    * src/experimental/contract.cc
    [_GLIBCXX_INLINE_VERSION](handle_contract_violation): Provide 
symbol alias

    without version namespace decoration for gcc.

Here is what I'm testing eventually, ok to commit if successful ?

François

On 20/09/2023 11:32, Jonathan Wakely wrote:

On Wed, 20 Sept 2023 at 05:51, François Dumont via Libstdc++
 wrote:

libstdc++: Remove std::constract_violation from versioned namespace

Spelling mistake in contract_violation, and it's not
std::contract_violation, it's std::experimental::contract_violation


GCC expects this type to be in std namespace directly.

Again, it's in std::experimental not in std directly.

Will this change cause problems when including another experimental
header, which does put experimental below std::__8?

I think std::__8::experimental and std::experimental will become 
ambiguous.


Maybe we do want to remove the inline __8 namespace from all
experimental headers. That needs a bit more thought though.


libstdc++-v3/ChangeLog:

  * include/experimental/contract:
  Remove 
_GLIBCXX_BEGIN_NAMESPACE_VERSION/_GLIBCXX_END_NAMESPACE_VERSION.

This line is too long for the changelog.


It does fix 29 g++.dg/contracts in gcc testsuite.

Ok to commit ?

François


Re: [PATCH][_GLIBCXX_INLINE_VERSION] Fix

2023-09-20 Thread François Dumont
libstdc++: [_GLIBCXX_INLINE_VERSION] Add handle_contract_violation 
symbol alias


libstdc++-v3/ChangeLog:

    * src/experimental/contract.cc
    [_GLIBCXX_INLINE_VERSION](handle_contract_violation): Provide 
symbol alias

    without version namespace decoration for gcc.

Here is what I'm testing eventually, ok to commit if successful ?

François

On 20/09/2023 11:32, Jonathan Wakely wrote:

On Wed, 20 Sept 2023 at 05:51, François Dumont via Libstdc++
 wrote:

libstdc++: Remove std::constract_violation from versioned namespace

Spelling mistake in contract_violation, and it's not
std::contract_violation, it's std::experimental::contract_violation


GCC expects this type to be in std namespace directly.

Again, it's in std::experimental not in std directly.

Will this change cause problems when including another experimental
header, which does put experimental below std::__8?

I think std::__8::experimental and std::experimental will become ambiguous.

Maybe we do want to remove the inline __8 namespace from all
experimental headers. That needs a bit more thought though.


libstdc++-v3/ChangeLog:

  * include/experimental/contract:
  Remove _GLIBCXX_BEGIN_NAMESPACE_VERSION/_GLIBCXX_END_NAMESPACE_VERSION.

This line is too long for the changelog.


It does fix 29 g++.dg/contracts in gcc testsuite.

Ok to commit ?

Françoisdiff --git a/libstdc++-v3/src/experimental/contract.cc b/libstdc++-v3/src/experimental/contract.cc
index 504a6c041f1..17daa3312ca 100644
--- a/libstdc++-v3/src/experimental/contract.cc
+++ b/libstdc++-v3/src/experimental/contract.cc
@@ -67,3 +67,14 @@ handle_contract_violation (const std::experimental::contract_violation 
   std::cerr << std::endl;
 #endif
 }
+
+#if _GLIBCXX_INLINE_VERSION
+// Provide symbol alias without version namespace decoration for gcc.
+extern "C"
+void _Z25handle_contract_violationRKNSt12experimental18contract_violationE
+(const std::experimental::contract_violation )
+__attribute__ (
+(alias
+ ("_Z25handle_contract_violationRKNSt3__812experimental18contract_violationE"),
+ weak));
+#endif


[PATCH][_GLIBCXX_INLINE_VERSION] Fix

2023-09-19 Thread François Dumont

libstdc++: Remove std::constract_violation from versioned namespace

GCC expects this type to be in std namespace directly.

libstdc++-v3/ChangeLog:

    * include/experimental/contract:
    Remove _GLIBCXX_BEGIN_NAMESPACE_VERSION/_GLIBCXX_END_NAMESPACE_VERSION.

It does fix 29 g++.dg/contracts in gcc testsuite.

Ok to commit ?

François
diff --git a/libstdc++-v3/include/experimental/contract b/libstdc++-v3/include/experimental/contract
index fbf5ed01d8b..8bc12380cec 100644
--- a/libstdc++-v3/include/experimental/contract
+++ b/libstdc++-v3/include/experimental/contract
@@ -39,7 +39,6 @@
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
-_GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 namespace experimental
 {
@@ -71,7 +70,6 @@ namespace experimental
 
 } // namespace experimental
 
-_GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 
 // To override the contract violation handler, define


[PATCH][_Hashtable] Avoid redundant usage of rehash policy

2023-09-17 Thread François Dumont via Gcc-patches

libstdc++: [_Hashtable] Avoid redundant usage of rehash policy

Bypass usage of __detail::__distance_fwd and check for need to rehash 
when assigning an initializer_list to

an unordered_multimap or unordered_multiset.

libstdc++-v3/ChangeLog:

    * include/bits/hashtable_policy.h
    (_Insert_base<>::_M_insert_range(_InputIte, _InputIte, _NodeGen&)): 
New.
    (_Insert_base<>::_M_insert_range(_InputIte, _InputIte, true_type)): 
Use latter.
    (_Insert_base<>::_M_insert_range(_InputIte, _InputIte, 
false_type)): Likewise.

    * include/bits/hashtable.h
(_Hashtable<>::operator=(initializer_list)): Likewise.
    (_Hashtable<>::_Hashtable(_InputIte, _InputIte, size_type, const 
_Hash&, const _Equal&,

    const allocator_type&, false_type)): Likewise.

Ok to commit ?

François

diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index 4c12dc895b2..c544094847d 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -614,7 +614,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	if (_M_bucket_count < __l_bkt_count)
 	  rehash(__l_bkt_count);
 
-	this->_M_insert_range(__l.begin(), __l.end(), __roan, __unique_keys{});
+	this->_M_insert_range(__l.begin(), __l.end(), __roan);
 	return *this;
   }
 
@@ -1254,8 +1254,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  }
 
 	__alloc_node_gen_t __node_gen(*this);
-	for (; __f != __l; ++__f)
-	  _M_insert(*__f, __node_gen, __uks);
+	this->_M_insert_range(__f, __l, __node_gen);
   }
 
   template
 	void
 	_M_insert_range(_InputIterator __first, _InputIterator __last,
-			const _NodeGetter&, true_type __uks);
+			const _NodeGetter&);
 
-  template
+  template
 	void
 	_M_insert_range(_InputIterator __first, _InputIterator __last,
-			const _NodeGetter&, false_type __uks);
+			true_type __uks);
+
+  template
+	void
+	_M_insert_range(_InputIterator __first, _InputIterator __last,
+			false_type __uks);
 
 public:
   using iterator = _Node_iterator<_Value, __constant_iterators::value,
@@ -966,11 +971,7 @@ namespace __detail
   template
 	void
 	insert(_InputIterator __first, _InputIterator __last)
-	{
-	  __hashtable& __h = _M_conjure_hashtable();
-	  __node_gen_type __node_gen(__h);
-	  return _M_insert_range(__first, __last, __node_gen, __unique_keys{});
-	}
+	{ _M_insert_range(__first, __last, __unique_keys{}); }
 };
 
   template::
   _M_insert_range(_InputIterator __first, _InputIterator __last,
-		  const _NodeGetter& __node_gen, true_type __uks)
+		  const _NodeGetter& __node_gen)
   {
 	__hashtable& __h = _M_conjure_hashtable();
 	for (; __first != __last; ++__first)
-	  __h._M_insert(*__first, __node_gen, __uks);
+	  __h._M_insert(*__first, __node_gen, __unique_keys{});
   }
 
   template
-template
+template
+  void
+  _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
+		   _Hash, _RangeHash, _Unused,
+		   _RehashPolicy, _Traits>::
+  _M_insert_range(_InputIterator __first, _InputIterator __last,
+		  true_type /* __uks */)
+  {
+	__hashtable& __h = _M_conjure_hashtable();
+	__node_gen_type __node_gen(__h);
+	_M_insert_range(__first, __last, __node_gen);
+  }
+
+  template
+template
   void
   _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal,
 		   _Hash, _RangeHash, _Unused,
 		   _RehashPolicy, _Traits>::
   _M_insert_range(_InputIterator __first, _InputIterator __last,
-		  const _NodeGetter& __node_gen, false_type __uks)
+		  false_type /* __uks */)
   {
 	using __rehash_type = typename __hashtable::__rehash_type;
 	using __rehash_state = typename __hashtable::__rehash_state;
@@ -1020,8 +1038,8 @@ namespace __detail
 	if (__do_rehash.first)
 	  __h._M_rehash(__do_rehash.second, __saved_state);
 
-	for (; __first != __last; ++__first)
-	  __h._M_insert(*__first, __node_gen, __uks);
+	__node_gen_type __node_gen(__h);
+	_M_insert_range(__first, __last, __node_gen);
   }
 
   /**


Re: [PATCH] [11/12/13/14 Regression] ABI break in _Hash_node_value_base since GCC 11 [PR 111050]

2023-09-13 Thread François Dumont via Gcc-patches

Author: TC 
Date:   Wed Sep 6 19:31:55 2023 +0200

    libstdc++: Force _Hash_node_value_base methods inline to fix abi 
(PR111050)


https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=1b6f0476837205932613ddb2b3429a55c26c409d
    changed _Hash_node_value_base to no longer derive from 
_Hash_node_base, which means
    that its member functions expect _M_storage to be at a different 
offset. So explosions
    result if an out-of-line definition is emitted for any of the 
member functions (say,
    in a non-optimized build) and the resulting object file is then 
linked with code built

    using older version of GCC/libstdc++.

    libstdc++-v3/ChangeLog:

    PR libstdc++/111050
    * include/bits/hashtable_policy.h
    (_Hash_node_value_base<>::_M_valptr(), 
_Hash_node_value_base<>::_M_v())

    Add [[__gnu__::__always_inline__]].

Ok to commit ?

On 12/09/2023 18:09, Jonathan Wakely wrote:

On Mon, 11 Sept 2023 at 18:19, François Dumont  wrote:


On 11/09/2023 13:51, Jonathan Wakely wrote:

On Sun, 10 Sept 2023 at 14:57, François Dumont via Libstdc++
 wrote:

Following confirmation of the fix by TC here is the patch where I'm
simply adding a 'constexpr' on _M_next().

Please let me know this ChangeLog entry is correct. I would prefer this
patch to be assigned to 'TC' with me as co-author but I don't know how
to do such a thing. Unless I need to change my user git identity to do so ?

Sam already explained that, but please check with Tim how he wants to
be credited, if at all. He doesn't have a copyright assignment, and
hasn't added a DCO sign-off to the patch, but it's small enough to not
need it as this is the first contribution credited to him.



   libstdc++: Add constexpr qualification to _Hash_node::_M_next()

What has this constexpr addition got to do with the ABI change and the
always_inline attributes?

It certainly doesn't seem like it should be the summary line of the
git commit message.

Oops, sorry, that's what I had started to do before Tim submitted anything.

Here is latest version:

No patch attached, and the ChangeLog below still mentions the constexpr.

I've pinged Tim via another channel to ask him about the author attribution.



Author: TC 
Date:   Wed Sep 6 19:31:55 2023 +0200

  libstdc++: Force inline on _Hash_node_value_base methods to fix abi
(PR111050)

https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=1b6f0476837205932613ddb2b3429a55c26c409d
  changed _Hash_node_value_base to no longer derive from
_Hash_node_base, which means
  that its member functions expect _M_storage to be at a different
offset. So explosions
  result if an out-of-line definition is emitted for any of the
member functions (say,
  in a non-optimized build) and the resulting object file is then
linked with code built
  using older version of GCC/libstdc++.

  libstdc++-v3/ChangeLog:

  PR libstdc++/111050
  * include/bits/hashtable_policy.h
  (_Hash_node_value_base<>::_M_valptr(),
_Hash_node_value_base<>::_M_v())
  Add [[__gnu__::__always_inline__]].
  (_Hash_node<>::_M_next()): Add constexpr.

  Co-authored-by: François Dumont 

Ok for you TC (Tim ?) ?

diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h
index 347d468ea86..86b32fb15f2 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -327,18 +327,22 @@ namespace __detail
 
   __gnu_cxx::__aligned_buffer<_Value> _M_storage;
 
+  [[__gnu__::__always_inline__]]
   _Value*
   _M_valptr() noexcept
   { return _M_storage._M_ptr(); }
 
+  [[__gnu__::__always_inline__]]
   const _Value*
   _M_valptr() const noexcept
   { return _M_storage._M_ptr(); }
 
+  [[__gnu__::__always_inline__]]
   _Value&
   _M_v() noexcept
   { return *_M_valptr(); }
 
+  [[__gnu__::__always_inline__]]
   const _Value&
   _M_v() const noexcept
   { return *_M_valptr(); }


[committed] Limit header synopsis test to normal namespace

2023-09-13 Thread François Dumont via Gcc-patches

Committed as trivial.

    libstdc++: Limit  synopsis test to normal namespace

    libstdc++-v3/ChangeLog

    * testsuite/19_diagnostics/stacktrace/synopsis.cc: Add
    { dg-require-normal-namespace "" }.

François
diff --git a/libstdc++-v3/testsuite/19_diagnostics/stacktrace/synopsis.cc b/libstdc++-v3/testsuite/19_diagnostics/stacktrace/synopsis.cc
index ece5d526fb9..21c94f34a13 100644
--- a/libstdc++-v3/testsuite/19_diagnostics/stacktrace/synopsis.cc
+++ b/libstdc++-v3/testsuite/19_diagnostics/stacktrace/synopsis.cc
@@ -1,6 +1,7 @@
 // { dg-options "-std=gnu++23" }
 // { dg-do compile { target c++23 } }
 // { dg-require-effective-target stacktrace }
+// { dg-require-normal-namespace "" }
 
 #include 
 


Re: [PATCH][_GLIBCXX_INLINE_VERSION] Fix friend declarations

2023-09-13 Thread François Dumont via Gcc-patches

It's working and what's I've committed.

Thanks

On 12/09/2023 19:04, Jonathan Wakely wrote:

On Tue, 12 Sept 2023 at 17:47, Jonathan Wakely  wrote:

On Wed, 23 Aug 2023 at 18:35, François Dumont via Libstdc++
 wrote:

Hi

The few tests that are failing in versioned namespace mode are due to
those friend declarations.

This is a fix proposal even if I considered 2 other options:

1. Make __format::_Arg_store a struct and so do not bother with friend
declarations.

2. Consider it as a compiler bug and do nothing. In this case I think we
might still need this patch to avoid a non-working format library in
versioned namespace mode in gcc 14 if compiler bug is not fixed.

It definitely is a compiler bug, this is PR c++/59256.

Please add a comment to the new macro definition, so we remember to
remove it when it's not needed:


#if _GLIBCXX_INLINE_VERSION
// Needed because of PR c++/59526
# define _GLIBCXX_STD_V std::__8
#else
# define _GLIBCXX_STD_V std
#endif


OK with that change, thanks.

Actually, are you sure the friend std::basic_format_args declaration
needs to change?

I only see errors for the friend function, not the friend class. So
this seems to fix it:

--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -3437,7 +3437,13 @@ namespace __format

   template
friend auto
-   std::make_format_args(_Argz&&...) noexcept;
+#if _GLIBCXX_INLINE_VERSION
+   // Needed for PR c++/59526
+   std::__8::
+#else
+   std::
+#endif
+   make_format_args(_Argz&&...) noexcept;

   // For a sufficiently small number of arguments we only store values.
   // basic_format_args can get the types from the _Args pack.







I can also define _GLIBCXX_STD_V at  level to limit impact.

  libstdc++: [_GLIBCXX_INLINE_VERSION] Fix  friend declarations

  GCC do not consider the inline namespace in friend declarations. We
need
  to explicit this namespace.

  libstdc++-v3/ChangeLog:

  * include/bits/c++config (_GLIBCXX_STD_V): New macro giving
current
  std namespace with optionally the version namespace.
  * include/std/format (std::__format::_Arg_store): Use
latter on friend
  declarations.

Tested under versioned mode.

Ok to commit ?

François


Re: [PATCH] [11/12/13/14 Regression] ABI break in _Hash_node_value_base since GCC 11 [PR 111050]

2023-09-11 Thread François Dumont via Gcc-patches



On 11/09/2023 13:51, Jonathan Wakely wrote:

On Sun, 10 Sept 2023 at 14:57, François Dumont via Libstdc++
 wrote:

Following confirmation of the fix by TC here is the patch where I'm
simply adding a 'constexpr' on _M_next().

Please let me know this ChangeLog entry is correct. I would prefer this
patch to be assigned to 'TC' with me as co-author but I don't know how
to do such a thing. Unless I need to change my user git identity to do so ?

Sam already explained that, but please check with Tim how he wants to
be credited, if at all. He doesn't have a copyright assignment, and
hasn't added a DCO sign-off to the patch, but it's small enough to not
need it as this is the first contribution credited to him.



  libstdc++: Add constexpr qualification to _Hash_node::_M_next()

What has this constexpr addition got to do with the ABI change and the
always_inline attributes?

It certainly doesn't seem like it should be the summary line of the
git commit message.


Oops, sorry, that's what I had started to do before Tim submitted anything.

Here is latest version:

Author: TC 
Date:   Wed Sep 6 19:31:55 2023 +0200

    libstdc++: Force inline on _Hash_node_value_base methods to fix abi 
(PR111050)


https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=1b6f0476837205932613ddb2b3429a55c26c409d
    changed _Hash_node_value_base to no longer derive from 
_Hash_node_base, which means
    that its member functions expect _M_storage to be at a different 
offset. So explosions
    result if an out-of-line definition is emitted for any of the 
member functions (say,
    in a non-optimized build) and the resulting object file is then 
linked with code built

    using older version of GCC/libstdc++.

    libstdc++-v3/ChangeLog:

    PR libstdc++/111050
    * include/bits/hashtable_policy.h
    (_Hash_node_value_base<>::_M_valptr(), 
_Hash_node_value_base<>::_M_v())

    Add [[__gnu__::__always_inline__]].
    (_Hash_node<>::_M_next()): Add constexpr.

    Co-authored-by: François Dumont 

Ok for you TC (Tim ?) ?




[PATCH] [11/12/13/14 Regression] ABI break in _Hash_node_value_base since GCC 11 [PR 111050]

2023-09-10 Thread François Dumont via Gcc-patches
Following confirmation of the fix by TC here is the patch where I'm 
simply adding a 'constexpr' on _M_next().


Please let me know this ChangeLog entry is correct. I would prefer this 
patch to be assigned to 'TC' with me as co-author but I don't know how 
to do such a thing. Unless I need to change my user git identity to do so ?


    libstdc++: Add constexpr qualification to _Hash_node::_M_next()

https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=1b6f0476837205932613ddb2b3429a55c26c409d
    changed _Hash_node_value_base to no longer derive from 
_Hash_node_base, which means
    that its member functions expect _M_storage to be at a different 
offset. So explosions
    result if an out-of-line definition is emitted for any of the 
member functions (say,
    in a non-optimized build) and the resulting object file is then 
linked with code built

    using older version of GCC/libstdc++.

    libstdc++-v3/ChangeLog:

    * include/bits/hashtable_policy.h
    (_Hash_node_value_base<>::_M_valptr(), 
_Hash_node_value_base<>::_M_v())

    Add [[__gnu__::__always_inline__]].
    (_Hash_node<>::_M_next()): Add constexpr.

    Co-authored-by: TC 

Ok to commit and backport to GCC 11, 12, 13 branches ?

François

diff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h
index 347d468ea86..101c5eb639c 100644
--- a/libstdc++-v3/include/bits/hashtable_policy.h
+++ b/libstdc++-v3/include/bits/hashtable_policy.h
@@ -327,18 +327,22 @@ namespace __detail
 
   __gnu_cxx::__aligned_buffer<_Value> _M_storage;
 
+  [[__gnu__::__always_inline__]]
   _Value*
   _M_valptr() noexcept
   { return _M_storage._M_ptr(); }
 
+  [[__gnu__::__always_inline__]]
   const _Value*
   _M_valptr() const noexcept
   { return _M_storage._M_ptr(); }
 
+  [[__gnu__::__always_inline__]]
   _Value&
   _M_v() noexcept
   { return *_M_valptr(); }
 
+  [[__gnu__::__always_inline__]]
   const _Value&
   _M_v() const noexcept
   { return *_M_valptr(); }
@@ -372,7 +376,7 @@ namespace __detail
 : _Hash_node_base
 , _Hash_node_value<_Value, _Cache_hash_code>
 {
-  _Hash_node*
+  constexpr _Hash_node*
   _M_next() const noexcept
   { return static_cast<_Hash_node*>(this->_M_nxt); }
 };


Re: [PATCH][_GLIBCXX_INLINE_VERSION] Fix friend declarations

2023-09-07 Thread François Dumont via Gcc-patches

Hi

Any news regarding this problem ?

François

On 23/08/2023 19:35, François Dumont wrote:

Hi

The few tests that are failing in versioned namespace mode are due to 
those friend declarations.


This is a fix proposal even if I considered 2 other options:

1. Make __format::_Arg_store a struct and so do not bother with friend 
declarations.


2. Consider it as a compiler bug and do nothing. In this case I think 
we might still need this patch to avoid a non-working format library 
in versioned namespace mode in gcc 14 if compiler bug is not fixed.


I can also define _GLIBCXX_STD_V at  level to limit impact.

    libstdc++: [_GLIBCXX_INLINE_VERSION] Fix  friend declarations

    GCC do not consider the inline namespace in friend declarations. 
We need

    to explicit this namespace.

    libstdc++-v3/ChangeLog:

    * include/bits/c++config (_GLIBCXX_STD_V): New macro 
giving current

    std namespace with optionally the version namespace.
    * include/std/format (std::__format::_Arg_store): Use 
latter on friend

    declarations.

Tested under versioned mode.

Ok to commit ?

François


Re: [PATCH][Hashtable] Performance optimization through use of insertion hint

2023-09-07 Thread François Dumont via Gcc-patches



On 01/09/2023 10:59, Jonathan Wakely wrote:

On Tue, 29 Aug 2023 at 20:52, François Dumont via Libstdc++
 wrote:

Hi

Any feedback regarding this patch ?

This is a fairly large patch


I've decided to split it, at least in 2.

So just ignore this one, I'll submit new ones once abi issue is fixed.


  and before we make any more changes to
unordered containers we have an ABI break to fix:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111050



François

On 24/07/2023 13:02, François Dumont wrote:

libstdc++: [_Hashtable] Make more use of insertion hint


 When inserting an element into an empty bucket we currently insert
the new node
 after the before-begin node so in first position. The drawback of
doing this is
 that we are forced to update the bucket that was containing this
before-begin
 node to point to the newly inserted node. To do so we need at best
to do a modulo
 to find this bucket and when hash code is not cached also compute it.

 To avoid this side effect it is better to insert after the last
node. Adding
 a member to keep track of this last node would be an abi breaking
change. Still we
 can ask the user to maintain and provide this last node as an
insertion hint.

 Adapt range insertion methods to try to detect the last node and
then use it as
 the insertion hint.

 libstdc++-v3/ChangeLog:

 * include/bits/hashtable_policy.h:
 (_Insert_base::try_emplace): Adapt to use hint.
 (_Insert_base::_M_insert_range): Try to detect container
last node and use it
 as hint for insertions.
 (_Hash_code_base::_M_hash_code(const _Hash&, const
_Hash_node_value<>&)): Remove.
 (_Hash_code_base::_M_hash_code<_H2>(const _H2&, const
_Hash_node_value<>&)): Remove.
 * include/bits/hashtable.h
 (_Hashtable<>::_M_insert_bucket_begin): Add hint parameter
and use it when inserting
 into an empty bucket if hint is the last container node.
 (_Hashtable<>::_InsertInfo): New struct.
 (_Hashtable<>::_M_get_insert_info): New, return latter.
 (_Hashtable<>::_M_insert_multi_node): Add _InsertInfo
parameter.
 (_Hashtable<>::_M_insert_unique_node): Add __node_ptr hint
parameter.
 (_Hashtable<>::_M_emplace_unique(__node_ptr, _Args&&...)):
New.
 (_Hashtable<>::_M_emplace_multi(__node_ptr, _Args&&...)):
New.
 (_Hashtable<>::_M_emplace()): Adapt to use latters.
 (_Hashtable<>::_M_insert_unique): Add __node_ptr parameter.
 (_Hashtable<>::_M_insert_unique_aux): Add __node_ptr
parameter.
 (_Hashtable<>::_M_insert(__node_ptr, _Arg&&, const
_NodeGenerator&, true_type)):
 Use latter.
 (_Hashtable<>::_M_reinsert_node(const_iterator,
node_type&&)):
 Add hint parameter, adapt to use it.
 (_Hashtable<>::_M_reinsert_node_multi): Use hint parameter
if available to extract
 hash code.
 (_Hashtable<>::_M_compute_hash_code(const _Hash&,
__node_ptr, __node_ptr,
 const key_type&)): New.
(_Hashtable<>::_M_compute_hash_code<_H2>(const _H2&, __node_ptr,
__node_ptr,
 const key_type&)): New.
 (_Hashtable<>::_M_merge_unique): Adapt to use latter.
Implement small size
 optimization.
 (_Hashtable<>::_M_get_insert_info(const _Hash&,
__node_ptr, __node_ptr,
 const key_type&)): New.
(_Hashtable<>::_M_get_insert_info<_H2>(const _H2&, __node_ptr,
__node_ptr,
 const key_type&)): New.
 (_Hashtable<>::_M_merge_multi): Adapt to use latter.
 * include/bits/unordered_map.h
(unordered_map<>::insert(node_type&&)): Pass cend as
 hint.
 (unordered_map<>::insert(const_iterator, node_type&&)):
Adapt to use hint.
 * include/bits/unordered_set.h
(unordered_set<>::insert(node_type&&)): Pass cend as
 hint.
 (unordered_set<>::insert(const_iterator, node_type&&)):
Adapt to use hint.
 *
testsuite/23_containers/unordered_multimap/insert/hint.cc: Adapt
implementation
 specific tests.

Tested under linux x86_64.

Here is the performance results of this patch, before:

unordered_multiset_hint.cc-threadhash code NOT cached 200
insertions w/o hint  94r   94u0s 191999712mem0pf
unordered_multiset_hint.cc-threadhash code NOT cached 200
insertions with perfect hint  95r   94u0s 191999712mem 0pf
unordered_multiset_hint.cc-threadhash code NOT cached 200
insertions with bad hint  94r   94u0s 191999712mem0pf
unordered_multis

Re: [PATCH][Hashtable] Performance optimization through use of insertion hint

2023-08-29 Thread François Dumont via Gcc-patches

Hi

Any feedback regarding this patch ?

François

On 24/07/2023 13:02, François Dumont wrote:

libstdc++: [_Hashtable] Make more use of insertion hint


    When inserting an element into an empty bucket we currently insert 
the new node
    after the before-begin node so in first position. The drawback of 
doing this is
    that we are forced to update the bucket that was containing this 
before-begin
    node to point to the newly inserted node. To do so we need at best 
to do a modulo

    to find this bucket and when hash code is not cached also compute it.

    To avoid this side effect it is better to insert after the last 
node. Adding
    a member to keep track of this last node would be an abi breaking 
change. Still we
    can ask the user to maintain and provide this last node as an 
insertion hint.


    Adapt range insertion methods to try to detect the last node and 
then use it as

    the insertion hint.

    libstdc++-v3/ChangeLog:

    * include/bits/hashtable_policy.h:
    (_Insert_base::try_emplace): Adapt to use hint.
    (_Insert_base::_M_insert_range): Try to detect container 
last node and use it

    as hint for insertions.
    (_Hash_code_base::_M_hash_code(const _Hash&, const 
_Hash_node_value<>&)): Remove.
    (_Hash_code_base::_M_hash_code<_H2>(const _H2&, const 
_Hash_node_value<>&)): Remove.

    * include/bits/hashtable.h
    (_Hashtable<>::_M_insert_bucket_begin): Add hint parameter 
and use it when inserting

    into an empty bucket if hint is the last container node.
    (_Hashtable<>::_InsertInfo): New struct.
    (_Hashtable<>::_M_get_insert_info): New, return latter.
    (_Hashtable<>::_M_insert_multi_node): Add _InsertInfo 
parameter.
    (_Hashtable<>::_M_insert_unique_node): Add __node_ptr hint 
parameter.
    (_Hashtable<>::_M_emplace_unique(__node_ptr, _Args&&...)): 
New.
    (_Hashtable<>::_M_emplace_multi(__node_ptr, _Args&&...)): 
New.

    (_Hashtable<>::_M_emplace()): Adapt to use latters.
    (_Hashtable<>::_M_insert_unique): Add __node_ptr parameter.
    (_Hashtable<>::_M_insert_unique_aux): Add __node_ptr 
parameter.
    (_Hashtable<>::_M_insert(__node_ptr, _Arg&&, const 
_NodeGenerator&, true_type)):

    Use latter.
    (_Hashtable<>::_M_reinsert_node(const_iterator, 
node_type&&)):

    Add hint parameter, adapt to use it.
    (_Hashtable<>::_M_reinsert_node_multi): Use hint parameter 
if available to extract

    hash code.
    (_Hashtable<>::_M_compute_hash_code(const _Hash&, 
__node_ptr, __node_ptr,

    const key_type&)): New.
(_Hashtable<>::_M_compute_hash_code<_H2>(const _H2&, __node_ptr, 
__node_ptr,

    const key_type&)): New.
    (_Hashtable<>::_M_merge_unique): Adapt to use latter. 
Implement small size

    optimization.
    (_Hashtable<>::_M_get_insert_info(const _Hash&, 
__node_ptr, __node_ptr,

    const key_type&)): New.
(_Hashtable<>::_M_get_insert_info<_H2>(const _H2&, __node_ptr, 
__node_ptr,

    const key_type&)): New.
    (_Hashtable<>::_M_merge_multi): Adapt to use latter.
    * include/bits/unordered_map.h 
(unordered_map<>::insert(node_type&&)): Pass cend as

    hint.
    (unordered_map<>::insert(const_iterator, node_type&&)): 
Adapt to use hint.
    * include/bits/unordered_set.h 
(unordered_set<>::insert(node_type&&)): Pass cend as

    hint.
    (unordered_set<>::insert(const_iterator, node_type&&)): 
Adapt to use hint.
    * 
testsuite/23_containers/unordered_multimap/insert/hint.cc: Adapt 
implementation

    specific tests.

Tested under linux x86_64.

Here is the performance results of this patch, before:

unordered_multiset_hint.cc-thread    hash code NOT cached 200 
insertions w/o hint      94r   94u    0s 191999712mem    0pf
unordered_multiset_hint.cc-thread    hash code NOT cached 200 
insertions with perfect hint      95r   94u    0s 191999712mem 0pf
unordered_multiset_hint.cc-thread    hash code NOT cached 200 
insertions with bad hint      94r   94u    0s 191999712mem    0pf
unordered_multiset_hint.cc-thread    hash code NOT cached 200 
range insertions      88r   88u    0s 191999712mem    0pf
unordered_multiset_hint.cc-thread    hash code cached 200 
insertions w/o hint      91r   91u    0s 191999712mem    0pf
unordered_multiset_hint.cc-thread    hash code cached 200 
insertions with perfect hint      92r   93u    0s 191999712mem 0pf
unordered_multiset_hint.cc-thread    hash code 

Re: [PATCH] sso-string@gnu-versioned-namespace [PR83077]

2023-08-24 Thread François Dumont via Gcc-patches

I've now prepared the patch to support following config:

--disable-libstdcxx-dual-abi --with-default-libstdcxx-abi=new

and so detected yet another problem with src/c++98/compatibility.cc. We 
need basic_istream<>::ignore(streamsize) definitions that rely here but 
not the rest of it.


François

On 17/08/2023 19:17, François Dumont wrote:


Another fix to define __cow_string(const std::string&) in 
cxx11-stdexcept.cc even if ! _GLIBCXX_USE_DUAL_ABI.


On 13/08/2023 21:51, François Dumont wrote:


Here is another version with enhanced sizeof/alignof static_assert in 
string-inst.cc for the std::__cow_string definition from . 
The assertions in cow-stdexcept.cc are now checking the definition 
which is in the same file.


On 13/08/2023 15:27, François Dumont wrote:


Here is the fixed patch tested in all 3 modes:

- _GLIBCXX_USE_DUAL_ABI

- !_GLIBCXX_USE_DUAL_ABI && !_GLIBCXX_USE_CXX11_ABI

- !_GLIBCXX_USE_DUAL_ABI && _GLIBCXX_USE_CXX11_ABI

I don't know what you have in mind for the change below but I wanted 
to let you know that I tried to put COW std::basic_string into a 
nested __cow namespace when _GLIBCXX_USE_CXX11_ABI. But it had more 
impact on string-inst.cc so I preferred the macro substitution approach.


There are some test failing when !_GLIBCXX_USE_CXX11_ABI that are 
unrelated with my changes. I'll propose fixes in coming days.


    libstdc++: [_GLIBCXX_INLINE_VERSION] Use cxx11 abi [PR83077]

    Use cxx11 abi when activating versioned namespace mode. To do 
support
    a new configuration mode where !_GLIBCXX_USE_DUAL_ABI and 
_GLIBCXX_USE_CXX11_ABI.


    The main change is that std::__cow_string is now defined 
whenever _GLIBCXX_USE_DUAL_ABI
    or _GLIBCXX_USE_CXX11_ABI is true. Implementation is using 
available std::string in

    case of dual abi and a subset of it when it's not.

    On the other side std::__sso_string is defined only when 
_GLIBCXX_USE_DUAL_ABI is true
    and _GLIBCXX_USE_CXX11_ABI is false. Meaning that 
std::__sso_string is a typedef for the
    cow std::string implementation when dual abi is disabled and cow 
string is being used.


    libstdcxx-v3/ChangeLog:

    PR libstdc++/83077
    * acinclude.m4 [GLIBCXX_ENABLE_LIBSTDCXX_DUAL_ABI]: 
Default to "new" libstdcxx abi.
    * config/locale/dragonfly/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Define money_base

    members.
    * config/locale/generic/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Likewise.
    * config/locale/gnu/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Likewise.

    * config/locale/gnu/numeric_members.cc
[!_GLIBCXX_USE_DUAL_ABI](__narrow_multibyte_chars): Define.
    * configure: Regenerate.
    * include/bits/c++config
[_GLIBCXX_INLINE_VERSION](_GLIBCXX_NAMESPACE_CXX11, 
_GLIBCXX_BEGIN_NAMESPACE_CXX11):

    Define empty.
[_GLIBCXX_INLINE_VERSION](_GLIBCXX_END_NAMESPACE_CXX11, 
_GLIBCXX_DEFAULT_ABI_TAG):

    Likewise.
    * include/bits/cow_string.h [!_GLIBCXX_USE_CXX11_ABI]: 
Define a light version of COW

    basic_string as __std_cow_string for use in stdexcept.
    * include/std/stdexcept [_GLIBCXX_USE_CXX11_ABI]: Define 
__cow_string.

    (__cow_string(const char*)): New.
    (__cow_string::c_str()): New.
    * python/libstdcxx/v6/printers.py 
(StdStringPrinter::__init__): Set self.new_string to True

    when std::__8::basic_string type is found.
    * src/Makefile.am 
[ENABLE_SYMVERS_GNU_NAMESPACE](ldbl_alt128_compat_sources): Define 
empty.

    * src/Makefile.in: Regenerate.
    * src/c++11/Makefile.am (cxx11_abi_sources): Rename into...
    (dual_abi_sources): ...this. Also move 
cow-local_init.cc, cxx11-hash_tr1.cc,

    cxx11-ios_failure.cc entries to...
    (sources): ...this.
    (extra_string_inst_sources): Move cow-fstream-inst.cc, 
cow-sstream-inst.cc, cow-string-inst.cc,
    cow-string-io-inst.cc, cow-wtring-inst.cc, 
cow-wstring-io-inst.cc, cxx11-locale-inst.cc,

    cxx11-wlocale-inst.cc entries to...
    (inst_sources): ...this.
    * src/c++11/Makefile.in: Regenerate.
    * src/c++11/cow-fstream-inst.cc 
[_GLIBCXX_USE_CXX11_ABI]: Skip definitions.
    * src/c++11/cow-locale_init.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-sstream-inst.cc 
[_GLIBCXX_USE_CXX11_ABI]: Skip definitions.
    * src/c++11/cow-stdexcept.cc [_GLIBCXX_USE_CXX11_ABI]: 
Include .
    [_GLIBCXX_USE_DUAL_ABI || 
_GLIBCXX_USE_CXX11_ABI](__cow_string): Redefine before
    including . Define 
_GLIBCXX_DEFINE_STDEXCEPT_INSTANTIATIONS so that

    __cow_string definition in  is skipped.
    [_GLIBCXX_USE_CXX11_ABI]: Skip Transaction Memory TS 
definitions.
    Move static_assert to check std::_cow_string abi layout 
to...

  

[PATCH][_GLIBCXX_INLINE_VERSION] Fix friend declarations

2023-08-23 Thread François Dumont via Gcc-patches

Hi

The few tests that are failing in versioned namespace mode are due to 
those friend declarations.


This is a fix proposal even if I considered 2 other options:

1. Make __format::_Arg_store a struct and so do not bother with friend 
declarations.


2. Consider it as a compiler bug and do nothing. In this case I think we 
might still need this patch to avoid a non-working format library in 
versioned namespace mode in gcc 14 if compiler bug is not fixed.


I can also define _GLIBCXX_STD_V at  level to limit impact.

    libstdc++: [_GLIBCXX_INLINE_VERSION] Fix  friend declarations

    GCC do not consider the inline namespace in friend declarations. We 
need

    to explicit this namespace.

    libstdc++-v3/ChangeLog:

    * include/bits/c++config (_GLIBCXX_STD_V): New macro giving 
current

    std namespace with optionally the version namespace.
    * include/std/format (std::__format::_Arg_store): Use 
latter on friend

    declarations.

Tested under versioned mode.

Ok to commit ?

François
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index 0a41cdd29a9..a917fb58225 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -449,6 +449,7 @@ _GLIBCXX_END_NAMESPACE_VERSION
 // of some nested namespace within it corresponding to the active mode.
 // _GLIBCXX_STD_A
 // _GLIBCXX_STD_C
+// _GLIBCXX_STD_V
 //
 // Macros for opening/closing conditional namespaces.
 // _GLIBCXX_BEGIN_NAMESPACE_ALGO
@@ -477,6 +478,12 @@ _GLIBCXX_END_NAMESPACE_VERSION
 # define _GLIBCXX_END_NAMESPACE_ALGO
 #endif
 
+#if _GLIBCXX_INLINE_VERSION
+# define _GLIBCXX_STD_V std::__8
+#else
+# define _GLIBCXX_STD_V std
+#endif
+
 // GLIBCXX_ABI Deprecated
 // Define if compatibility should be provided for -mlong-double-64.
 #undef _GLIBCXX_LONG_DOUBLE_COMPAT
diff --git a/libstdc++-v3/include/std/format b/libstdc++-v3/include/std/format
index f3d9ae152f9..94417c321e4 100644
--- a/libstdc++-v3/include/std/format
+++ b/libstdc++-v3/include/std/format
@@ -3429,11 +3429,11 @@ namespace __format
   template
 class __format::_Arg_store
 {
-  friend std::basic_format_args<_Context>;
+  friend _GLIBCXX_STD_V::basic_format_args<_Context>;
 
   template
 	friend auto
-	std::make_format_args(_Argz&&...) noexcept;
+	_GLIBCXX_STD_V::make_format_args(_Argz&&...) noexcept;
 
   // For a sufficiently small number of arguments we only store values.
   // basic_format_args can get the types from the _Args pack.


Re: [PATCH] Fix tests sensitive to internal library allocations

2023-08-23 Thread François Dumont via Gcc-patches



On 21/08/2023 23:26, Jonathan Wakely wrote:

On Mon, 21 Aug 2023 at 21:20, François Dumont  wrote:

Here is the updated and tested patch.

OK for trunk, thanks.

We could consider it for the branches too (I'm going to remove the
global strings on the gcc-13 branch tomorrow).


It's not fixing anything so I don't think it worth it but let me know if 
you want me to do so.





Re: [PATCH] Fix tests sensitive to internal library allocations

2023-08-21 Thread François Dumont via Gcc-patches

Here is the updated and tested patch.

On 21/08/2023 20:07, Jonathan Wakely wrote:

On Mon, 21 Aug 2023 at 18:05, François Dumont via Libstdc++
 wrote:

Hi

Here is a propocal to fix tests sensitive to libstdc++ internal allocations.

Surely the enter() and exit() calls should be a constructor and destructor?

The constructor could use count() to get the count, and then restore
it in the destructor. Something like:

--- a/libstdc++-v3/testsuite/util/replacement_memory_operators.h
+++ b/libstdc++-v3/testsuite/util/replacement_memory_operators.h
@@ -75,12 +75,30 @@ namespace __gnu_test
   counter& cntr = get();
   cntr._M_increments = cntr._M_decrements = 0;
 }
+
+struct scope
+{
+  scope() : _M_count(counter::count()) { }
+  ~scope() { counter::get()._M_count = _M_count; }
+
+private:
+  std::size_t _M_count;
+
+#if __cplusplus >= 201103L
+  scope(const scope&) = delete;
+  scope& operator=(const scope&) = delete;
+#else
+  scope(const scope&);
+  scope& operator=(const scope&);
+#endif
+};
   };

   template
 bool
 check_new(Alloc a = Alloc())
 {
+  __gnu_test::counter::scope s;
   __gnu_test::counter::exceptions(false);
   __gnu_test::counter::reset();
   (void) a.allocate(10);







Tested by restoring allocation in tzdb.cc.

As announced I'm also adding a test to detect such allocations. If it is
ok let me know if you prefer to see it in a different place.

The test is a good idea. I think 17_intro/no_library_allocation.cc
would be a better place for it.


  libstdc++: Fix tests relying on operator new/delete overload

  Fix tests that are checking for an allocation plan. They are failing if
  an allocation is taking place outside the test.

  libstdc++-v3/ChangeLog

  * testsuite/util/replacement_memory_operators.h
  (counter::_M_pre_enter_count): New.
  (counter::enter, counter::exit): New static methods to call
on main() enter/exit.
  * testsuite/23_containers/unordered_map/96088.cc (main):
  Call __gnu_test::counter::enter/exit.
  * testsuite/23_containers/unordered_multimap/96088.cc
(main): Likewise.
  * testsuite/23_containers/unordered_multiset/96088.cc
(main): Likewise.
  * testsuite/23_containers/unordered_set/96088.cc (main):
Likewise.
  * testsuite/ext/malloc_allocator/deallocate_local.cc
(main): Likewise.
  * testsuite/ext/new_allocator/deallocate_local.cc (main):
Likewise.
  * testsuite/ext/throw_allocator/deallocate_local.cc (main):
Likewise.
  * testsuite/ext/pool_allocator/allocate_chunk.cc (started):
New global.
  (operator new(size_t)): Check started.
  (main): Set/Unset started.
  * testsuite/ext/no_library_allocation.cc: New test case.

Ok to commit ?

Françoisdiff --git a/libstdc++-v3/testsuite/17_intro/no_library_allocation.cc b/libstdc++-v3/testsuite/17_intro/no_library_allocation.cc
new file mode 100644
index 000..278d4757c93
--- /dev/null
+++ b/libstdc++-v3/testsuite/17_intro/no_library_allocation.cc
@@ -0,0 +1,8 @@
+#include 
+#include 
+
+int main()
+{
+  VERIFY( __gnu_test::counter::count() == 0 );
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/96088.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/96088.cc
index c6d50c20fbf..cdf00c93d80 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_map/96088.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/96088.cc
@@ -268,6 +268,7 @@ test03()
 int
 main()
 {
+  __gnu_test::counter::scope s;
   test01();
   test02();
   test11();
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/96088.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/96088.cc
index 214bc91a559..d8b9a40c174 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/96088.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/96088.cc
@@ -61,6 +61,7 @@ test02()
 int
 main()
 {
+  __gnu_test::counter::scope s;
   test01();
   test02();
   return 0;
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/96088.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/96088.cc
index 838ce8d5bc5..db17cda0ddd 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/96088.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/96088.cc
@@ -61,6 +61,7 @@ test02()
 int
 main()
 {
+  __gnu_test::counter::scope s;
   test01();
   test02();
   return 0;
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/96088.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/96088.cc
index 0f7dce2b38c..831f2aa1210 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_set/96088.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/96088.cc
@@ -269,6 +269,7 @@ test03()
 int
 main()
 {
+  __gnu_test::counter::

[PATCH] Fix tests sensitive to internal library allocations

2023-08-21 Thread François Dumont via Gcc-patches

Hi

Here is a propocal to fix tests sensitive to libstdc++ internal allocations.

Tested by restoring allocation in tzdb.cc.

As announced I'm also adding a test to detect such allocations. If it is 
ok let me know if you prefer to see it in a different place.


    libstdc++: Fix tests relying on operator new/delete overload

    Fix tests that are checking for an allocation plan. They are failing if
    an allocation is taking place outside the test.

    libstdc++-v3/ChangeLog

    * testsuite/util/replacement_memory_operators.h
    (counter::_M_pre_enter_count): New.
    (counter::enter, counter::exit): New static methods to call 
on main() enter/exit.

    * testsuite/23_containers/unordered_map/96088.cc (main):
    Call __gnu_test::counter::enter/exit.
    * testsuite/23_containers/unordered_multimap/96088.cc 
(main): Likewise.
    * testsuite/23_containers/unordered_multiset/96088.cc 
(main): Likewise.
    * testsuite/23_containers/unordered_set/96088.cc (main): 
Likewise.
    * testsuite/ext/malloc_allocator/deallocate_local.cc 
(main): Likewise.
    * testsuite/ext/new_allocator/deallocate_local.cc (main): 
Likewise.
    * testsuite/ext/throw_allocator/deallocate_local.cc (main): 
Likewise.
    * testsuite/ext/pool_allocator/allocate_chunk.cc (started): 
New global.

    (operator new(size_t)): Check started.
    (main): Set/Unset started.
    * testsuite/ext/no_library_allocation.cc: New test case.

Ok to commit ?

François
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/96088.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/96088.cc
index c6d50c20fbf..bcae891e5ec 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_map/96088.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/96088.cc
@@ -268,6 +268,7 @@ test03()
 int
 main()
 {
+  __gnu_test::counter::enter();
   test01();
   test02();
   test11();
@@ -275,5 +276,6 @@ main()
   test21();
   test22();
   test03();
+  __gnu_test::counter::exit();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/96088.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/96088.cc
index 214bc91a559..9f16ad68218 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multimap/96088.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/96088.cc
@@ -61,7 +61,9 @@ test02()
 int
 main()
 {
+  __gnu_test::counter::enter();
   test01();
   test02();
+  __gnu_test::counter::exit();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/96088.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/96088.cc
index 838ce8d5bc5..b34cfe67092 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_multiset/96088.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/96088.cc
@@ -61,7 +61,9 @@ test02()
 int
 main()
 {
+  __gnu_test::counter::enter();
   test01();
   test02();
+  __gnu_test::counter::exit();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/96088.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/96088.cc
index 0f7dce2b38c..d5717fcec2b 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_set/96088.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/96088.cc
@@ -269,6 +269,7 @@ test03()
 int
 main()
 {
+  __gnu_test::counter::enter();
   test01();
   test02();
   test11();
@@ -277,5 +278,6 @@ main()
   test22();
   test23();
   test03();
+  __gnu_test::counter::exit();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/ext/malloc_allocator/deallocate_local.cc b/libstdc++-v3/testsuite/ext/malloc_allocator/deallocate_local.cc
index 79b583bd716..3aa65f298b1 100644
--- a/libstdc++-v3/testsuite/ext/malloc_allocator/deallocate_local.cc
+++ b/libstdc++-v3/testsuite/ext/malloc_allocator/deallocate_local.cc
@@ -27,6 +27,7 @@ typedef std::basic_string string_t;
 
 int main()
 {
+  __gnu_test::counter::enter();
   {
 string_t s;
 s += "bayou bend";
@@ -34,5 +35,7 @@ int main()
 
   if (__gnu_test::counter::count() != 0)
 throw std::runtime_error("count not zero");
+
+  __gnu_test::counter::exit();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/ext/new_allocator/deallocate_local.cc b/libstdc++-v3/testsuite/ext/new_allocator/deallocate_local.cc
index fcde46e6e10..ac4996698c7 100644
--- a/libstdc++-v3/testsuite/ext/new_allocator/deallocate_local.cc
+++ b/libstdc++-v3/testsuite/ext/new_allocator/deallocate_local.cc
@@ -27,6 +27,7 @@ typedef std::basic_string string_t;
 
 int main()
 {
+  __gnu_test::counter::enter();
   {
 string_t s;
 s += "bayou bend";
@@ -34,5 +35,7 @@ int main()
 
   if (__gnu_test::counter::count() != 0)
 throw std::runtime_error("count not zero");
+
+  __gnu_test::counter::exit();
   return 0;
 }
diff --git a/libstdc++-v3/testsuite/ext/no_library_allocation.cc b/libstdc++-v3/testsuite/ext/no_library_allocation.cc
new 

Re: [PATCH] sso-string@gnu-versioned-namespace [PR83077]

2023-08-19 Thread François Dumont via Gcc-patches

Here is a rebased patch following the resize_and_overwrite change.

I confirm that tests are now fixed after the change in tzdb.cc.

I'll prepare a fix for those tests still but preparing also a test to 
detect allocations in the lib.


François

On 17/08/2023 21:44, Jonathan Wakely wrote:

On Thu, 17 Aug 2023 at 20:37, Jonathan Wakely  wrote:

On Thu, 17 Aug 2023 at 19:59, Jonathan Wakely  wrote:

On Thu, 17 Aug 2023 at 18:40, François Dumont  wrote:


On 17/08/2023 19:22, Jonathan Wakely wrote:

On Sun, 13 Aug 2023 at 14:27, François Dumont via Libstdc++
 wrote:

Here is the fixed patch tested in all 3 modes:

- _GLIBCXX_USE_DUAL_ABI

- !_GLIBCXX_USE_DUAL_ABI && !_GLIBCXX_USE_CXX11_ABI

- !_GLIBCXX_USE_DUAL_ABI && _GLIBCXX_USE_CXX11_ABI

I don't know what you have in mind for the change below but I wanted to
let you know that I tried to put COW std::basic_string into a nested
__cow namespace when _GLIBCXX_USE_CXX11_ABI. But it had more impact on
string-inst.cc so I preferred the macro substitution approach.

I was thinking of implementing the necessary special members functions
of __cow_string directly, so they are ABI compatible with the COW
std::basic_string but don't actually reuse the code. That would mean
we don't need to compile and instantiate the whole COW string just to
use a few members from it. But that can be done later, the macro
approach seems OK for now.

You'll see that when cow_string.h is included while
_GLIBCXX_USE_CXX11_ABI == 1 then I am hiding a big part of the
basic_string definition. Initially it was to avoid to have to include
basic_string.tcc but it is also a lot of useless code indeed.



There are some test failing when !_GLIBCXX_USE_CXX11_ABI that are
unrelated with my changes. I'll propose fixes in coming days.

Which tests? I run the entire testsuite with
-D_GLIBCXX_USE_CXX11_ABI=0 several times per day and I'm not seeing
failures.

I'll review the patch ASAP, thanks for working on it.


So far the only issue I found are in the mode !_GLIBCXX_USE_DUAL_ABI &&
!_GLIBCXX_USE_CXX11_ABI. They are:

23_containers/unordered_map/96088.cc
23_containers/unordered_multimap/96088.cc
23_containers/unordered_multiset/96088.cc
23_containers/unordered_set/96088.cc
ext/debug_allocator/check_new.cc
ext/malloc_allocator/check_new.cc
ext/malloc_allocator/deallocate_local.cc
ext/new_allocator/deallocate_local.cc
ext/pool_allocator/allocate_chunk.cc
ext/throw_allocator/deallocate_local.cc

Ah yes, they fail for !USE_DUAL_ABI builds, I wonder why.

/home/test/src/gcc/libstdc++-v3/testsuite/23_containers/unordered_map/96088.
cc:44: void test01(): Assertion '__gnu_test::counter::count() == 3' failed.
FAIL: 23_containers/unordered_map/96088.cc execution test

It's due to this global object in src/c++20/tzdb.cc:
1081const string tzdata_file = "/tzdata.zi";

When the library uses COW strings that requires an allocation before
main, which uses the replacement operator new in the tests, which
fails to allocate. For example, in 22_locale/locale/cons/12352.cc we
have this function used by operator new:

int times_to_fail = 0;

void* allocate(std::size_t n)
{
   if (!times_to_fail--)
 return 0;

The counter is initially zero, so if we try to allocate before it gets
set to a non-zero value in test01() then we fail.

The test should not assume no allocations before main() begins. The
simplest way to do that is with another global that says "we have
started testing" e.g.

--- a/libstdc++-v3/testsuite/22_locale/locale/cons/12352.cc
+++ b/libstdc++-v3/testsuite/22_locale/locale/cons/12352.cc
@@ -26,11 +26,12 @@
  #include 
  #include 

+bool tests_started = false;
  int times_to_fail = 0;

  void* allocate(std::size_t n)
  {
-  if (!times_to_fail--)
+  if (tests_started && !times_to_fail--)
  return 0;

void* ret = std::malloc(n ? n : 1);
@@ -106,6 +107,8 @@ void operator delete[](void* p, const
std::nothrow_t&) throw()
  // libstdc++/12352
  void test01(int iters)
  {
+  tests_started = true;
+
for (int j = 0; j < iters; ++j)
  {
for (int i = 0; i < 100; ++i)


This way the replacement operator new doesn't start intentionally
failing until we ask it to do so.

I'll replace the global std::string objects with std::string_view
objects, so that they don't allocate even if the library only uses COW
strings.

We should still fix those tests though.
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index b25378eaace..322f1e42611 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -4875,12 +4875,16 @@ dnl
 AC_DEFUN([GLIBCXX_ENABLE_LIBSTDCXX_DUAL_ABI], [
   GLIBCXX_ENABLE(libstdcxx-dual-abi,$1,,[support two versions of std::string])
   if test x$enable_symvers = xgnu-versioned-namespace; then
-# gnu-versioned-namespace is incompatible with the dual ABI.
-enable_libstdcxx_dual_abi="no"
-  fi
-  if test x"$enable_libstdcxx_dual_abi" != xyes; then
+   

Re: [PATCH] sso-string@gnu-versioned-namespace [PR83077]

2023-08-17 Thread François Dumont via Gcc-patches



On 17/08/2023 19:22, Jonathan Wakely wrote:

On Sun, 13 Aug 2023 at 14:27, François Dumont via Libstdc++
 wrote:

Here is the fixed patch tested in all 3 modes:

- _GLIBCXX_USE_DUAL_ABI

- !_GLIBCXX_USE_DUAL_ABI && !_GLIBCXX_USE_CXX11_ABI

- !_GLIBCXX_USE_DUAL_ABI && _GLIBCXX_USE_CXX11_ABI

I don't know what you have in mind for the change below but I wanted to
let you know that I tried to put COW std::basic_string into a nested
__cow namespace when _GLIBCXX_USE_CXX11_ABI. But it had more impact on
string-inst.cc so I preferred the macro substitution approach.

I was thinking of implementing the necessary special members functions
of __cow_string directly, so they are ABI compatible with the COW
std::basic_string but don't actually reuse the code. That would mean
we don't need to compile and instantiate the whole COW string just to
use a few members from it. But that can be done later, the macro
approach seems OK for now.


You'll see that when cow_string.h is included while 
_GLIBCXX_USE_CXX11_ABI == 1 then I am hiding a big part of the 
basic_string definition. Initially it was to avoid to have to include 
basic_string.tcc but it is also a lot of useless code indeed.






There are some test failing when !_GLIBCXX_USE_CXX11_ABI that are
unrelated with my changes. I'll propose fixes in coming days.

Which tests? I run the entire testsuite with
-D_GLIBCXX_USE_CXX11_ABI=0 several times per day and I'm not seeing
failures.

I'll review the patch ASAP, thanks for working on it.

So far the only issue I found are in the mode !_GLIBCXX_USE_DUAL_ABI && 
!_GLIBCXX_USE_CXX11_ABI. They are:


23_containers/unordered_map/96088.cc
23_containers/unordered_multimap/96088.cc
23_containers/unordered_multiset/96088.cc
23_containers/unordered_set/96088.cc
ext/debug_allocator/check_new.cc
ext/malloc_allocator/check_new.cc
ext/malloc_allocator/deallocate_local.cc
ext/new_allocator/deallocate_local.cc
ext/pool_allocator/allocate_chunk.cc
ext/throw_allocator/deallocate_local.cc

but not sure I'll try to fix those in this context.

François



Re: [PATCH] sso-string@gnu-versioned-namespace [PR83077]

2023-08-17 Thread François Dumont via Gcc-patches
Another fix to define __cow_string(const std::string&) in 
cxx11-stdexcept.cc even if ! _GLIBCXX_USE_DUAL_ABI.


On 13/08/2023 21:51, François Dumont wrote:


Here is another version with enhanced sizeof/alignof static_assert in 
string-inst.cc for the std::__cow_string definition from . 
The assertions in cow-stdexcept.cc are now checking the definition 
which is in the same file.


On 13/08/2023 15:27, François Dumont wrote:


Here is the fixed patch tested in all 3 modes:

- _GLIBCXX_USE_DUAL_ABI

- !_GLIBCXX_USE_DUAL_ABI && !_GLIBCXX_USE_CXX11_ABI

- !_GLIBCXX_USE_DUAL_ABI && _GLIBCXX_USE_CXX11_ABI

I don't know what you have in mind for the change below but I wanted 
to let you know that I tried to put COW std::basic_string into a 
nested __cow namespace when _GLIBCXX_USE_CXX11_ABI. But it had more 
impact on string-inst.cc so I preferred the macro substitution approach.


There are some test failing when !_GLIBCXX_USE_CXX11_ABI that are 
unrelated with my changes. I'll propose fixes in coming days.


    libstdc++: [_GLIBCXX_INLINE_VERSION] Use cxx11 abi [PR83077]

    Use cxx11 abi when activating versioned namespace mode. To do support
    a new configuration mode where !_GLIBCXX_USE_DUAL_ABI and 
_GLIBCXX_USE_CXX11_ABI.


    The main change is that std::__cow_string is now defined whenever 
_GLIBCXX_USE_DUAL_ABI
    or _GLIBCXX_USE_CXX11_ABI is true. Implementation is using 
available std::string in

    case of dual abi and a subset of it when it's not.

    On the other side std::__sso_string is defined only when 
_GLIBCXX_USE_DUAL_ABI is true
    and _GLIBCXX_USE_CXX11_ABI is false. Meaning that 
std::__sso_string is a typedef for the
    cow std::string implementation when dual abi is disabled and cow 
string is being used.


    libstdcxx-v3/ChangeLog:

    PR libstdc++/83077
    * acinclude.m4 [GLIBCXX_ENABLE_LIBSTDCXX_DUAL_ABI]: 
Default to "new" libstdcxx abi.
    * config/locale/dragonfly/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Define money_base

    members.
    * config/locale/generic/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Likewise.
    * config/locale/gnu/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Likewise.

    * config/locale/gnu/numeric_members.cc
[!_GLIBCXX_USE_DUAL_ABI](__narrow_multibyte_chars): Define.
    * configure: Regenerate.
    * include/bits/c++config
[_GLIBCXX_INLINE_VERSION](_GLIBCXX_NAMESPACE_CXX11, 
_GLIBCXX_BEGIN_NAMESPACE_CXX11):

    Define empty.
[_GLIBCXX_INLINE_VERSION](_GLIBCXX_END_NAMESPACE_CXX11, 
_GLIBCXX_DEFAULT_ABI_TAG):

    Likewise.
    * include/bits/cow_string.h [!_GLIBCXX_USE_CXX11_ABI]: 
Define a light version of COW

    basic_string as __std_cow_string for use in stdexcept.
    * include/std/stdexcept [_GLIBCXX_USE_CXX11_ABI]: Define 
__cow_string.

    (__cow_string(const char*)): New.
    (__cow_string::c_str()): New.
    * python/libstdcxx/v6/printers.py 
(StdStringPrinter::__init__): Set self.new_string to True

    when std::__8::basic_string type is found.
    * src/Makefile.am 
[ENABLE_SYMVERS_GNU_NAMESPACE](ldbl_alt128_compat_sources): Define empty.

    * src/Makefile.in: Regenerate.
    * src/c++11/Makefile.am (cxx11_abi_sources): Rename into...
    (dual_abi_sources): ...this. Also move cow-local_init.cc, 
cxx11-hash_tr1.cc,

    cxx11-ios_failure.cc entries to...
    (sources): ...this.
    (extra_string_inst_sources): Move cow-fstream-inst.cc, 
cow-sstream-inst.cc, cow-string-inst.cc,
    cow-string-io-inst.cc, cow-wtring-inst.cc, 
cow-wstring-io-inst.cc, cxx11-locale-inst.cc,

    cxx11-wlocale-inst.cc entries to...
    (inst_sources): ...this.
    * src/c++11/Makefile.in: Regenerate.
    * src/c++11/cow-fstream-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-locale_init.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-sstream-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-stdexcept.cc [_GLIBCXX_USE_CXX11_ABI]: 
Include .
    [_GLIBCXX_USE_DUAL_ABI || 
_GLIBCXX_USE_CXX11_ABI](__cow_string): Redefine before
    including . Define 
_GLIBCXX_DEFINE_STDEXCEPT_INSTANTIATIONS so that

    __cow_string definition in  is skipped.
    [_GLIBCXX_USE_CXX11_ABI]: Skip Transaction Memory TS 
definitions.

    Move static_assert to check std::_cow_string abi layout to...
    * src/c++11/string-inst.cc: ...here.
    (_GLIBCXX_DEFINING_CXX11_ABI_INSTANTIATIONS): Define 
following _GLIBCXX_USE_CXX11_ABI

    value.
    [_GLIBCXX_USE_CXX11_ABI && 
!_GLIBCXX_DEFINING_CXX11_ABI_INSTANTIATIONS]:
    Define _GLIBCXX_DEFINING_COW_STRING_INSTANTIATIONS. 
Include .
    D

Re: [PATCH] sso-string@gnu-versioned-namespace [PR83077]

2023-08-13 Thread François Dumont via Gcc-patches
Here is another version with enhanced sizeof/alignof static_assert in 
string-inst.cc for the std::__cow_string definition from . 
The assertions in cow-stdexcept.cc are now checking the definition which 
is in the same file.


On 13/08/2023 15:27, François Dumont wrote:


Here is the fixed patch tested in all 3 modes:

- _GLIBCXX_USE_DUAL_ABI

- !_GLIBCXX_USE_DUAL_ABI && !_GLIBCXX_USE_CXX11_ABI

- !_GLIBCXX_USE_DUAL_ABI && _GLIBCXX_USE_CXX11_ABI

I don't know what you have in mind for the change below but I wanted 
to let you know that I tried to put COW std::basic_string into a 
nested __cow namespace when _GLIBCXX_USE_CXX11_ABI. But it had more 
impact on string-inst.cc so I preferred the macro substitution approach.


There are some test failing when !_GLIBCXX_USE_CXX11_ABI that are 
unrelated with my changes. I'll propose fixes in coming days.


    libstdc++: [_GLIBCXX_INLINE_VERSION] Use cxx11 abi [PR83077]

    Use cxx11 abi when activating versioned namespace mode. To do support
    a new configuration mode where !_GLIBCXX_USE_DUAL_ABI and 
_GLIBCXX_USE_CXX11_ABI.


    The main change is that std::__cow_string is now defined whenever 
_GLIBCXX_USE_DUAL_ABI
    or _GLIBCXX_USE_CXX11_ABI is true. Implementation is using 
available std::string in

    case of dual abi and a subset of it when it's not.

    On the other side std::__sso_string is defined only when 
_GLIBCXX_USE_DUAL_ABI is true
    and _GLIBCXX_USE_CXX11_ABI is false. Meaning that 
std::__sso_string is a typedef for the
    cow std::string implementation when dual abi is disabled and cow 
string is being used.


    libstdcxx-v3/ChangeLog:

    PR libstdc++/83077
    * acinclude.m4 [GLIBCXX_ENABLE_LIBSTDCXX_DUAL_ABI]: 
Default to "new" libstdcxx abi.
    * config/locale/dragonfly/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Define money_base

    members.
    * config/locale/generic/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Likewise.
    * config/locale/gnu/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Likewise.

    * config/locale/gnu/numeric_members.cc
    [!_GLIBCXX_USE_DUAL_ABI](__narrow_multibyte_chars): Define.
    * configure: Regenerate.
    * include/bits/c++config
    [_GLIBCXX_INLINE_VERSION](_GLIBCXX_NAMESPACE_CXX11, 
_GLIBCXX_BEGIN_NAMESPACE_CXX11):

    Define empty.
[_GLIBCXX_INLINE_VERSION](_GLIBCXX_END_NAMESPACE_CXX11, 
_GLIBCXX_DEFAULT_ABI_TAG):

    Likewise.
    * include/bits/cow_string.h [!_GLIBCXX_USE_CXX11_ABI]: 
Define a light version of COW

    basic_string as __std_cow_string for use in stdexcept.
    * include/std/stdexcept [_GLIBCXX_USE_CXX11_ABI]: Define 
__cow_string.

    (__cow_string(const char*)): New.
    (__cow_string::c_str()): New.
    * python/libstdcxx/v6/printers.py 
(StdStringPrinter::__init__): Set self.new_string to True

    when std::__8::basic_string type is found.
    * src/Makefile.am 
[ENABLE_SYMVERS_GNU_NAMESPACE](ldbl_alt128_compat_sources): Define empty.

    * src/Makefile.in: Regenerate.
    * src/c++11/Makefile.am (cxx11_abi_sources): Rename into...
    (dual_abi_sources): ...this. Also move cow-local_init.cc, 
cxx11-hash_tr1.cc,

    cxx11-ios_failure.cc entries to...
    (sources): ...this.
    (extra_string_inst_sources): Move cow-fstream-inst.cc, 
cow-sstream-inst.cc, cow-string-inst.cc,
    cow-string-io-inst.cc, cow-wtring-inst.cc, 
cow-wstring-io-inst.cc, cxx11-locale-inst.cc,

    cxx11-wlocale-inst.cc entries to...
    (inst_sources): ...this.
    * src/c++11/Makefile.in: Regenerate.
    * src/c++11/cow-fstream-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-locale_init.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-sstream-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-stdexcept.cc [_GLIBCXX_USE_CXX11_ABI]: 
Include .
    [_GLIBCXX_USE_DUAL_ABI || 
_GLIBCXX_USE_CXX11_ABI](__cow_string): Redefine before
    including . Define 
_GLIBCXX_DEFINE_STDEXCEPT_INSTANTIATIONS so that

    __cow_string definition in  is skipped.
    [_GLIBCXX_USE_CXX11_ABI]: Skip Transaction Memory TS 
definitions.

    Move static_assert to check std::_cow_string abi layout to...
    * src/c++11/string-inst.cc: ...here.
    (_GLIBCXX_DEFINING_CXX11_ABI_INSTANTIATIONS): Define 
following _GLIBCXX_USE_CXX11_ABI

    value.
    [_GLIBCXX_USE_CXX11_ABI && 
!_GLIBCXX_DEFINING_CXX11_ABI_INSTANTIATIONS]:
    Define _GLIBCXX_DEFINING_COW_STRING_INSTANTIATIONS. 
Include .
    Define basic_string as __std_cow_string for the current 
translation unit.
    * src/c++11/cow-string-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip de

Re: [PATCH] sso-string@gnu-versioned-namespace [PR83077]

2023-08-13 Thread François Dumont via Gcc-patches
finitions.
    * src/c++11/cxx11-hash_tr1.cc [!_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cxx11-ios_failure.cc [!_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.

    [!_GLIBCXX_USE_DUAL_ABI] (__ios_failure): Remove.
    * src/c++11/cxx11-locale-inst.cc: Cleanup, just include 
locale-inst.cc.
    * src/c++11/cxx11-stdexcept.cc [!_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cxx11-wlocale-inst.cc 
[!_GLIBCXX_USE_CXX11_ABI]: Skip definitions.

    * src/c++11/locale-inst-numeric.h
[!_GLIBCXX_USE_DUAL_ABI](std::use_facet>, 
std::use_facet>): Instantiate.
[!_GLIBCXX_USE_DUAL_ABI](std::has_facet>, 
std::has_facet>): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](std::num_getistreambuf_iterator>): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](std::num_putostreambuf_iterator>): Instantiate.
    * src/c++11/locale-inst.cc [!_GLIBCXX_USE_DUAL_ABI]: Build 
only when configured

    _GLIBCXX_USE_CXX11_ABI is equal to currently built abi.
    [!_GLIBCXX_USE_DUAL_ABI](__moneypunct_cache): 
Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](__moneypunct_cache): 
Instantiate.

    [!_GLIBCXX_USE_DUAL_ABI](__numpunct_cache): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](__timepunct): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](__timepunct_cache): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](time_putostreambuf_iterator>): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](time_put_bynameostreambuf_iterator>): Instantiate.

[!_GLIBCXX_USE_DUAL_ABI](__ctype_abstract_base): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](ctype_byname): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](__codecvt_abstract_basembstate_t>): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](codecvt_bynamembstate_t>): Instantiate.

[!_GLIBCXX_USE_DUAL_ABI](use_facet>(const locale&)): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](use_facetmbstate_t>>(const locale&)): Instantiate.
[!_GLIBCXX_USE_DUAL_ABI](use_facet<__timepunct>(const locale&)): 
Instantiate.
[!_GLIBCXX_USE_DUAL_ABI](use_facet>(const locale&)): 
Instantiate.

[!_GLIBCXX_USE_DUAL_ABI](has_facet>(const locale&)): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](has_facetmbstate_t>>(const locale&)): Instantiate.
[!_GLIBCXX_USE_DUAL_ABI](has_facet<__timepunct>(const locale&)): 
Instantiate.
[!_GLIBCXX_USE_DUAL_ABI](has_facet>(const locale&)): 
Instantiate.

    [!_GLIBCXX_USE_DUAL_ABI](__add_grouping): Define.
    [!_GLIBCXX_USE_DUAL_ABI](__pad>): 
Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](__int_to_char(C*, unsigned long, 
const C*,

    ios_base::fmtflags, bool)): Define.
    [!_GLIBCXX_USE_DUAL_ABI](__int_to_char(C*, unsigned long 
long, const C*,

    ios_base::fmtflags, bool)): Define.
    * src/c++11/wlocale-inst.cc [!_GLIBCXX_USE_CXX11_ABI]: Skip 
definitions.
    * src/c++98/Makefile.am (cxx11_abi_sources): Remove, unique 
cow-istream-string.cc entry

    move to...
    (inst_sources): ...this.
    * src/c++98/Makefile.in: Regenerate.
    * src/c++98/cow-istream-string.cc: Include .
    [_GLIBCXX_USE_CXX11_ABI]: Skip definitions.
    * src/c++98/hash_tr1.cc [_GLIBCXX_USE_CXX11_ABI]: Skip 
definitions.
    * src/c++98/ios_failure.cc 
[_GLIBCXX_USE_CXX11_ABI][_GLIBCXX_USE_DUAL_ABI]: Skip definitions.
    * src/c++98/istream-string.cc [!_GLIBCXX_USE_DUAL_ABI]: 
Build only when configured

    _GLIBCXX_USE_CXX11_ABI is equal to currently built abi.
    * src/c++98/locale_facets.cc 
[_GLIBCXX_USE_CXX11_ABI](__verify_grouping): Remove.

    * src/c++98/stdexcept.cc
    [_GLIBCXX_USE_CXX11_ABI](logic_error(const string&): Remove.
    [_GLIBCXX_USE_CXX11_ABI](domain_error(const string&): Remove.
    [_GLIBCXX_USE_CXX11_ABI](invalid_argument(const string&): 
Remove.

    [_GLIBCXX_USE_CXX11_ABI](length_error(const string&): Remove.
    [_GLIBCXX_USE_CXX11_ABI](out_of_range(const string&): Remove.
    [_GLIBCXX_USE_CXX11_ABI](runtime_error(const string&): Remove.
    [_GLIBCXX_USE_CXX11_ABI](range_error(const string&): Remove.
    [_GLIBCXX_USE_CXX11_ABI](overflow_error(const string&): Remove.
    [_GLIBCXX_USE_CXX11_ABI](underflow_error(const string&): 
Remove.


Ok to commit ?

François

On 11/08/2023 09:51, Jonathan Wakely wrote:



On Fri, 11 Aug 2023, 06:44 François Dumont via Libstdc++, 
mailto:libstdc%2b...@gcc.gnu.org>> wrote:


I hadn't tested the most basic default configuration and it is
failing,


I did wonder about that when you said which configurations you had 
tested :)





I need some more time yet.


OK, no problem.

I actually have an idea for replacing the __cow_str

Re: [PATCH] sso-string@gnu-versioned-namespace [PR83077]

2023-08-10 Thread François Dumont via Gcc-patches
I hadn't tested the most basic default configuration and it is failing, 
I need some more time yet.


François


On 10/08/2023 07:13, François Dumont wrote:

Hi

I've eventually completed this work.

This evolution will allow to build libstdc++ without dual abi and 
using cxx11 abi. For the moment such a config is only accessible 
through the --enable-symvers=gnu-versioned-namespace configuration.


    libstdc++: [_GLIBCXX_INLINE_VERSION] Use cxx11 abi [PR83077]

    Use cxx11 abi when activating versioned namespace mode.

    libstdcxx-v3/ChangeLog:

    PR libstdc++/83077
    * acinclude.m4 [GLIBCXX_ENABLE_LIBSTDCXX_DUAL_ABI]: 
Default to "new" libstdcxx abi.
    * config/locale/dragonfly/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Define money_base

    members.
    * config/locale/generic/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Likewise.
    * config/locale/gnu/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Likewise.

    * config/locale/gnu/numeric_members.cc
    [!_GLIBCXX_USE_DUAL_ABI](__narrow_multibyte_chars): Define.
    * configure: Regenerate.
    * include/bits/c++config
    [_GLIBCXX_INLINE_VERSION](_GLIBCXX_NAMESPACE_CXX11, 
_GLIBCXX_BEGIN_NAMESPACE_CXX11):

    Define empty.
[_GLIBCXX_INLINE_VERSION](_GLIBCXX_END_NAMESPACE_CXX11, 
_GLIBCXX_DEFAULT_ABI_TAG):

    Likewise.
    * include/bits/cow_string.h [!_GLIBCXX_USE_CXX11_ABI]: 
Define a light version of COW

    basic_string as __std_cow_string for use in stdexcept.
    * include/std/stdexcept [_GLIBCXX_USE_CXX11_ABI]: Define 
__cow_string.

    (__cow_string(const char*)): New.
    (__cow_string::c_str()): New.
    * python/libstdcxx/v6/printers.py 
(StdStringPrinter::__init__): Set self.new_string to True

    when std::__8::basic_string type is found.
    * src/Makefile.am 
[ENABLE_SYMVERS_GNU_NAMESPACE](ldbl_alt128_compat_sources): Define empty.

    * src/Makefile.in: Regenerate.
    * src/c++11/Makefile.am (cxx11_abi_sources): Rename into...
    (dual_abi_sources): ...this. Also move cow-local_init.cc, 
cxx11-hash_tr1.cc,

    cxx11-ios_failure.cc entries to...
    (sources): ...this.
    (extra_string_inst_sources): Move cow-fstream-inst.cc, 
cow-sstream-inst.cc, cow-string-inst.cc,
    cow-string-io-inst.cc, cow-wtring-inst.cc, 
cow-wstring-io-inst.cc, cxx11-locale-inst.cc,

    cxx11-wlocale-inst.cc entries to...
    (inst_sources): ...this.
    * src/c++11/Makefile.in: Regenerate.
    * src/c++11/cow-fstream-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-locale_init.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-sstream-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-stdexcept.cc [_GLIBCXX_USE_CXX11_ABI]: 
Include .
    [_GLIBCXX_USE_DUAL_ABI || 
_GLIBCXX_USE_CXX11_ABI](__cow_string): Redefine before including
    . Define 
_GLIBCXX_DEFINE_STDEXCEPT_INSTANTIATIONS so that __cow_string definition

    in  is skipped.
    [_GLIBCXX_USE_CXX11_ABI]: Skip Transaction Memory TS 
definitions.
    * src/c++11/cow-string-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-string-io-inst.cc 
[_GLIBCXX_USE_CXX11_ABI]: Skip definitions.
    * src/c++11/cow-wstring-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-wstring-io-inst.cc 
[_GLIBCXX_USE_CXX11_ABI]: Skip definitions.
    * src/c++11/cxx11-hash_tr1.cc [!_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cxx11-ios_failure.cc 
[!_GLIBCXX_USE_CXX11_ABI]: Skip definitions.

    [!_GLIBCXX_USE_DUAL_ABI] (__ios_failure): Remove.
    * src/c++11/cxx11-locale-inst.cc: Cleanup, just include 
locale-inst.cc.
    * src/c++11/cxx11-stdexcept.cc [!_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cxx11-wlocale-inst.cc 
[!_GLIBCXX_USE_CXX11_ABI]: Skip definitions.

    * src/c++11/locale-inst-numeric.h
[!_GLIBCXX_USE_DUAL_ABI](std::use_facet>, 
std::use_facet>): Instantiate.
[!_GLIBCXX_USE_DUAL_ABI](std::has_facet>, 
std::has_facet>): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](std::num_getistreambuf_iterator>): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](std::num_putostreambuf_iterator>): Instantiate.
    * src/c++11/locale-inst.cc [!_GLIBCXX_USE_DUAL_ABI]: Build 
only when configured

    _GLIBCXX_USE_CXX11_ABI is equal to currently built abi.
    [!_GLIBCXX_USE_DUAL_ABI](__moneypunct_cache): 
Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](__moneypunct_cache): 
Instantiate.

    [!_GLIBCXX_USE_DUAL_ABI](__numpunct_cache): Instantiate.
    [!_GLIBCXX_USE_DUAL_AB

[PATCH] sso-string@gnu-versioned-namespace [PR83077]

2023-08-09 Thread François Dumont via Gcc-patches

Hi

I've eventually completed this work.

This evolution will allow to build libstdc++ without dual abi and using 
cxx11 abi. For the moment such a config is only accessible through the 
--enable-symvers=gnu-versioned-namespace configuration.


    libstdc++: [_GLIBCXX_INLINE_VERSION] Use cxx11 abi [PR83077]

    Use cxx11 abi when activating versioned namespace mode.

    libstdcxx-v3/ChangeLog:

    PR libstdc++/83077
    * acinclude.m4 [GLIBCXX_ENABLE_LIBSTDCXX_DUAL_ABI]: Default 
to "new" libstdcxx abi.
    * config/locale/dragonfly/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Define money_base

    members.
    * config/locale/generic/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Likewise.
    * config/locale/gnu/monetary_members.cc 
[!_GLIBCXX_USE_DUAL_ABI]: Likewise.

    * config/locale/gnu/numeric_members.cc
    [!_GLIBCXX_USE_DUAL_ABI](__narrow_multibyte_chars): Define.
    * configure: Regenerate.
    * include/bits/c++config
    [_GLIBCXX_INLINE_VERSION](_GLIBCXX_NAMESPACE_CXX11, 
_GLIBCXX_BEGIN_NAMESPACE_CXX11):

    Define empty.
[_GLIBCXX_INLINE_VERSION](_GLIBCXX_END_NAMESPACE_CXX11, 
_GLIBCXX_DEFAULT_ABI_TAG):

    Likewise.
    * include/bits/cow_string.h [!_GLIBCXX_USE_CXX11_ABI]: 
Define a light version of COW

    basic_string as __std_cow_string for use in stdexcept.
    * include/std/stdexcept [_GLIBCXX_USE_CXX11_ABI]: Define 
__cow_string.

    (__cow_string(const char*)): New.
    (__cow_string::c_str()): New.
    * python/libstdcxx/v6/printers.py 
(StdStringPrinter::__init__): Set self.new_string to True

    when std::__8::basic_string type is found.
    * src/Makefile.am 
[ENABLE_SYMVERS_GNU_NAMESPACE](ldbl_alt128_compat_sources): Define empty.

    * src/Makefile.in: Regenerate.
    * src/c++11/Makefile.am (cxx11_abi_sources): Rename into...
    (dual_abi_sources): ...this. Also move cow-local_init.cc, 
cxx11-hash_tr1.cc,

    cxx11-ios_failure.cc entries to...
    (sources): ...this.
    (extra_string_inst_sources): Move cow-fstream-inst.cc, 
cow-sstream-inst.cc, cow-string-inst.cc,
    cow-string-io-inst.cc, cow-wtring-inst.cc, 
cow-wstring-io-inst.cc, cxx11-locale-inst.cc,

    cxx11-wlocale-inst.cc entries to...
    (inst_sources): ...this.
    * src/c++11/Makefile.in: Regenerate.
    * src/c++11/cow-fstream-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-locale_init.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-sstream-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-stdexcept.cc [_GLIBCXX_USE_CXX11_ABI]: 
Include .
    [_GLIBCXX_USE_DUAL_ABI || 
_GLIBCXX_USE_CXX11_ABI](__cow_string): Redefine before including
    . Define 
_GLIBCXX_DEFINE_STDEXCEPT_INSTANTIATIONS so that __cow_string definition

    in  is skipped.
    [_GLIBCXX_USE_CXX11_ABI]: Skip Transaction Memory TS 
definitions.
    * src/c++11/cow-string-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-string-io-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-wstring-inst.cc [_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cow-wstring-io-inst.cc 
[_GLIBCXX_USE_CXX11_ABI]: Skip definitions.
    * src/c++11/cxx11-hash_tr1.cc [!_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cxx11-ios_failure.cc [!_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.

    [!_GLIBCXX_USE_DUAL_ABI] (__ios_failure): Remove.
    * src/c++11/cxx11-locale-inst.cc: Cleanup, just include 
locale-inst.cc.
    * src/c++11/cxx11-stdexcept.cc [!_GLIBCXX_USE_CXX11_ABI]: 
Skip definitions.
    * src/c++11/cxx11-wlocale-inst.cc 
[!_GLIBCXX_USE_CXX11_ABI]: Skip definitions.

    * src/c++11/locale-inst-numeric.h
[!_GLIBCXX_USE_DUAL_ABI](std::use_facet>, 
std::use_facet>): Instantiate.
[!_GLIBCXX_USE_DUAL_ABI](std::has_facet>, 
std::has_facet>): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](std::num_getistreambuf_iterator>): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](std::num_putostreambuf_iterator>): Instantiate.
    * src/c++11/locale-inst.cc [!_GLIBCXX_USE_DUAL_ABI]: Build 
only when configured

    _GLIBCXX_USE_CXX11_ABI is equal to currently built abi.
    [!_GLIBCXX_USE_DUAL_ABI](__moneypunct_cache): 
Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](__moneypunct_cache): 
Instantiate.

    [!_GLIBCXX_USE_DUAL_ABI](__numpunct_cache): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](__timepunct): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](__timepunct_cache): Instantiate.
    [!_GLIBCXX_USE_DUAL_ABI](time_putostreambuf_iterator>): Instantiate.
    

[committed][_GLIBCXX_INLINE_VERSION] Add __cxa_call_terminate symbol export

2023-08-06 Thread François Dumont via Gcc-patches

libstdc++: [_GLIBCXX_INLINE_VERSION] Add __cxa_call_terminate symbol export

libstdc++-v3/ChangeLog:

    * config/abi/pre/gnu-versioned-namespace.ver: Add __cxa_call_terminate
    symbol export.
diff --git a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
index d7ef127cf02..267ab8fc719 100644
--- a/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
+++ b/libstdc++-v3/config/abi/pre/gnu-versioned-namespace.ver
@@ -164,6 +164,7 @@ CXXABI_2.0 {
 __cxa_begin_catch;
 __cxa_begin_cleanup;
 __cxa_call_unexpected;
+__cxa_call_terminate;
 __cxa_current_exception_type;
 __cxa_deleted_virtual;
 __cxa_demangle;


[committed] Fix several preprocessor directives

2023-07-30 Thread François Dumont via Gcc-patches

Committed as obvious.

    libstdc++: Fix several preprocessor directives

    A wrong usage of #define in place of a #error seems to have been 
replicated

    at different places in source files.

    libstdc++-v3/ChangeLog:

    * src/c++11/compatibility-ldbl-facets-aliases.h: Replace 
#define with

    proper #error.
    * src/c++11/locale-inst-monetary.h: Likewise.
    * src/c++11/locale-inst-numeric.h: Likewise.

François
diff --git a/libstdc++-v3/src/c++11/compatibility-ldbl-facets-aliases.h b/libstdc++-v3/src/c++11/compatibility-ldbl-facets-aliases.h
index 70c9342d88a..faf8221b273 100644
--- a/libstdc++-v3/src/c++11/compatibility-ldbl-facets-aliases.h
+++ b/libstdc++-v3/src/c++11/compatibility-ldbl-facets-aliases.h
@@ -23,11 +23,11 @@
 // .
 
 #ifndef C
-#define "This file should not be compiled directly, only included"
+# error "This file should not be compiled directly, only included"
 #endif
 
 #ifndef _GLIBCXX_LONG_DOUBLE_COMPAT
-#define "This file should only be used for _GLIBCXX_LONG_DOUBLE_COMPAT builds"
+# error "This file should only be used for _GLIBCXX_LONG_DOUBLE_COMPAT builds"
 #endif
 
 // XXX GLIBCXX_ABI Deprecated
diff --git a/libstdc++-v3/src/c++11/locale-inst-monetary.h b/libstdc++-v3/src/c++11/locale-inst-monetary.h
index d8fecf26596..954de1f52cf 100644
--- a/libstdc++-v3/src/c++11/locale-inst-monetary.h
+++ b/libstdc++-v3/src/c++11/locale-inst-monetary.h
@@ -23,7 +23,7 @@
 // .
 
 #ifndef C
-#define "This file should not be compiled directly, only included"
+# error "This file should not be compiled directly, only included"
 #endif
 
 #include "facet_inst_macros.h"
diff --git a/libstdc++-v3/src/c++11/locale-inst-numeric.h b/libstdc++-v3/src/c++11/locale-inst-numeric.h
index c77ee9e8d38..b917fe5802e 100644
--- a/libstdc++-v3/src/c++11/locale-inst-numeric.h
+++ b/libstdc++-v3/src/c++11/locale-inst-numeric.h
@@ -23,7 +23,7 @@
 // .
 
 #ifndef C
-#define "This file should not be compiled directly, only included"
+# error "This file should not be compiled directly, only included"
 #endif
 
 #include "facet_inst_macros.h"


[PATCH][Hashtable] Performance optimization through use of insertion hint

2023-07-24 Thread François Dumont via Gcc-patches

    libstdc++: [_Hashtable] Make more use of insertion hint


    When inserting an element into an empty bucket we currently insert 
the new node
    after the before-begin node so in first position. The drawback of 
doing this is
    that we are forced to update the bucket that was containing this 
before-begin
    node to point to the newly inserted node. To do so we need at best 
to do a modulo

    to find this bucket and when hash code is not cached also compute it.

    To avoid this side effect it is better to insert after the last 
node. Adding
    a member to keep track of this last node would be an abi breaking 
change. Still we
    can ask the user to maintain and provide this last node as an 
insertion hint.


    Adapt range insertion methods to try to detect the last node and 
then use it as

    the insertion hint.

    libstdc++-v3/ChangeLog:

    * include/bits/hashtable_policy.h:
    (_Insert_base::try_emplace): Adapt to use hint.
    (_Insert_base::_M_insert_range): Try to detect container 
last node and use it

    as hint for insertions.
    (_Hash_code_base::_M_hash_code(const _Hash&, const 
_Hash_node_value<>&)): Remove.
    (_Hash_code_base::_M_hash_code<_H2>(const _H2&, const 
_Hash_node_value<>&)): Remove.

    * include/bits/hashtable.h
    (_Hashtable<>::_M_insert_bucket_begin): Add hint parameter 
and use it when inserting

    into an empty bucket if hint is the last container node.
    (_Hashtable<>::_InsertInfo): New struct.
    (_Hashtable<>::_M_get_insert_info): New, return latter.
    (_Hashtable<>::_M_insert_multi_node): Add _InsertInfo 
parameter.
    (_Hashtable<>::_M_insert_unique_node): Add __node_ptr hint 
parameter.

    (_Hashtable<>::_M_emplace_unique(__node_ptr, _Args&&...)): New.
    (_Hashtable<>::_M_emplace_multi(__node_ptr, _Args&&...)): New.
    (_Hashtable<>::_M_emplace()): Adapt to use latters.
    (_Hashtable<>::_M_insert_unique): Add __node_ptr parameter.
    (_Hashtable<>::_M_insert_unique_aux): Add __node_ptr parameter.
    (_Hashtable<>::_M_insert(__node_ptr, _Arg&&, const 
_NodeGenerator&, true_type)):

    Use latter.
    (_Hashtable<>::_M_reinsert_node(const_iterator, node_type&&)):
    Add hint parameter, adapt to use it.
    (_Hashtable<>::_M_reinsert_node_multi): Use hint parameter 
if available to extract

    hash code.
    (_Hashtable<>::_M_compute_hash_code(const _Hash&, 
__node_ptr, __node_ptr,

    const key_type&)): New.
(_Hashtable<>::_M_compute_hash_code<_H2>(const _H2&, __node_ptr, __node_ptr,
    const key_type&)): New.
    (_Hashtable<>::_M_merge_unique): Adapt to use latter. 
Implement small size

    optimization.
    (_Hashtable<>::_M_get_insert_info(const _Hash&, __node_ptr, 
__node_ptr,

    const key_type&)): New.
(_Hashtable<>::_M_get_insert_info<_H2>(const _H2&, __node_ptr, __node_ptr,
    const key_type&)): New.
    (_Hashtable<>::_M_merge_multi): Adapt to use latter.
    * include/bits/unordered_map.h 
(unordered_map<>::insert(node_type&&)): Pass cend as

    hint.
    (unordered_map<>::insert(const_iterator, node_type&&)): 
Adapt to use hint.
    * include/bits/unordered_set.h 
(unordered_set<>::insert(node_type&&)): Pass cend as

    hint.
    (unordered_set<>::insert(const_iterator, node_type&&)): 
Adapt to use hint.
    * 
testsuite/23_containers/unordered_multimap/insert/hint.cc: Adapt 
implementation

    specific tests.

Tested under linux x86_64.

Here is the performance results of this patch, before:

unordered_multiset_hint.cc-thread    hash code NOT cached 200 
insertions w/o hint      94r   94u    0s 191999712mem    0pf
unordered_multiset_hint.cc-thread    hash code NOT cached 200 
insertions with perfect hint      95r   94u    0s 191999712mem 0pf
unordered_multiset_hint.cc-thread    hash code NOT cached 200 
insertions with bad hint      94r   94u    0s 191999712mem    0pf
unordered_multiset_hint.cc-thread    hash code NOT cached 200 range 
insertions      88r   88u    0s 191999712mem    0pf
unordered_multiset_hint.cc-thread    hash code cached 200 insertions 
w/o hint      91r   91u    0s 191999712mem    0pf
unordered_multiset_hint.cc-thread    hash code cached 200 insertions 
with perfect hint      92r   93u    0s 191999712mem 0pf
unordered_multiset_hint.cc-thread    hash code cached 200 insertions 
with bad hint      93r   93u    0s 191999712mem    0pf
unordered_multiset_hint.cc-thread    hash code cached 200 range 
insertions      88r   88u    0s 191999712mem    0pf
unordered_set_hint.cc-thread    hash code NOT cached 200 insertions 
w/o hint      94r   95u    0s 191999712mem    0pf
unordered_set_hint.cc-thread    hash code NOT cached 200 

Re: [PATCH v3 1/3] c++, libstdc++: Implement __is_arithmetic built-in trait

2023-07-22 Thread François Dumont via Gcc-patches



On 18/07/2023 08:27, Ken Matsui via Libstdc++ wrote:

This patch implements built-in trait for std::is_arithmetic.

gcc/cp/ChangeLog:

* cp-trait.def: Define __is_arithmetic.
* constraint.cc (diagnose_trait_expr): Handle CPTK_IS_ARITHMETIC.
* semantics.cc (trait_expr_value): Likewise.
(finish_trait_expr): Likewise.

gcc/testsuite/ChangeLog:

* g++.dg/ext/has-builtin-1.C: Test existence of __is_arithmetic.
* g++.dg/ext/is_arithmetic.C: New test.
* g++.dg/tm/pr46567.C (__is_arithmetic): Rename to ...
(__is_arith): ... this.
* g++.dg/torture/pr57107.C: Likewise.

libstdc++-v3/ChangeLog:

* include/bits/cpp_type_traits.h (__is_arithmetic): Rename to ...
(__is_arith): ... this.
* include/c_global/cmath: Use __is_arith instead.
* include/c_std/cmath: Likewise.
* include/tr1/cmath: Likewise.

Signed-off-by: Ken Matsui 
---
  gcc/cp/constraint.cc|  3 ++
  gcc/cp/cp-trait.def |  1 +
  gcc/cp/semantics.cc |  4 ++
  gcc/testsuite/g++.dg/ext/has-builtin-1.C|  3 ++
  gcc/testsuite/g++.dg/ext/is_arithmetic.C| 33 ++
  gcc/testsuite/g++.dg/tm/pr46567.C   |  6 +--
  gcc/testsuite/g++.dg/torture/pr57107.C  |  4 +-
  libstdc++-v3/include/bits/cpp_type_traits.h |  4 +-
  libstdc++-v3/include/c_global/cmath | 48 ++---
  libstdc++-v3/include/c_std/cmath| 24 +--
  libstdc++-v3/include/tr1/cmath  | 24 +--
  11 files changed, 99 insertions(+), 55 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/ext/is_arithmetic.C

diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 8cf0f2d0974..bd517d08843 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3754,6 +3754,9 @@ diagnose_trait_expr (tree expr, tree args)
  case CPTK_IS_AGGREGATE:
inform (loc, "  %qT is not an aggregate", t1);
break;
+case CPTK_IS_ARITHMETIC:
+  inform (loc, "  %qT is not an arithmetic type", t1);
+  break;
  case CPTK_IS_TRIVIALLY_COPYABLE:
inform (loc, "  %qT is not trivially copyable", t1);
break;
diff --git a/gcc/cp/cp-trait.def b/gcc/cp/cp-trait.def
index 8b7fece0cc8..a95aeeaf778 100644
--- a/gcc/cp/cp-trait.def
+++ b/gcc/cp/cp-trait.def
@@ -82,6 +82,7 @@ DEFTRAIT_EXPR (IS_TRIVIALLY_ASSIGNABLE, 
"__is_trivially_assignable", 2)
  DEFTRAIT_EXPR (IS_TRIVIALLY_CONSTRUCTIBLE, "__is_trivially_constructible", -1)
  DEFTRAIT_EXPR (IS_TRIVIALLY_COPYABLE, "__is_trivially_copyable", 1)
  DEFTRAIT_EXPR (IS_UNION, "__is_union", 1)
+DEFTRAIT_EXPR (IS_ARITHMETIC, "__is_arithmetic", 1)
  DEFTRAIT_EXPR (REF_CONSTRUCTS_FROM_TEMPORARY, 
"__reference_constructs_from_temporary", 2)
  DEFTRAIT_EXPR (REF_CONVERTS_FROM_TEMPORARY, 
"__reference_converts_from_temporary", 2)
  /* FIXME Added space to avoid direct usage in GCC 13.  */
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 8fb47fd179e..4531f047d73 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -12118,6 +12118,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree 
type2)
  case CPTK_IS_UNION:
return type_code1 == UNION_TYPE;
  
+case CPTK_IS_ARITHMETIC:

+  return ARITHMETIC_TYPE_P (type1);
+
  case CPTK_IS_ASSIGNABLE:
return is_xible (MODIFY_EXPR, type1, type2);
  
@@ -12296,6 +12299,7 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)

  case CPTK_IS_ENUM:
  case CPTK_IS_UNION:
  case CPTK_IS_SAME:
+case CPTK_IS_ARITHMETIC:
break;
  
  case CPTK_IS_LAYOUT_COMPATIBLE:

diff --git a/gcc/testsuite/g++.dg/ext/has-builtin-1.C 
b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
index f343e153e56..3d63b0101d1 100644
--- a/gcc/testsuite/g++.dg/ext/has-builtin-1.C
+++ b/gcc/testsuite/g++.dg/ext/has-builtin-1.C
@@ -146,3 +146,6 @@
  #if !__has_builtin (__remove_cvref)
  # error "__has_builtin (__remove_cvref) failed"
  #endif
+#if !__has_builtin (__is_arithmetic)
+# error "__has_builtin (__is_arithmetic) failed"
+#endif
diff --git a/gcc/testsuite/g++.dg/ext/is_arithmetic.C 
b/gcc/testsuite/g++.dg/ext/is_arithmetic.C
new file mode 100644
index 000..fd35831f646
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/is_arithmetic.C
@@ -0,0 +1,33 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+using namespace __gnu_test;
+
+#define SA(X) static_assert((X),#X)
+#define SA_TEST_CATEGORY(TRAIT, TYPE, EXPECT)  \
+  SA(TRAIT(TYPE) == EXPECT);   \
+  SA(TRAIT(const TYPE) == EXPECT); \
+  SA(TRAIT(volatile TYPE) == EXPECT);  \
+  SA(TRAIT(const volatile TYPE) == EXPECT)
+
+SA_TEST_CATEGORY(__is_arithmetic, void, false);
+
+SA_TEST_CATEGORY(__is_arithmetic, char, true);
+SA_TEST_CATEGORY(__is_arithmetic, signed char, true);
+SA_TEST_CATEGORY(__is_arithmetic, unsigned char, true);

  1   2   3   4   5   6   7   8   9   10   >