Re: [COMMITED] [lto] ipcp don't propagate where not needed

2024-11-06 Thread Jonathan Wakely

On 06/11/24 13:39 +0100, Michal Jires wrote:

Commited with suggested changes.

-

This patch disables propagation of ipcp information into partitions
where all instances of the node are marked to be inlined.

Motivation:
Incremental LTO needs stable values between compilations to be
effective. This requirement fails with following example:

void heavily_used_function(int);
...
heavily_used_function(__LINE__);

Ipcp creates long list of all __LINE__ arguments, and then
propagates it with every function clone, even though for inlined
functions this information is not useful.

gcc/ChangeLog:

* ipa-prop.cc (write_ipcp_transformation_info): Disable
  uneeded value propagation.
* lto-cgraph.cc (lto_symtab_encoder_encode): Default values.
(lto_symtab_encoder_always_inlined_p): New.
(lto_set_symtab_encoder_not_always_inlined): New.
(add_node_to): Set always inlined.
* lto-streamer.h (struct lto_encoder_entry): New field.
(lto_symtab_encoder_always_inlined_p): New.
---
gcc/ipa-prop.cc| 12 +---
gcc/lto-cgraph.cc  | 47 +-
gcc/lto-streamer.h | 11 +++
3 files changed, 50 insertions(+), 20 deletions(-)

diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc
index 032358fde22..c5633796721 100644
--- a/gcc/ipa-prop.cc
+++ b/gcc/ipa-prop.cc
@@ -5404,9 +5404,15 @@ write_ipcp_transformation_info (output_block *ob, 
cgraph_node *node,
  streamer_write_bitpack (&bp);
}

-  streamer_write_uhwi (ob, vec_safe_length (ts->m_vr));
-  for (const ipa_vr &parm_vr : ts->m_vr)
-parm_vr.streamer_write (ob);
+  /* If all instances of this node are inlined, ipcp info is not useful.  */
+  if (!lto_symtab_encoder_only_for_inlining_p (encoder, node))
+{
+  streamer_write_uhwi (ob, vec_safe_length (ts->m_vr));
+  for (const ipa_vr &parm_vr : ts->m_vr)
+   parm_vr.streamer_write (ob);
+}
+  else
+streamer_write_uhwi (ob, 0);
}

/* Stream in the aggregate value replacement chain for NODE from IB.  */
diff --git a/gcc/lto-cgraph.cc b/gcc/lto-cgraph.cc
index 53cc965bdfd..c66f32852a7 100644
--- a/gcc/lto-cgraph.cc
+++ b/gcc/lto-cgraph.cc
@@ -114,7 +114,7 @@ lto_symtab_encoder_encode (lto_symtab_encoder_t encoder,

  if (!encoder->map)
{
-  lto_encoder_entry entry = {node, false, false, false};
+  lto_encoder_entry entry (node);

  ref = encoder->nodes.length ();
  encoder->nodes.safe_push (entry);
@@ -124,7 +124,7 @@ lto_symtab_encoder_encode (lto_symtab_encoder_t encoder,
  size_t *slot = encoder->map->get (node);
  if (!slot || !*slot)
{
-  lto_encoder_entry entry = {node, false, false, false};
+  lto_encoder_entry entry (node);
  ref = encoder->nodes.length ();
  if (!slot)
encoder->map->put (node, ref + 1);
@@ -168,6 +168,15 @@ lto_symtab_encoder_delete_node (lto_symtab_encoder_t 
encoder,
  return true;
}

+/* Return TRUE if the NODE and its clones are always inlined.  */
+
+bool
+lto_symtab_encoder_only_for_inlining_p (lto_symtab_encoder_t encoder,
+   struct cgraph_node *node)
+{
+  int index = lto_symtab_encoder_lookup (encoder, node);
+  return encoder->nodes[index].only_for_inlining;
+}

/* Return TRUE if we should encode the body of NODE (if any).  */

@@ -179,17 +188,6 @@ lto_symtab_encoder_encode_body_p (lto_symtab_encoder_t 
encoder,
  return encoder->nodes[index].body;
}

-/* Specify that we encode the body of NODE in this partition.  */
-
-static void
-lto_set_symtab_encoder_encode_body (lto_symtab_encoder_t encoder,
-   struct cgraph_node *node)
-{
-  int index = lto_symtab_encoder_encode (encoder, node);
-  gcc_checking_assert (encoder->nodes[index].node == node);
-  encoder->nodes[index].body = true;
-}
-
/* Return TRUE if we should encode initializer of NODE (if any).  */

bool
@@ -799,13 +797,28 @@ output_refs (lto_symtab_encoder_t encoder)

static void
add_node_to (lto_symtab_encoder_t encoder, struct cgraph_node *node,
-bool include_body)
+bool include_body, bool not_inlined)
{
  if (node->clone_of)
-add_node_to (encoder, node->clone_of, include_body);
+add_node_to (encoder, node->clone_of, include_body, not_inlined);
+
+  int index = lto_symtab_encoder_encode (encoder, node);
+  gcc_checking_assert (encoder->nodes[index].node == node);
+
  if (include_body)
-lto_set_symtab_encoder_encode_body (encoder, node);
-  lto_symtab_encoder_encode (encoder, node);
+encoder->nodes[index].body = true;
+  if (not_inlined)
+encoder->nodes[index].only_for_inlining = false;
+}
+
+/* Add NODE into encoder as well as nodes it is cloned from.
+   Do it in a way so clones appear first.  */
+
+static void
+add_node_to (lto_symtab_encoder_t encoder, struct cgraph_node *node,
+bool include_body)
+{
+  add_node_to (encoder, node, include_body, include_body

[PATCH] libstdc++: Refactor std::hash specializations

2024-11-06 Thread Jonathan Wakely
This attempts to simplify and clean up our std::hash code. The primary
benefit is improved diagnostics for users when they do something wrong
involving std::hash or unordered containers. An additional benefit is
that for the unstable ABI (--enable-symvers=gnu-versioned-namespace) we
can reduce the memory footprint of several std::hash specializations.

In the current design, __hash_enum is a base class of the std::hash
primary template, but the partial specialization of __hash_enum for
non-enum types is disabled.  This means that if a user forgets to
specialize std::hash for their class type (or forgets to use a custom
hash function for unordered containers) they get error messages about
std::__hash_enum not being constructible.  This is confusing when there
is no enum type involved: why should users care about __hash_enum not
being constructible if they're not trying to hash enums?

This change makes the std::hash primary template only derive from
__hash_enum when the template argument type is an enum. Otherwise, it
derives directly from a new class template, __hash_not_enabled. This new
class template defines the deleted members that cause a given std::hash
specialization to be a disabled specialization (as per P0513R0). Now
when users try to use a disabled specialization, they get more
descriptive errors that mention __hash_not_enabled instead of
__hash_enum.

Additionally, adjust __hash_base to remove the deprecated result_type
and argument_type typedefs for C++20 and later.

In the current code we use a __poison_hash base class in the std::hash
specializations for std::unique_ptr, std::optional, and std::variant.
The primary template of __poison_hash has deleted special members, which
is used to conditionally disable the derived std::hash specialization.
This can also result in confusing diagnostics, because seeing "poison"
in an enabled specialization is misleading. Only some uses of
__poison_hash actually "poison" anything, i.e. cause a specialization to
be disabled. In other cases it's just an empty base class that does
nothing.

This change removes __poison_hash and changes the std::hash
specializations that were using it to conditionally derive from
__hash_not_enabled instead. When the std::hash specialization is
enabled, there is no more __poison_hash base class. However, to preserve
the ABI properties of those std::hash specializations, we need to
replace __poison_hash with some other empty base class. This is needed
because in the current code std::hash> has
two __poison_hash base classes, which must have unique addresses,
so sizeof(std::hash>) == 2. To preserve
this unfortunate property, a new __hash_empty_base class is used as a
base class to re-introduce du0plicate base classes that increase the
class size. For the unstable ABI we don't use __hash_empty_base so the
std::hash> specializations are always size 1, and
the class hierarchy is much simpler so will compile faster.

Additionally, remove the result_type and argument_type typedefs from all
disabled specializations of std::hash for std::unique_ptr,
std::optional, and std::variant. Those typedefs are useless for disabled
specializations, and although the standard doesn't say they must *not*
be present for disabled specializations, it certainly only requires them
for enabled specializations. Finally, for C++20 the typedefs are also
removed from enabled specializations of std::hash for std::unique_ptr,
std::optional, and std::variant.

libstdc++-v3/ChangeLog:

* doc/xml/manual/evolution.xml: Document removal of nested types
from std::hash specializations.
* doc/html/manual/api.html: Regenerate.
* include/bits/functional_hash.h (__hash_base): Remove
deprecated nested types for C++20.
(__hash_empty_base): Define new class template.
(__is_hash_enabled_for): Define new variable template.
(__poison_hash): Remove.
(__hash_not_enabled): Define new class template.
(__hash_enum): Remove partial specialization for non-enums.
(hash): Derive from __hash_not_enabled for non-enums, instead of
__hash_enum.
* include/bits/unique_ptr.h (__uniq_ptr_hash): Derive from
__hash_base. Conditionally derive from __hash_empty_base.
(__uniq_ptr_hash<>): Remove disabled specialization.
(hash): Do not derive from __hash_base unconditionally.
Conditionally derive from either __uniq_ptr_hash or
__hash_not_enabled.
* include/std/optional (__optional_hash_call_base): Remove.
(__optional_hash): Define new class template.
(hash): Derive from either
(hash): Conditionally derive from either __optional_hash or
__hash_not_enabled. Remove nested typedefs.
* include/std/variant (_Base_dedup): Replace __poison_hash with
__hash_empty_base.
(__variant_hash_call_base_impl): Remove.
(__variant_hash): Define new class template.
(hash): Conditionally derive from eit

Re: [PATCH 2/2] libstdc++: More user-friendly failed assertions from shared_ptr dereference

2024-11-06 Thread Jonathan Wakely
Pushed

On Thu, 31 Oct 2024 at 20:08, Jonathan Wakely  wrote:
>
> Currently dereferencing an empty shared_ptr prints a complicated
> internal type in the assertion message:
>
> include/bits/shared_ptr_base.h:1377: std::__shared_ptr_access<_Tp, _Lp, 
> ,  >::element_type& std::__shared_ptr_access<_Tp, _Lp, 
> ,  >::operator*() const [with _Tp = 
> std::filesystem::__cxx11::recursive_directory_iterator::_Dir_stack; 
> __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool  = false; 
> bool  = false; element_type = 
> std::filesystem::__cxx11::recursive_directory_iterator::_Dir_stack]: 
> Assertion '_M_get() != nullptr' failed.
>
> Users don't care about any of the _Lp and  template
> parameters, so this is unnecessarily verbose.
>
> We can simplify it to something that only mentions "shared_ptr_deref"
> and the element type:
>
> include/bits/shared_ptr_base.h:1371: _Tp* std::__shared_ptr_deref(_Tp*) [with 
> _Tp = filesystem::__cxx11::recursive_directory_iterator::_Dir_stack]: 
> Assertion '__p != nullptr' failed.
>
> libstdc++-v3/ChangeLog:
>
> * include/bits/shared_ptr_base.h (__shared_ptr_deref): New
> function template.
> (__shared_ptr_access, __shared_ptr_access<>): Use it.
> ---
> Tested x86_64-linux.
>
> Also available for review at:
> https://forge.sourceware.org/gcc/gcc-TEST/pulls/13
>
>  libstdc++-v3/include/bits/shared_ptr_base.h | 28 +
>  1 file changed, 17 insertions(+), 11 deletions(-)
>
> diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h 
> b/libstdc++-v3/include/bits/shared_ptr_base.h
> index 9a7617e7014..ee01594ce0c 100644
> --- a/libstdc++-v3/include/bits/shared_ptr_base.h
> +++ b/libstdc++-v3/include/bits/shared_ptr_base.h
> @@ -1337,6 +1337,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  { };
>
>
> +  template
> +[[__gnu__::__always_inline__]]
> +inline _Tp*
> +__shared_ptr_deref(_Tp* __p)
> +{
> +  __glibcxx_assert(__p != nullptr);
> +  return __p;
> +}
> +
>// Define operator* and operator-> for shared_ptr.
>templatebool = is_array<_Tp>::value, bool = is_void<_Tp>::value>
> @@ -1347,10 +1356,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>
>element_type&
>operator*() const noexcept
> -  {
> -   __glibcxx_assert(_M_get() != nullptr);
> -   return *_M_get();
> -  }
> +  { return *std::__shared_ptr_deref(_M_get()); }
>
>element_type*
>operator->() const noexcept
> @@ -1392,10 +1398,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>[[__deprecated__("shared_ptr::operator* is absent from C++17")]]
>element_type&
>operator*() const noexcept
> -  {
> -   __glibcxx_assert(_M_get() != nullptr);
> -   return *_M_get();
> -  }
> +  { return *std::__shared_ptr_deref(_M_get()); }
>
>[[__deprecated__("shared_ptr::operator-> is absent from C++17")]]
>element_type*
> @@ -1406,13 +1409,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>}
>  #endif
>
> +#pragma GCC diagnostic push
> +#pragma GCC diagnostic ignored "-Wc++17-extensions"
>element_type&
>operator[](ptrdiff_t __i) const noexcept
>{
> -   __glibcxx_assert(_M_get() != nullptr);
> -   __glibcxx_assert(!extent<_Tp>::value || __i < extent<_Tp>::value);
> -   return _M_get()[__i];
> +   if constexpr (extent<_Tp>::value)
> + __glibcxx_assert(__i < extent<_Tp>::value);
> +   return std::__shared_ptr_deref(_M_get())[__i];
>}
> +#pragma GCC diagnostic pop
>
>  private:
>element_type*
> --
> 2.47.0
>



Re: [PATCH 1/2] libstdc++: Enable debug assertions for filesystem directory iterators

2024-11-06 Thread Jonathan Wakely
Pushed

On Thu, 31 Oct 2024 at 20:06, Jonathan Wakely  wrote:
>
> Several member functions of filesystem::directory_iterator and
> filesystem::recursive_directory_iterator currently dereference their
> shared_ptr data member without checking for non-null. Because they use
> operator-> and that function only uses _GLIBCXX_DEBUG_PEDASSERT rather
> than __glibcxx_assert there is no assertion even when the library is
> built with _GLIBCXX_ASSERTIONS defined. This means that dereferencing
> invalid directory iterators gives an unhelpful segfault.
>
> By using (*p). instead of p-> we get an assertion when the library is
> built with _GLIBCXX_ASSERTIONS, with a "_M_get() != nullptr" message.
>
> libstdc++-v3/ChangeLog:
>
> * src/c++17/fs_dir.cc (fs::directory_iterator::operator*): Use
> shared_ptr::operator* instead of shared_ptr::operator->.
> (fs::recursive_directory_iterator::options): Likewise.
> (fs::recursive_directory_iterator::depth): Likewise.
> (fs::recursive_directory_iterator::recursion_pending): Likewise.
> (fs::recursive_directory_iterator::operator*): Likewise.
> (fs::recursive_directory_iterator::disable_recursion_pending):
> Likewise.
> ---
> Tested x86_64-linux.
>
> Also available for review at:
> https://forge.sourceware.org/gcc/gcc-TEST/pulls/13
>
>
>  libstdc++-v3/src/c++17/fs_dir.cc | 12 ++--
>  1 file changed, 6 insertions(+), 6 deletions(-)
>
> diff --git a/libstdc++-v3/src/c++17/fs_dir.cc 
> b/libstdc++-v3/src/c++17/fs_dir.cc
> index 28d27f6a9fa..8fe9e5e4cc8 100644
> --- a/libstdc++-v3/src/c++17/fs_dir.cc
> +++ b/libstdc++-v3/src/c++17/fs_dir.cc
> @@ -230,7 +230,7 @@ directory_iterator(const path& p, directory_options 
> options, error_code* ecptr)
>  const fs::directory_entry&
>  fs::directory_iterator::operator*() const noexcept
>  {
> -  return _M_dir->entry;
> +  return (*_M_dir).entry;
>  }
>
>  fs::directory_iterator&
> @@ -327,25 +327,25 @@ 
> fs::recursive_directory_iterator::~recursive_directory_iterator() = default;
>  fs::directory_options
>  fs::recursive_directory_iterator::options() const noexcept
>  {
> -  return _M_dirs->options;
> +  return (*_M_dirs).options;
>  }
>
>  int
>  fs::recursive_directory_iterator::depth() const noexcept
>  {
> -  return int(_M_dirs->size()) - 1;
> +  return int((*_M_dirs).size()) - 1;
>  }
>
>  bool
>  fs::recursive_directory_iterator::recursion_pending() const noexcept
>  {
> -  return _M_dirs->pending;
> +  return (*_M_dirs).pending;
>  }
>
>  const fs::directory_entry&
>  fs::recursive_directory_iterator::operator*() const noexcept
>  {
> -  return _M_dirs->top().entry;
> +  return (*_M_dirs).top().entry;
>  }
>
>  fs::recursive_directory_iterator&
> @@ -453,7 +453,7 @@ fs::recursive_directory_iterator::pop()
>  void
>  fs::recursive_directory_iterator::disable_recursion_pending() noexcept
>  {
> -  _M_dirs->pending = false;
> +  (*_M_dirs).pending = false;
>  }
>
>  // Used to implement filesystem::remove_all.
> --
> 2.47.0
>



[committed v2] libstdc++: Deprecate useless compatibility headers for C++17

2024-11-06 Thread Jonathan Wakely
These headers make no sense for C++ programs, because they either define
different content to the corresponding  C header, or define
nothing at all in namespace std. They were all deprecated in C++17, so
add deprecation warnings to them, which can be disabled with
-Wno-deprecated. For C++20 and later these headers are no longer in the
standard at all, so compiling with _GLIBCXX_USE_DEPRECATED defined to 0
will give an error when they are included.

Because #warning is non-standard before C++23 we need to use pragmas to
ignore -Wc++23-extensions for the -Wsystem-headers -pedantic case.

One g++ test needs adjustment because it includes , but that
can be made conditional on the __cplusplus value without any reduction
in test coverage.

For the library tests, consolidate the std_c++0x_neg.cc XFAIL tests into
the macros.cc test, using dg-error with a { target c++98_only }
selector. This avoids having two separate test files, one for C++98 and
one for everything later. Also add tests for the  headers to
ensure that they behave as expected and don't give deprecated warnings.

libstdc++-v3/ChangeLog:

* doc/xml/manual/evolution.xml: Document deprecations.
* doc/html/*: Regenerate.
* include/c_compatibility/complex.h (_GLIBCXX_COMPLEX_H): Move
include guard to start of file. Include  directly
instead of .
* include/c_compatibility/tgmath.h: Include  and
 directly, instead of .
* include/c_global/ccomplex: Add deprecated #warning for C++17
and #error for C++20 if _GLIBCXX_USE_DEPRECATED == 0.
* include/c_global/ciso646: Likewise.
* include/c_global/cstdalign: Likewise.
* include/c_global/cstdbool: Likewise.
* include/c_global/ctgmath: Likewise.
* include/c_std/ciso646: Likewise.
* include/precompiled/stdc++.h: Do not include ccomplex,
ciso646, cstdalign, cstdbool, or ctgmath in C++17 and later.
* testsuite/18_support/headers/cstdalign/macros.cc: Check for
warnings and errors for unsupported dialects.
* testsuite/18_support/headers/cstdbool/macros.cc: Likewise.
* testsuite/26_numerics/headers/ctgmath/complex.cc: Likewise.
* testsuite/27_io/objects/char/1.cc: Do not include .
* testsuite/27_io/objects/wchar_t/1.cc: Likewise.
* testsuite/18_support/headers/cstdbool/std_c++0x_neg.cc: Removed.
* testsuite/18_support/headers/cstdalign/std_c++0x_neg.cc: Removed.
* testsuite/26_numerics/headers/ccomplex/std_c++0x_neg.cc: Removed.
* testsuite/26_numerics/headers/ctgmath/std_c++0x_neg.cc: Removed.
* testsuite/18_support/headers/ciso646/macros.cc: New test.
* testsuite/18_support/headers/ciso646/macros.h.cc: New test.
* testsuite/18_support/headers/cstdbool/macros.h.cc: New test.
* testsuite/26_numerics/headers/ccomplex/complex.cc: New test.
* testsuite/26_numerics/headers/ccomplex/complex.h.cc: New test.
* testsuite/26_numerics/headers/ctgmath/complex.h.cc: New test.

gcc/testsuite/ChangeLog:

* g++.old-deja/g++.other/headers1.C: Do not include ciso646 for
C++17 and later.
---
I tweaked the #error and #warning text slightly since the v1 patch. I'll
also add something to the gcc-15/porting_to.html web page.

Tested x86_64-linux, aarch64-linux, powerpc64le-linux.

Pushed to trunk.

 .../g++.old-deja/g++.other/headers1.C |  2 +
 libstdc++-v3/doc/html/manual/api.html |  8 +++
 libstdc++-v3/doc/xml/manual/evolution.xml | 10 
 .../include/c_compatibility/complex.h |  4 +-
 libstdc++-v3/include/c_compatibility/tgmath.h | 11 ++--
 libstdc++-v3/include/c_global/ccomplex|  9 
 libstdc++-v3/include/c_global/ciso646 |  9 
 libstdc++-v3/include/c_global/cstdalign   |  8 +++
 libstdc++-v3/include/c_global/cstdbool|  8 +++
 libstdc++-v3/include/c_global/ctgmath |  8 +++
 libstdc++-v3/include/c_std/ciso646| 10 
 libstdc++-v3/include/precompiled/stdc++.h | 13 +++--
 .../18_support/headers/ciso646/macros.cc  | 51 +++
 .../18_support/headers/ciso646/macros.h.cc| 49 ++
 .../18_support/headers/cstdalign/macros.cc| 10 +++-
 .../18_support/headers/cstdalign/macros.h.cc  | 25 +
 .../headers/cstdalign/std_c++0x_neg.cc| 24 -
 .../18_support/headers/cstdbool/macros.cc |  9 +++-
 .../18_support/headers/cstdbool/macros.h.cc   | 21 
 .../headers/cstdbool/std_c++0x_neg.cc | 26 --
 .../26_numerics/headers/ccomplex/complex.cc   | 10 
 .../26_numerics/headers/ccomplex/complex.h.cc | 10 
 .../headers/ccomplex/std_c++0x_neg.cc | 26 --
 .../26_numerics/headers/ctgmath/complex.cc|  9 +++-
 .../26_numerics/headers/ctgmath/complex.h.cc  | 10 
 .../headers/ctgmath/std_c++0x_neg.cc  | 26 --
 .../testsuite/27_io/objects/char/1.cc |  1 -
 .../testsuite/27_io

[committed] libstdc++: Move include guards to start of headers

2024-11-06 Thread Jonathan Wakely
libstdc++-v3/ChangeLog:

* include/c_compatibility/complex.h (_GLIBCXX_COMPLEX_H): Move
include guard to start of the header.
* include/c_global/ctgmath (_GLIBCXX_CTGMATH): Likewise.
---
Tested x86_64-linux. Pushed to trunk.


 libstdc++-v3/include/c_compatibility/complex.h | 6 +++---
 libstdc++-v3/include/c_global/ctgmath  | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/libstdc++-v3/include/c_compatibility/complex.h 
b/libstdc++-v3/include/c_compatibility/complex.h
index 605d1f30e06..a3102d9fce3 100644
--- a/libstdc++-v3/include/c_compatibility/complex.h
+++ b/libstdc++-v3/include/c_compatibility/complex.h
@@ -26,6 +26,9 @@
  *  This is a Standard C++ Library header.
  */
 
+#ifndef _GLIBCXX_COMPLEX_H
+#define _GLIBCXX_COMPLEX_H 1
+
 #include 
 
 #if __cplusplus >= 201103L
@@ -42,7 +45,4 @@
 # endif
 #endif
 
-#ifndef _GLIBCXX_COMPLEX_H
-#define _GLIBCXX_COMPLEX_H 1
-
 #endif
diff --git a/libstdc++-v3/include/c_global/ctgmath 
b/libstdc++-v3/include/c_global/ctgmath
index 79c1a029f41..39c17668f16 100644
--- a/libstdc++-v3/include/c_global/ctgmath
+++ b/libstdc++-v3/include/c_global/ctgmath
@@ -26,13 +26,13 @@
  *  This is a Standard C++ Library header.
  */
 
+#ifndef _GLIBCXX_CTGMATH
+#define _GLIBCXX_CTGMATH 1
+
 #ifdef _GLIBCXX_SYSHDR
 #pragma GCC system_header
 #endif
 
-#ifndef _GLIBCXX_CTGMATH
-#define _GLIBCXX_CTGMATH 1
-
 #if __cplusplus < 201103L
 #  include 
 #else
-- 
2.47.0



Re: [Bug libstdc++/115285] [12/13/14/15 Regression] std::unordered_set can have duplicate value

2024-11-05 Thread Jonathan Wakely

On 05/11/24 17:50 +, Jonathan Wakely wrote:

On 28/10/24 21:51 +0100, François Dumont wrote:



On 24/10/2024 21:49, Jonathan Wakely wrote:

On Thu, 24 Oct 2024 at 19:43, François Dumont  wrote:

Committed as trivial the attached patch.

libstdc++: Fix test broken when using COW std::string

libstdc++-v3/ChangeLog:

* testsuite/23_containers/unordered_map/96088.cc (test03):

Thanks! I think it was affecting the unordered_set test too.


Hi

This was indeed revealing a problem in my attempt to fix this bug.

Here is the complete patch that I will backport if validated.

libstdc++: [_Hashtable] Avoid temporaries when inserting existing key

Following PR 115285 fix, the hashtable _S_forward_key responsible 
for finding

the best way to transmit the key part of the argument parameter to the hash
functor was modified to return a key_type instance for any argument 
type. Only
the overloads for const key_type& and key_type&& were still 
preventing a key_type

instanciation.

It revealed that a overload for key_type& was missing. To fix this 
problem we now
deal with all sort of key_type of reference type in the unique 
_S_forward_key static
method and remove the overloads. When decayed type of the input 
instance is the same
as key_type we avoid the instanciation. Note that for the comparison 
we also decay
key_type to properly managed when unordered container is 
instantiated with a const

type.

libstdc++-v3/ChangeLog:

    * include/bits/hashtable_policy.h
    (_ConvertToValueType<_Select1st, 
_Value>::operator(std::pair<>&)): New,
    allow consistent behavior with 
_ConvertToValueType<_Identity, _Value>.

    * include/bits/hashtable.h
    (_S_forward_key<_Kt>(_Kt&&)): Adapt to return _Kt&& when 
decayed _Kt is

    key_type, return a new key_type instance otherwise.
    (_S_forward_key(const key_type&)): Remove.
    (_S_forward_key(key_type&&)): Remove.
    * testsuite/23_containers/unordered_set/96088.cc (test03): 
Adapt expected

    allocation increment.

Tested under linux x64, both std::string abi.

Ok to commit ?


No, because it's still not a complete fix, just more special cases.

I think the attached patch (actually two patches, as there's one to
add __is_pair first) fixes PR 115285, including all the other cases I
added in comment 14. It also avoids regressing PR 96088.

This seems small and safe enough to backport. On trunk I still plan to
follow this with the bigger refactoring.

Tests are still running ...





commit 590091e997248dd475d7329f4613765d7cff8bb6
Author: Jonathan Wakely 
Date:   Fri Nov 1 10:09:55 2024

   libstdc++: Define __is_pair variable template for C++11
   
   libstdc++-v3/ChangeLog:
   
   * include/bits/stl_pair.h (__is_pair): Define for C++11 and

   C++14 as well.

diff --git a/libstdc++-v3/include/bits/stl_pair.h 
b/libstdc++-v3/include/bits/stl_pair.h
index e92fcad2d66..527fb9105f0 100644
--- a/libstdc++-v3/include/bits/stl_pair.h
+++ b/libstdc++-v3/include/bits/stl_pair.h
@@ -1189,12 +1189,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION

  template
inline constexpr size_t tuple_size_v> = 2;
+#endif

+#if __cplusplus >= 201103L
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++14-extensions" // variable templates
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // inline variables
  template
inline constexpr bool __is_pair = false;

  template
inline constexpr bool __is_pair> = true;
+#pragma GCC diagnostic pop
#endif

  /// @cond undocumented

commit 23328cc25365593d045096ccf913cb273202edb0
Author: Jonathan Wakely 
Date:   Tue Nov 5 17:19:06 2024

   libstdc++: Fix conversions to key/value type for insertions into hash tables 
[PR115285]
   
   The conversions to key_type and value_type that are performed when

   inserting into _Hashtable need to be fixed to do any required
   conversions explicitly. The current code assumes that conversions from
   the parameter to the key_type or value_type can be done implicitly,
   which isn't necessarily true.
   
   Remove the _S_forward_key function which doesn't handle all cases and

   either forward the parameter if it already has type cv key_type, or
   explicitly construct a temporary of type key_type.
   
   Similarly, for the _ConvertToValueType specialization for maps, either

   forward a std::pair parameter unchanged, or explicitly construct a
   temporary of type value_type.
   
   libstdc++-v3/ChangeLog:
   
   PR libstdc++/115285

   * include/bits/hashtable.h (_Hashtable::_S_forward_key): Remove.
   (_Hashtable::_M_insert_unique_aux):
   * include/bits/hashtable_policy.h (_ConvertToValueType): Add
   comment.
   (_ConvertToValueType<_Select1st, _Value>): Replace incomplete
   overload set with two overloads, one for std::pair
 

Re: [Bug libstdc++/115285] [12/13/14/15 Regression] std::unordered_set can have duplicate value

2024-11-05 Thread Jonathan Wakely

On 28/10/24 21:51 +0100, François Dumont wrote:



On 24/10/2024 21:49, Jonathan Wakely wrote:

On Thu, 24 Oct 2024 at 19:43, François Dumont  wrote:

Committed as trivial the attached patch.

 libstdc++: Fix test broken when using COW std::string

 libstdc++-v3/ChangeLog:

 * testsuite/23_containers/unordered_map/96088.cc (test03):

Thanks! I think it was affecting the unordered_set test too.


Hi

This was indeed revealing a problem in my attempt to fix this bug.

Here is the complete patch that I will backport if validated.

libstdc++: [_Hashtable] Avoid temporaries when inserting existing key

Following PR 115285 fix, the hashtable _S_forward_key responsible for 
finding

the best way to transmit the key part of the argument parameter to the hash
functor was modified to return a key_type instance for any argument 
type. Only
the overloads for const key_type& and key_type&& were still preventing 
a key_type

instanciation.

It revealed that a overload for key_type& was missing. To fix this 
problem we now
deal with all sort of key_type of reference type in the unique 
_S_forward_key static
method and remove the overloads. When decayed type of the input 
instance is the same
as key_type we avoid the instanciation. Note that for the comparison 
we also decay
key_type to properly managed when unordered container is instantiated 
with a const

type.

libstdc++-v3/ChangeLog:

    * include/bits/hashtable_policy.h
    (_ConvertToValueType<_Select1st, 
_Value>::operator(std::pair<>&)): New,
    allow consistent behavior with _ConvertToValueType<_Identity, 
_Value>.

    * include/bits/hashtable.h
    (_S_forward_key<_Kt>(_Kt&&)): Adapt to return _Kt&& when 
decayed _Kt is

    key_type, return a new key_type instance otherwise.
    (_S_forward_key(const key_type&)): Remove.
    (_S_forward_key(key_type&&)): Remove.
    * testsuite/23_containers/unordered_set/96088.cc (test03): 
Adapt expected

    allocation increment.

Tested under linux x64, both std::string abi.

Ok to commit ?


No, because it's still not a complete fix, just more special cases.

I think the attached patch (actually two patches, as there's one to
add __is_pair first) fixes PR 115285, including all the other cases I
added in comment 14. It also avoids regressing PR 96088.

This seems small and safe enough to backport. On trunk I still plan to
follow this with the bigger refactoring.

Tests are still running ...


commit 590091e997248dd475d7329f4613765d7cff8bb6
Author: Jonathan Wakely 
Date:   Fri Nov 1 10:09:55 2024

libstdc++: Define __is_pair variable template for C++11

libstdc++-v3/ChangeLog:

* include/bits/stl_pair.h (__is_pair): Define for C++11 and
C++14 as well.

diff --git a/libstdc++-v3/include/bits/stl_pair.h b/libstdc++-v3/include/bits/stl_pair.h
index e92fcad2d66..527fb9105f0 100644
--- a/libstdc++-v3/include/bits/stl_pair.h
+++ b/libstdc++-v3/include/bits/stl_pair.h
@@ -1189,12 +1189,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
 inline constexpr size_t tuple_size_v> = 2;
+#endif
 
+#if __cplusplus >= 201103L
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++14-extensions" // variable templates
+#pragma GCC diagnostic ignored "-Wc++17-extensions" // inline variables
   template
 inline constexpr bool __is_pair = false;
 
   template
 inline constexpr bool __is_pair> = true;
+#pragma GCC diagnostic pop
 #endif
 
   /// @cond undocumented

commit 23328cc25365593d045096ccf913cb273202edb0
Author: Jonathan Wakely 
Date:   Tue Nov 5 17:19:06 2024

libstdc++: Fix conversions to key/value type for insertions into hash tables [PR115285]

The conversions to key_type and value_type that are performed when
inserting into _Hashtable need to be fixed to do any required
conversions explicitly. The current code assumes that conversions from
the parameter to the key_type or value_type can be done implicitly,
which isn't necessarily true.

Remove the _S_forward_key function which doesn't handle all cases and
either forward the parameter if it already has type cv key_type, or
explicitly construct a temporary of type key_type.

Similarly, for the _ConvertToValueType specialization for maps, either
forward a std::pair parameter unchanged, or explicitly construct a
temporary of type value_type.

libstdc++-v3/ChangeLog:

PR libstdc++/115285
* include/bits/hashtable.h (_Hashtable::_S_forward_key): Remove.
(_Hashtable::_M_insert_unique_aux):
* include/bits/hashtable_policy.h (_ConvertToValueType): Add
comment.
(_ConvertToValueType<_Select1st, _Value>): Replace incomplete
overload set with two overloads, one for std::pair

Re: [PATCH] libstdc++: Remove workaround for modules issue [PR113814]

2024-11-04 Thread Jonathan Wakely
On Mon, 4 Nov 2024 at 22:46, Nathaniel Shead  wrote:
>
> Thought I should probably clean this up before closing off the PR.
> Regtested on x86_64-pc-linux-gnu with no regressions, OK for trunk?

OK, thanks.


>
> -- >8 --
>
> The modules bug requiring this workaround was fixed with commit
> r15-4862-g815e48e3d42231.
>
> PR testsuite/113710
> PR c++/113814
>
> libstdc++-v3/ChangeLog:
>
> * include/bits/stl_pair.h: Remove workaround.
>
> Signed-off-by: Nathaniel Shead 
> ---
>  libstdc++-v3/include/bits/stl_pair.h | 5 -
>  1 file changed, 5 deletions(-)
>
> diff --git a/libstdc++-v3/include/bits/stl_pair.h 
> b/libstdc++-v3/include/bits/stl_pair.h
> index 0d60eaba194..e92fcad2d66 100644
> --- a/libstdc++-v3/include/bits/stl_pair.h
> +++ b/libstdc++-v3/include/bits/stl_pair.h
> @@ -1183,11 +1183,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>  struct tuple_element<1, pair<_Tp1, _Tp2>>
>  { typedef _Tp2 type; };
>
> -  // Forward declare the partial specialization for std::tuple
> -  // to work around modules bug PR c++/113814.
> -  template
> -struct tuple_element<__i, tuple<_Types...>>;
> -
>  #if __cplusplus >= 201703L
>template
>  inline constexpr size_t tuple_size_v> = 2;
> --
> 2.47.0
>



Re: [PATCH] Add fancy pointer support in std::map/set

2024-11-04 Thread Jonathan Wakely
On Mon, 4 Nov 2024 at 18:30, François Dumont  wrote:
>
>
> On 21/10/2024 06:56, François Dumont wrote:
>
>
> On 17/10/2024 23:11, Jonathan Wakely wrote:
>
>
>
> On Thu, 17 Oct 2024 at 21:39, Jonathan Wakely  wrote:
>>
>>
>>
>> On Thu, 17 Oct 2024 at 20:52, François Dumont  wrote:
>>>
>>> Here is an updated version that compiles, I think, all your feedbacks. It's 
>>> much cleaner indeed.
>>
>>
>> Thanks, I'll take a look tomorrow.
>>
>>>
>>> It's also tested in C++98/17/23.
>>>
>>> I'm surprised that we do not need to consider potential 
>>> allocator::const_pointer.
>>
>> Do you mean consider the case where Alloc::const_pointer is not the same 
>> type as rebinding 'pointer' to a const element type?
>
> Yes, exactly.
>
>
>>
>> We don't need to consider that because we never get a 'const_pointer' from 
>> the allocator, and we never need to pass a 'const_pointer' to the allocator. 
>> The allocator's 'allocate' and 'deallocate' members both work with the 
>> 'pointer' type, so we only need to use that type when interacting with the 
>> allocator. For all the other uses, such as _Const_Node_ptr, what we need is 
>> a pointer-to-const that's compatible with the allocator's pointer type. It 
>> doesn't actually matter if it's the same type as 
>> allocator_traits::const_pointer, because we don't need
>
>
> Sorry, I sent the email before finishing that thought!
>
> ... we don't need to pass a const_pointer to anything, we only need it for 
> the container's own purposes.
>
> But thinking about it some more, do we even need a const-pointer for the 
> container?  Currently the const_iterator stores a const-pointer, and some 
> members like _M_root() and _M_leftmost() return a const-pointer. But they 
> don't need to. The nodes are all pointed to by a non-const _Base_ptr, none of 
> the storage managed by the container is const.
>
> Except _M_impl._M_header in a const context.
>
> Using const_cast would result in a similar UB that you fixed on 
> _GLIBCXX_DEBUG containers, no ?

We only use a pointer to _M_header for the past-the-end iterator,
which is not dereferenceable. It's OK to do the const_cast, it's not
OK to write something through that pointer/reference if the object is
really const. But you can't write through a past-the-end pointer
anyway.


>
> I can provide a version with the const_cast but I'm not sure it worth it.
>
> François
>
>



Re: [PATCH] libstdc++: Fix up 117406.cc test [PR117406]

2024-11-04 Thread Jonathan Wakely
On Mon, 4 Nov 2024 at 10:55, Jakub Jelinek  wrote:
>
> Hi!
>
> Christophe mentioned in bugzilla that the test FAILs on aarch64,
> I'm not including  and use INT_MAX.
> Apparently during my testing I got it because the test preinclude
> -include bits/stdc++.h
> and that includes , dunno why that didn't happen on aarch64.
> In any case, either I can add #include , or because the
> test already has #include  I've changed uses of INT_MAX
> with std::numeric_limits::max(), that should be the same thing.
> But if you prefer
> #include 
> I can surely add that instead.

Using std::numeric_limits is fine here.

> Tested on x86_64-linux, ok for trunk?

OK, thanks.

>
> 2024-11-04  Jakub Jelinek  
>
> PR libstdc++/117406
> * testsuite/26_numerics/headers/cmath/117406.cc: Use
> std::numeric_limits::max() instead of INT_MAX.
>
> --- libstdc++-v3/testsuite/26_numerics/headers/cmath/117406.cc.jj   
> 2024-11-02 18:48:47.466350158 +0100
> +++ libstdc++-v3/testsuite/26_numerics/headers/cmath/117406.cc  2024-11-04 
> 11:40:25.793831812 +0100
> @@ -31,9 +31,9 @@ test ()
>int t0 = std::ilogb(T(4.0));
>VERIFY( t0 == 2 );
>int t1 = std::ilogb(lim::infinity());
> -  VERIFY( t1 == INT_MAX );
> +  VERIFY( t1 == std::numeric_limits::max() );
>int t2 = std::ilogb(-lim::infinity());
> -  VERIFY( t2 == INT_MAX );
> +  VERIFY( t2 == std::numeric_limits::max() );
>  }
>
>  int
>
> Jakub
>



Re: [PATCH] libstdc++: Fix up std::{, b}float16_t std::{ilogb, l{, l}r{ound, int}} [PR117406]

2024-11-02 Thread Jonathan Wakely
On Sat, 2 Nov 2024 at 07:11, Jakub Jelinek  wrote:
>
> Hi!
>
> These overloads incorrectly cast the result of the float __builtin_*
> to _Float or __gnu_cxx::__bfloat16_t.  For std::ilogb that changes
> behavior for the INT_MAX return because that isn't representable in
> either of the floating point formats, for the others it is I think
> just a very inefficient hop from int/long/long long to std::{,b}float16_t
> and back.  I mean for the round/rint cases, either the argument is small
> and then the return value should be representable in the floating point
> format too, or it is too large that the argument is already integral
> and then it should just return the argument with the round trips.
> Too large value is unspecified unlike ilogb.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

OK for trunk, thanks.

I think it's worth backporting too.

>
> 2024-11-02  Jakub Jelinek  
>
> PR libstdc++/117406
> * include/c_global/cmath (std::ilogb(_Float16), std::llrint(_Float16),
> std::llround(_Float16), std::lrint(_Float16), std::lround(_Float16)):
> Don't cast __builtin_* return to _Float16.
> (std::ilogb(__gnu_cxx::__bfloat16_t),
> std::llrint(__gnu_cxx::__bfloat16_t),
> std::llround(__gnu_cxx::__bfloat16_t),
> std::lrint(__gnu_cxx::__bfloat16_t),
> std::lround(__gnu_cxx::__bfloat16_t)): Don't cast __builtin_* return 
> to
> __gnu_cxx::__bfloat16_t.
> * testsuite/26_numerics/headers/cmath/117406.cc: New test.
>
> --- libstdc++-v3/include/c_global/cmath.jj  2024-10-29 11:13:47.741803660 
> +0100
> +++ libstdc++-v3/include/c_global/cmath 2024-11-01 21:11:40.367678439 +0100
> @@ -2838,7 +2838,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>
>constexpr int
>ilogb(_Float16 __x)
> -  { return _Float16(__builtin_ilogbf(__x)); }
> +  { return __builtin_ilogbf(__x); }
>
>constexpr _Float16
>lgamma(_Float16 __x)
> @@ -2846,11 +2846,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>
>constexpr long long
>llrint(_Float16 __x)
> -  { return _Float16(__builtin_llrintf(__x)); }
> +  { return __builtin_llrintf(__x); }
>
>constexpr long long
>llround(_Float16 __x)
> -  { return _Float16(__builtin_llroundf(__x)); }
> +  { return __builtin_llroundf(__x); }
>
>constexpr _Float16
>log1p(_Float16 __x)
> @@ -2867,11 +2867,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>
>constexpr long
>lrint(_Float16 __x)
> -  { return _Float16(__builtin_lrintf(__x)); }
> +  { return __builtin_lrintf(__x); }
>
>constexpr long
>lround(_Float16 __x)
> -  { return _Float16(__builtin_lroundf(__x)); }
> +  { return __builtin_lroundf(__x); }
>
>constexpr _Float16
>nearbyint(_Float16 __x)
> @@ -3560,7 +3560,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>
>constexpr int
>ilogb(__gnu_cxx::__bfloat16_t __x)
> -  { return __gnu_cxx::__bfloat16_t(__builtin_ilogbf(__x)); }
> +  { return __builtin_ilogbf(__x); }
>
>constexpr __gnu_cxx::__bfloat16_t
>lgamma(__gnu_cxx::__bfloat16_t __x)
> @@ -3568,11 +3568,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>
>constexpr long long
>llrint(__gnu_cxx::__bfloat16_t __x)
> -  { return __gnu_cxx::__bfloat16_t(__builtin_llrintf(__x)); }
> +  { return __builtin_llrintf(__x); }
>
>constexpr long long
>llround(__gnu_cxx::__bfloat16_t __x)
> -  { return __gnu_cxx::__bfloat16_t(__builtin_llroundf(__x)); }
> +  { return __builtin_llroundf(__x); }
>
>constexpr __gnu_cxx::__bfloat16_t
>log1p(__gnu_cxx::__bfloat16_t __x)
> @@ -3589,11 +3589,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>
>constexpr long
>lrint(__gnu_cxx::__bfloat16_t __x)
> -  { return __gnu_cxx::__bfloat16_t(__builtin_lrintf(__x)); }
> +  { return __builtin_lrintf(__x); }
>
>constexpr long
>lround(__gnu_cxx::__bfloat16_t __x)
> -  { return __gnu_cxx::__bfloat16_t(__builtin_lroundf(__x)); }
> +  { return __builtin_lroundf(__x); }
>
>constexpr __gnu_cxx::__bfloat16_t
>nearbyint(__gnu_cxx::__bfloat16_t __x)
> --- libstdc++-v3/testsuite/26_numerics/headers/cmath/117406.cc.jj   
> 2024-11-02 07:55:07.555121231 +0100
> +++ libstdc++-v3/testsuite/26_numerics/headers/cmath/117406.cc  2024-11-02 
> 08:00:14.150679537 +0100
> @@ -0,0 +1,59 @@
> +// Copyright (C) 2024 Free Software Foundation, Inc.
> +//
> +// This file is part of the GNU ISO C++ Library.  This library is free
> +// software; you can redistribute it and/or modify it under the
> +// terms of the GNU General Public License as published by the
> +// Free Software Foundation; either version 3, or (at your option)
> +// any later version.
> +
> +// This library is distributed in the hope that it will be useful,
> +// but WITHOUT ANY WARRANTY; without even the implied warranty of
> +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +// GNU General Public License for more details.
> +
> +// You should have received a copy of the GNU General Public License along
> +// with this library; see the file COPYI

Re: [PATCH] libstdc++: Deprecate useless compatibility headers for C++17

2024-11-01 Thread Jonathan Wakely

On 31/10/24 20:09 +, Jonathan Wakely wrote:

Tested x86_64-linux. Is the g++ test change OK?

Also available for review at:
https://forge.sourceware.org/gcc/gcc-TEST/pulls/4

-- >8 --

These headers make no sense for C++ programs, because they either define
different content to the corresponding  C header, or define
nothing at all in namespace std. They were all deprecated in C++17, so
add deprecation warnings to them, which can be disabled with
-Wno-deprecated. For C++20 and later these headers are no longer in the
standard at all, so compiling with _GLIBCXX_USE_DEPRECATED defined to 0
will give an error when they are included.

Because #warning is non-standard before C++23 we need to use pragmas to
ignore -Wc++23-extensions for the -Wsystem-headers -pedantic case.

One g++ test needs adjustment because it includes , but that
can be made conditional on the __cplusplus value without any reduction
in test coverage.

For the library tests, consolidate the std_c++0x_neg.cc XFAIL tests into
the macros.cc test, using dg-error with a { target c++98_only }
selector. This avoids having two separate test files, one for C++98 and
one for everything later. Also add tests for the  headers to
ensure that they behave as expected and don't give deprecated warnings.

libstdc++-v3/ChangeLog:

* doc/xml/manual/evolution.xml: Document deprecations.
* doc/html/*: Regenerate.
* include/c_compatibility/complex.h (_GLIBCXX_COMPLEX_H): Move
include guard to start of file. Include  directly
instead of .
* include/c_compatibility/tgmath.h: Include  and
 directly, instead of .
* include/c_global/ccomplex: Add deprecated #warning for C++17
and #error for C++20 if _GLIBCXX_USE_DEPRECATED == 0.
* include/c_global/ciso646: Likewise.
* include/c_global/cstdalign: Likewise.
* include/c_global/cstdbool: Likewise.
* include/c_global/ctgmath: Likewise.
* include/c_std/ciso646: Likewise.
* include/precompiled/stdc++.h: Do not include ccomplex,
ciso646, cstdalign, cstdbool, or ctgmath in C++17 and later.
* testsuite/18_support/headers/cstdalign/macros.cc: Check for
warnings and errors for unsupported dialects.
* testsuite/18_support/headers/cstdbool/macros.cc: Likewise.
* testsuite/26_numerics/headers/ctgmath/complex.cc: Likewise.
* testsuite/27_io/objects/char/1.cc: Do not include .
* testsuite/27_io/objects/wchar_t/1.cc: Likewise.
* testsuite/18_support/headers/cstdbool/std_c++0x_neg.cc: Removed.
* testsuite/18_support/headers/cstdalign/std_c++0x_neg.cc: Removed.
* testsuite/26_numerics/headers/ccomplex/std_c++0x_neg.cc: Removed.
* testsuite/26_numerics/headers/ctgmath/std_c++0x_neg.cc: Removed.
* testsuite/18_support/headers/ciso646/macros.cc: New test.
* testsuite/18_support/headers/ciso646/macros.h.cc: New test.
* testsuite/18_support/headers/cstdbool/macros.h.cc: New test.
* testsuite/26_numerics/headers/ccomplex/complex.cc: New test.
* testsuite/26_numerics/headers/ccomplex/complex.h.cc: New test.
* testsuite/26_numerics/headers/ctgmath/complex.h.cc: New test.

gcc/testsuite/ChangeLog:

* g++.old-deja/g++.other/headers1.C: Do not include ciso646 for
C++17 and later.
---
.../g++.old-deja/g++.other/headers1.C |  2 +
libstdc++-v3/doc/html/manual/api.html |  8 +++
libstdc++-v3/doc/xml/manual/evolution.xml | 10 
.../include/c_compatibility/complex.h | 10 ++--
libstdc++-v3/include/c_compatibility/tgmath.h | 11 ++--
libstdc++-v3/include/c_global/ccomplex|  9 
libstdc++-v3/include/c_global/ciso646 |  9 
libstdc++-v3/include/c_global/cstdalign   |  8 +++
libstdc++-v3/include/c_global/cstdbool|  8 +++
libstdc++-v3/include/c_global/ctgmath | 14 +++--
libstdc++-v3/include/c_std/ciso646| 10 
libstdc++-v3/include/precompiled/stdc++.h | 13 +++--
.../18_support/headers/ciso646/macros.cc  | 51 +++
.../18_support/headers/ciso646/macros.h.cc| 49 ++
.../18_support/headers/cstdalign/macros.cc| 10 +++-
.../18_support/headers/cstdalign/macros.h.cc  | 25 +
.../headers/cstdalign/std_c++0x_neg.cc| 24 -
.../18_support/headers/cstdbool/macros.cc |  9 +++-
.../18_support/headers/cstdbool/macros.h.cc   | 21 
.../headers/cstdbool/std_c++0x_neg.cc | 26 --
.../26_numerics/headers/ccomplex/complex.cc   | 10 
.../26_numerics/headers/ccomplex/complex.h.cc | 10 
.../headers/ccomplex/std_c++0x_neg.cc | 26 --
.../26_numerics/headers/ctgmath/complex.cc|  9 +++-
.../26_numerics/headers/ctgmath/complex.h.cc  | 10 
.../headers/ctgmath/std_c++0x_neg.cc  | 26 --
.../testsuite/27_io/objects/char/1.cc |  1 -
.../testsuite/27_io/objects/wchar_t/1.cc  |

Re: [PATCH] libstdc++: Deprecate useless compatibility headers for C++17

2024-11-01 Thread Jonathan Wakely

On 01/11/24 20:56 +, Jonathan Wakely wrote:

On 31/10/24 20:09 +, Jonathan Wakely wrote:

Tested x86_64-linux. Is the g++ test change OK?

Also available for review at:
https://forge.sourceware.org/gcc/gcc-TEST/pulls/4

-- >8 --

These headers make no sense for C++ programs, because they either define
different content to the corresponding  C header, or define
nothing at all in namespace std. They were all deprecated in C++17, so
add deprecation warnings to them, which can be disabled with
-Wno-deprecated. For C++20 and later these headers are no longer in the
standard at all, so compiling with _GLIBCXX_USE_DEPRECATED defined to 0
will give an error when they are included.

Because #warning is non-standard before C++23 we need to use pragmas to
ignore -Wc++23-extensions for the -Wsystem-headers -pedantic case.

One g++ test needs adjustment because it includes , but that
can be made conditional on the __cplusplus value without any reduction
in test coverage.

For the library tests, consolidate the std_c++0x_neg.cc XFAIL tests into
the macros.cc test, using dg-error with a { target c++98_only }
selector. This avoids having two separate test files, one for C++98 and
one for everything later. Also add tests for the  headers to
ensure that they behave as expected and don't give deprecated warnings.

libstdc++-v3/ChangeLog:

* doc/xml/manual/evolution.xml: Document deprecations.
* doc/html/*: Regenerate.
* include/c_compatibility/complex.h (_GLIBCXX_COMPLEX_H): Move
include guard to start of file. Include  directly
instead of .
* include/c_compatibility/tgmath.h: Include  and
 directly, instead of .
* include/c_global/ccomplex: Add deprecated #warning for C++17
and #error for C++20 if _GLIBCXX_USE_DEPRECATED == 0.
* include/c_global/ciso646: Likewise.
* include/c_global/cstdalign: Likewise.
* include/c_global/cstdbool: Likewise.
* include/c_global/ctgmath: Likewise.
* include/c_std/ciso646: Likewise.
* include/precompiled/stdc++.h: Do not include ccomplex,
ciso646, cstdalign, cstdbool, or ctgmath in C++17 and later.
* testsuite/18_support/headers/cstdalign/macros.cc: Check for
warnings and errors for unsupported dialects.
* testsuite/18_support/headers/cstdbool/macros.cc: Likewise.
* testsuite/26_numerics/headers/ctgmath/complex.cc: Likewise.
* testsuite/27_io/objects/char/1.cc: Do not include .
* testsuite/27_io/objects/wchar_t/1.cc: Likewise.
* testsuite/18_support/headers/cstdbool/std_c++0x_neg.cc: Removed.
* testsuite/18_support/headers/cstdalign/std_c++0x_neg.cc: Removed.
* testsuite/26_numerics/headers/ccomplex/std_c++0x_neg.cc: Removed.
* testsuite/26_numerics/headers/ctgmath/std_c++0x_neg.cc: Removed.
* testsuite/18_support/headers/ciso646/macros.cc: New test.
* testsuite/18_support/headers/ciso646/macros.h.cc: New test.
* testsuite/18_support/headers/cstdbool/macros.h.cc: New test.
* testsuite/26_numerics/headers/ccomplex/complex.cc: New test.
* testsuite/26_numerics/headers/ccomplex/complex.h.cc: New test.
* testsuite/26_numerics/headers/ctgmath/complex.h.cc: New test.

gcc/testsuite/ChangeLog:

* g++.old-deja/g++.other/headers1.C: Do not include ciso646 for
C++17 and later.
---
.../g++.old-deja/g++.other/headers1.C |  2 +
libstdc++-v3/doc/html/manual/api.html |  8 +++
libstdc++-v3/doc/xml/manual/evolution.xml | 10 
.../include/c_compatibility/complex.h | 10 ++--
libstdc++-v3/include/c_compatibility/tgmath.h | 11 ++--
libstdc++-v3/include/c_global/ccomplex|  9 
libstdc++-v3/include/c_global/ciso646 |  9 
libstdc++-v3/include/c_global/cstdalign   |  8 +++
libstdc++-v3/include/c_global/cstdbool|  8 +++
libstdc++-v3/include/c_global/ctgmath | 14 +++--
libstdc++-v3/include/c_std/ciso646| 10 
libstdc++-v3/include/precompiled/stdc++.h | 13 +++--
.../18_support/headers/ciso646/macros.cc  | 51 +++
.../18_support/headers/ciso646/macros.h.cc| 49 ++
.../18_support/headers/cstdalign/macros.cc| 10 +++-
.../18_support/headers/cstdalign/macros.h.cc  | 25 +
.../headers/cstdalign/std_c++0x_neg.cc| 24 -
.../18_support/headers/cstdbool/macros.cc |  9 +++-
.../18_support/headers/cstdbool/macros.h.cc   | 21 
.../headers/cstdbool/std_c++0x_neg.cc | 26 --
.../26_numerics/headers/ccomplex/complex.cc   | 10 
.../26_numerics/headers/ccomplex/complex.h.cc | 10 
.../headers/ccomplex/std_c++0x_neg.cc | 26 --
.../26_numerics/headers/ctgmath/complex.cc|  9 +++-
.../26_numerics/headers/ctgmath/complex.h.cc  | 10 
.../headers/ctgmath/std_c++0x_neg.cc  | 26 --
.../testsuite/27_io/objects/char/1.cc 

[committed] libstdc++: Check feature test macros in unordered containers

2024-11-01 Thread Jonathan Wakely
Replace some `__cplusplus > 201402L` preprocessor checks with more
expressive checks for the appropriate feature test macros.

libstdc++-v3/ChangeLog:

* include/bits/unordered_map.h: Check __glibcxx_node_extract and
__glibcxx_unordered_map_try_emplace instead of __cplusplus.
* include/bits/unordered_set.h: Check __glibcxx_node_extract
instead of __cplusplus.
---
Tested x86_64-linux. Pushed to trunk.

 libstdc++-v3/include/bits/unordered_map.h | 28 +++
 libstdc++-v3/include/bits/unordered_set.h | 24 +--
 2 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/libstdc++-v3/include/bits/unordered_map.h 
b/libstdc++-v3/include/bits/unordered_map.h
index 8607944d565..3b472534c66 100644
--- a/libstdc++-v3/include/bits/unordered_map.h
+++ b/libstdc++-v3/include/bits/unordered_map.h
@@ -137,7 +137,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   typedef typename _Hashtable::difference_type difference_type;
   ///@}
 
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
   using node_type = typename _Hashtable::node_type;
   using insert_return_type = typename _Hashtable::insert_return_type;
 #endif
@@ -426,7 +426,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
emplace_hint(const_iterator __pos, _Args&&... __args)
{ return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); }
 
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
   /// Extract a node.
   node_type
   extract(const_iterator __pos)
@@ -449,7 +449,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   iterator
   insert(const_iterator, node_type&& __nh)
   { return _M_h._M_reinsert_node(std::move(__nh)).position; }
-#endif // C++17
+#endif // node_extract
 
 #ifdef __glibcxx_unordered_map_try_emplace // C++ >= 17 && HOSTED
   /**
@@ -636,7 +636,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   { _M_h.insert(__l); }
 
 
-#if __cplusplus > 201402L
+#ifdef __glibcxx_unordered_map_try_emplace // >= C++17 && HOSTED
   /**
*  @brief Attempts to insert a std::pair into the %unordered_map.
*  @param __kKey to use for finding a possibly existing pair in
@@ -728,7 +728,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
__ret.first->second = std::forward<_Obj>(__obj);
  return __ret.first;
}
-#endif
+#endif // unordered_map_try_emplace
 
   ///@{
   /**
@@ -813,7 +813,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   noexcept( noexcept(_M_h.swap(__x._M_h)) )
   { _M_h.swap(__x._M_h); }
 
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
   template
friend class std::_Hash_merge_helper;
 
@@ -842,7 +842,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
void
merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>&& __source)
{ merge(__source); }
-#endif // C++17
+#endif // node_extract
 
   // observers.
 
@@ -1283,7 +1283,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   typedef typename _Hashtable::difference_type difference_type;
   ///@}
 
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
   using node_type = typename _Hashtable::node_type;
 #endif
 
@@ -1648,7 +1648,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   insert(initializer_list __l)
   { _M_h.insert(__l); }
 
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
   /// Extract a node.
   node_type
   extract(const_iterator __pos)
@@ -1671,7 +1671,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   iterator
   insert(const_iterator __hint, node_type&& __nh)
   { return _M_h._M_reinsert_node_multi(__hint, std::move(__nh)); }
-#endif // C++17
+#endif // node_extract
 
   ///@{
   /**
@@ -1756,7 +1756,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
   noexcept( noexcept(_M_h.swap(__x._M_h)) )
   { _M_h.swap(__x._M_h); }
 
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
   template
friend class std::_Hash_merge_helper;
 
@@ -1787,7 +1787,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
void
merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>&& __source)
{ merge(__source); }
-#endif // C++17
+#endif // node_extract
 
   // observers.
 
@@ -2169,7 +2169,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
 _GLIBCXX_END_NAMESPACE_CONTAINER
 
-#if __cplusplus > 201402L
+#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
   // Allow std::unordered_map access to internals of compatible maps.
   template
@@ -2217,7 +2217,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
   _S_get_table(unordered_multimap<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map)
   { return __map._M_h; }
 };
-#endif // C++17
+#endif // node_extract
 
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
diff --git a/libstdc++-v3/include/bits/unordered_set.h 
b/libstdc++-v3/include/bits/unordered_set.h
index a2fa2b4a083..08dcfa2a9b9 

[committed] libstdc++: Minor comment improvements in

2024-11-01 Thread Jonathan Wakely
libstdc++-v3/ChangeLog:

* include/bits/hashtable.h: Improve comments.
---
Tested x86_64-linux. Pushed to trunk.

 libstdc++-v3/include/bits/hashtable.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/include/bits/hashtable.h 
b/libstdc++-v3/include/bits/hashtable.h
index f1a5490b5ff..47321a9cb13 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -1019,7 +1019,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   iterator
   erase(const_iterator);
 
-  // LWG 2059.
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2059. C++0x ambiguity problem with map::erase
   iterator
   erase(iterator __it)
   { return erase(const_iterator(__it)); }
@@ -1041,7 +1042,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // DR 1189.
   // reserve, if present, comes from _Rehash_base.
 
-#if __glibcxx_node_extract // >= C++17
+#if __glibcxx_node_extract // >= C++17 && HOSTED
   /// Re-insert an extracted node into a container with unique keys.
   insert_return_type
   _M_reinsert_node(node_type&& __nh)
-- 
2.47.0



[committed] libstdc++: Remove stray whitespace in #endif

2024-11-01 Thread Jonathan Wakely
This isn't nested within another #if group so shouldn't be indented like
this.

libstdc++-v3/ChangeLog:

* libsupc++/typeinfo: Remove whitespace in #endif
---
Pushed as obvious.

 libstdc++-v3/libsupc++/typeinfo | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libstdc++-v3/libsupc++/typeinfo b/libstdc++-v3/libsupc++/typeinfo
index 71066eb1e46..721268cb3fa 100644
--- a/libstdc++-v3/libsupc++/typeinfo
+++ b/libstdc++-v3/libsupc++/typeinfo
@@ -212,7 +212,7 @@ namespace std
 return false;
 #endif
   }
-# endif
+#endif
 
 
   /**
-- 
2.47.0



[committed] libstdc++: Add missing header to unordered_set/pr115285.cc test

2024-11-01 Thread Jonathan Wakely
libstdc++-v3/ChangeLog:

* testsuite/23_containers/unordered_set/pr115285.cc: Include
missing header for std::vector.
---
Pushed as obvious.

 libstdc++-v3/testsuite/23_containers/unordered_set/pr115285.cc | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/pr115285.cc 
b/libstdc++-v3/testsuite/23_containers/unordered_set/pr115285.cc
index 6c5cc24930c..85954aed74b 100644
--- a/libstdc++-v3/testsuite/23_containers/unordered_set/pr115285.cc
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/pr115285.cc
@@ -2,8 +2,9 @@
 
 // libstdc++/115285
 
-#include 
 #include 
+#include 
+#include 
 
 #include 
 
-- 
2.47.0



[PATCH] libstdc++: Deprecate useless compatibility headers for C++17

2024-10-31 Thread Jonathan Wakely
Tested x86_64-linux. Is the g++ test change OK?

Also available for review at:
https://forge.sourceware.org/gcc/gcc-TEST/pulls/4

-- >8 --

These headers make no sense for C++ programs, because they either define
different content to the corresponding  C header, or define
nothing at all in namespace std. They were all deprecated in C++17, so
add deprecation warnings to them, which can be disabled with
-Wno-deprecated. For C++20 and later these headers are no longer in the
standard at all, so compiling with _GLIBCXX_USE_DEPRECATED defined to 0
will give an error when they are included.

Because #warning is non-standard before C++23 we need to use pragmas to
ignore -Wc++23-extensions for the -Wsystem-headers -pedantic case.

One g++ test needs adjustment because it includes , but that
can be made conditional on the __cplusplus value without any reduction
in test coverage.

For the library tests, consolidate the std_c++0x_neg.cc XFAIL tests into
the macros.cc test, using dg-error with a { target c++98_only }
selector. This avoids having two separate test files, one for C++98 and
one for everything later. Also add tests for the  headers to
ensure that they behave as expected and don't give deprecated warnings.

libstdc++-v3/ChangeLog:

* doc/xml/manual/evolution.xml: Document deprecations.
* doc/html/*: Regenerate.
* include/c_compatibility/complex.h (_GLIBCXX_COMPLEX_H): Move
include guard to start of file. Include  directly
instead of .
* include/c_compatibility/tgmath.h: Include  and
 directly, instead of .
* include/c_global/ccomplex: Add deprecated #warning for C++17
and #error for C++20 if _GLIBCXX_USE_DEPRECATED == 0.
* include/c_global/ciso646: Likewise.
* include/c_global/cstdalign: Likewise.
* include/c_global/cstdbool: Likewise.
* include/c_global/ctgmath: Likewise.
* include/c_std/ciso646: Likewise.
* include/precompiled/stdc++.h: Do not include ccomplex,
ciso646, cstdalign, cstdbool, or ctgmath in C++17 and later.
* testsuite/18_support/headers/cstdalign/macros.cc: Check for
warnings and errors for unsupported dialects.
* testsuite/18_support/headers/cstdbool/macros.cc: Likewise.
* testsuite/26_numerics/headers/ctgmath/complex.cc: Likewise.
* testsuite/27_io/objects/char/1.cc: Do not include .
* testsuite/27_io/objects/wchar_t/1.cc: Likewise.
* testsuite/18_support/headers/cstdbool/std_c++0x_neg.cc: Removed.
* testsuite/18_support/headers/cstdalign/std_c++0x_neg.cc: Removed.
* testsuite/26_numerics/headers/ccomplex/std_c++0x_neg.cc: Removed.
* testsuite/26_numerics/headers/ctgmath/std_c++0x_neg.cc: Removed.
* testsuite/18_support/headers/ciso646/macros.cc: New test.
* testsuite/18_support/headers/ciso646/macros.h.cc: New test.
* testsuite/18_support/headers/cstdbool/macros.h.cc: New test.
* testsuite/26_numerics/headers/ccomplex/complex.cc: New test.
* testsuite/26_numerics/headers/ccomplex/complex.h.cc: New test.
* testsuite/26_numerics/headers/ctgmath/complex.h.cc: New test.

gcc/testsuite/ChangeLog:

* g++.old-deja/g++.other/headers1.C: Do not include ciso646 for
C++17 and later.
---
 .../g++.old-deja/g++.other/headers1.C |  2 +
 libstdc++-v3/doc/html/manual/api.html |  8 +++
 libstdc++-v3/doc/xml/manual/evolution.xml | 10 
 .../include/c_compatibility/complex.h | 10 ++--
 libstdc++-v3/include/c_compatibility/tgmath.h | 11 ++--
 libstdc++-v3/include/c_global/ccomplex|  9 
 libstdc++-v3/include/c_global/ciso646 |  9 
 libstdc++-v3/include/c_global/cstdalign   |  8 +++
 libstdc++-v3/include/c_global/cstdbool|  8 +++
 libstdc++-v3/include/c_global/ctgmath | 14 +++--
 libstdc++-v3/include/c_std/ciso646| 10 
 libstdc++-v3/include/precompiled/stdc++.h | 13 +++--
 .../18_support/headers/ciso646/macros.cc  | 51 +++
 .../18_support/headers/ciso646/macros.h.cc| 49 ++
 .../18_support/headers/cstdalign/macros.cc| 10 +++-
 .../18_support/headers/cstdalign/macros.h.cc  | 25 +
 .../headers/cstdalign/std_c++0x_neg.cc| 24 -
 .../18_support/headers/cstdbool/macros.cc |  9 +++-
 .../18_support/headers/cstdbool/macros.h.cc   | 21 
 .../headers/cstdbool/std_c++0x_neg.cc | 26 --
 .../26_numerics/headers/ccomplex/complex.cc   | 10 
 .../26_numerics/headers/ccomplex/complex.h.cc | 10 
 .../headers/ccomplex/std_c++0x_neg.cc | 26 --
 .../26_numerics/headers/ctgmath/complex.cc|  9 +++-
 .../26_numerics/headers/ctgmath/complex.h.cc  | 10 
 .../headers/ctgmath/std_c++0x_neg.cc  | 26 --
 .../testsuite/27_io/objects/char/1.cc |  1 -
 .../testsuite/27_io/objects/wchar_t/1.cc  |  1 -
 28 files changed, 294 insert

[PATCH 2/2] libstdc++: More user-friendly failed assertions from shared_ptr dereference

2024-10-31 Thread Jonathan Wakely
Currently dereferencing an empty shared_ptr prints a complicated
internal type in the assertion message:

include/bits/shared_ptr_base.h:1377: std::__shared_ptr_access<_Tp, _Lp, 
,  >::element_type& std::__shared_ptr_access<_Tp, _Lp, 
,  >::operator*() const [with _Tp = 
std::filesystem::__cxx11::recursive_directory_iterator::_Dir_stack; 
__gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic; bool  = false; 
bool  = false; element_type = 
std::filesystem::__cxx11::recursive_directory_iterator::_Dir_stack]: Assertion 
'_M_get() != nullptr' failed.

Users don't care about any of the _Lp and  template
parameters, so this is unnecessarily verbose.

We can simplify it to something that only mentions "shared_ptr_deref"
and the element type:

include/bits/shared_ptr_base.h:1371: _Tp* std::__shared_ptr_deref(_Tp*) [with 
_Tp = filesystem::__cxx11::recursive_directory_iterator::_Dir_stack]: Assertion 
'__p != nullptr' failed.

libstdc++-v3/ChangeLog:

* include/bits/shared_ptr_base.h (__shared_ptr_deref): New
function template.
(__shared_ptr_access, __shared_ptr_access<>): Use it.
---
Tested x86_64-linux.

Also available for review at:
https://forge.sourceware.org/gcc/gcc-TEST/pulls/13

 libstdc++-v3/include/bits/shared_ptr_base.h | 28 +
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h 
b/libstdc++-v3/include/bits/shared_ptr_base.h
index 9a7617e7014..ee01594ce0c 100644
--- a/libstdc++-v3/include/bits/shared_ptr_base.h
+++ b/libstdc++-v3/include/bits/shared_ptr_base.h
@@ -1337,6 +1337,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { };
 
 
+  template
+[[__gnu__::__always_inline__]]
+inline _Tp*
+__shared_ptr_deref(_Tp* __p)
+{
+  __glibcxx_assert(__p != nullptr);
+  return __p;
+}
+
   // Define operator* and operator-> for shared_ptr.
   template::value, bool = is_void<_Tp>::value>
@@ -1347,10 +1356,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   element_type&
   operator*() const noexcept
-  {
-   __glibcxx_assert(_M_get() != nullptr);
-   return *_M_get();
-  }
+  { return *std::__shared_ptr_deref(_M_get()); }
 
   element_type*
   operator->() const noexcept
@@ -1392,10 +1398,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   [[__deprecated__("shared_ptr::operator* is absent from C++17")]]
   element_type&
   operator*() const noexcept
-  {
-   __glibcxx_assert(_M_get() != nullptr);
-   return *_M_get();
-  }
+  { return *std::__shared_ptr_deref(_M_get()); }
 
   [[__deprecated__("shared_ptr::operator-> is absent from C++17")]]
   element_type*
@@ -1406,13 +1409,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   }
 #endif
 
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions"
   element_type&
   operator[](ptrdiff_t __i) const noexcept
   {
-   __glibcxx_assert(_M_get() != nullptr);
-   __glibcxx_assert(!extent<_Tp>::value || __i < extent<_Tp>::value);
-   return _M_get()[__i];
+   if constexpr (extent<_Tp>::value)
+ __glibcxx_assert(__i < extent<_Tp>::value);
+   return std::__shared_ptr_deref(_M_get())[__i];
   }
+#pragma GCC diagnostic pop
 
 private:
   element_type*
-- 
2.47.0



[PATCH 1/2] libstdc++: Enable debug assertions for filesystem directory iterators

2024-10-31 Thread Jonathan Wakely
Several member functions of filesystem::directory_iterator and
filesystem::recursive_directory_iterator currently dereference their
shared_ptr data member without checking for non-null. Because they use
operator-> and that function only uses _GLIBCXX_DEBUG_PEDASSERT rather
than __glibcxx_assert there is no assertion even when the library is
built with _GLIBCXX_ASSERTIONS defined. This means that dereferencing
invalid directory iterators gives an unhelpful segfault.

By using (*p). instead of p-> we get an assertion when the library is
built with _GLIBCXX_ASSERTIONS, with a "_M_get() != nullptr" message.

libstdc++-v3/ChangeLog:

* src/c++17/fs_dir.cc (fs::directory_iterator::operator*): Use
shared_ptr::operator* instead of shared_ptr::operator->.
(fs::recursive_directory_iterator::options): Likewise.
(fs::recursive_directory_iterator::depth): Likewise.
(fs::recursive_directory_iterator::recursion_pending): Likewise.
(fs::recursive_directory_iterator::operator*): Likewise.
(fs::recursive_directory_iterator::disable_recursion_pending):
Likewise.
---
Tested x86_64-linux.

Also available for review at:
https://forge.sourceware.org/gcc/gcc-TEST/pulls/13


 libstdc++-v3/src/c++17/fs_dir.cc | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/libstdc++-v3/src/c++17/fs_dir.cc b/libstdc++-v3/src/c++17/fs_dir.cc
index 28d27f6a9fa..8fe9e5e4cc8 100644
--- a/libstdc++-v3/src/c++17/fs_dir.cc
+++ b/libstdc++-v3/src/c++17/fs_dir.cc
@@ -230,7 +230,7 @@ directory_iterator(const path& p, directory_options 
options, error_code* ecptr)
 const fs::directory_entry&
 fs::directory_iterator::operator*() const noexcept
 {
-  return _M_dir->entry;
+  return (*_M_dir).entry;
 }
 
 fs::directory_iterator&
@@ -327,25 +327,25 @@ 
fs::recursive_directory_iterator::~recursive_directory_iterator() = default;
 fs::directory_options
 fs::recursive_directory_iterator::options() const noexcept
 {
-  return _M_dirs->options;
+  return (*_M_dirs).options;
 }
 
 int
 fs::recursive_directory_iterator::depth() const noexcept
 {
-  return int(_M_dirs->size()) - 1;
+  return int((*_M_dirs).size()) - 1;
 }
 
 bool
 fs::recursive_directory_iterator::recursion_pending() const noexcept
 {
-  return _M_dirs->pending;
+  return (*_M_dirs).pending;
 }
 
 const fs::directory_entry&
 fs::recursive_directory_iterator::operator*() const noexcept
 {
-  return _M_dirs->top().entry;
+  return (*_M_dirs).top().entry;
 }
 
 fs::recursive_directory_iterator&
@@ -453,7 +453,7 @@ fs::recursive_directory_iterator::pop()
 void
 fs::recursive_directory_iterator::disable_recursion_pending() noexcept
 {
-  _M_dirs->pending = false;
+  (*_M_dirs).pending = false;
 }
 
 // Used to implement filesystem::remove_all.
-- 
2.47.0



[committed] libstdc++: Fix copy&paste comments in vector range tests

2024-10-30 Thread Jonathan Wakely
These comments were copied from the std::vector tests, but the
value_type is not bool in these ones.

libstdc++-v3/ChangeLog:

* testsuite/23_containers/vector/cons/from_range.cc: Fix copy &
paste error in comment.
* testsuite/23_containers/vector/modifiers/append_range.cc:
Likewise.
* testsuite/23_containers/vector/modifiers/assign/assign_range.cc:
Likewise.
* testsuite/23_containers/vector/modifiers/insert/insert_range.cc:
Likewise.
---
Pushed to trunk.

 libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc  | 2 +-
 .../testsuite/23_containers/vector/modifiers/append_range.cc| 2 +-
 .../23_containers/vector/modifiers/assign/assign_range.cc   | 2 +-
 .../23_containers/vector/modifiers/insert/insert_range.cc   | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc 
b/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc
index e91465f5a71..ed2e3ca6ba1 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc
@@ -80,7 +80,7 @@ test_ranges()
   do_test_a>();
   do_test_a>();
 
-  // Not lvalue-convertible to bool
+  // Not lvalue-convertible to int
   struct C {
 C(int v) : val(v) { }
 operator int() && { return val; }
diff --git 
a/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc 
b/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc
index 24a5c7d0e7c..5725cd2ad48 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc
@@ -69,7 +69,7 @@ test_ranges()
   do_test_a>();
   do_test_a>();
 
-  // Not lvalue-convertible to bool
+  // Not lvalue-convertible to int
   struct C {
 C(int v) : val(v) { }
 operator int() && { return val; }
diff --git 
a/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc 
b/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc
index 4e8d8af1614..db3b06cfbc0 100644
--- 
a/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc
+++ 
b/libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc
@@ -90,7 +90,7 @@ test_ranges()
   do_test_a>();
   do_test_a>();
 
-  // Not lvalue-convertible to bool
+  // Not lvalue-convertible to int
   struct C {
 C(int v) : val(v) { }
 operator int() && { return val; }
diff --git 
a/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc 
b/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc
index 30219f5da02..68218e94f28 100644
--- 
a/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc
+++ 
b/libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc
@@ -80,7 +80,7 @@ test_ranges()
   do_test_a>();
   do_test_a>();
 
-  // Not lvalue-convertible to bool
+  // Not lvalue-convertible to int
   struct C {
 C(int v) : val(v) { }
 operator int() && { return val; }
-- 
2.47.0



Re: [PATCH] libstdc++: Add align_alloc attribute to aligned operator new

2024-10-30 Thread Jonathan Wakely
On Wed, 30 Oct 2024 at 21:54, Jakub Jelinek  wrote:
>
> On Wed, Oct 30, 2024 at 09:24:05PM +, Jonathan Wakely wrote:
> > The aligned versions of operator new should use the align_alloc
> > attribute to help the compiler.
> >
> > PR c++/86878 requests that the compiler would use the attribute to warn
> > about invalid attributes, so an XFAILed test is added for that.
> >
> > libstdc++-v3/ChangeLog:
> >
> >   * libsupc++/new (operator new): Add attribute align_alloc(2) to
> >   overloads taking a std::align_val_t argument.
> >   * testsuite/18_support/new_aligned_warn.cc: New test.
> > ---
> > I think this makes sense, but maybe there's some property of the
> > attribute that means this isn't a good idea? I think the compiler can
> > use the value of align_val_t even though it's a scoped enumeration type.
>
> We document that alloc_align (and alloc_size etc.) arguments can have
> integer or enumerated types, the implemented check is INTEGRAL_TYPE_P (t)
> && TREE_CODE (t) != BOOLEAN_TYPE.

I suppose the "not implicitly convertible to an integer" rule for
scoped enums is just a language constraint, the compiler sees scoped
enumerations like any other integral value.

> And the meaning of the attribute is exactly what the C++ standard requires
> from such operators, so the patch LGTM.

Great, thanks, I'll push in the morning.



Re: [PATCH] libstdc++: Add align_alloc attribute to aligned operator new

2024-10-30 Thread Jonathan Wakely
On Wed, 30 Oct 2024 at 21:26, Jonathan Wakely  wrote:
>
> The aligned versions of operator new should use the align_alloc
> attribute to help the compiler.
>
> PR c++/86878 requests that the compiler would use the attribute to warn
> about invalid attributes, so an XFAILed test is added for that.
>
> libstdc++-v3/ChangeLog:
>
> * libsupc++/new (operator new): Add attribute align_alloc(2) to
> overloads taking a std::align_val_t argument.
> * testsuite/18_support/new_aligned_warn.cc: New test.
> ---
> I think this makes sense, but maybe there's some property of the
> attribute that means this isn't a good idea? I think the compiler can
> use the value of align_val_t even though it's a scoped enumeration type.
>
> Tested x86_64-linux.

I forgot to say that this is also available for review at:
https://forge.sourceware.org/gcc/gcc-TEST/pulls/12

>
>  libstdc++-v3/libsupc++/new  |  6 +++---
>  .../testsuite/18_support/new_aligned_warn.cc| 13 +
>  2 files changed, 16 insertions(+), 3 deletions(-)
>  create mode 100644 libstdc++-v3/testsuite/18_support/new_aligned_warn.cc
>
> diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new
> index e9a3d9b49a3..4345030071b 100644
> --- a/libstdc++-v3/libsupc++/new
> +++ b/libstdc++-v3/libsupc++/new
> @@ -167,7 +167,7 @@ void operator delete[](void*, const std::nothrow_t&)
>  #if __cpp_aligned_new
>  _GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t)
>_GLIBCXX_TXN_SAFE
> -  __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__));
> +  __attribute__((__externally_visible__, __alloc_size__ (1), __alloc_align__ 
> (2),  __malloc__));
>  _GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t, const 
> std::nothrow_t&)
> _GLIBCXX_TXN_SAFE
>_GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, 
> __alloc_size__ (1), __malloc__));
> @@ -178,10 +178,10 @@ void operator delete(void*, std::align_val_t, const 
> std::nothrow_t&)
>_GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
>  _GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t)
>_GLIBCXX_TXN_SAFE
> -  __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__));
> +  __attribute__((__externally_visible__, __alloc_size__ (1), __alloc_align__ 
> (2), __malloc__));
>  _GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t, const 
> std::nothrow_t&)
>_GLIBCXX_TXN_SAFE
> -  _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, 
> __alloc_size__ (1), __malloc__));
> +  _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, 
> __alloc_size__ (1), __alloc_align__ (2), __malloc__));
>  void operator delete[](void*, std::align_val_t) _GLIBCXX_TXN_SAFE
>_GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
>  void operator delete[](void*, std::align_val_t, const std::nothrow_t&)
> diff --git a/libstdc++-v3/testsuite/18_support/new_aligned_warn.cc 
> b/libstdc++-v3/testsuite/18_support/new_aligned_warn.cc
> new file mode 100644
> index 000..e9d374abe31
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/18_support/new_aligned_warn.cc
> @@ -0,0 +1,13 @@
> +// { dg-options "-Wattributes" }
> +// { dg-do compile { target c++17 } }
> +
> +#include 
> +
> +int main()
> +{
> +  // PR c++/86878 has a patch to make these warn.
> +  (void) operator new(1, std::align_val_t(3)); // { dg-warning "power of 
> two" "" { xfail *-*-* } }
> +  (void) operator new[](1, std::align_val_t(10)); // { dg-warning "power of 
> two" "" { xfail *-*-* } }
> +  (void) operator new(1, std::align_val_t(0), std::nothrow_t()); // { 
> dg-warning "power of two" "" { xfail *-*-* } }
> +  (void) operator new[](1, std::align_val_t(-1), std::nothrow_t()); // { 
> dg-warning "power of two" "" { xfail *-*-* } }
> +}
> --
> 2.47.0
>



[PATCH] libstdc++: Add align_alloc attribute to aligned operator new

2024-10-30 Thread Jonathan Wakely
The aligned versions of operator new should use the align_alloc
attribute to help the compiler.

PR c++/86878 requests that the compiler would use the attribute to warn
about invalid attributes, so an XFAILed test is added for that.

libstdc++-v3/ChangeLog:

* libsupc++/new (operator new): Add attribute align_alloc(2) to
overloads taking a std::align_val_t argument.
* testsuite/18_support/new_aligned_warn.cc: New test.
---
I think this makes sense, but maybe there's some property of the
attribute that means this isn't a good idea? I think the compiler can
use the value of align_val_t even though it's a scoped enumeration type.

Tested x86_64-linux.

 libstdc++-v3/libsupc++/new  |  6 +++---
 .../testsuite/18_support/new_aligned_warn.cc| 13 +
 2 files changed, 16 insertions(+), 3 deletions(-)
 create mode 100644 libstdc++-v3/testsuite/18_support/new_aligned_warn.cc

diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new
index e9a3d9b49a3..4345030071b 100644
--- a/libstdc++-v3/libsupc++/new
+++ b/libstdc++-v3/libsupc++/new
@@ -167,7 +167,7 @@ void operator delete[](void*, const std::nothrow_t&)
 #if __cpp_aligned_new
 _GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t)
   _GLIBCXX_TXN_SAFE
-  __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__));
+  __attribute__((__externally_visible__, __alloc_size__ (1), __alloc_align__ 
(2),  __malloc__));
 _GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t, const 
std::nothrow_t&)
_GLIBCXX_TXN_SAFE
   _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, __alloc_size__ 
(1), __malloc__));
@@ -178,10 +178,10 @@ void operator delete(void*, std::align_val_t, const 
std::nothrow_t&)
   _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
 _GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t)
   _GLIBCXX_TXN_SAFE
-  __attribute__((__externally_visible__, __alloc_size__ (1), __malloc__));
+  __attribute__((__externally_visible__, __alloc_size__ (1), __alloc_align__ 
(2), __malloc__));
 _GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t, const 
std::nothrow_t&)
   _GLIBCXX_TXN_SAFE
-  _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, __alloc_size__ 
(1), __malloc__));
+  _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, __alloc_size__ 
(1), __alloc_align__ (2), __malloc__));
 void operator delete[](void*, std::align_val_t) _GLIBCXX_TXN_SAFE
   _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__));
 void operator delete[](void*, std::align_val_t, const std::nothrow_t&)
diff --git a/libstdc++-v3/testsuite/18_support/new_aligned_warn.cc 
b/libstdc++-v3/testsuite/18_support/new_aligned_warn.cc
new file mode 100644
index 000..e9d374abe31
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/new_aligned_warn.cc
@@ -0,0 +1,13 @@
+// { dg-options "-Wattributes" }
+// { dg-do compile { target c++17 } }
+
+#include 
+
+int main()
+{
+  // PR c++/86878 has a patch to make these warn.
+  (void) operator new(1, std::align_val_t(3)); // { dg-warning "power of two" 
"" { xfail *-*-* } }
+  (void) operator new[](1, std::align_val_t(10)); // { dg-warning "power of 
two" "" { xfail *-*-* } }
+  (void) operator new(1, std::align_val_t(0), std::nothrow_t()); // { 
dg-warning "power of two" "" { xfail *-*-* } }
+  (void) operator new[](1, std::align_val_t(-1), std::nothrow_t()); // { 
dg-warning "power of two" "" { xfail *-*-* } }
+}
-- 
2.47.0



[PATCH] libstdc++: Add P1206R7 from_range members to std::list and std::forward_list [PR111055]

2024-10-30 Thread Jonathan Wakely
This is another piece of P1206R7, adding new members to std::list and
std::forward_list.

libstdc++-v3/ChangeLog:

PR libstdc++/111055
* include/bits/forward_list.h
(forward_list(from_range, R&&, const Alloc&), assign_range)
(prepend_range, insert_range_after): Define.
* include/bits/stl_list.h: (list(from_range, R&&, const Alloc&))
(assign_range, prepend_range, append_range, insert_range):
Define.
* testsuite/23_containers/forward_list/cons/from_range.cc: New
test.
* testsuite/23_containers/forward_list/modifiers/assign_range.cc:
New test.
* testsuite/23_containers/forward_list/modifiers/insert_range_after.cc:
New test.
* testsuite/23_containers/forward_list/modifiers/prepend_range.cc:
New test.
* testsuite/23_containers/list/cons/from_range.cc: New test.
* testsuite/23_containers/list/modifiers/append_range.cc: New
test.
* testsuite/23_containers/list/modifiers/assign/assign_range.cc:
New test.
* testsuite/23_containers/list/modifiers/insert/insert_range.cc:
New test.
* testsuite/23_containers/list/modifiers/prepend_range.cc: New
test.
---
Tested x86_64-linux.

This is also available for review at:
https://forge.sourceware.org/gcc/gcc-TEST/pulls/11/files

 libstdc++-v3/include/bits/forward_list.h  | 121 +
 libstdc++-v3/include/bits/stl_list.h  | 126 ++
 .../forward_list/cons/from_range.cc   | 100 ++
 .../forward_list/modifiers/assign_range.cc|  97 ++
 .../modifiers/insert_range_after.cc   |  93 +
 .../forward_list/modifiers/prepend_range.cc   |  86 
 .../23_containers/list/cons/from_range.cc | 100 ++
 .../list/modifiers/append_range.cc|  86 
 .../list/modifiers/assign/assign_range.cc |  99 ++
 .../list/modifiers/insert/insert_range.cc |  98 ++
 .../list/modifiers/prepend_range.cc   |  86 
 11 files changed, 1092 insertions(+)
 create mode 100644 
libstdc++-v3/testsuite/23_containers/forward_list/cons/from_range.cc
 create mode 100644 
libstdc++-v3/testsuite/23_containers/forward_list/modifiers/assign_range.cc
 create mode 100644 
libstdc++-v3/testsuite/23_containers/forward_list/modifiers/insert_range_after.cc
 create mode 100644 
libstdc++-v3/testsuite/23_containers/forward_list/modifiers/prepend_range.cc
 create mode 100644 libstdc++-v3/testsuite/23_containers/list/cons/from_range.cc
 create mode 100644 
libstdc++-v3/testsuite/23_containers/list/modifiers/append_range.cc
 create mode 100644 
libstdc++-v3/testsuite/23_containers/list/modifiers/assign/assign_range.cc
 create mode 100644 
libstdc++-v3/testsuite/23_containers/list/modifiers/insert/insert_range.cc
 create mode 100644 
libstdc++-v3/testsuite/23_containers/list/modifiers/prepend_range.cc

diff --git a/libstdc++-v3/include/bits/forward_list.h 
b/libstdc++-v3/include/bits/forward_list.h
index eee773c0212..6ccf2eb2bff 100644
--- a/libstdc++-v3/include/bits/forward_list.h
+++ b/libstdc++-v3/include/bits/forward_list.h
@@ -42,6 +42,10 @@
 #include 
 #include 
 #include 
+#if __glibcxx_ranges_to_container // C++ >= 23
+# include  // ranges::begin, ranges::distance etc.
+# include  // ranges::subrange
+#endif
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -564,6 +568,30 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
: _Base(_Node_alloc_type(__al))
{ _M_range_initialize(__first, __last); }
 
+#if __glibcxx_ranges_to_container // C++ >= 23
+  /**
+   * @brief Construct a forward_list from a range.
+   * @param __rg An input range with elements that are convertible to
+   * the forward_list's value_type.
+   * @param __a An allocator.
+   *
+   * @since C++23
+   */
+  template<__detail::__container_compatible_range<_Tp> _Rg>
+   forward_list(from_range_t, _Rg&& __rg, const _Alloc& __a = _Alloc())
+   : _Base(_Node_alloc_type(__a))
+   {
+ _Node_base* __to = &this->_M_impl._M_head;
+ auto __first = ranges::begin(__rg);
+ const auto __last = ranges::end(__rg);
+ for (; __first != __last; ++__first)
+   {
+ __to->_M_next = this->_M_create_node(*__first);
+ __to = __to->_M_next;
+   }
+   }
+#endif // ranges_to_container
+
   /**
*  @brief  The %forward_list copy constructor.
*  @param  __list  A %forward_list of identical element and allocator
@@ -675,6 +703,39 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
  _M_assign(__first, __last, __assignable());
}
 
+#if __glibcxx_ranges_to_container // C++ >= 23
+  /**
+   * @brief Assign a range to a forward_list.
+   * @since C++23
+   */
+  template<__detail::__container_compatible_range<_Tp> _Rg>
+   void
+   assign_range

[committed] libstdc++: Fix some typos and grammatical errors in docs

2024-10-30 Thread Jonathan Wakely
Also remove some redundant 'void' parameters from code examples.

libstdc++-v3/ChangeLog:

* doc/xml/manual/using_exceptions.xml: Fix typos and grammatical
errors.
* doc/html/manual/using_exceptions.html: Regenerate.
---
Pushed to trunk.

 libstdc++-v3/doc/html/manual/using_exceptions.html | 12 ++--
 libstdc++-v3/doc/xml/manual/using_exceptions.xml   | 12 ++--
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/libstdc++-v3/doc/html/manual/using_exceptions.html 
b/libstdc++-v3/doc/html/manual/using_exceptions.html
index 706b27e1479..eb4501b1f6b 100644
--- a/libstdc++-v3/doc/html/manual/using_exceptions.html
+++ b/libstdc++-v3/doc/html/manual/using_exceptions.html
@@ -158,7 +158,7 @@ exception neutrality and exception safety.
   Doing without
 C++ is a language that strives to be as efficient as is possible
 in delivering features. As such, considerable care is used by both
-language implementer and designers to make sure unused features
+language implementer and designers to make sure unused features do
 not impose hidden or unexpected costs. The GNU system tries to be
 as flexible and as configurable as possible. So, it should come as
 no surprise that GNU C++ provides an optional language extension,
@@ -166,7 +166,7 @@ exception neutrality and exception safety.
 implicitly generated magic necessary to
 support try and catch blocks
 and thrown objects. (Language support
-for -fno-exceptions is documented in the GCC 
+for -fno-exceptions is documented in the GCC
 https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options";
 target="_top">manual.)
   Before detailing the library support
 for -fno-exceptions, first a passing note on
@@ -179,7 +179,7 @@ exception neutrality and exception safety.
 uses try or catch, you
 shouldn't use -fno-exceptions.
   
-And what it to be gained, tinkering in the back alleys with a
+And what is to be gained, tinkering in the back alleys with a
 language like this? Exception handling overhead can be measured
 in the size of the executable binary, and varies with the
 capabilities of the underlying operating system and specific
@@ -216,15 +216,15 @@ exception neutrality and exception safety.
 # define __throw_exception_again
 #endif
 
-  In addition, for every object derived from
+  In addition, for most of the classes derived from
   class exception, there exists a corresponding
   function with C language linkage. An example:
 
 #if __cpp_exceptions
-  void __throw_bad_exception(void)
+  void __throw_bad_exception()
   { throw bad_exception(); }
 #else
-  void __throw_bad_exception(void)
+  void __throw_bad_exception()
   { abort(); }
 #endif
 
diff --git a/libstdc++-v3/doc/xml/manual/using_exceptions.xml 
b/libstdc++-v3/doc/xml/manual/using_exceptions.xml
index ab42c809939..ac2ba9dffd4 100644
--- a/libstdc++-v3/doc/xml/manual/using_exceptions.xml
+++ b/libstdc++-v3/doc/xml/manual/using_exceptions.xml
@@ -274,7 +274,7 @@ exception neutrality and exception safety.
   
 C++ is a language that strives to be as efficient as is possible
 in delivering features. As such, considerable care is used by both
-language implementer and designers to make sure unused features
+language implementer and designers to make sure unused features do
 not impose hidden or unexpected costs. The GNU system tries to be
 as flexible and as configurable as possible. So, it should come as
 no surprise that GNU C++ provides an optional language extension,
@@ -282,7 +282,7 @@ exception neutrality and exception safety.
 implicitly generated magic necessary to
 support try and catch blocks
 and thrown objects. (Language support
-for -fno-exceptions is documented in the GCC 
+for -fno-exceptions is documented in the GCC
 http://www.w3.org/1999/xlink"; 
xlink:href="https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options";>manual.)
   
 
@@ -299,7 +299,7 @@ exception neutrality and exception safety.
   
 
   
-And what it to be gained, tinkering in the back alleys with a
+And what is to be gained, tinkering in the back alleys with a
 language like this? Exception handling overhead can be measured
 in the size of the executable binary, and varies with the
 capabilities of the underlying operating system and specific
@@ -344,17 +344,17 @@ exception neutrality and exception safety.
 
 
 
-  In addition, for every object derived from
+  In addition, for most of the classes derived from
   class exception, there exists a corresponding
   function with C language linkage. An example:
 
 
 
 #if __cpp_exceptions
-  void __throw_bad_exception(void)
+  void __throw_bad_exception()
   { throw bad_exception(); }
 #else
-  void __throw_bad_exception(void)
+  void __throw_bad_exception()
   { abort(); }
 #endif
 
-- 
2.47.0



Re: [pushed: r15-4760] diagnostics: support multiple output formats simultaneously [PR116613]

2024-10-30 Thread Jonathan Wakely

On 29/10/24 19:19 -0400, David Malcolm wrote:

This patch generalizes diagnostic_context so that rather than having
a single output format, it has a vector of zero or more.


[snip]


+/* Class for parsing the arguments of -fdiagnostics-add-output= and
+   -fdiagnostics-set-output=, and making diagnostic_output_format
+   instances (or issuing errors).  */
+
+class output_factory
+{
+public:
+  class handler
+  {
+  public:
+handler (std::string name) : m_name (name) {}


How long are these names?

If they don't fit in 15 chars, then this should be std::move(name).

So for a name like "sarif:version=2.1" it should be moved, otherwise
you make a deep copy and reallocate a new string.




Re: [PATCH] libstdc++: Use if consteval rather than if (std::__is_constant_evaluated()) for {,b}float16_t nextafter [PR117321]

2024-10-29 Thread Jonathan Wakely
On Tue, 29 Oct 2024, 09:00 Jakub Jelinek,  wrote:

> Hi!
>
> The nextafter_c++23.cc testcase fails to link at -O0.
> The problem is that eventhough std::__is_constant_evaluated() has
> always_inline attribute, that at -O0 just means that we inline the
> call, but its result is still assigned to a temporary which is tested
> later, nothing at -O0 propagates that false into the if and optimizes
> away the if body.  And the __builtin_nextafterf16{,b} calls are meant
> to be used solely for constant evaluation, the C libraries don't
> define nextafterf16 these days.
>
> As __STDCPP_FLOAT16_T__ and __STDCPP_BFLOAT16_T__ are predefined right
> now only by GCC, not by clang which doesn't implement the extended floating
> point types paper, and as they are predefined in C++23 and later modes
> only,
> I think we can just use if consteval which is folded already during the FE
> and the body isn't included even at -O0.  I've added a feature test for
> that just in case clang implements those and implements those in some weird
> way.  Note, if (__builtin_is_constant_evaluted()) would work correctly too,
> that is also folded to false at gimplification time and the corresponding
> if block not emitted at all.  But for -O0 it can't be wrapped into a helper
> inline function.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>

OK, thanks


> 2024-10-29  Jakub Jelinek  
>
> PR libstdc++/117321
> * include/c_global/cmath (nextafter(_Float16, _Float16)): Use
> if consteval rather than if (std::__is_constant_evaluated()) around
> the __builtin_nextafterf16 call.
> (nextafter(__gnu_cxx::__bfloat16_t, __gnu_cxx::__bfloat16_t)): Use
> if consteval rather than if (std::__is_constant_evaluated()) around
> the __builtin_nextafterf16b call.
> * testsuite/26_numerics/headers/cmath/117321.cc: New test.
>
> --- libstdc++-v3/include/c_global/cmath.jj  2024-09-25
> 17:25:07.227360607 +0200
> +++ libstdc++-v3/include/c_global/cmath 2024-10-28 13:10:46.348655046 +0100
> @@ -2880,8 +2880,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>constexpr _Float16
>nextafter(_Float16 __x, _Float16 __y)
>{
> -if (std::__is_constant_evaluated())
> -  return __builtin_nextafterf16(__x, __y);
> +#if __cpp_if_consteval >= 202106L
> +// Can't use if (std::__is_constant_evaluated()) here, as it
> +// doesn't guarantee optimizing the body away at -O0 and
> +// nothing defines nextafterf16.
> +if consteval { return __builtin_nextafterf16(__x, __y); }
> +#endif
>  #ifdef __INT16_TYPE__
>  using __float16_int_type = __INT16_TYPE__;
>  #else
> @@ -3598,8 +3602,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>constexpr __gnu_cxx::__bfloat16_t
>nextafter(__gnu_cxx::__bfloat16_t __x, __gnu_cxx::__bfloat16_t __y)
>{
> -if (std::__is_constant_evaluated())
> -  return __builtin_nextafterf16b(__x, __y);
> +#if __cpp_if_consteval >= 202106L
> +// Can't use if (std::__is_constant_evaluated()) here, as it
> +// doesn't guarantee optimizing the body away at -O0 and
> +// nothing defines nextafterf16b.
> +if consteval { return __builtin_nextafterf16b(__x, __y); }
> +#endif
>  #ifdef __INT16_TYPE__
>  using __bfloat16_int_type = __INT16_TYPE__;
>  #else
> --- libstdc++-v3/testsuite/26_numerics/headers/cmath/117321.cc.jj
>  2024-10-28 12:56:10.699876240 +0100
> +++ libstdc++-v3/testsuite/26_numerics/headers/cmath/117321.cc  2024-10-28
> 12:56:59.875189173 +0100
> @@ -0,0 +1,5 @@
> +// { dg-do run { target c++23 } }
> +// { dg-require-cmath "" }
> +// { dg-additional-options "-O0" }
> +
> +#include "nextafter_c++23.cc"
>
> Jakub
>
>


Re: [PATCH] libstdc++: Fix complexity of drop_view::begin const [PR112641]

2024-10-28 Thread Jonathan Wakely
On Fri, 25 Oct 2024 at 16:24, Patrick Palka  wrote:
>
> Tested on x86_64-pc-linux-gnu, does this look OK for trunk/backports?

OK for all (also approved on the forge).

> Also available in PR form at https://forge.sourceware.org/gcc/gcc-TEST/pulls/8
>
> -- >8 --
>
> Views are required to have a amortized O(1) begin(), but our drop_view's
> const begin overload is O(n) for non-common ranges.  This patch
> reimplements it so that it's O(1) even in that case.  See also LWG 4009.
>
> PR libstdc++/112641
>
> libstdc++-v3/ChangeLog:
>
> * include/std/ranges (drop_view::begin const): Reimplement
> so that it's O(1) instead of O(n) even in the non-common
> range case.
> * testsuite/std/ranges/adaptors/drop.cc (test10): New test.
> ---
>  libstdc++-v3/include/std/ranges|  4 ++--
>  libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc | 12 
>  2 files changed, 14 insertions(+), 2 deletions(-)
>
> diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
> index cebe10683f9..743429dbcea 100644
> --- a/libstdc++-v3/include/std/ranges
> +++ b/libstdc++-v3/include/std/ranges
> @@ -2664,8 +2664,8 @@ namespace views::__adaptor
>begin() const
> requires random_access_range && sized_range
>{
> -   return ranges::next(ranges::begin(_M_base), _M_count,
> -   ranges::end(_M_base));
> +   return ranges::begin(_M_base) + ranges::min(ranges::distance(_M_base),
> +   _M_count);
>}
>
>constexpr auto
> diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc 
> b/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc
> index c9987c61e3c..0bd5bebb785 100644
> --- a/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc
> +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/drop.cc
> @@ -274,6 +274,17 @@ test09()
>static_assert(!requires { views::all | drop; });
>  }
>
> +constexpr bool
> +test10()
> +{
> +  // PR libstdc++/112641 - drop_view::begin const may have O(n) complexity
> +  const auto s = ranges::subrange(views::iota(size_t(1)), size_t(-1));
> +  const auto r = ranges::drop_view(s, s.size() - 1);
> +  const auto b = r.begin(); // time out
> +  VERIFY( *b == size_t(-1) );
> +  return true;
> +}
> +
>  int
>  main()
>  {
> @@ -286,4 +297,5 @@ main()
>test07();
>test08();
>test09();
> +  static_assert(test10());
>  }
> --
> 2.47.0.118.gfd3785337b
>



[committed] libstdc++: Fix tests for std::vector range operations

2024-10-28 Thread Jonathan Wakely
The commit I pushed was not the one I'd tested, so it had older versions
of the tests, with bugs that I'd already fixed locally. This commit has
the fixed tests that I'd intended to push in the first place.

libstdc++-v3/ChangeLog:

* testsuite/23_containers/vector/bool/cons/from_range.cc: Use
dg-do run instead of compile.
(test_ranges): Use do_test instead of do_test_a for rvalue
range.
(test_constexpr): Call function template instead of just
instantiating it.
* testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc:
Use dg-do run instead of compile.
(do_test): Use same test logic for vector as for primary
template.
(test_constexpr): Call function template instead of just
instantiating it.
* testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc:
Use dg-do run instead of compile.
(test_ranges): Use do_test instead of do_test_a for rvalue
range.
(test_constexpr): Call function template instead of just
instantiating it.
* testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc:
Use dg-do run instead of compile.
(do_test): Fix incorrect function arguments to match intended
results.
(test_ranges): Use do_test instead of do_test_a for rvalue
range.
(test_constexpr): Call function template instead of just
instantiating it.
* testsuite/23_containers/vector/cons/from_range.cc: Use dg-do
run instead of compile.
(test_ranges): Fix ill-formed call to do_test.
(test_constexpr): Call function template instead of just
instantiating it.
* testsuite/23_containers/vector/modifiers/append_range.cc:
Use dg-do run instead of compile.
(test_constexpr): Likewise.
* testsuite/23_containers/vector/modifiers/assign/assign_range.cc:
Use dg-do run instead of compile.
(do_test): Do not reuse input ranges.
(test_constexpr): Call function template instead of just
instantiating it.
* testsuite/23_containers/vector/modifiers/insert/insert_range.cc:
Use dg-do run instead of compile.
(do_test): Fix incorrect function arguments to match intended
results.
(test_constexpr): Call function template instead of just
instantiating it.
---
Tested x86_64-linux. Pushed to trunk.


 .../vector/bool/cons/from_range.cc|  6 ++--
 .../bool/modifiers/assign/assign_range.cc | 30 ---
 .../bool/modifiers/insert/append_range.cc |  6 ++--
 .../bool/modifiers/insert/insert_range.cc | 10 +++
 .../23_containers/vector/cons/from_range.cc   |  6 ++--
 .../vector/modifiers/append_range.cc  |  4 +--
 .../vector/modifiers/assign/assign_range.cc   | 25 +++-
 .../vector/modifiers/insert/insert_range.cc   |  8 ++---
 8 files changed, 50 insertions(+), 45 deletions(-)

diff --git 
a/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc 
b/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc
index f5180e5a243..f531e7f5039 100644
--- a/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc
+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc
@@ -1,4 +1,4 @@
-// { dg-do compile { target c++23 } }
+// { dg-do run { target c++23 } }
 
 #include 
 #include 
@@ -71,7 +71,7 @@ test_ranges()
 bool val;
   };
   using rvalue_input_range = test_range;
-  do_test_a();
+  do_test(std::allocator());
 
   return true;
 }
@@ -80,7 +80,7 @@ constexpr bool
 test_constexpr()
 {
   // XXX: this doesn't test the non-forward_range code paths are constexpr.
-  do_test, std::allocator>;
+  do_test>(std::allocator());
   return true;
 }
 
diff --git 
a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc
 
b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc
index a014dfe90de..7e58700ff2b 100644
--- 
a/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc
+++ 
b/libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc
@@ -1,4 +1,4 @@
-// { dg-do compile { target c++23 } }
+// { dg-do run { target c++23 } }
 
 #include 
 #include 
@@ -22,29 +22,37 @@ do_test()
 return true;
   };
 
-  Range r4(a, a+4);
-  Range r9(a);
-
+  // assign to empty vector
   std::vector v;
   v.assign_range(Range(a, a));
   VERIFY( v.empty() );
   VERIFY( v.capacity() == 0 );
-  v.assign_range(r4);
+  v.assign_range(Range(a, a+4));
   VERIFY( eq(v, {a, 4}) );
   v.clear();
-  v.assign_range(r9); // larger than v.capacity()
+  v.assign_range(Range(a)); // larger than v.capacity()
   VERIFY( eq(v, a) );
-  v.assign_range(r9); // equal to size() and equal to capacity()
+  v.clear();
+  v.assign_range(Range(a, a+4)); // smaller than v.capacity()
+  VERIFY( eq(v, {a, 4}) );
+  v.clear();
+

[committed] libstdc++: Fix std::vector::emplace to forward parameter

2024-10-27 Thread Jonathan Wakely
If the parameter is not lvalue-convertible to bool then the current code
will fail to compile. The parameter should be forwarded to restore the
original value category.

libstdc++-v3/ChangeLog:

* include/bits/stl_bvector.h (emplace_back, emplace): Forward
parameter pack to preserve value category.
* testsuite/23_containers/vector/bool/emplace_rvalue.cc: New
test.
---
Tested x86_64-linux. Pushed to trunk.

 libstdc++-v3/include/bits/stl_bvector.h   |  4 ++--
 .../vector/bool/emplace_rvalue.cc | 24 +++
 2 files changed, 26 insertions(+), 2 deletions(-)
 create mode 100644 
libstdc++-v3/testsuite/23_containers/vector/bool/emplace_rvalue.cc

diff --git a/libstdc++-v3/include/bits/stl_bvector.h 
b/libstdc++-v3/include/bits/stl_bvector.h
index 42261ac5915..70f69b5b5b5 100644
--- a/libstdc++-v3/include/bits/stl_bvector.h
+++ b/libstdc++-v3/include/bits/stl_bvector.h
@@ -1343,7 +1343,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 #endif
emplace_back(_Args&&... __args)
{
- push_back(bool(__args...));
+ push_back(bool(std::forward<_Args>(__args)...));
 #if __cplusplus > 201402L
  return back();
 #endif
@@ -1353,7 +1353,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_GLIBCXX20_CONSTEXPR
iterator
emplace(const_iterator __pos, _Args&&... __args)
-   { return insert(__pos, bool(__args...)); }
+   { return insert(__pos, bool(std::forward<_Args>(__args)...)); }
 #endif
 
 protected:
diff --git a/libstdc++-v3/testsuite/23_containers/vector/bool/emplace_rvalue.cc 
b/libstdc++-v3/testsuite/23_containers/vector/bool/emplace_rvalue.cc
new file mode 100644
index 000..5dea2426d60
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/bool/emplace_rvalue.cc
@@ -0,0 +1,24 @@
+// { dg-do compile { target c++11 } }
+
+#include 
+
+struct S
+{
+  explicit operator bool() &&;
+};
+
+void
+test_emplace_back()
+{
+  S s;
+  std::vector v;
+  v.emplace_back(std::move(s));
+}
+
+void
+test_emplace()
+{
+  S s;
+  std::vector v;
+  v.emplace(v.begin(), std::move(s));
+}
-- 
2.47.0



Re: [PATCH] Fix tab after space in leading whitespace

2024-10-25 Thread Jonathan Wakely
On Fri, 25 Oct 2024 at 12:10, Jakub Jelinek  wrote:
>
> Hi!
>
> The following patch fixes 2 -Wleading-whitespace=blanks issues in gcc/,
> include/, libiberty/, libcpp/, libgcc/ and libstdc++-v3/
> One is the
> ../../gcc/c/c-typeck.cc:196:1: warning: whitespace other than spaces and tabs 
> in leading whitespace [-Wleading-whitespace=]
> case (where there was a form-feed immediately followed by a comment
> rather than having a new-line separating it) and then tons of
> warning: tab after space in leading whitespace [-Wleading-whitespace=]
> warnings.  For the latter I've used
> find -name \*.h -o -name \*.c -o -name \*.cc | grep -v testsuite/ | grep -v 
> gofrontend/ | xargs grep -l '^[ ]*   '
> to find affected files (also left out the m2 'do not edit' files) and in an
> editor searched for the same regex and fixed up manually.
>
> xz compressed patch attached, followed by -ubp diff which shows that
> a few changes beyond just space removal or replacement by tab were done
> while I was at it, but only very few.
>
> Ok for trunk if this passes bootstrap/regtest?

The libstdc++-v3 parts are all OK, thanks.

> libstdc++-v3/
> * config/locale/dragonfly/numeric_members.cc: Fix space after tab
> issues in leading whitespace.
> * config/locale/dragonfly/time_members.cc: Likewise.
> * include/parallel/unique_copy.h: Likewise.
> * include/parallel/partition.h: Likewise.
> * include/parallel/random_shuffle.h: Likewise.
> * include/parallel/losertree.h: Likewise.
> * include/parallel/set_operations.h: Likewise.
> * include/parallel/multiway_merge.h: Likewise.
> * include/parallel/balanced_quicksort.h: Likewise.
> * include/bits/streambuf_iterator.h: Likewise.
> * include/bits/unordered_set.h: Likewise.
> * include/bits/stl_vector.h: Likewise.
> * include/bits/uses_allocator.h: Likewise.
> * include/tr1/hashtable.h: Likewise.
> * include/ext/rc_string_base.h: Likewise.
> * src/c++98/mt_allocator.cc: Likewise.
> * src/c++11/limits.cc: Likewise.



Re: [PATCH] Replace 8 consecutive spaces in leading whitespace by tab

2024-10-25 Thread Jonathan Wakely
On Fri, 25 Oct 2024 at 12:17, Jakub Jelinek  wrote:
>
> Hi!
>
> On top of the previously posted leading whitespace patch, this change
> just replaces 8 consecutive spaces in leading whitespace by tab.
> The patch is too large (1MB xz -9e compressed), so I'm not even trying to
> split it up into 4+ pieces to fit under the mailing list limits.
> But the change was done purely by a script,
> for i in `find gcc -name \*.h -o -name \*.cc -o -name \*.c | grep -v 
> testsuite/ | grep -v gofrontend/`; do grep -l '^[  ]*' $i; done > 
> /tmp/2
> grep -L 'do not edit' `cat /tmp/2` > /tmp/3
> for i in `find include lib{iberty,gcc,cpp,stdc++-v3} -name \*.h -o -name 
> \*.cc -o -name \*.c | grep -v testsuite/ | grep -v gofrontend/`; do grep -l 
> '^[]*' $i; done >> /tmp/3
> for j in `seq 32`; do for i in `cat /tmp/3`; do sed -i -e 's/^\(\t*\)
> /\1\t/g' $i; done; done
> diff -upb yields nothing.
>
> Ok for trunk if this passes bootstrap/regtest?
>
> 2024-10-25  Jakub Jelinek  
>

> libstdc++-v3/
> * doc/doxygen/stdheader.cc: Replace 8 spaces with tab in leading
> whitespace.
> * config/os/aix/ctype_inline.h: Likewise.
> * config/locale/newlib/ctype_members.cc: Likewise.
> * config/locale/dragonfly/monetary_members.cc: Likewise.
> * config/locale/dragonfly/ctype_members.cc: Likewise.
> * config/locale/gnu/monetary_members.cc: Likewise.
> * config/locale/gnu/ctype_members.cc: Likewise.
> * config/locale/generic/ctype_members.cc: Likewise.
> * config/locale/darwin/ctype_members.cc: Likewise.
> * config/cpu/i486/opt/bits/opt_random.h: Likewise.
> * include/debug/functions.h: Likewise.
> * include/debug/map.h: Likewise.
> * include/debug/formatter.h: Likewise.
> * include/debug/safe_iterator.h: Likewise.
> * include/parallel/types.h: Likewise.
> * include/parallel/sort.h: Likewise.
> * include/parallel/algorithmfwd.h: Likewise.
> * include/parallel/numericfwd.h: Likewise.
> * include/parallel/unique_copy.h: Likewise.
> * include/parallel/for_each.h: Likewise.
> * include/parallel/partition.h: Likewise.
> * include/parallel/multiway_merge.h: Likewise.
> * include/parallel/losertree.h: Likewise.
> * include/parallel/queue.h: Likewise.
> * include/parallel/workstealing.h: Likewise.
> * include/parallel/tags.h: Likewise.
> * include/parallel/omp_loop_static.h: Likewise.
> * include/parallel/partial_sum.h: Likewise.
> * include/parallel/list_partition.h: Likewise.
> * include/parallel/iterator.h: Likewise.
> * include/parallel/set_operations.h: Likewise.
> * include/parallel/equally_split.h: Likewise.
> * include/parallel/multiway_mergesort.h: Likewise.
> * include/parallel/random_shuffle.h: Likewise.
> * include/parallel/base.h: Likewise.
> * include/parallel/omp_loop.h: Likewise.
> * include/parallel/settings.h: Likewise.
> * include/parallel/algobase.h: Likewise.
> * include/parallel/checkers.h: Likewise.
> * include/parallel/find.h: Likewise.
> * include/parallel/for_each_selectors.h: Likewise.
> * include/parallel/search.h: Likewise.
> * include/parallel/multiseq_selection.h: Likewise.
> * include/parallel/merge.h: Likewise.
> * include/parallel/random_number.h: Likewise.
> * include/parallel/quicksort.h: Likewise.
> * include/parallel/find_selectors.h: Likewise.
> * include/parallel/balanced_quicksort.h: Likewise.
> * include/bits/random.h: Likewise.
> * include/bits/stl_construct.h: Likewise.
> * include/bits/valarray_after.h: Likewise.
> * include/bits/stl_uninitialized.h: Likewise.
> * include/bits/shared_ptr_base.h: Likewise.
> * include/bits/unique_ptr.h: Likewise.
> * include/bits/stl_pair.h: Likewise.
> * include/bits/stringfwd.h: Likewise.
> * include/bits/stl_iterator.h: Likewise.
> * include/bits/atomic_base.h: Likewise.
> * include/bits/valarray_array.h: Likewise.
> * include/bits/stl_vector.h: Likewise.
> * include/bits/fs_dir.h: Likewise.
> * include/bits/shared_ptr.h: Likewise.
> * include/bits/char_traits.h: Likewise.
> * include/bits/stream_iterator.h: Likewise.
> * include/bits/predefined_ops.h: Likewise.
> * include/bits/basic_string.h: Likewise.
> * include/bits/concept_check.h: Likewise.
> * include/bits/stl_iterator_base_types.h: Likewise.
> * include/bits/enable_special_members.h: Likewise.
> * include/bits/locale_classes.h: Likewise.
> * include/bits/stl_tempbuf.h: Likewise.
> * include/bits/ptr_traits.h: Likewise.
> * include/bits/stl_algo.h: Likewise.
> * include/bits/stl_functio

Re: [PATCH] Replace 8 consecutive spaces in leading whitespace by tab

2024-10-25 Thread Jonathan Wakely
On Fri, 25 Oct 2024 at 12:54, Jakub Jelinek  wrote:
>
> On Fri, Oct 25, 2024 at 01:25:25PM +0200, Arsen Arsenović wrote:
> > Maybe we should go the other way around?  Compressing eight spaces into
> > a tab leads to strange artifacts in diffs (where lines appear
> > misindented because some were aligned by tabs and some by spaces), and
> > nowadays editor authors seem to have forgotten tabs are eight spaces and
> > instead default to (or, worse, hard-code) four, obviously making the
> > codebase quite unreadable.  We also don't get the benefit of being able
> > to adjust tabstop locally to our preferences when we use two-column
> > indentation, so I don't see an advantage to keeping 'indent-tabs-mode
> > (or equivalent in other editors) enabled.
>
> Editors which are worth a dime handle tabs fine, and I think using tabs is
> better.

And if we put a .editorconfig file at the top level, then most decent
editors will be auto-configured as we want.

And we can tease people who use bad editors that ignore .editorconfig ;-)



Re: [PATCH v4] libstdc++: implement concatenation of strings and string_views

2024-10-25 Thread Jonathan Wakely
On Sun, 13 Oct 2024 at 18:59, Giuseppe D'Angelo
 wrote:
>
> Hello,
>
> On 09/10/2024 22:39, Patrick Palka wrote:
> >> +#if __glibcxx_string_view >= 202403L
> >> +  // const string & + string_view
> >> +  template
> >> +[[nodiscard]]
> >> +constexpr inline basic_string<_CharT, _Traits, _Alloc>
> >
> > Redundant 'inline's
> >
> >> +operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
> >> +   type_identity_t> __rhs)
> >> +{
> >> +  typedef basic_string<_CharT, _Traits, _Alloc> _Str;
> >
> > These typedefs might as well be usings instead
> >
> > Besides that LGTM!
>
> Thank you for the review, updated patch attached to fix both of these.
> (Just for the record, these had been C&P from the corresponding
> operator+ overloads that deal with const char *.)

Those are from C++98 though, so the 'constexpr' is conditional and so
the 'inline' is not redundant.

I'm going to push your patch in the morning, with one tiny fix for the
COW std::string (which isn't usable in constexpr). See attached.

Thanks for implementing this.
commit 97a03ae904150a65dd2cf41816fed94c283e21b1
Author: Jonathan Wakely 
Date:   Thu Oct 24 20:12:08 2024

libstdc++: Disable parts of new test that depend on constexpr std::string

The compile-time assertions don't work with -D_GLIBCXX_USE_CXX11_ABI=0.

libstdc++-v3/ChangeLog:

* 
testsuite/21_strings/basic_string/operators/char/op_plus_string_view.cc:
Check __cpp_lib_constexpr_string.

diff --git 
a/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view.cc
 
b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view.cc
index 364d5bd5aba..2d474519f60 100644
--- 
a/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view.cc
+++ 
b/libstdc++-v3/testsuite/21_strings/basic_string/operators/char/op_plus_string_view.cc
@@ -44,6 +44,7 @@ struct convertible_to_lots
   constexpr operator std::string() const { return "convertible_to_lots3"; }
 };
 
+#if __cpp_lib_constexpr_string >= 201907 // constexpr std::string
 using namespace std::literals;
 static_assert( "costa "s + "marbella"sv == "costa marbella"s );
 static_assert( "costa "sv + "marbella"s == "costa marbella"s );
@@ -52,6 +53,7 @@ static_assert( "costa "s + convertible_to_string_view2{} == 
"costa convertible_t
 static_assert( "costa "s + convertible_to_string_view3{} == "costa 
convertible_to_sv3 non_const"s );
 static_assert( "costa "s + convertible_to_string_view_and_char_star{} == 
"costa convertible_to_sv_and_charstar1"s );
 static_assert( "costa "s + convertible_to_lots{} == "costa 
convertible_to_lots1"s );
+#endif // __cpp_lib_constexpr_string
 
 void
 test01()


[PATCH 1/3] libstdc++: Fix typos in tests using macros for std::float128_t support

2024-10-25 Thread Jonathan Wakely
These tests check `_GLIBCXX_DOUBLE_IS_IEEE_BINARY128` but that's never
defined, it should be "LDOUBLE" not "DOUBLE".

libstdc++-v3/ChangeLog:

* testsuite/26_numerics/complex/ext_c++23.cc: Fix typo in macro.
* testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc:
Likewise.
* testsuite/26_numerics/headers/cmath/functions_std_c++23.cc:
Likewise.
* testsuite/26_numerics/headers/cmath/nextafter_c++23.cc:
Likewise.
---
This first patch is an obvious fix for a typo, but tests still pass
after fixing it, which is reassuring!

I'll push it shortly.

Tested powerpc64le-linux.

 libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc | 2 +-
 .../testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc  | 2 +-
 .../testsuite/26_numerics/headers/cmath/functions_std_c++23.cc  | 2 +-
 .../testsuite/26_numerics/headers/cmath/nextafter_c++23.cc  | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc 
b/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc
index 0fc3d6f1a66..5f4ff06448e 100644
--- a/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc
+++ b/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc
@@ -70,7 +70,7 @@ main()
   }
 #endif
 #if defined(__STDCPP_FLOAT128_T__) \
-&& (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \
+&& (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \
|| defined(_GLIBCXX_HAVE_FLOAT128_MATH))
   {
 std::float128_t p[2] = {};
diff --git 
a/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc 
b/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc
index 3c2377fd698..983027ff654 100644
--- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc
+++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc
@@ -119,7 +119,7 @@ main()
   test_functions();
 #endif
 #if defined(__STDCPP_FLOAT128_T__) \
-&& (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \
+&& (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \
|| defined(_GLIBCXX_HAVE_FLOAT128_MATH))
   test_functions();
 #endif
diff --git 
a/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc 
b/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc
index ea68ac5da75..bf07493ecd4 100644
--- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc
+++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc
@@ -131,7 +131,7 @@ main()
   }
 #endif
 #if defined(__STDCPP_FLOAT128_T__) \
-&& (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \
+&& (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \
|| defined(_GLIBCXX_HAVE_FLOAT128_MATH))
   {
 std::float128_t p[128] = {};
diff --git 
a/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc 
b/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc
index 91767d22cc3..2d0f8017f4a 100644
--- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc
+++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc
@@ -117,7 +117,7 @@ main ()
   test ();
 #endif
 #if defined(__STDCPP_FLOAT128_T__) \
-&& (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \
+&& (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \
|| defined(_GLIBCXX_HAVE_FLOAT128_MATH))
   test ();
 #endif
-- 
2.47.0



Re: [PATCH] libstdc++: Add P1206R7 from_range members to std::vector [PR111055]

2024-10-25 Thread Jonathan Wakely
On Thu, 24 Oct 2024 at 16:00, Jonathan Wakely  wrote:
>
> This is another piece of P1206R7, adding new members to std::vector and
> std::vector.
>
> The __uninitialized_copy_a extension needs to be enhanced to support
> passing non-common ranges (i.e. a sentinel that is a different type from
> the iterator) and move-only input iterators.

I forgot to say that this patch is also available at
https://forge.sourceware.org/gcc/gcc-TEST/pulls/5


>
> libstdc++-v3/ChangeLog:
>
> PR libstdc++/111055
> * include/bits/ranges_base.h (__container_compatible_range): New
> concept.
> * include/bits/stl_bvector.h (vector(from_range, R&&, const Alloc&))
> (assign_range, insert_range, append_range): Define.
> * include/bits/stl_uninitialized.h (__do_uninit_copy): Support
> non-common ranges.
> (__uninitialized_copy_a): Likewise.
> * include/bits/stl_vector.h (_Vector_base::_M_append_range_to):
> New function.
> (_Vector_base::_M_append_range): Likewise.
> (vector(from_range, R&&, const Alloc&), assign_range): Define.
> (append_range): Define.
> (insert_range): Declare.
> * include/debug/vector (vector(from_range, R&&, const Alloc&))
> (assign_range, insert_range, append_range): Define.
> * include/bits/vector.tcc (insert_range): Define.
> * testsuite/23_containers/vector/bool/cons/from_range.cc: New test.
> * 
> testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc:
> New test.
> * 
> testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc:
> New test.
> * 
> testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc:
> New test.
> * testsuite/23_containers/vector/cons/from_range.cc: New test.
> * testsuite/23_containers/vector/modifiers/append_range.cc: New test.
> * testsuite/23_containers/vector/modifiers/assign/assign_range.cc:
> New test.
> * testsuite/23_containers/vector/modifiers/insert/insert_range.cc:
> New test.
> ---
> Tested x86_64-linux.
>
>  libstdc++-v3/include/bits/ranges_base.h   |  10 ++
>  libstdc++-v3/include/bits/stl_bvector.h   | 120 +
>  libstdc++-v3/include/bits/stl_uninitialized.h |  38 +++-
>  libstdc++-v3/include/bits/stl_vector.h| 166 ++
>  libstdc++-v3/include/bits/vector.tcc  | 124 +
>  libstdc++-v3/include/debug/vector |  70 
>  .../vector/bool/cons/from_range.cc|  81 +
>  .../bool/modifiers/assign/assign_range.cc |  96 ++
>  .../bool/modifiers/insert/append_range.cc |  83 +
>  .../bool/modifiers/insert/insert_range.cc |  94 ++
>  .../23_containers/vector/cons/from_range.cc   |  94 ++
>  .../vector/modifiers/append_range.cc  |  83 +
>  .../vector/modifiers/assign/assign_range.cc   | 107 +++
>  .../vector/modifiers/insert/insert_range.cc   |  94 ++
>  14 files changed, 1252 insertions(+), 8 deletions(-)
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc
>  create mode 100644 
> libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc
>
> diff --git a/libstdc++-v3/include/bits/ranges_base.h 
> b/libstdc++-v3/include/bits/ranges_base.h
> index cb2eba1f841..a2c743ff56b 100644
> --- a/libstdc++-v3/include/bits/ranges_base.h
> +++ b/libstdc++-v3/include/bits/ranges_base.h
> @@ -1079,6 +1079,16 @@ namespace ranges
>  #if __glibcxx_ranges_to_container // C++ >= 23
>struct from_range_t { explicit from_range_t() = default; };
>inline constexpr from_range_t from_range{};
> +
> +/// @cond undocumented
> +namespace __detail
> +{
> +  template
> +concept __container_compatible_range
> +  = ranges::input_range<_Rg>
> + && convertible_to, _Tp>;
> +}
> +/// @endcond
>  #endif
>
>  _GLIBCXX_END_NAMESPACE_VERSION
> diff -

[PATCH 2/3] libstdc++: Define __memcpyable as true

2024-10-25 Thread Jonathan Wakely
This allows optimizing copying ranges of floating-point types when they
have the same size and representation, e.g. between _Float32 and float
when we know that float uses the same IEEE binary32 format as _Float32.

On some targets double and long double both use IEEE binary64 format so
we could enable memcpy between those types, but we don't have existing
macros to check for that case.

libstdc++-v3/ChangeLog:

* include/bits/cpp_type_traits.h (__memcpyable): Add
specializations for compatible floating-point types.
---
Tested powerpc64le-linux.

 libstdc++-v3/include/bits/cpp_type_traits.h | 23 +
 1 file changed, 23 insertions(+)

diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h 
b/libstdc++-v3/include/bits/cpp_type_traits.h
index 2f9ce75e82c..e412f8d0770 100644
--- a/libstdc++-v3/include/bits/cpp_type_traits.h
+++ b/libstdc++-v3/include/bits/cpp_type_traits.h
@@ -472,6 +472,8 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3)
   template struct __memcpyable_integer;
 
   // For heterogeneous types, allow memcpy between equal-sized integers.
+  // N.B. we cannot do the same for equal-sized enums, they're not assignable.
+  // We cannot do it for pointers, because derived-to-base can adjust offset.
   template
 struct __memcpyable<_Tp*, _Up*>
 {
@@ -554,6 +556,27 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3)
 struct __memcpyable_integer { enum { __width = 128 }; };
 #endif
 
+#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  template<>
+struct __memcpyable<_Float32*, float*> { enum { __value = true }; };
+  template<>
+struct __memcpyable { enum { __value = true }; };
+#endif
+
+#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+  template<>
+struct __memcpyable<_Float64*, double*> { enum { __value = true }; };
+  template<>
+struct __memcpyable { enum { __value = true }; };
+#endif
+
+#if defined(__STDCPP_FLOAT128_T__) && 
defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128)
+  template<>
+struct __memcpyable<_Float128*, long double*> { enum { __value = true }; };
+  template<>
+struct __memcpyable { enum { __value = true }; };
+#endif
+
   // Whether two iterator types can be used with memcmp.
   // This trait only says it's well-formed to use memcmp, not that it
   // gives the right answer for a given algorithm. So for example, std::equal
-- 
2.47.0



[PATCH 3/3] libstdc++: Define config macros for additional IEEE formats

2024-10-24 Thread Jonathan Wakely
Some targets use IEEE binary64 for both double and long double, which
means we could use memmove to optimize a std::copy from a range of
double to a range of long double. We currently have no config macro to
detect when long double is binary64, so add that to .

This also adds config macros for the case where double and long double
both use the same binary32 format as float, which is true for the avr
target. No specializations of __memcpyable for that case are added by
this patch, but they could be added later.

libstdc++-v3/ChangeLog:

* include/bits/c++config (_GLIBCXX_DOUBLE_IS_IEEE_BINARY32):
Define.
(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY64): Define.
(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY32): Define.
* include/bits/cpp_type_traits.h (__memcpyable): Define
specializations when double and long double are compatible.
---
Tested powerpc64le-linux.

 libstdc++-v3/include/bits/c++config | 21 ++---
 libstdc++-v3/include/bits/cpp_type_traits.h |  7 +++
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/libstdc++-v3/include/bits/c++config 
b/libstdc++-v3/include/bits/c++config
index b87a3527f24..1076803a865 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -836,25 +836,40 @@ namespace std
 # endif
 #endif
 
-// Define if float has the IEEE binary32 format.
 #if __FLT_MANT_DIG__ == 24 \
   && __FLT_MIN_EXP__ == -125 \
   && __FLT_MAX_EXP__ == 128
+// Define if float has the IEEE binary32 format.
 # define _GLIBCXX_FLOAT_IS_IEEE_BINARY32 1
 #endif
 
-// Define if double has the IEEE binary64 format.
 #if __DBL_MANT_DIG__ == 53 \
   && __DBL_MIN_EXP__ == -1021 \
   && __DBL_MAX_EXP__ == 1024
+// Define if double has the IEEE binary64 format.
 # define _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 1
+#elif __FLT_MANT_DIG__ == 24 \
+  && __FLT_MIN_EXP__ == -125 \
+  && __FLT_MAX_EXP__ == 128
+// Define if double has the IEEE binary32 format.
+# define _GLIBCXX_DOUBLE_IS_IEEE_BINARY32 1
 #endif
 
-// Define if long double has the IEEE binary128 format.
 #if __LDBL_MANT_DIG__ == 113 \
   && __LDBL_MIN_EXP__ == -16381 \
   && __LDBL_MAX_EXP__ == 16384
+// Define if long double has the IEEE binary128 format.
 # define _GLIBCXX_LDOUBLE_IS_IEEE_BINARY128 1
+#elif __LDBL_MANT_DIG__ == 53 \
+  && __LDBL_MIN_EXP__ == -1021 \
+  && __LDBL_MAX_EXP__ == 1024
+// Define if long double has the IEEE binary64 format.
+# define _GLIBCXX_LDOUBLE_IS_IEEE_BINARY64 1
+#elif __LDBL_MANT_DIG__ == 24 \
+  && __LDBL_MIN_EXP__ == -125 \
+  && __LDBL_MAX_EXP__ == 128
+// Define if long double has the IEEE binary32 format.
+# define _GLIBCXX_LDOUBLE_IS_IEEE_BINARY32 1
 #endif
 
 #if defined __cplusplus && defined __BFLT16_DIG__
diff --git a/libstdc++-v3/include/bits/cpp_type_traits.h 
b/libstdc++-v3/include/bits/cpp_type_traits.h
index e412f8d0770..e5a5efece42 100644
--- a/libstdc++-v3/include/bits/cpp_type_traits.h
+++ b/libstdc++-v3/include/bits/cpp_type_traits.h
@@ -556,6 +556,13 @@ __INT_N(__GLIBCXX_TYPE_INT_N_3)
 struct __memcpyable_integer { enum { __width = 128 }; };
 #endif
 
+#if _GLIBCXX_DOUBLE_IS_IEEE_BINARY64 && _GLIBCXX_LDOUBLE_IS_IEEE_BINARY64
+  template<>
+struct __memcpyable { enum { __value = true }; };
+  template<>
+struct __memcpyable { enum { __value = true }; };
+#endif
+
 #if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
   template<>
 struct __memcpyable<_Float32*, float*> { enum { __value = true }; };
-- 
2.47.0



Re: [PATCH] libstdc++: Implement P0849R8 auto(x) library changes

2024-10-24 Thread Jonathan Wakely
On Wed, 9 Oct 2024 at 14:02, Patrick Palka  wrote:
>
> On Mon, 7 Oct 2024, Patrick Palka wrote:
>
> > Tested on x86_64-pc-linux-gnu, does this look OK for trunk only?
> > This doesn't seem worth backporting since there should be no
> > behavior change.
> >
> > -- >8 --
> >
> > This implements the library changes in P0849R8 "auto(x): decay-copy
> > in the language" which consist of replacing most uses of the
> > exposition-only function decay-copy with auto(x) throughout the library
> > wording.
> >
> > Note the main difference between the two is that decay-copy materializes
> > its argument whereas auto(x) doesn't, and so the latter is a no-op when
> > its argument is a prvalue.  Effectively the former could introduce an
> > unnecessary move constructor call in some contexts.  In C++20 and earlier
> > we could emulate auto(x) with decay_t(x).
>
> I should note this patch is treating this paper as a DR against C++20,
> which should be fine since there should be no behavior change in
> practice (especially in light of LWG 3724 which constrains decay-copy
> to make it SFINAE-friendly).

Yes, that seems fine.

OK for trunk, thanks.


>
> >
> > After this paper the only remaining uses of decay-copy in the library
> > are in the specification of some range adaptors.  In our implementation
> > of those range adaptors I believe decay-copy is already implied which
> > is why we don't mirror the wording and use __decay_copy explicitly.  So
> > since it's apparently no longer needed this patch goes ahead and removes
> > __decay_copy.
> >
> > libstdc++-v3/ChangeLog:
> >
> >   * c++config (_GLIBCXX_AUTO_CAST): Define.
> >   * include/bits/iterator_concepts.h (_Decay_copy, __decay_copy):
> >   Remove.
> >   (__member_begin, __adl_begin): Use _GLIBCXX_AUTO_CAST instead of
> >   __decay_copy as per P0849R8.
> >   * include/bits/ranges_base.h (_Begin): Likewise.
> >   (__member_end, __adl_end, _End): Likewise.
> >   (__member_rbegin, __adl_rbegin, _RBegin): Likewise.
> >   (__member_rend, __adl_rend, _Rend): Likewise.
> >   (__member_size, __adl_size, _Size): Likewise.
> >   (_Data): Likewise.
> > ---
> >  libstdc++-v3/include/bits/c++config   |  6 +++
> >  libstdc++-v3/include/bits/iterator_concepts.h | 13 +-
> >  libstdc++-v3/include/bits/ranges_base.h   | 40 +--
> >  3 files changed, 28 insertions(+), 31 deletions(-)
> >
> > diff --git a/libstdc++-v3/include/bits/c++config 
> > b/libstdc++-v3/include/bits/c++config
> > index 29d795f687c..fdbf90e28fc 100644
> > --- a/libstdc++-v3/include/bits/c++config
> > +++ b/libstdc++-v3/include/bits/c++config
> > @@ -265,6 +265,12 @@
> >  #define _GLIBCXX_NOEXCEPT_QUAL
> >  #endif
> >
> > +#if __cpp_auto_cast
> > +# define _GLIBCXX_AUTO_CAST(X) auto(X)
> > +#else
> > +# define _GLIBCXX_AUTO_CAST(X) ::std::__decay_t(X)
> > +#endif
> > +
> >  // Macro for extern template, ie controlling template linkage via use
> >  // of extern keyword on template declaration. As documented in the g++
> >  // manual, it inhibits all implicit instantiations and is used
> > diff --git a/libstdc++-v3/include/bits/iterator_concepts.h 
> > b/libstdc++-v3/include/bits/iterator_concepts.h
> > index 490a362cdf1..0fcfed56737 100644
> > --- a/libstdc++-v3/include/bits/iterator_concepts.h
> > +++ b/libstdc++-v3/include/bits/iterator_concepts.h
> > @@ -1003,19 +1003,10 @@ namespace ranges
> >{
> >  using std::__detail::__class_or_enum;
> >
> > -struct _Decay_copy final
> > -{
> > -  template
> > - constexpr decay_t<_Tp>
> > - operator()(_Tp&& __t) const
> > - noexcept(is_nothrow_convertible_v<_Tp, decay_t<_Tp>>)
> > - { return std::forward<_Tp>(__t); }
> > -} inline constexpr __decay_copy{};
> > -
> >  template
> >concept __member_begin = requires(_Tp& __t)
> >   {
> > -   { __decay_copy(__t.begin()) } -> input_or_output_iterator;
> > +   { _GLIBCXX_AUTO_CAST(__t.begin()) } -> input_or_output_iterator;
> >   };
> >
> >  // Poison pill so that unqualified lookup doesn't find std::begin.
> > @@ -1025,7 +1016,7 @@ namespace ranges
> >concept __adl_begin = __class_or_enum>
> >   && requires(_Tp& __t)
> >   {
> > -   { __decay_copy(begin(__t)) } -> input_or_output_iterator;
> > +   { _GLIBCXX_AUTO_CAST(begin(__t)) } -> input_or_output_iterator;
> >   };
> >
> >  // Simplified version of std::ranges::begin that only supports lvalues,
> > diff --git a/libstdc++-v3/include/bits/ranges_base.h 
> > b/libstdc++-v3/include/bits/ranges_base.h
> > index cb2eba1f841..80ff1e300ce 100644
> > --- a/libstdc++-v3/include/bits/ranges_base.h
> > +++ b/libstdc++-v3/include/bits/ranges_base.h
> > @@ -115,9 +115,9 @@ namespace ranges
> > if constexpr (is_array_v>)
> >   return true;
> > else if constexpr (__member_begin<_Tp>)
> > - return noexcept(__decay_copy(std::declval<_Tp&>().begin()));
> > + return noexcept(_GLIBCX

Re: [PATCH 1/3] libstdc++: Fix typos in tests using macros for std::float128_t support

2024-10-24 Thread Jonathan Wakely
On Thu, 24 Oct 2024 at 15:45, Jonathan Wakely  wrote:
>
> These tests check `_GLIBCXX_DOUBLE_IS_IEEE_BINARY128` but that's never
> defined, it should be "LDOUBLE" not "DOUBLE".
>
> libstdc++-v3/ChangeLog:
>
> * testsuite/26_numerics/complex/ext_c++23.cc: Fix typo in macro.
> * testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc:
> Likewise.
> * testsuite/26_numerics/headers/cmath/functions_std_c++23.cc:
> Likewise.
> * testsuite/26_numerics/headers/cmath/nextafter_c++23.cc:
> Likewise.
> ---
> This first patch is an obvious fix for a typo, but tests still pass
> after fixing it, which is reassuring!
>
> I'll push it shortly.

PATCH 1/3 is now pushed. The patch series is also available at
https://forge.sourceware.org/gcc/gcc-TEST/pulls/6/files


>
> Tested powerpc64le-linux.
>
>  libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc | 2 +-
>  .../testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc  | 2 +-
>  .../testsuite/26_numerics/headers/cmath/functions_std_c++23.cc  | 2 +-
>  .../testsuite/26_numerics/headers/cmath/nextafter_c++23.cc  | 2 +-
>  4 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc 
> b/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc
> index 0fc3d6f1a66..5f4ff06448e 100644
> --- a/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc
> +++ b/libstdc++-v3/testsuite/26_numerics/complex/ext_c++23.cc
> @@ -70,7 +70,7 @@ main()
>}
>  #endif
>  #if defined(__STDCPP_FLOAT128_T__) \
> -&& (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \
> +&& (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \
> || defined(_GLIBCXX_HAVE_FLOAT128_MATH))
>{
>  std::float128_t p[2] = {};
> diff --git 
> a/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc 
> b/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc
> index 3c2377fd698..983027ff654 100644
> --- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc
> +++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc
> @@ -119,7 +119,7 @@ main()
>test_functions();
>  #endif
>  #if defined(__STDCPP_FLOAT128_T__) \
> -&& (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \
> +&& (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \
> || defined(_GLIBCXX_HAVE_FLOAT128_MATH))
>test_functions();
>  #endif
> diff --git 
> a/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc 
> b/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc
> index ea68ac5da75..bf07493ecd4 100644
> --- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc
> +++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/functions_std_c++23.cc
> @@ -131,7 +131,7 @@ main()
>}
>  #endif
>  #if defined(__STDCPP_FLOAT128_T__) \
> -&& (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \
> +&& (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \
> || defined(_GLIBCXX_HAVE_FLOAT128_MATH))
>{
>  std::float128_t p[128] = {};
> diff --git 
> a/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc 
> b/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc
> index 91767d22cc3..2d0f8017f4a 100644
> --- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc
> +++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/nextafter_c++23.cc
> @@ -117,7 +117,7 @@ main ()
>test ();
>  #endif
>  #if defined(__STDCPP_FLOAT128_T__) \
> -&& (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \
> +&& (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \
> || defined(_GLIBCXX_HAVE_FLOAT128_MATH))
>test ();
>  #endif
> --
> 2.47.0
>



[committed v2] libstdc++: Simplify std::__throw_bad_variant_access

2024-10-24 Thread Jonathan Wakely
This removes the overload of __throw_bad_variant_access that must be
called with a string literal. This avoids a potential source of
undefined behaviour if that function got misused. The other overload
that takes a bool parameter can be adjusted to take an integer index
selecting one of the four possible string literals to use, ensuring
that the std::bad_variant_access constructor is only called with those
literals.

Passing an index outside the range [0,3] is bogus, but will still select
a valid string literal and avoid undefined behaviour.

libstdc++-v3/ChangeLog:

* include/std/variant (__throw_bad_variant_access(unsigned)):
Define new function as inline friend, with namespace-scope
declaration using noreturn attribute.
(__throw_bad_variant_access(const char*)): Remove.
(__throw_bad_variant_access(bool)): Remove.
(visit, visit): Adjust calls to __throw_bad_variant_access.

Reviewed-by: Patrick Palka 
---
Patch v2 based on Patrick's review comments at:
https://forge.sourceware.org/gcc/gcc-TEST/pulls/3

Changes:

- Changed parameter type to unsigned.
- Added [[maybe_unused]] to the parameter and array.
- Added [[noreturn]] (which required declaring it before the
  class and then defining it as an inline friend).
- Made the array static constexpr.
- Added a trailing comma after the last array element.

Tested x86_64-linux.

Pushed to trunk.

 libstdc++-v3/include/std/variant | 32 +++-
 1 file changed, 15 insertions(+), 17 deletions(-)

diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
index cf532126d79..bd0f9c3252a 100644
--- a/libstdc++-v3/include/std/variant
+++ b/libstdc++-v3/include/std/variant
@@ -1402,6 +1402,8 @@ namespace __detail::__variant
   && (is_swappable_v<_Types> && ...))>
 swap(variant<_Types...>&, variant<_Types...>&) = delete;
 
+  [[noreturn]] void __throw_bad_variant_access(unsigned);
+
   class bad_variant_access : public exception
   {
   public:
@@ -1411,28 +1413,24 @@ namespace __detail::__variant
 { return _M_reason; }
 
   private:
+// Must only be called with a string literal
 bad_variant_access(const char* __reason) noexcept : _M_reason(__reason) { }
 
 // Must point to a string with static storage duration:
 const char* _M_reason = "bad variant access";
 
-friend void __throw_bad_variant_access(const char* __what);
+friend void __throw_bad_variant_access([[maybe_unused]] unsigned __n)
+{
+  [[maybe_unused]] static constexpr const char* __reasons[] = {
+   "std::get: wrong index for variant",
+   "std::get: variant is valueless",
+   "std::visit: variant is valueless",
+   "std::visit: variant is valueless",
+  };
+  _GLIBCXX_THROW_OR_ABORT(bad_variant_access(__reasons[__n % 4u]));
+}
   };
 
-  // Must only be called with a string literal
-  inline void
-  __throw_bad_variant_access(const char* __what)
-  { _GLIBCXX_THROW_OR_ABORT(bad_variant_access(__what)); }
-
-  inline void
-  __throw_bad_variant_access(bool __valueless)
-  {
-if (__valueless) [[__unlikely__]]
-  __throw_bad_variant_access("std::get: variant is valueless");
-else
-  __throw_bad_variant_access("std::get: wrong index for variant");
-  }
-
   template
 class variant
 : private __detail::__variant::_Variant_base<_Types...>,
@@ -1941,7 +1939,7 @@ namespace __detail::__variant
   namespace __variant = std::__detail::__variant;
 
   if ((__variant::__as(__variants).valueless_by_exception() || ...))
-   __throw_bad_variant_access("std::visit: variant is valueless");
+   __throw_bad_variant_access(2);
 
   using _Result_type
= __detail::__variant::__visit_result_t<_Visitor, _Variants...>;
@@ -1981,7 +1979,7 @@ namespace __detail::__variant
   namespace __variant = std::__detail::__variant;
 
   if ((__variant::__as(__variants).valueless_by_exception() || ...))
-   __throw_bad_variant_access("std::visit: variant is valueless");
+   __throw_bad_variant_access(3);
 
   return std::__do_visit<_Res>(std::forward<_Visitor>(__visitor),
  __variant::__as(std::forward<_Variants>(__variants))...);
-- 
2.47.0



[PATCH] libstdc++: Add P1206R7 from_range members to std::vector [PR111055]

2024-10-24 Thread Jonathan Wakely
This is another piece of P1206R7, adding new members to std::vector and
std::vector.

The __uninitialized_copy_a extension needs to be enhanced to support
passing non-common ranges (i.e. a sentinel that is a different type from
the iterator) and move-only input iterators.

libstdc++-v3/ChangeLog:

PR libstdc++/111055
* include/bits/ranges_base.h (__container_compatible_range): New
concept.
* include/bits/stl_bvector.h (vector(from_range, R&&, const Alloc&))
(assign_range, insert_range, append_range): Define.
* include/bits/stl_uninitialized.h (__do_uninit_copy): Support
non-common ranges.
(__uninitialized_copy_a): Likewise.
* include/bits/stl_vector.h (_Vector_base::_M_append_range_to):
New function.
(_Vector_base::_M_append_range): Likewise.
(vector(from_range, R&&, const Alloc&), assign_range): Define.
(append_range): Define.
(insert_range): Declare.
* include/debug/vector (vector(from_range, R&&, const Alloc&))
(assign_range, insert_range, append_range): Define.
* include/bits/vector.tcc (insert_range): Define.
* testsuite/23_containers/vector/bool/cons/from_range.cc: New test.
* testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc:
New test.
* testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc:
New test.
* testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc:
New test.
* testsuite/23_containers/vector/cons/from_range.cc: New test.
* testsuite/23_containers/vector/modifiers/append_range.cc: New test.
* testsuite/23_containers/vector/modifiers/assign/assign_range.cc:
New test.
* testsuite/23_containers/vector/modifiers/insert/insert_range.cc:
New test.
---
Tested x86_64-linux.

 libstdc++-v3/include/bits/ranges_base.h   |  10 ++
 libstdc++-v3/include/bits/stl_bvector.h   | 120 +
 libstdc++-v3/include/bits/stl_uninitialized.h |  38 +++-
 libstdc++-v3/include/bits/stl_vector.h| 166 ++
 libstdc++-v3/include/bits/vector.tcc  | 124 +
 libstdc++-v3/include/debug/vector |  70 
 .../vector/bool/cons/from_range.cc|  81 +
 .../bool/modifiers/assign/assign_range.cc |  96 ++
 .../bool/modifiers/insert/append_range.cc |  83 +
 .../bool/modifiers/insert/insert_range.cc |  94 ++
 .../23_containers/vector/cons/from_range.cc   |  94 ++
 .../vector/modifiers/append_range.cc  |  83 +
 .../vector/modifiers/assign/assign_range.cc   | 107 +++
 .../vector/modifiers/insert/insert_range.cc   |  94 ++
 14 files changed, 1252 insertions(+), 8 deletions(-)
 create mode 100644 
libstdc++-v3/testsuite/23_containers/vector/bool/cons/from_range.cc
 create mode 100644 
libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/assign/assign_range.cc
 create mode 100644 
libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/append_range.cc
 create mode 100644 
libstdc++-v3/testsuite/23_containers/vector/bool/modifiers/insert/insert_range.cc
 create mode 100644 
libstdc++-v3/testsuite/23_containers/vector/cons/from_range.cc
 create mode 100644 
libstdc++-v3/testsuite/23_containers/vector/modifiers/append_range.cc
 create mode 100644 
libstdc++-v3/testsuite/23_containers/vector/modifiers/assign/assign_range.cc
 create mode 100644 
libstdc++-v3/testsuite/23_containers/vector/modifiers/insert/insert_range.cc

diff --git a/libstdc++-v3/include/bits/ranges_base.h 
b/libstdc++-v3/include/bits/ranges_base.h
index cb2eba1f841..a2c743ff56b 100644
--- a/libstdc++-v3/include/bits/ranges_base.h
+++ b/libstdc++-v3/include/bits/ranges_base.h
@@ -1079,6 +1079,16 @@ namespace ranges
 #if __glibcxx_ranges_to_container // C++ >= 23
   struct from_range_t { explicit from_range_t() = default; };
   inline constexpr from_range_t from_range{};
+
+/// @cond undocumented
+namespace __detail
+{
+  template
+concept __container_compatible_range
+  = ranges::input_range<_Rg>
+ && convertible_to, _Tp>;
+}
+/// @endcond
 #endif
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/include/bits/stl_bvector.h 
b/libstdc++-v3/include/bits/stl_bvector.h
index 42261ac5915..ebb5ff2c594 100644
--- a/libstdc++-v3/include/bits/stl_bvector.h
+++ b/libstdc++-v3/include/bits/stl_bvector.h
@@ -892,6 +892,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
}
 #endif
 
+#if __glibcxx_ranges_to_container // C++ >= 23
+  /**
+   * @brief Construct a vector from a range.
+   * @since C++23
+   */
+  template<__detail::__container_compatible_range _Rg>
+   constexpr
+   vector(from_range_t, _Rg&& __rg, const _Alloc& __a = _Alloc())
+   : _Base(__a)
+   {
+ if constexpr (ranges::forward_range<_Rg> || ranges::sized_range<_Rg>)
+   {
+   

Re: [PATCH] non-gcc: Remove trailing whitespace

2024-10-24 Thread Jonathan Wakely
On Thu, 24 Oct 2024 at 10:32, Jonathan Wakely  wrote:

>
>
> On Thu, 24 Oct 2024, 09:19 Jakub Jelinek,  wrote:
>
>> Hi!
>>
>> Here is the non-gcc part of the previous patch, include/, libiberty/,
>> libcpp/, libgcc/, libstdc++-v3/.
>>
>> Is there something that should be left out?
>>
>
>
> libstdc++-v3/src/c++17/fast_float/fast_float.h comes from an external
> project. Please leave that out, and we can ask upstream to fix it.
>

Ironically, the line above in my previous email has trailing whitespace ;)

These upstream commits already removed the trailing whitespace in the code:
https://github.com/jwakely/fast_float/commit/e3fd438c64c973f38c7f4e89790052a67adeba9a
https://github.com/fastfloat/fast_float/commit/39e04ea7668b191e748cd294a4942dabdd9ace12

I've submitted https://github.com/fastfloat/fast_float/pull/272 to stop
adding it to the licence header.

Next time Patrick syncs from upstream we should get rid of the trailing
whitespace in that file.



>
> The other libstdc++ changes are OK, thanks for doing this.
>
> I don't know whether Doxygen treats two spaces at the end of a line as a
> forced line-break, like Markdown does, but I checked that none of the
> libstdc++ changes in the patch would be affected by that anyway.
>
>
>


Re: [PATCH] non-gcc: Remove trailing whitespace

2024-10-24 Thread Jonathan Wakely
On Thu, 24 Oct 2024, 09:19 Jakub Jelinek,  wrote:

> Hi!
>
> Here is the non-gcc part of the previous patch, include/, libiberty/,
> libcpp/, libgcc/, libstdc++-v3/.
>
> Is there something that should be left out?
>


libstdc++-v3/src/c++17/fast_float/fast_float.h comes from an external
project. Please leave that out, and we can ask upstream to fix it.

The other libstdc++ changes are OK, thanks for doing this.

I don't know whether Doxygen treats two spaces at the end of a line as a
forced line-break, like Markdown does, but I checked that none of the
libstdc++ changes in the patch would be affected by that anyway.



> Ok for trunk if it passes bootstrap/regtest?
>
> 2024-10-24  Jakub Jelinek  
>
> include/
> * dyn-string.h: Remove trailing whitespace.
> * libiberty.h: Likewise.
> * xregex.h: Likewise.
> * splay-tree.h: Likewise.
> * partition.h: Likewise.
> * plugin-api.h: Likewise.
> * demangle.h: Likewise.
> * vtv-change-permission.h: Likewise.
> * fibheap.h: Likewise.
> * hsa_ext_image.h: Likewise.
> * hashtab.h: Likewise.
> * libcollector.h: Likewise.
> * sort.h: Likewise.
> * symcat.h: Likewise.
> * hsa_ext_amd.h: Likewise.
> libcpp/
> * directives.cc: Remove trailing whitespace.
> * mkdeps.cc: Likewise.
> * line-map.cc: Likewise.
> * internal.h: Likewise.
> * files.cc: Likewise.
> * init.cc: Likewise.
> * makeucnid.cc: Likewise.
> * system.h: Likewise.
> * include/line-map.h: Likewise.
> * include/symtab.h: Likewise.
> * include/cpplib.h: Likewise.
> * expr.cc: Likewise.
> * charset.cc: Likewise.
> * macro.cc: Likewise.
> * errors.cc: Likewise.
> * lex.cc: Likewise.
> * traditional.cc: Likewise.
> libgcc/
> * crtstuff.c: Remove trailing whitespace.
> * libgcov.h: Likewise.
> * config/alpha/crtfastmath.c: Likewise.
> * config/alpha/vms-gcc_shell_handler.c: Likewise.
> * config/alpha/vms-unwind.h: Likewise.
> * config/pa/linux-atomic.c: Likewise.
> * config/pa/linux-unwind.h: Likewise.
> * config/pa/quadlib.c: Likewise.
> * config/pa/fptr.c: Likewise.
> * config/s390/32/_fixsfdi.c: Likewise.
> * config/s390/32/_fixunssfdi.c: Likewise.
> * config/s390/32/_fixunsdfdi.c: Likewise.
> * config/c6x/pr-support.c: Likewise.
> * config/lm32/_udivsi3.c: Likewise.
> * config/lm32/libgcc_lm32.h: Likewise.
> * config/lm32/_udivmodsi4.c: Likewise.
> * config/lm32/_mulsi3.c: Likewise.
> * config/lm32/_modsi3.c: Likewise.
> * config/lm32/_umodsi3.c: Likewise.
> * config/lm32/_divsi3.c: Likewise.
> * config/darwin-crt3.c: Likewise.
> * config/msp430/mpy.c: Likewise.
> * config/ia64/tf-signs.c: Likewise.
> * config/ia64/fde-vms.c: Likewise.
> * config/ia64/unwind-ia64.c: Likewise.
> * config/ia64/vms-unwind.h: Likewise.
> * config/ia64/sfp-exceptions.c: Likewise.
> * config/ia64/quadlib.c: Likewise.
> * config/ia64/unwind-ia64.h: Likewise.
> * config/avr/libf7/f7-renames.h: Likewise.
> * config/rl78/vregs.h: Likewise.
> * config/arm/bpabi.c: Likewise.
> * config/arm/unwind-arm.c: Likewise.
> * config/arm/pr-support.c: Likewise.
> * config/arm/linux-atomic.c: Likewise.
> * config/arm/bpabi-lib.h: Likewise.
> * config/frv/frvend.c: Likewise.
> * config/frv/cmovw.c: Likewise.
> * config/frv/frvbegin.c: Likewise.
> * config/frv/cmovd.c: Likewise.
> * config/frv/cmovh.c: Likewise.
> * config/aarch64/cpuinfo.c: Likewise.
> * config/i386/crtfastmath.c: Likewise.
> * config/i386/cygming-crtend.c: Likewise.
> * config/i386/32/tf-signs.c: Likewise.
> * config/i386/crtprec.c: Likewise.
> * config/i386/sfp-exceptions.c: Likewise.
> * config/i386/w32-unwind.h: Likewise.
> * config/libbid/_le_td.c: Likewise.
> * config/libbid/bid128_compare.c: Likewise.
> * config/libbid/bid_div_macros.h: Likewise.
> * config/libbid/bid64_to_bid128.c: Likewise.
> * config/libbid/bid64_to_uint32.c: Likewise.
> * config/libbid/bid128_to_uint64.c: Likewise.
> * config/libbid/bid64_div.c: Likewise.
> * config/libbid/bid128_round_integral.c: Likewise.
> * config/libbid/bid_binarydecimal.c: Likewise.
> * config/libbid/bid128_string.c: Likewise.
> * config/libbid/bid_flag_operations.c: Likewise.
> * config/libbid/bid128_to_int64.c: Likewise.
> * config/libbid/_mul_sd.c: Likewise.
> * config/libbid/bid64_mul.c: Likewise.
> * config/libbid/bid128_noncomp.c: Likewise.
> * config/libbid/_gt_dd.c: Likewise

Re: [Bug libstdc++/115285] [12/13/14/15 Regression] std::unordered_set can have duplicate value

2024-10-24 Thread Jonathan Wakely
I'm seeing new FAILs with -D_GLIBCXX_USE_CXX11_ABI=0

/home/test/src/gcc/libstdc++-v3/testsuite/23_containers/unordered_set/96088.cc:247:
void test03(): Assertion '__gnu_test::counter::get()._M_increments ==
in
crements + 1' failed.
FAIL: 23_containers/unordered_set/96088.cc  -std=gnu++17 execution test

/home/test/src/gcc/libstdc++-v3/testsuite/23_containers/unordered_map/96088.cc:240:
void test03(): Assertion '__gnu_test::counter::count() == origin +
incre
ments' failed.
FAIL: 23_containers/unordered_map/96088.cc  -std=gnu++17 execution test



On Tue, 22 Oct 2024 at 18:28, François Dumont  wrote:
>
> Hi
>
>  libstdc++: Always instantiate key_type to compute hash code [PR115285]
>
>  Even if it is possible to compute a hash code from the inserted
> arguments
>  we need to instantiate the key_type to guaranty hash code consistency.
>
>  Preserve the lazy instantiation of the mapped_type in the context of
>  associative containers.
>
>  libstdc++-v3/ChangeLog:
>
>  PR libstdc++/115285
>  * include/bits/hashtable.h (_S_forward_key<_Kt>): Always
> return a temporary
>  key_type instance.
>  * testsuite/23_containers/unordered_map/96088.cc: Adapt to
> additional instanciation.
>  Also check that mapped_type is not instantiated when there
> is no insertion.
>  * testsuite/23_containers/unordered_multimap/96088.cc:
> Adapt to additional
>  instanciation.
>  * testsuite/23_containers/unordered_multiset/96088.cc:
> Likewise.
>  * testsuite/23_containers/unordered_set/96088.cc: Likewise.
>  * testsuite/23_containers/unordered_set/pr115285.cc: New
> test case.
>
>
> Tested under Linux x64,
>
> ok to commit ?
>
> François



[PATCH] libstdc++: Simplify std::__throw_bad_variant_access

2024-10-23 Thread Jonathan Wakely
This removes the overload of __throw_bad_variant_access that must be
called with a string literal. This avoids a potential source of
undefined behaviour if that function got misused. The other overload
that takes a bool parameter can be adjusted to take an int describing
which of the four possible string literals to use, and ensure that the
std::bad_variant_access constructor is only called with those. Passing
an int outside the range [0,3] is bogus, but will still select a valid
string literal and avoid undefined behaviour.

libstdc++-v3/ChangeLog:

* include/std/variant (bad_variant_access): Adjust friend
declaration.
(__throw_bad_variant_access(const char*)): Remove.
(__throw_bad_variant_access(bool)): Change parameter to int.
(visit, visit): Adjust calls to __throw_bad_variant_access.
---
Tested x86_64-linux.

Also available for review at https://forge.sourceware.org/gcc/gcc-TEST/pulls/3

 libstdc++-v3/include/std/variant | 25 -
 1 file changed, 12 insertions(+), 13 deletions(-)

diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
index cf532126d79..d79299be634 100644
--- a/libstdc++-v3/include/std/variant
+++ b/libstdc++-v3/include/std/variant
@@ -1411,26 +1411,25 @@ namespace __detail::__variant
 { return _M_reason; }
 
   private:
+// Must only be called with a string literal
 bad_variant_access(const char* __reason) noexcept : _M_reason(__reason) { }
 
 // Must point to a string with static storage duration:
 const char* _M_reason = "bad variant access";
 
-friend void __throw_bad_variant_access(const char* __what);
+friend void __throw_bad_variant_access(int);
   };
 
-  // Must only be called with a string literal
   inline void
-  __throw_bad_variant_access(const char* __what)
-  { _GLIBCXX_THROW_OR_ABORT(bad_variant_access(__what)); }
-
-  inline void
-  __throw_bad_variant_access(bool __valueless)
+  __throw_bad_variant_access(int __reason)
   {
-if (__valueless) [[__unlikely__]]
-  __throw_bad_variant_access("std::get: variant is valueless");
-else
-  __throw_bad_variant_access("std::get: wrong index for variant");
+const char* __reasons[] = {
+  "std::get: wrong index for variant",
+  "std::get: variant is valueless",
+  "std::visit: variant is valueless",
+  "std::visit: variant is valueless"
+};
+_GLIBCXX_THROW_OR_ABORT(bad_variant_access(__reasons[__reason % 4u]));
   }
 
   template
@@ -1941,7 +1940,7 @@ namespace __detail::__variant
   namespace __variant = std::__detail::__variant;
 
   if ((__variant::__as(__variants).valueless_by_exception() || ...))
-   __throw_bad_variant_access("std::visit: variant is valueless");
+   __throw_bad_variant_access(2);
 
   using _Result_type
= __detail::__variant::__visit_result_t<_Visitor, _Variants...>;
@@ -1981,7 +1980,7 @@ namespace __detail::__variant
   namespace __variant = std::__detail::__variant;
 
   if ((__variant::__as(__variants).valueless_by_exception() || ...))
-   __throw_bad_variant_access("std::visit: variant is valueless");
+   __throw_bad_variant_access(3);
 
   return std::__do_visit<_Res>(std::forward<_Visitor>(__visitor),
  __variant::__as(std::forward<_Variants>(__variants))...);
-- 
2.46.2



Re: [PATCH] ginclude: stdalign.h should define __xxx_is_defined macros for C++

2024-10-23 Thread Jonathan Wakely
On Wed, 23 Oct 2024 at 19:44, Jonathan Wakely  wrote:
>
> On Wed, 23 Oct 2024 at 19:41, Jonathan Wakely  wrote:
> >
> > On Wed, 23 Oct 2024 at 16:02, Jason Merrill  wrote:
> > >
> > > Should there also/instead be a test with ?
> >
> > We don't usually (or ever?) bother to test the .h versions of headers.
> > For these ones that are deprecated it probably makes sense to do so,
> > because  isn't deprecated, only . So we should
> > ensure that the .h forms work fine without diagnostics even in C++17
> > and later.
> > I'll add more tests.
>
> But I think it makes sense to do that as part of a follow-up commit
> where I deprecate .

Here's a preview of that follow-up, without the new tests I need to add:
https://forge.sourceware.org/gcc/gcc-TEST/pulls/4



Re: [PATCH] ginclude: stdalign.h should define __xxx_is_defined macros for C++

2024-10-23 Thread Jonathan Wakely
On Wed, 23 Oct 2024 at 19:41, Jonathan Wakely  wrote:
>
> On Wed, 23 Oct 2024 at 16:02, Jason Merrill  wrote:
> >
> > Should there also/instead be a test with ?
>
> We don't usually (or ever?) bother to test the .h versions of headers.
> For these ones that are deprecated it probably makes sense to do so,
> because  isn't deprecated, only . So we should
> ensure that the .h forms work fine without diagnostics even in C++17
> and later.
> I'll add more tests.

But I think it makes sense to do that as part of a follow-up commit
where I deprecate .



Re: [PATCH] ginclude: stdalign.h should define __xxx_is_defined macros for C++

2024-10-23 Thread Jonathan Wakely
On Wed, 23 Oct 2024 at 16:02, Jason Merrill  wrote:
>
> On 10/23/24 10:39 AM, Jonathan Wakely wrote:
> > The __alignas_is_defined macro has been required by C++ since C++11, and
> > C++ Library DR 4036 clarified that __alignof_is_defined should be
> > defined too.
> >
> > The macros alignas and alignof should not be defined, as they're
> > keywords in C++.
> >
> > Technically it's implementation-defined whether __STDC_VERSION__ is
> > defined by a C++ compiler, but G++ does not define it. Adjusting the
> > first #if this way works as intended: A C23 compiler will not enter the
> > outer if-group and so will not define any of the macros, a C17 compiler
> > will enter both if-groups and so define all the macros, and a C++
> > compiler will enter the outer if-group but not the inner if-group.
> >
> > gcc/ChangeLog:
> >
> >   * ginclude/stdalign.h (__alignas_is_defined): Define for C++.
> >   (__alignof_is_defined): Likewise.
>
> Do we want to note somehow that these macros are deprecated since C++17?

The  header is deprecated in C++17, but the macros aren't
if you get them via . They were deprecated for C++23 by my
NB comment https://cplusplus.github.io/LWG/issue3827

Would you like it to be noted in the commit message, or in the header
itself, something like this?

--- a/gcc/ginclude/stdalign.h
+++ b/gcc/ginclude/stdalign.h
@@ -33,6 +33,7 @@ see the files COPYING3 and COPYING.RUNTIME
respectively.  If not, see
#define alignof _Alignof
#endif

+/* These are defined for C++, but deprecated in C++23.  */
#define __alignas_is_defined 1
#define __alignof_is_defined 1

I expect  to be removed completely for C++26, if my P3348
is approved. I'm not sure if we want to add deprecation warnings to
 for C++26, or just make it empty. That's for another day
anyway.


> > libstdc++-v3/ChangeLog:
> >
> >   * testsuite/18_support/headers/cstdalign/macros.cc: New test.
> > ---
> >
> > The libc++ devs noticed recently that GCC's  doesn't conform
> > to the C++ requirements.
> >
> > Tested x86_64-linux.
> >
> > OK for trunk?
> >
> >   gcc/ginclude/stdalign.h   |  5 ++--
> >   .../18_support/headers/cstdalign/macros.cc| 24 +++
> >   2 files changed, 27 insertions(+), 2 deletions(-)
> >   create mode 100644 
> > libstdc++-v3/testsuite/18_support/headers/cstdalign/macros.cc
> >
> > diff --git a/gcc/ginclude/stdalign.h b/gcc/ginclude/stdalign.h
> > index 5f82f2d68f2..af73c322624 100644
> > --- a/gcc/ginclude/stdalign.h
> > +++ b/gcc/ginclude/stdalign.h
> > @@ -26,11 +26,12 @@ see the files COPYING3 and COPYING.RUNTIME 
> > respectively.  If not, see
> >   #ifndef _STDALIGN_H
> >   #define _STDALIGN_H
> >
> > -#if (!defined __cplusplus\
> > - && !(defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L))
> > +#if !(defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L)
> >
> > +#ifndef __cplusplus
> >   #define alignas _Alignas
> >   #define alignof _Alignof
> > +#endif
> >
> >   #define __alignas_is_defined 1
> >   #define __alignof_is_defined 1
> > diff --git a/libstdc++-v3/testsuite/18_support/headers/cstdalign/macros.cc 
> > b/libstdc++-v3/testsuite/18_support/headers/cstdalign/macros.cc
> > new file mode 100644
> > index 000..c50c921cd59
> > --- /dev/null
> > +++ b/libstdc++-v3/testsuite/18_support/headers/cstdalign/macros.cc
> > @@ -0,0 +1,24 @@
> > +// { dg-options "-D_GLIBCXX_USE_DEPRECATED=1 -Wno-deprecated" }
> > +// { dg-do preprocess { target c++11 } }
> > +
> > +#include 
>
> Should there also/instead be a test with ?

We don't usually (or ever?) bother to test the .h versions of headers.
For these ones that are deprecated it probably makes sense to do so,
because  isn't deprecated, only . So we should
ensure that the .h forms work fine without diagnostics even in C++17
and later.
I'll add more tests.

> > +
> > +#ifndef __alignas_is_defined
> > +# error "The header  fails to define a macro named  
> > __alignas_is_defined"
> > +#elif __alignas_is_defined != 1
> > +# error "__alignas_is_defined is not defined to 1 in "
> > +#endif
> > +
> > +#ifndef __alignof_is_defined
> > +# error "The header  fails to define a macro named 
> > __alignof_is_defined"
> > +#elif __alignof_is_defined != 1
> > +# error "__alignof_is_defined is not defined to 1 in "
> > +#endif
> > +
> > +#ifdef alignas
> > +# error "The header  defines a macro named alignas"
> > +#endif
> > +
> > +#ifdef alignof
> > +# error "The header  defines a macro named alignof"
> > +#endif
>



Re: [Bug libstdc++/115285] [12/13/14/15 Regression] std::unordered_set can have duplicate value

2024-10-23 Thread Jonathan Wakely
On Wed, 23 Oct 2024 at 18:37, François Dumont  wrote:
>
> Sorry but I'm not sure, is it also ok for the 3 backports ?

Yeah, I should have said - OK for the branches too, thanks.

>
> On 22/10/2024 22:43, Jonathan Wakely wrote:
> > On Tue, 22 Oct 2024 at 18:28, François Dumont  wrote:
> >> Hi
> >>
> >>   libstdc++: Always instantiate key_type to compute hash code 
> >> [PR115285]
> >>
> >>   Even if it is possible to compute a hash code from the inserted
> >> arguments
> >>   we need to instantiate the key_type to guaranty hash code 
> >> consistency.
> >>
> >>   Preserve the lazy instantiation of the mapped_type in the context of
> >>   associative containers.
> >>
> >>   libstdc++-v3/ChangeLog:
> >>
> >>   PR libstdc++/115285
> >>   * include/bits/hashtable.h (_S_forward_key<_Kt>): Always
> >> return a temporary
> >>   key_type instance.
> >>   * testsuite/23_containers/unordered_map/96088.cc: Adapt to
> >> additional instanciation.
> >>   Also check that mapped_type is not instantiated when there
> >> is no insertion.
> >>   * testsuite/23_containers/unordered_multimap/96088.cc:
> >> Adapt to additional
> >>   instanciation.
> >>   * testsuite/23_containers/unordered_multiset/96088.cc:
> >> Likewise.
> >>   * testsuite/23_containers/unordered_set/96088.cc: Likewise.
> >>   * testsuite/23_containers/unordered_set/pr115285.cc: New
> >> test case.
> >>
> >>
> >> Tested under Linux x64,
> >>
> >> ok to commit ?
> > OK, thanks
> >
>



[committed] libstdc++: Add -D_GLIBCXX_ASSERTIONS default for -O0 to API history

2024-10-23 Thread Jonathan Wakely
Excuse the huge diff, it's because it adds a new section heading so all
the TOC pages and section listings change.

Pushed to trunk.

-- >8 --

libstdc++-v3/ChangeLog:

* doc/xml/manual/evolution.xml: Document that assertions are
enabled for unoptimized builds.
* doc/html/*: Regenerate.
---
 libstdc++-v3/doc/html/index.html   | 2 +-
 libstdc++-v3/doc/html/manual/api.html  | 2 ++
 libstdc++-v3/doc/html/manual/appendix.html | 2 +-
 libstdc++-v3/doc/html/manual/appendix_porting.html | 2 +-
 libstdc++-v3/doc/html/manual/index.html| 2 +-
 libstdc++-v3/doc/xml/manual/evolution.xml  | 8 
 6 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/libstdc++-v3/doc/html/index.html b/libstdc++-v3/doc/html/index.html
index 395908f17a1..e96f2cb2704 100644
--- a/libstdc++-v3/doc/html/index.html
+++ b/libstdc++-v3/doc/html/index.html
@@ -142,7 +142,7 @@
 Existing tests
 
 C++11 Requirements Test Sequence Descriptions
-ABI Policy and 
GuidelinesThe C++ 
InterfaceVersioningGoalsHistoryPrerequisitesConfiguringChecking 
ActiveAllowed 
ChangesProhibited 
ChangesImplementationTestingSingle ABI 
TestingMultiple ABI 
TestingOutstanding 
IssuesAPI Evolution and Deprecation 
History3.03.13.23.33.44.04.14.24.34.44.54.64.74.84.955.3677.27.38910111212.31313.314Backwards 
CompatibilityFirstSecondThirdPre-ISO headers 
removedExtension headers hash_map, 
hash_set moved to ext or backwardsNo ios::nocreate/ios::noreplace.
+ABI Policy and 
GuidelinesThe C++ 
InterfaceVersioningGoalsHistoryPrerequisitesConfiguringChecking 
ActiveAllowed 
ChangesProhibited 
ChangesImplementationTestingSingle ABI 
TestingMultiple ABI 
TestingOutstanding 
IssuesAPI Evolution and Deprecation 
History3.03.13.23.33.44.04.14.24.34.44.54.64.74.84.955.3677.27.38910111212.31313.31415Backwards 
CompatibilityFirstSecondThirdPre-ISO headers 
removedExtension headers hash_map, 
hash_set moved to ext or backwardsNo ios::nocreate/ios::noreplace.
 
 No stream::attach(int fd)
 
diff --git a/libstdc++-v3/doc/html/manual/api.html 
b/libstdc++-v3/doc/html/manual/api.html
index 59ed4c88862..799f6eae2a2 100644
--- a/libstdc++-v3/doc/html/manual/api.html
+++ b/libstdc++-v3/doc/html/manual/api.html
@@ -496,4 +496,6 @@ to be used with std::basic_istream.
   The extension allowing std::basic_string to be 
instantiated
   with an allocator that doesn't match the string's character type is no
   longer allowed in C++20 mode.
+15
+Enabled debug assertions by default for unoptimized builds.
 Prev Up NextABI Policy and Guidelines Home Backwards 
Compatibility
\ No newline at end of file
diff --git a/libstdc++-v3/doc/html/manual/appendix.html 
b/libstdc++-v3/doc/html/manual/appendix.html
index affd5839f43..69a0e0018f3 100644
--- a/libstdc++-v3/doc/html/manual/appendix.html
+++ b/libstdc++-v3/doc/html/manual/appendix.html
@@ -16,7 +16,7 @@
 Existing tests
 
 C++11 Requirements Test Sequence Descriptions
-ABI Policy and GuidelinesThe C++ 
InterfaceVersioningGoalsHistoryPrerequisitesConfiguringChecking 
ActiveAllowed ChangesProhibited 
ChangesImplementationTestingSingle ABI 
TestingMultiple ABI 
TestingOutstanding 
IssuesAPI Evolution and Deprecation 
History3.03.13.23.33.44.04.14.24.34.44.54.64.74.84.955.3677.27.38910111212.31313.314Backwards 
CompatibilityFirstSecondThirdPre-ISO 
headers removedExtension headers hash_map, hash_set 
moved to ext or backwardsNo ios::nocreate/ios::noreplace.
+ABI Policy and GuidelinesThe C++ 
InterfaceVersioningGoalsHistoryPrerequisitesConfiguringChecking 
ActiveAllowed ChangesProhibited 
ChangesImplementationTestingSingle ABI 
TestingMultiple ABI 
TestingOutstanding 
IssuesAPI Evolution and Deprecation 
History3.03.13.23.33.44.04.14.24.34.44.54.64.74.84.955.3677.27.38910111212.31313.31415Backwards 
CompatibilityFirstSecondThirdPre-ISO 
headers removedExtension headers hash_map, hash_set 
moved to ext or backwardsNo ios::nocreate/ios::noreplace.
 
 No stream::attach(int fd)
 
diff --git a/libstdc++-v3/doc/html/manual/appendix_porting.html 
b/libstdc++-v3/doc/html/manual/appendix_porting.html
index 5d8d5da0bf9..c76ef295e78 100644
--- a/libstdc++-v3/doc/html/manual/appendix_porting.html
+++ b/libstdc++-v3/doc/html/manual/appendix_porting.html
@@ -14,7 +14,7 @@
 Existing tests
 
 C++11 Requirements Test Sequence Descriptions
-ABI Policy and GuidelinesThe C++ 
InterfaceVersioningGoalsHistoryPrerequisitesConfiguringChecking 
ActiveAllowed ChangesProhibited 
ChangesImplementationTestingSingle ABI 
TestingMultiple ABI 
TestingOutstanding 
IssuesAPI Evolution and Deprecation 
History3.03.13.23.33.44.04.14.24.34.44.54.64.74.84.955.3677.27.38910111212.31313.314Backwards 
CompatibilityFirstSecondThirdPre-ISO 
headers removedExtension headers hash_map, hash_set 
moved to ext or backwardsNo ios::nocreate/ios::noreplace.
+ABI Policy and GuidelinesThe C++ 
InterfaceVersioningGoalsHistoryPrerequisitesConfiguringChecking 
ActiveAllowed ChangesProhibited 
ChangesImpleme

[PATCH] ginclude: stdalign.h should define __xxx_is_defined macros for C++

2024-10-23 Thread Jonathan Wakely
The __alignas_is_defined macro has been required by C++ since C++11, and
C++ Library DR 4036 clarified that __alignof_is_defined should be
defined too.

The macros alignas and alignof should not be defined, as they're
keywords in C++.

Technically it's implementation-defined whether __STDC_VERSION__ is
defined by a C++ compiler, but G++ does not define it. Adjusting the
first #if this way works as intended: A C23 compiler will not enter the
outer if-group and so will not define any of the macros, a C17 compiler
will enter both if-groups and so define all the macros, and a C++
compiler will enter the outer if-group but not the inner if-group.

gcc/ChangeLog:

* ginclude/stdalign.h (__alignas_is_defined): Define for C++.
(__alignof_is_defined): Likewise.

libstdc++-v3/ChangeLog:

* testsuite/18_support/headers/cstdalign/macros.cc: New test.
---

The libc++ devs noticed recently that GCC's  doesn't conform
to the C++ requirements.

Tested x86_64-linux.

OK for trunk?

 gcc/ginclude/stdalign.h   |  5 ++--
 .../18_support/headers/cstdalign/macros.cc| 24 +++
 2 files changed, 27 insertions(+), 2 deletions(-)
 create mode 100644 
libstdc++-v3/testsuite/18_support/headers/cstdalign/macros.cc

diff --git a/gcc/ginclude/stdalign.h b/gcc/ginclude/stdalign.h
index 5f82f2d68f2..af73c322624 100644
--- a/gcc/ginclude/stdalign.h
+++ b/gcc/ginclude/stdalign.h
@@ -26,11 +26,12 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  
If not, see
 #ifndef _STDALIGN_H
 #define _STDALIGN_H
 
-#if (!defined __cplusplus  \
- && !(defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L))
+#if !(defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L)
 
+#ifndef __cplusplus
 #define alignas _Alignas
 #define alignof _Alignof
+#endif
 
 #define __alignas_is_defined 1
 #define __alignof_is_defined 1
diff --git a/libstdc++-v3/testsuite/18_support/headers/cstdalign/macros.cc 
b/libstdc++-v3/testsuite/18_support/headers/cstdalign/macros.cc
new file mode 100644
index 000..c50c921cd59
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/headers/cstdalign/macros.cc
@@ -0,0 +1,24 @@
+// { dg-options "-D_GLIBCXX_USE_DEPRECATED=1 -Wno-deprecated" }
+// { dg-do preprocess { target c++11 } }
+
+#include 
+
+#ifndef __alignas_is_defined
+# error "The header  fails to define a macro named  
__alignas_is_defined"
+#elif __alignas_is_defined != 1
+# error "__alignas_is_defined is not defined to 1 in "
+#endif
+
+#ifndef __alignof_is_defined
+# error "The header  fails to define a macro named 
__alignof_is_defined"
+#elif __alignof_is_defined != 1
+# error "__alignof_is_defined is not defined to 1 in "
+#endif
+
+#ifdef alignas
+# error "The header  defines a macro named alignas"
+#endif
+
+#ifdef alignof
+# error "The header  defines a macro named alignof"
+#endif
-- 
2.46.2



[PATCH] top-level: Add pull request template for Forgejo

2024-10-23 Thread Jonathan Wakely
This complements the existing .github/PULL_REQUEST_TEMPLATE.md file,
which is used when somebody opens a pull request for an unofficial
mirror/fork of GCC on Github. The text in the existing file is very
specific to GitHub and doesn't make much sense to include on every PR
created on forge.sourceware.org.

I tested it by pushing this file to my own fork and opening a pull
request against that fork. This template in .forgejo was used instead of
the one in .github, see https://forge.sourceware.org/redi/gcc/pulls/1

OK for trunk?

-- >8 --

ChangeLog:

* .forgejo/PULL_REQUEST_TEMPLATE.md: New file.
---
 .forgejo/PULL_REQUEST_TEMPLATE.md | 9 +
 1 file changed, 9 insertions(+)
 create mode 100644 .forgejo/PULL_REQUEST_TEMPLATE.md

diff --git a/.forgejo/PULL_REQUEST_TEMPLATE.md 
b/.forgejo/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 000..fc645f11305
--- /dev/null
+++ b/.forgejo/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,9 @@
+Thanks for taking the time to contribute to GCC!
+
+Please be advised that https://forge.sourceware.org/ is currently a trial
+that is being used by the GCC community to experiment with a new workflow
+based on pull requests.
+
+Pull requests sent here may be forgotten or ignored. Patches that you want to
+propose for inclusion in GCC should use the existing email-based workflow,
+see https://gcc.gnu.org/contribute.html
-- 
2.46.2



Re: [PATCH] libstdc++: Replace std::__to_address in C++20 branch in

2024-10-23 Thread Jonathan Wakely
On Wed, 23 Oct 2024 at 13:18, Jonathan Wakely  wrote:
>
> As noted by Patrick, r15-4546-g85e5b80ee2de80 should have changed the
> usage of std::__to_address to std::to_address in the C++20-specific
> branch that works on types satisfying std::contiguous_iterator.
>
> libstdc++-v3/ChangeLog:
>
> * include/bits/basic_string.h (assign(Iter, Iter)): Call
> std::to_address instead of __to_address.
> ---
> Tested x86_64-linux.
>
> This patch is also available as a pull request in the forge:
> https://forge.sourceware.org/gcc/gcc-TEST/pulls/2

Patrick approved this on the forge (thanks!), so I've added his
Reviewed-by: tag and pushed it now.

>
>  libstdc++-v3/include/bits/basic_string.h | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/libstdc++-v3/include/bits/basic_string.h 
> b/libstdc++-v3/include/bits/basic_string.h
> index 16e356e0678..28b3e536185 100644
> --- a/libstdc++-v3/include/bits/basic_string.h
> +++ b/libstdc++-v3/include/bits/basic_string.h
> @@ -1748,7 +1748,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
> {
>   __glibcxx_requires_valid_range(__first, __last);
>   return _M_replace(size_type(0), size(),
> -   std::__to_address(__first), __last - __first);
> +   std::to_address(__first), __last - __first);
> }
>  #endif
>   else
> --
> 2.46.2
>



[PATCH] libstdc++: Add GLIBCXX_TESTSUITE_STDS example to docs

2024-10-23 Thread Jonathan Wakely
libstdc++-v3/ChangeLog:

* doc/xml/manual/test.xml: Add GLIBCXX_TESTSUITE_STDS example.
* doc/html/manual/test.html: Regenerate.
---

This patch is also available as a pull request in the forge:
https://forge.sourceware.org/gcc/gcc-TEST/pulls/1

 libstdc++-v3/doc/html/manual/test.html | 5 +++--
 libstdc++-v3/doc/xml/manual/test.xml   | 5 +++--
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/libstdc++-v3/doc/html/manual/test.html 
b/libstdc++-v3/doc/html/manual/test.html
index 3657997fad4..1c7af1193da 100644
--- a/libstdc++-v3/doc/html/manual/test.html
+++ b/libstdc++-v3/doc/html/manual/test.html
@@ -352,12 +352,13 @@ cat 27_io/objects/char/3_xin.in | 
a.out-std, similar to 
the G++ tests.
   Adding set v3_std_list { 11 17 23 } to
-  ~/.dejagnurc or a file named by the
+  ~/.dejagnurc or to a file named by the
   DEJAGNU environment variable will cause every 
test to
   be run three times, using a different -std 
each time.
   Alternatively, a list of standard versions to test with can be specified
   as a comma-separated list in the GLIBCXX_TESTSUITE_STDS
-  environment variable.
+  environment variable, e.g. GLIBCXX_TESTSUITE_STDS=11,17,23
+  is equivalent to the v3_std_list value above.
 
   To run the libstdc++ test suite under the
   debug mode, use
diff --git a/libstdc++-v3/doc/xml/manual/test.xml 
b/libstdc++-v3/doc/xml/manual/test.xml
index 40926946fe7..6b7f1b04a2a 100644
--- a/libstdc++-v3/doc/xml/manual/test.xml
+++ b/libstdc++-v3/doc/xml/manual/test.xml
@@ -600,12 +600,13 @@ cat 27_io/objects/char/3_xin.in | a.out
   Since GCC 14, the libstdc++ testsuite has built-in support for running
   tests with more than one -std, similar to the G++ tests.
   Adding set v3_std_list { 11 17 23 } to
-  ~/.dejagnurc or a file named by the
+  ~/.dejagnurc or to a file named by the
   DEJAGNU environment variable will cause every test to
   be run three times, using a different -std each time.
   Alternatively, a list of standard versions to test with can be specified
   as a comma-separated list in the GLIBCXX_TESTSUITE_STDS
-  environment variable.
+  environment variable, e.g. GLIBCXX_TESTSUITE_STDS=11,17,23
+  is equivalent to the v3_std_list value above.
 
 
 
-- 
2.46.2



[PATCH] libstdc++: Replace std::__to_address in C++20 branch in

2024-10-23 Thread Jonathan Wakely
As noted by Patrick, r15-4546-g85e5b80ee2de80 should have changed the
usage of std::__to_address to std::to_address in the C++20-specific
branch that works on types satisfying std::contiguous_iterator.

libstdc++-v3/ChangeLog:

* include/bits/basic_string.h (assign(Iter, Iter)): Call
std::to_address instead of __to_address.
---
Tested x86_64-linux.

This patch is also available as a pull request in the forge:
https://forge.sourceware.org/gcc/gcc-TEST/pulls/2

 libstdc++-v3/include/bits/basic_string.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/bits/basic_string.h 
b/libstdc++-v3/include/bits/basic_string.h
index 16e356e0678..28b3e536185 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -1748,7 +1748,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{
  __glibcxx_requires_valid_range(__first, __last);
  return _M_replace(size_type(0), size(),
-   std::__to_address(__first), __last - __first);
+   std::to_address(__first), __last - __first);
}
 #endif
  else
-- 
2.46.2



Re: [Bug libstdc++/115285] [12/13/14/15 Regression] std::unordered_set can have duplicate value

2024-10-22 Thread Jonathan Wakely
On Tue, 22 Oct 2024 at 18:28, François Dumont  wrote:
>
> Hi
>
>  libstdc++: Always instantiate key_type to compute hash code [PR115285]
>
>  Even if it is possible to compute a hash code from the inserted
> arguments
>  we need to instantiate the key_type to guaranty hash code consistency.
>
>  Preserve the lazy instantiation of the mapped_type in the context of
>  associative containers.
>
>  libstdc++-v3/ChangeLog:
>
>  PR libstdc++/115285
>  * include/bits/hashtable.h (_S_forward_key<_Kt>): Always
> return a temporary
>  key_type instance.
>  * testsuite/23_containers/unordered_map/96088.cc: Adapt to
> additional instanciation.
>  Also check that mapped_type is not instantiated when there
> is no insertion.
>  * testsuite/23_containers/unordered_multimap/96088.cc:
> Adapt to additional
>  instanciation.
>  * testsuite/23_containers/unordered_multiset/96088.cc:
> Likewise.
>  * testsuite/23_containers/unordered_set/96088.cc: Likewise.
>  * testsuite/23_containers/unordered_set/pr115285.cc: New
> test case.
>
>
> Tested under Linux x64,
>
> ok to commit ?

OK, thanks



Re: [PATCH] libstdc++: Implement LWG 4166 changes to concat_view::end()

2024-10-22 Thread Jonathan Wakely
On Tue, 22 Oct 2024 at 19:22, Patrick Palka  wrote:
>
> Tested on x86_64-pc-linux-gnu, does this look OK for trunk?

OK, thanks.

>
> -- >8 --
>
> This patch proactively implements the proposed resolution for this LWG
> issue, which seems straightforward and slated to be approved as-is.
>
> I opted to not add a _GLIBCXX_RESOLVE_LIB_DEFECTS code comment for this
> since concat_view is C++26 and hasn't been shipped in a GCC release yet.

Yup, that's fine. The LWG issue isn't a DR against a published
standard, so once we get a finished C++26 standard, this issue will
already be part of that standard.

>
> libstdc++-v3/ChangeLog:
>
> * include/std/ranges (concat_view::begin): Add space after
> 'requires' starting a requires-clause.
> (concat_view::end): Refine condition for returning an iterator
> rather than default_sentinel as per LWG 4166.
> * testsuite/std/ranges/concat/1.cc (test03): Verify LWG 4166
> example.
> ---
>  libstdc++-v3/include/std/ranges   | 10 
>  libstdc++-v3/testsuite/std/ranges/concat/1.cc | 23 +++
>  2 files changed, 29 insertions(+), 4 deletions(-)
>
> diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
> index 5b455888536..a6c4d66520c 100644
> --- a/libstdc++-v3/include/std/ranges
> +++ b/libstdc++-v3/include/std/ranges
> @@ -9687,7 +9687,7 @@ namespace ranges
>  { }
>
>  constexpr iterator
> -begin() requires(!(__detail::__simple_view<_Vs> && ...))
> +begin() requires (!(__detail::__simple_view<_Vs> && ...))
>  {
>iterator __it(this, in_place_index<0>, 
> ranges::begin(std::get<0>(_M_views)));
>__it.template _M_satisfy<0>();
> @@ -9703,9 +9703,10 @@ namespace ranges
>  }
>
>  constexpr auto
> -end() requires(!(__detail::__simple_view<_Vs> && ...))
> +end() requires (!(__detail::__simple_view<_Vs> && ...))
>  {
> -  if constexpr (__detail::__last_is_common<_Vs...>::value)
> +  if constexpr ((semiregular> && ...)
> +   && __detail::__last_is_common<_Vs...>::value)
> {
>   constexpr auto __n = sizeof...(_Vs);
>   return iterator(this, in_place_index<__n - 1>,
> @@ -9718,7 +9719,8 @@ namespace ranges
>  constexpr auto
>  end() const requires (range && ...) && 
> __detail::__concatable
>  {
> -  if constexpr (__detail::__last_is_common::value)
> +  if constexpr ((semiregular> && ...)
> +   && __detail::__last_is_common::value)
> {
>   constexpr auto __n = sizeof...(_Vs);
>   return iterator(this, in_place_index<__n - 1>,
> diff --git a/libstdc++-v3/testsuite/std/ranges/concat/1.cc 
> b/libstdc++-v3/testsuite/std/ranges/concat/1.cc
> index 6ffe28ece51..511a7e8a858 100644
> --- a/libstdc++-v3/testsuite/std/ranges/concat/1.cc
> +++ b/libstdc++-v3/testsuite/std/ranges/concat/1.cc
> @@ -10,6 +10,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -66,9 +67,31 @@ test02()
>VERIFY( ranges::equal(v | views::drop(1), x) );
>  }
>
> +void
> +test03()
> +{
> +  // LWG 4166 - concat_view::end() should be more constrained in order to
> +  // support noncopyable iterators
> +  auto range_copyable_it = std::vector{1, 2, 3};
> +
> +  std::stringstream ss{"4 5 6"};
> +  auto range_noncopyable_it = views::istream(ss);
> +
> +  auto view1 = views::concat(range_copyable_it, range_noncopyable_it);
> +  static_assert( ranges::range );
> +  VERIFY( ranges::equal(view1, std::vector{1, 2, 3, 4, 5, 6}) );
> +
> +  ss = std::stringstream{"4 5 6"};
> +  range_noncopyable_it = views::istream(ss);
> +  auto view2 = views::concat(range_noncopyable_it, range_copyable_it);
> +  static_assert( ranges::range );
> +  VERIFY( ranges::equal(view2, std::vector{4, 5, 6, 1, 2, 3}) );
> +}
> +
>  int
>  main()
>  {
>static_assert(test01());
>test02();
> +  test03();
>  }
> --
> 2.47.0.107.g34b6ce9b30
>



Re: [PATCH] libstdc++: Avoid using std::__to_address with iterators

2024-10-22 Thread Jonathan Wakely
On Tue, 22 Oct 2024 at 18:43, Patrick Palka  wrote:
>
> On Fri, 18 Oct 2024, Jonathan Wakely wrote:
>
> > Do others agree with my reasoning below?
> >
> > The changes to implement the rule "use std::__niter_base before C++20
> > and use std::to_address after C++20" were easier than I expected. There
> > weren't many places that were doing it "wrong" and needed to change.
> >
> > Tested x86_64-linux.
> >
> > -- >8 --
> >
> > In r12-3935-g82626be2d633a9 I added the partial specialization
> > std::pointer_traits<__normal_iterator> so that __to_address
> > would work with __normal_iterator objects. Soon after that, François
> > replaced it in r12-6004-g807ad4bc854cae with an overload of __to_address
> > that served the same purpose, but was less complicated and less wrong.
> >
> > I now think that both commits were mistakes, and that instead of adding
> > hacks to make __normal_iterator work with __to_address, we should not be
> > using __to_address with iterators at all before C++20.
> >
> > The pre-C++20 std::__to_address function should only be used with
> > pointer-like types, specifically allocator_traits::pointer types.
> > Those pointer-like types are guaranteed to be contiguous iterators, so
> > that getting a raw memory address from them is OK.
> >
> > For arbitrary iterators, even random access iterators, we don't know
> > that it's safe to lower the iterator to a pointer e.g. for std::deque
> > iterators it's not, because (it + n) == (std::to_address(it) + n) only
> > holds within the same block of the deque's storage.
> >
> > For C++20, std::to_address does work correctly for contiguous iterators,
> > including __normal_iterator, and __to_address just calls std::to_address
> > so also works. But we have to be sure we have an iterator that satisfies
> > the std::contiguous_iterator concept for it to be safe, and we can't
> > check that before C++20.
> >
> > So for pre-C++20 code the correct way to handle iterators that might be
> > pointers or might be __normal_iterator is to call __niter_base, and if
> > necessary use is_pointer to check whether __niter_base returned a real
> > pointer.
> >
> > We currently have some uses of std::__to_address with iterators where
> > we've checked that they're either pointers, or __normal_iterator
> > wrappers around pointers, or satisfy std::contiguous_iterator. But this
> > seems a little fragile, and it would be better to just use
> > std::__niter_base for the pointers and __normal_iterator cases, and use
> > C++20 std::to_address when the C++20 std::contiguous_iterator concept is
> > satisfied. This patch does that.
> >
> > libstdc++-v3/ChangeLog:
> >
> >   * include/bits/basic_string.h (basic_string::assign): Replace
> >   use of __to_address with __niter_base or std::to_address as
> >   appropriate.
> >   * include/bits/ptr_traits.h (__to_address): Add comment.
> >   * include/bits/shared_ptr_base.h (__shared_ptr): Qualify calls
> >   to __to_address.
> >   * include/bits/stl_algo.h (find): Replace use of __to_address
> >   with __niter_base or std::to_address as appropriate. Only use
> >   either of them when the range is not empty.
> >   * include/bits/stl_iterator.h (__to_address): Remove overload
> >   for __normal_iterator.
> >   * include/debug/safe_iterator.h (__to_address): Remove overload
> >   for _Safe_iterator.
> >   * include/std/ranges (views::counted): Replace use of
> >   __to_address with std::to_address.
> >   * testsuite/24_iterators/normal_iterator/to_address.cc: Removed.
> > ---
> >  libstdc++-v3/include/bits/basic_string.h  | 19 +--
> >  libstdc++-v3/include/bits/ptr_traits.h|  4 
> >  libstdc++-v3/include/bits/shared_ptr_base.h   |  4 ++--
> >  libstdc++-v3/include/bits/stl_algo.h  | 16 +++-
> >  libstdc++-v3/include/bits/stl_iterator.h  | 12 
> >  libstdc++-v3/include/debug/safe_iterator.h| 17 -
> >  libstdc++-v3/include/std/ranges   |  2 +-
> >  .../normal_iterator/to_address.cc | 19 ---
> >  8 files changed, 31 insertions(+), 62 deletions(-)
> >  delete mode 100644 
> > libstdc++-v3/testsuite/24_iterators/normal_iterator/to_address.cc
> >
> > diff --git a/libstdc++-v3/include/bits/basic_string.h 
> > b/libstdc++-v3/include/bits/basic_string.h
> > index e9b17ea48b5..16e356e0678 1

Re: [WIP RFC] libstdc++: add module std

2024-10-22 Thread Jonathan Wakely
On Tue, 22 Oct 2024 at 15:03, Jason Merrill  wrote:
>
> On 10/22/24 4:26 AM, Jonathan Wakely wrote:
> > On Mon, 21 Oct 2024 at 17:51, Jason Merrill  wrote:
> >>
> >> On 10/18/24 11:21 AM, Patrick Palka wrote:
> >>> On Fri, 18 Oct 2024, Jason Merrill wrote:
> >>>>
> >>>> Is it useful for std.cc to live in a subdirectory of c++23 as in this 
> >>>> patch, or
> >>>> should it be in c++23 itself?  Or elsewhere?
> >>>
> >>> IIUC the src/ subdirectory is for stuff that gets compiled into the .so
> >>> which isn't the case here.
> >>
> >> Sure, though I thought that might change once we consider it ABI-stable.
> >>
> >>> And if we want to support the std module in
> >>> C++20 mode as an extension, a c++23 subdirectory might not be ideal 
> >>> either.
> >>
> >> My impression has been that the subdirectories are just for organization?
> >
> > Yes, and to group all the files which are built with -std=gnu++NN
> > together so that the option is set once by the directory's Makefile
> > (although we have a couple of cases where we override the directory's
> > -std for specific files).
> >
> >>
> >>> Maybe libstdc++-v3/modules/ then?
> >>
> >> Let's see what Jonathan thinks.
> >
> > I'm not sure we need a new directory (with Makefile.{in,am} etc.) for
> > just two files. If there's a suggestion to install them to
> > $(gxx_include_dir)/module then maybe libstdc++-v3/include/module/
> > makes sense? And install them via rules in
> > libstdc++-v3/include/Makefile.am?
> >
> >>
> >> On 10/18/24 12:04 PM, Maciej Cencora wrote:
> >>> On Fri, 18 Oct 2024, Jason Merrill wrote:
> >>>> stdc++.h also doesn't include the eternally deprecated .  
> >>>> There
> >>>> are some other deprecated facilities that I notice are included: 
> >>>> 
> >>>> and float_denorm_style, at least.  It would be nice for L{E,}WG to 
> >>>> clarify
> >>>> whether module std is intended to include interfaces that were 
> >>>> deprecated in
> >>>> C++23, since ancient code isn't going to be relying on module std.
> >>>
> >>> Per P2465r3 Standard Library Modules std and std.compat:
> >>>> Are deprecated features provided by the Standard Library modules?
> >>>> Yes. This is implied by the normative wording.
> >>
> >> Ah, thanks.
> >>
> >>> While doing some light testing, one thing that immediately popped up is 
> >>> that we need to export __normal_iterator related operators from __gnu_cxx 
> >>> namespace.
> >>> Otherwise it is impossible to even use std::vector in range-based for 
> >>> loops.
> >>
> >> Ah, good catch.
> >>
> >>> But I think a better solution (than exporting such impl details) is to 
> >>> make these operators hidden friends.
> >>
> >> That sounds right to me, and mechanically duplicating the declarations
> >> as friends seems to work (as attached).
> >
> > I think I'll just move them into the body to be hidden friends.
> >
> > The operators for __normal_iterator aren't declared explicitly in the
> > standard, so we aren't required to declare them at namespace scope.
> > Making them hidden friends should be fine.
> >
> >
> >>
> >>> Another thing - P2465r3 mentions only lerp, byte and related ops as 
> >>> special w.r.t skipping export from global namespace in std.compat, but 
> >>> for some reason Microsoft's impl treats 3-arg hypot as special as well.
> >>
> >> Curious. By not declaring it at all when building the module? I don't
> >> want to mess with that if the standard doesn't require it.
> >
> > That's https://cplusplus.github.io/LWG/issue3799
> >
> > The 3-arg std::hypot did not come from C, so is in exactly the same
> > situation as lerp.
>
> The implementation problem is that 'using' doesn't let you choose
> between overloads.
>
> Well, I suppose we could 'using' the other decls into e.g. namespace
> __hypot before declaring the 3-arg version, and then 'using
> __hypot::hypot' instead of std::hypot in std.compat.

Ah yes, I see.

I don't think it's a problem if we export the 3-arg version in the
global namespace alongside the 2-arg

Re: [WIP RFC] libstdc++: add module std

2024-10-22 Thread Jonathan Wakely
On Mon, 21 Oct 2024 at 17:51, Jason Merrill  wrote:
>
> On 10/18/24 11:21 AM, Patrick Palka wrote:
> > On Fri, 18 Oct 2024, Jason Merrill wrote:
> >>
> >> Is it useful for std.cc to live in a subdirectory of c++23 as in this 
> >> patch, or
> >> should it be in c++23 itself?  Or elsewhere?
> >
> > IIUC the src/ subdirectory is for stuff that gets compiled into the .so
> > which isn't the case here.
>
> Sure, though I thought that might change once we consider it ABI-stable.
>
> > And if we want to support the std module in
> > C++20 mode as an extension, a c++23 subdirectory might not be ideal either.
>
> My impression has been that the subdirectories are just for organization?

Yes, and to group all the files which are built with -std=gnu++NN
together so that the option is set once by the directory's Makefile
(although we have a couple of cases where we override the directory's
-std for specific files).

>
> > Maybe libstdc++-v3/modules/ then?
>
> Let's see what Jonathan thinks.

I'm not sure we need a new directory (with Makefile.{in,am} etc.) for
just two files. If there's a suggestion to install them to
$(gxx_include_dir)/module then maybe libstdc++-v3/include/module/
makes sense? And install them via rules in
libstdc++-v3/include/Makefile.am?

>
> On 10/18/24 12:04 PM, Maciej Cencora wrote:
> > On Fri, 18 Oct 2024, Jason Merrill wrote:
> >> stdc++.h also doesn't include the eternally deprecated .  There
> >> are some other deprecated facilities that I notice are included: 
> >> and float_denorm_style, at least.  It would be nice for L{E,}WG to clarify
> >> whether module std is intended to include interfaces that were deprecated 
> >> in
> >> C++23, since ancient code isn't going to be relying on module std.
> >
> > Per P2465r3 Standard Library Modules std and std.compat:
> >> Are deprecated features provided by the Standard Library modules?
> >> Yes. This is implied by the normative wording.
>
> Ah, thanks.
>
> > While doing some light testing, one thing that immediately popped up is 
> > that we need to export __normal_iterator related operators from __gnu_cxx 
> > namespace.
> > Otherwise it is impossible to even use std::vector in range-based for loops.
>
> Ah, good catch.
>
> > But I think a better solution (than exporting such impl details) is to make 
> > these operators hidden friends.
>
> That sounds right to me, and mechanically duplicating the declarations
> as friends seems to work (as attached).

I think I'll just move them into the body to be hidden friends.

The operators for __normal_iterator aren't declared explicitly in the
standard, so we aren't required to declare them at namespace scope.
Making them hidden friends should be fine.


>
> > Another thing - P2465r3 mentions only lerp, byte and related ops as special 
> > w.r.t skipping export from global namespace in std.compat, but for some 
> > reason Microsoft's impl treats 3-arg hypot as special as well.
>
> Curious. By not declaring it at all when building the module? I don't
> want to mess with that if the standard doesn't require it.

That's https://cplusplus.github.io/LWG/issue3799

The 3-arg std::hypot did not come from C, so is in exactly the same
situation as lerp.

>
> On 10/18/24 12:35 PM, Iain Sandoe wrote:
> >> Currently this installs the sources under $(pkgdata), i.e.
> >> /usr/share/libstdc++/modules.  It could also make sense to install them
> >> under $(gxx_include_dir), i.e. /usr/include/c++/15/modules.  And/or the
> >> subdirectory could be "miu" (module interface unit) instead of "modules".
>
> > I’d think that $(gxx_include_dir)/modules would be a good place, since that
> > allows us to tie it to the GCC version in side-by-side installs.  
> > Presumably that
> > might also simplify finding the relevant sources?
>
> With side-by-side installs presumably $(prefix) would be different
> between them as well or the libraries would also clash?
>
> But I'm certainly not opposed to putting them under the include dir,
> that had been my inclination for a while, and with my
> -fsearch-include-path patch would make a simple compile easier without
> needing to teach the driver to parse the json.
>
> > I guess it could be just “module”, but my vote would be for an obvious name
> > like that or “std-module”
>
> Indeed singular "module" would be more consistent with "include" and "lib".

As long as we're confident there will never be a  header that
needs to live at $(gxx_include_dir)/module, but I think that's a safe
bet.

> On 10/19/24 8:08 AM, Florian Weimer wrote:
> >> The build system can find this file with
> >> gcc -print-file-name=libstdc++.modules.json
> >
> > Is it possible to use specs file to redirect this to a different file
> > based on C++ compiler flags, should that become necessary?
>
> Well, the compiler looks up a -print-file-name argument on its library
> search path, which can be added to with -B.  But this is really an
> initial interface pending something more stable.
>
> Jason



Re: [PATCH] aarch64: libstdc++: Use shufflevector instead of shuffle in opt_random.h

2024-10-21 Thread Jonathan Wakely
On Mon, 21 Oct 2024 at 17:29, Ricardo Jesus  wrote:
>
> On 10/14/24 14:37, Jonathan Wakely wrote:
> >
> >
> > On Mon, 14 Oct 2024 at 14:36, Kyrylo Tkachov  wrote:
> >>
> >>
> >>
> >>> On 14 Oct 2024, at 15:28, Ricardo Jesus  wrote:
> >>>
> >>> External email: Use caution opening links or attachments
> >>>
> >>>
> >>> This patch modifies the implementation of the vectorized mersenne
> >>> twister random number generator to use __builtin_shufflevector instead
> >>> of __builtin_shuffle. This makes it (almost) compatible with Clang.
> >>>
> >>> To make the implementation fully compatible with Clang, Clang will need
> >>> to support internal Neon types like __Uint8x16_t and __Uint32x4_t, which
> >>> currently it does not. This looks like an oversight in Clang and so will
> >>> be addressed separately.
> >>>
> >>> I see no codegen change with this patch.
> >>
> >> FWIW the change looks ok to me from an aarch64 perspective.
> >> The only potential problem could have been a compile error so as long as 
> >> the CI buildbots are happy I think this would be safe to take.
> >
> > OK thanks for looking. I'll wait to see that CI is green (thanks for
> > resubmitting it, Ricardo!) and then push it.
> >
>
> Hi Jonathan,
>
> When you have a chance, could you please check if the CI is looking good?

Yes, it's green now:
https://patchwork.sourceware.org/project/gcc/patch/20241014132802.506972-1-...@nvidia.com/

With Kyrill's ack for the aarch64 codegen side, I'm happy to approve
this and will push it. Thanks!

>
> Thanks very much!
>
> Ricardo
>
> >
> >> Thanks,
> >> Kyrill
> >>
> >>>
> >>> Bootstrapped and tested on aarch64-none-linux-gnu.
> >>>
> >>> Signed-off-by: Ricardo Jesus 
> >>>
> >>> 2024-09-05  Ricardo Jesus  
> >>>
> >>>* config/cpu/aarch64/opt/ext/opt_random.h (__VEXT): Replace uses
> >>>of __builtin_shuffle with __builtin_shufflevector.
> >>>(__aarch64_lsl_128): Move shift amount to a template parameter.
> >>>(__aarch64_lsr_128): Move shift amount to a template parameter.
> >>>(__aarch64_recursion): Update call sites of __aarch64_lsl_128
> >>>and __aarch64_lsr_128.
> >>> ---
> >>> .../config/cpu/aarch64/opt/ext/opt_random.h   | 28 +++
> >>> 1 file changed, 16 insertions(+), 12 deletions(-)
> >>>
> >>> diff --git a/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h 
> >>> b/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h
> >>> index 7f756d1572f..7eb816abcd0 100644
> >>> --- a/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h
> >>> +++ b/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h
> >>> @@ -35,13 +35,13 @@
> >>> #ifdef __ARM_NEON
> >>>
> >>> #ifdef __ARM_BIG_ENDIAN
> >>> -# define __VEXT(_A,_B,_C) __builtin_shuffle (_A, _B, (__Uint8x16_t) \
> >>> -{16-_C, 17-_C, 18-_C, 19-_C, 20-_C, 21-_C, 22-_C, 23-_C, \
> >>> - 24-_C, 25-_C, 26-_C, 27-_C, 28-_C, 29-_C, 30-_C, 31-_C})
> >>> +# define __VEXT(_A,_B,_C) __builtin_shufflevector (_A, _B, \
> >>> +16-_C, 17-_C, 18-_C, 19-_C, 20-_C, 21-_C, 22-_C, 23-_C, \
> >>> +24-_C, 25-_C, 26-_C, 27-_C, 28-_C, 29-_C, 30-_C, 31-_C)
> >>> #else
> >>> -# define __VEXT(_A,_B,_C) __builtin_shuffle (_B, _A, (__Uint8x16_t) \
> >>> -{_C, _C+1, _C+2, _C+3, _C+4, _C+5, _C+6, _C+7, \
> >>> - _C+8, _C+9, _C+10, _C+11, _C+12, _C+13, _C+14, _C+15})
> >>> +# define __VEXT(_A,_B,_C) __builtin_shufflevector (_B, _A, \
> >>> +_C, _C+1, _C+2, _C+3, _C+4, _C+5, _C+6, _C+7, \
> >>> +_C+8, _C+9, _C+10, _C+11, _C+12, _C+13, _C+14, _C+15)
> >>> #endif
> >>>
> >>> #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
> >>> @@ -52,9 +52,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >>>   namespace {
> >>> // Logical Shift right 128-bits by c * 8 bits
> >>>
> >>> -__extension__ extern __inline __Uint32x4_t
> >>> +__extension__
> >>> +template
> >>> +extern __inline __Uint32x4_t
> >>> __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> >>> -__aarch64_lsr_128 (__Uint8x16_t

Re: [PATCH] libstdc++: Avoid using std::__to_address with iterators

2024-10-21 Thread Jonathan Wakely
On Mon, 21 Oct 2024 at 18:02, François Dumont  wrote:
>
> Reasoning is perfectly fine to me.
>
> It's not a good news for me cause I plan to extend usages of
> __niter_base to many algos to limit impact of _GLIBCXX_DEBUG mode at
> runtime. If we have random access iterator we can be sure that
> __glibcxx_requires_valid_range fully validated the range and so we can
> remove the _Safe_iterator layer.

Using __niter_base is fine, it's using __to_address with iterators
that I want to avoid.


> But that's a really minor problem compared to what you are trying to
> achieve here.
>
> François
>
>
> On 18/10/2024 17:13, Jonathan Wakely wrote:
> > Do others agree with my reasoning below?
> >
> > The changes to implement the rule "use std::__niter_base before C++20
> > and use std::to_address after C++20" were easier than I expected. There
> > weren't many places that were doing it "wrong" and needed to change.
> >
> > Tested x86_64-linux.
> >
> > -- >8 --
> >
> > In r12-3935-g82626be2d633a9 I added the partial specialization
> > std::pointer_traits<__normal_iterator> so that __to_address
> > would work with __normal_iterator objects. Soon after that, François
> > replaced it in r12-6004-g807ad4bc854cae with an overload of __to_address
> > that served the same purpose, but was less complicated and less wrong.
> >
> > I now think that both commits were mistakes, and that instead of adding
> > hacks to make __normal_iterator work with __to_address, we should not be
> > using __to_address with iterators at all before C++20.
> >
> > The pre-C++20 std::__to_address function should only be used with
> > pointer-like types, specifically allocator_traits::pointer types.
> > Those pointer-like types are guaranteed to be contiguous iterators, so
> > that getting a raw memory address from them is OK.
> >
> > For arbitrary iterators, even random access iterators, we don't know
> > that it's safe to lower the iterator to a pointer e.g. for std::deque
> > iterators it's not, because (it + n) == (std::to_address(it) + n) only
> > holds within the same block of the deque's storage.
> >
> > For C++20, std::to_address does work correctly for contiguous iterators,
> > including __normal_iterator, and __to_address just calls std::to_address
> > so also works. But we have to be sure we have an iterator that satisfies
> > the std::contiguous_iterator concept for it to be safe, and we can't
> > check that before C++20.
> >
> > So for pre-C++20 code the correct way to handle iterators that might be
> > pointers or might be __normal_iterator is to call __niter_base, and if
> > necessary use is_pointer to check whether __niter_base returned a real
> > pointer.
> >
> > We currently have some uses of std::__to_address with iterators where
> > we've checked that they're either pointers, or __normal_iterator
> > wrappers around pointers, or satisfy std::contiguous_iterator. But this
> > seems a little fragile, and it would be better to just use
> > std::__niter_base for the pointers and __normal_iterator cases, and use
> > C++20 std::to_address when the C++20 std::contiguous_iterator concept is
> > satisfied. This patch does that.
> >
> > libstdc++-v3/ChangeLog:
> >
> >   * include/bits/basic_string.h (basic_string::assign): Replace
> >   use of __to_address with __niter_base or std::to_address as
> >   appropriate.
> >   * include/bits/ptr_traits.h (__to_address): Add comment.
> >   * include/bits/shared_ptr_base.h (__shared_ptr): Qualify calls
> >   to __to_address.
> >   * include/bits/stl_algo.h (find): Replace use of __to_address
> >   with __niter_base or std::to_address as appropriate. Only use
> >   either of them when the range is not empty.
> >   * include/bits/stl_iterator.h (__to_address): Remove overload
> >   for __normal_iterator.
> >   * include/debug/safe_iterator.h (__to_address): Remove overload
> >   for _Safe_iterator.
> >   * include/std/ranges (views::counted): Replace use of
> >   __to_address with std::to_address.
> >   * testsuite/24_iterators/normal_iterator/to_address.cc: Removed.
> > ---
> >   libstdc++-v3/include/bits/basic_string.h  | 19 +--
> >   libstdc++-v3/include/bits/ptr_traits.h|  4 
> >   libstdc++-v3/include/bits/shared_ptr_base.h   |  4 ++--
> >   libstdc++-v3/include/bits/stl_algo.h  | 16 +++-
> >   libstdc++-v3/include/bits/stl_i

[committed] libstdc++: Fix order of [[...]] and __attribute__((...)) attrs [PR117220]

2024-10-21 Thread Jonathan Wakely
Tested x86_64-linux, and briefly checked with Clang. Pushed to trunk.

-- >8 --

GCC allows these in either order, but Clang doesn't like the C++11-style
[[__nodiscard__]] coming after __attribute__((__always_inline__)).

libstdc++-v3/ChangeLog:

PR libstdc++/117220
* include/bits/stl_iterator.h: Move _GLIBCXX_NODISCARD
annotations after __attribute__((__always_inline__)).
---
 libstdc++-v3/include/bits/stl_iterator.h | 46 
 1 file changed, 23 insertions(+), 23 deletions(-)

diff --git a/libstdc++-v3/include/bits/stl_iterator.h 
b/libstdc++-v3/include/bits/stl_iterator.h
index 26c5eab4b4e..1fbc115b116 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -1077,13 +1077,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   // Forward iterator requirements
 
-  __attribute__((__always_inline__)) _GLIBCXX_NODISCARD
+  _GLIBCXX_NODISCARD __attribute__((__always_inline__))
   _GLIBCXX_CONSTEXPR
   reference
   operator*() const _GLIBCXX_NOEXCEPT
   { return *_M_current; }
 
-  __attribute__((__always_inline__)) _GLIBCXX_NODISCARD
+  _GLIBCXX_NODISCARD __attribute__((__always_inline__))
   _GLIBCXX_CONSTEXPR
   pointer
   operator->() const _GLIBCXX_NOEXCEPT
@@ -1123,7 +1123,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   // Random access iterator requirements
 
-  __attribute__((__always_inline__)) _GLIBCXX_NODISCARD
+  _GLIBCXX_NODISCARD __attribute__((__always_inline__))
   _GLIBCXX_CONSTEXPR
   reference
   operator[](difference_type __n) const _GLIBCXX_NOEXCEPT
@@ -1135,7 +1135,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   operator+=(difference_type __n) _GLIBCXX_NOEXCEPT
   { _M_current += __n; return *this; }
 
-  __attribute__((__always_inline__)) _GLIBCXX_NODISCARD
+  _GLIBCXX_NODISCARD __attribute__((__always_inline__))
   _GLIBCXX_CONSTEXPR
   __normal_iterator
   operator+(difference_type __n) const _GLIBCXX_NOEXCEPT
@@ -1147,13 +1147,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   operator-=(difference_type __n) _GLIBCXX_NOEXCEPT
   { _M_current -= __n; return *this; }
 
-  __attribute__((__always_inline__)) _GLIBCXX_NODISCARD
+  _GLIBCXX_NODISCARD __attribute__((__always_inline__))
   _GLIBCXX_CONSTEXPR
   __normal_iterator
   operator-(difference_type __n) const _GLIBCXX_NOEXCEPT
   { return __normal_iterator(_M_current - __n); }
 
-  __attribute__((__always_inline__)) _GLIBCXX_NODISCARD
+  _GLIBCXX_NODISCARD __attribute__((__always_inline__))
   _GLIBCXX_CONSTEXPR
   const _Iterator&
   base() const _GLIBCXX_NOEXCEPT
@@ -1209,7 +1209,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #else
// Forward iterator requirements
   template
-__attribute__((__always_inline__)) _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
+_GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR
 inline bool
 operator==(const __normal_iterator<_IteratorL, _Container>& __lhs,
   const __normal_iterator<_IteratorR, _Container>& __rhs)
@@ -1217,7 +1217,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { return __lhs.base() == __rhs.base(); }
 
   template
-__attribute__((__always_inline__)) _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
+_GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR
 inline bool
 operator==(const __normal_iterator<_Iterator, _Container>& __lhs,
   const __normal_iterator<_Iterator, _Container>& __rhs)
@@ -1225,7 +1225,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { return __lhs.base() == __rhs.base(); }
 
   template
-__attribute__((__always_inline__)) _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
+_GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR
 inline bool
 operator!=(const __normal_iterator<_IteratorL, _Container>& __lhs,
   const __normal_iterator<_IteratorR, _Container>& __rhs)
@@ -1233,7 +1233,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { return __lhs.base() != __rhs.base(); }
 
   template
-__attribute__((__always_inline__)) _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
+_GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR
 inline bool
 operator!=(const __normal_iterator<_Iterator, _Container>& __lhs,
   const __normal_iterator<_Iterator, _Container>& __rhs)
@@ -1242,7 +1242,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   // Random access iterator requirements
   template
-__attribute__((__always_inline__)) _GLIBCXX_NODISCARD _GLIBCXX_CONSTEXPR
+_GLIBCXX_NODISCARD __attribute__((__always_inline__)) _GLIBCXX_CONSTEXPR
 inline bool
 operator<(const __normal_iterator<_IteratorL, _Container>& __lhs,
  const __normal_iterator<_IteratorR, _Container>& __rhs)
@@ -1250,7 +1250,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 { return __lhs.base() < __rhs.base(); }
 
   template
-__attribute__((__always_inline__)) _GLIBCXX_

Re: [PATCH 2/7] libstdc++: Make __normal_iterator constexpr, always_inline, nodiscard

2024-10-21 Thread Jonathan Wakely
On Mon, 21 Oct 2024, 07:10 Stephan Bergmann,  wrote:

> Clang appears to be a bit picky wrt the relative order of annotation
> notations here, and complains
>


Yes, this is https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117220


> >
> /home/sberg/gcc/inst/lib/gcc/x86_64-pc-linux-gnu/15.0.0/../../../../include/c++/15.0.0/bits/stl_iter
>   ator.h:1080:42: error: an attribute list cannot appear here
> >  1080 |   __attribute__((__always_inline__)) _GLIBCXX_NODISCARD
> >   |  ^~
> >
> /home/sberg/gcc/inst/lib/gcc/x86_64-pc-linux-gnu/15.0.0/../../../../include/c++/15.0.0/x86_64-pc-linux-gnu/bits/c++config.h:173:29:
> note: expanded from macro '_GLIBCXX_NODISCARD'
> >   173 | # define _GLIBCXX_NODISCARD [[__nodiscard__]]
> >   | ^
>
> which would be trivially solved by something like
>
> > diff --git a/libstdc++-v3/include/bits/stl_iterator.h
> b/libstdc++-v3/include/bits/stl_iterator.h
> > index 26c5eab4b4e..49d03188fda 100644
> > --- a/libstdc++-v3/include/bits/stl_iterator.h
> > +++ b/libstdc++-v3/include/bits/stl_iterator.h
> > @@ -1077,13 +1077,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >
> >// Forward iterator requirements
> >
> > -  __attribute__((__always_inline__)) _GLIBCXX_NODISCARD
> > +  _GLIBCXX_NODISCARD __attribute__((__always_inline__))
> >_GLIBCXX_CONSTEXPR
> >reference
> >operator*() const _GLIBCXX_NOEXCEPT
> >{ return *_M_current; }
> >
> > -  __attribute__((__always_inline__)) _GLIBCXX_NODISCARD
> > +  _GLIBCXX_NODISCARD __attribute__((__always_inline__))
> >_GLIBCXX_CONSTEXPR
> >pointer
> >operator->() const _GLIBCXX_NOEXCEPT
> > @@ -1123,7 +1123,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >
> >// Random access iterator requirements
> >
> > -  __attribute__((__always_inline__)) _GLIBCXX_NODISCARD
> > +  _GLIBCXX_NODISCARD __attribute__((__always_inline__))
> >_GLIBCXX_CONSTEXPR
> >reference
> >operator[](difference_type __n) const _GLIBCXX_NOEXCEPT
> > @@ -1135,7 +1135,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >operator+=(difference_type __n) _GLIBCXX_NOEXCEPT
> >{ _M_current += __n; return *this; }
> >
> > -  __attribute__((__always_inline__)) _GLIBCXX_NODISCARD
> > +  _GLIBCXX_NODISCARD __attribute__((__always_inline__))
> >_GLIBCXX_CONSTEXPR
> >__normal_iterator
> >operator+(difference_type __n) const _GLIBCXX_NOEXCEPT
> > @@ -1147,13 +1147,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >operator-=(difference_type __n) _GLIBCXX_NOEXCEPT
> >{ _M_current -= __n; return *this; }
> >
> > -  __attribute__((__always_inline__)) _GLIBCXX_NODISCARD
> > +  _GLIBCXX_NODISCARD __attribute__((__always_inline__))
> >_GLIBCXX_CONSTEXPR
> >__normal_iterator
> >operator-(difference_type __n) const _GLIBCXX_NOEXCEPT
> >{ return __normal_iterator(_M_current - __n); }
> >
> > -  __attribute__((__always_inline__)) _GLIBCXX_NODISCARD
> > +  _GLIBCXX_NODISCARD __attribute__((__always_inline__))
> >_GLIBCXX_CONSTEXPR
> >const _Iterator&
> >base() const _GLIBCXX_NOEXCEPT
>
>


[PATCH] libstdc++: Avoid using std::__to_address with iterators

2024-10-18 Thread Jonathan Wakely
Do others agree with my reasoning below?

The changes to implement the rule "use std::__niter_base before C++20
and use std::to_address after C++20" were easier than I expected. There
weren't many places that were doing it "wrong" and needed to change.

Tested x86_64-linux.

-- >8 --

In r12-3935-g82626be2d633a9 I added the partial specialization
std::pointer_traits<__normal_iterator> so that __to_address
would work with __normal_iterator objects. Soon after that, François
replaced it in r12-6004-g807ad4bc854cae with an overload of __to_address
that served the same purpose, but was less complicated and less wrong.

I now think that both commits were mistakes, and that instead of adding
hacks to make __normal_iterator work with __to_address, we should not be
using __to_address with iterators at all before C++20.

The pre-C++20 std::__to_address function should only be used with
pointer-like types, specifically allocator_traits::pointer types.
Those pointer-like types are guaranteed to be contiguous iterators, so
that getting a raw memory address from them is OK.

For arbitrary iterators, even random access iterators, we don't know
that it's safe to lower the iterator to a pointer e.g. for std::deque
iterators it's not, because (it + n) == (std::to_address(it) + n) only
holds within the same block of the deque's storage.

For C++20, std::to_address does work correctly for contiguous iterators,
including __normal_iterator, and __to_address just calls std::to_address
so also works. But we have to be sure we have an iterator that satisfies
the std::contiguous_iterator concept for it to be safe, and we can't
check that before C++20.

So for pre-C++20 code the correct way to handle iterators that might be
pointers or might be __normal_iterator is to call __niter_base, and if
necessary use is_pointer to check whether __niter_base returned a real
pointer.

We currently have some uses of std::__to_address with iterators where
we've checked that they're either pointers, or __normal_iterator
wrappers around pointers, or satisfy std::contiguous_iterator. But this
seems a little fragile, and it would be better to just use
std::__niter_base for the pointers and __normal_iterator cases, and use
C++20 std::to_address when the C++20 std::contiguous_iterator concept is
satisfied. This patch does that.

libstdc++-v3/ChangeLog:

* include/bits/basic_string.h (basic_string::assign): Replace
use of __to_address with __niter_base or std::to_address as
appropriate.
* include/bits/ptr_traits.h (__to_address): Add comment.
* include/bits/shared_ptr_base.h (__shared_ptr): Qualify calls
to __to_address.
* include/bits/stl_algo.h (find): Replace use of __to_address
with __niter_base or std::to_address as appropriate. Only use
either of them when the range is not empty.
* include/bits/stl_iterator.h (__to_address): Remove overload
for __normal_iterator.
* include/debug/safe_iterator.h (__to_address): Remove overload
for _Safe_iterator.
* include/std/ranges (views::counted): Replace use of
__to_address with std::to_address.
* testsuite/24_iterators/normal_iterator/to_address.cc: Removed.
---
 libstdc++-v3/include/bits/basic_string.h  | 19 +--
 libstdc++-v3/include/bits/ptr_traits.h|  4 
 libstdc++-v3/include/bits/shared_ptr_base.h   |  4 ++--
 libstdc++-v3/include/bits/stl_algo.h  | 16 +++-
 libstdc++-v3/include/bits/stl_iterator.h  | 12 
 libstdc++-v3/include/debug/safe_iterator.h| 17 -
 libstdc++-v3/include/std/ranges   |  2 +-
 .../normal_iterator/to_address.cc | 19 ---
 8 files changed, 31 insertions(+), 62 deletions(-)
 delete mode 100644 
libstdc++-v3/testsuite/24_iterators/normal_iterator/to_address.cc

diff --git a/libstdc++-v3/include/bits/basic_string.h 
b/libstdc++-v3/include/bits/basic_string.h
index e9b17ea48b5..16e356e0678 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -1732,18 +1732,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
basic_string&
assign(_InputIterator __first, _InputIterator __last)
{
+ using _IterTraits = iterator_traits<_InputIterator>;
+ if constexpr (is_pointer::value
+ && is_same::value)
+   {
+ __glibcxx_requires_valid_range(__first, __last);
+ return _M_replace(size_type(0), size(),
+   std::__niter_base(__first), __last - __first);
+   }
 #if __cplusplus >= 202002L
- if constexpr (contiguous_iterator<_InputIterator>
- && is_same_v, _CharT>)
-#else
- if constexpr (__is_one_of<_InputIterator, const_iterator, iterator,
-   const _CharT*, _CharT*>::value)
-#endif
+ else if constexpr (contiguous_iterat

Re: [PATCH 1/7] libstdc++: Refactor std::uninitialized_{copy, fill, fill_n} algos [PR68350]

2024-10-18 Thread Jonathan Wakely
On Fri, 18 Oct 2024 at 15:24, Patrick Palka  wrote:
>
> On Fri, 18 Oct 2024, Jonathan Wakely wrote:
>
> > On 16/10/24 21:39 -0400, Patrick Palka wrote:
> > > On Tue, 15 Oct 2024, Jonathan Wakely wrote:
> > > > +#if __cplusplus < 201103L
> > > > +
> > > > +  // True if we can unwrap _Iter to get a pointer by using
> > > > std::__niter_base.
> > > > +  template
> > > > +struct __unwrappable_niter
> > > > +{
> > > > +  template struct __is_ptr { enum { __value = 0 }; };
> > > > +  template struct __is_ptr<_Tp*> { enum { __value = 1
> > > > }; };
> > > > +
> > > > +  typedef __decltype(std::__niter_base(*(_Iter*)0)) _Base;
> > > > +
> > > > +  enum { __value = __is_ptr<_Base>::__value };
> > > > +};
> > >
> > > It might be slightly cheaper to define this without the nested class
> > > template as:
> > >
> > >  template > > __decltype(std::__niter_base(*(_Iter*)0))>
> > >  struct __unwrappable_niter
> > >  { enum { __value = false }; };
> > >
> > >  template
> > >  struct __unwrappable_niter<_Iter, _Tp*>
> > >  { enum { __value = true }; };
>
> One minor nit, we might as well use 'value' since it's a reserved name
> even in C++98?

Huh, I was under the impression it wasn't, but indeed we have
binder1st::value and binder2nd::value!

Why have we been using __value throughout cpp_type_traits.h then!?!

I have indeed pushed it now, but could tweak that, as I'm still
working in that file.



[PATCH] libstdc++: Improve 26_numerics/headers/cmath/types_std_c++0x_neg.cc

2024-10-18 Thread Jonathan Wakely
This test checks that the special functions in  are not declared
prior to C++17. But we can remove the target selector and allow it to be
tested for C++17 and later, and add target selectors to the individual
dg-error directives instead.

Also rename the test to match what it actually tests.

libstdc++-v3/ChangeLog:

* testsuite/26_numerics/headers/cmath/types_std_c++0x_neg.cc:
Move to ...
* testsuite/26_numerics/headers/cmath/specfun_c++17.cc: here and
adjust test to be valid for all -std dialects.
---

Tested x86_64-linux.

 ...ypes_std_c++0x_neg.cc => specfun_c++17.cc} | 47 ++-
 1 file changed, 24 insertions(+), 23 deletions(-)
 rename 
libstdc++-v3/testsuite/26_numerics/headers/cmath/{types_std_c++0x_neg.cc => 
specfun_c++17.cc} (57%)

diff --git 
a/libstdc++-v3/testsuite/26_numerics/headers/cmath/types_std_c++0x_neg.cc 
b/libstdc++-v3/testsuite/26_numerics/headers/cmath/specfun_c++17.cc
similarity index 57%
rename from 
libstdc++-v3/testsuite/26_numerics/headers/cmath/types_std_c++0x_neg.cc
rename to libstdc++-v3/testsuite/26_numerics/headers/cmath/specfun_c++17.cc
index 977f800a4b0..efb60ea1fbb 100644
--- a/libstdc++-v3/testsuite/26_numerics/headers/cmath/types_std_c++0x_neg.cc
+++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/specfun_c++17.cc
@@ -1,4 +1,4 @@
-// { dg-do compile { target { ! c++17 } } }
+// { dg-do compile }
 
 // Copyright (C) 2007-2024 Free Software Foundation, Inc.
 //
@@ -21,28 +21,29 @@
 
 namespace gnu
 {
-  // C++11 changes from TR1.
-  using std::assoc_laguerre;   // { dg-error "has not been declared" }
-  using std::assoc_legendre;   // { dg-error "has not been declared" }
-  using std::beta; // { dg-error "has not been declared" }
-  using std::comp_ellint_1;// { dg-error "has not been declared" }
-  using std::comp_ellint_2;// { dg-error "has not been declared" }
-  using std::comp_ellint_3;// { dg-error "has not been declared" }
+  // C++17 additions from TR1.
+  using std::assoc_laguerre;   // { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::assoc_legendre;   // { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::beta; // { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::comp_ellint_1;// { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::comp_ellint_2;// { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::comp_ellint_3;// { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::cyl_bessel_i; // { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::cyl_bessel_j; // { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::cyl_bessel_k; // { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::cyl_neumann;  // { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::ellint_1; // { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::ellint_2; // { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::ellint_3; // { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::expint;   // { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::hermite;  // { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::laguerre; // { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::legendre; // { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::riemann_zeta; // { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::sph_bessel;   // { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::sph_legendre; // { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  using std::sph_neumann;  // { dg-error "has not been declared" "" { 
target { ! c++17 } } }
+  // These two were in TR1 but not added to C++17.
   using std::conf_hyperg;  // { dg-error "has not been declared" }
-  using std::cyl_bessel_i; // { dg-error "has not been declared" }
-  using std::cyl_bessel_j; // { dg-error "has not been declared" }
-  using std::cyl_bessel_k; // { dg-error "has not been declared" }
-  using std::cyl_neumann;  // { dg-error "has not been declared" }
-  using std::ellint_1; // { dg-error "has not been declared" }
-  using std::ellint_2; // { dg-error "has not been declared" }
-  using std::ellint_3; // { dg-error "has not been declared" }
-  using std::expint;   // { dg-error "has not been declared" }
-  using std::hermite;  // { dg-error "has not been declared" }
   using std::hyperg;   // { dg-error "has not been declared" }
-  using std::laguerre; // { dg-error "has not been declared" }

[PATCH] libstdc++: Simplify C++98 std::vector::_M_data_ptr overload set

2024-10-18 Thread Jonathan Wakely
We don't need separate overloads for returning a const or non-const
pointer. We can make the member function const and return a non-const
pointer, and let `vector::data() const` convert it to const as needed.

libstdc++-v3/ChangeLog:

* include/bits/stl_vector.h (vector::_M_data_ptr): Remove
non-const overloads. Always return non-const pointer.
---

Tested x86_64-linux.

 libstdc++-v3/include/bits/stl_vector.h | 12 +---
 1 file changed, 1 insertion(+), 11 deletions(-)

diff --git a/libstdc++-v3/include/bits/stl_vector.h 
b/libstdc++-v3/include/bits/stl_vector.h
index e284536ad31..8982ca2b9ee 100644
--- a/libstdc++-v3/include/bits/stl_vector.h
+++ b/libstdc++-v3/include/bits/stl_vector.h
@@ -2034,20 +2034,10 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
_M_data_ptr(_Ptr __ptr) const
{ return empty() ? nullptr : std::__to_address(__ptr); }
 #else
-  template
-   _Up*
-   _M_data_ptr(_Up* __ptr) _GLIBCXX_NOEXCEPT
-   { return __ptr; }
-
   template
value_type*
-   _M_data_ptr(_Ptr __ptr)
-   { return empty() ? (value_type*)0 : __ptr.operator->(); }
-
-  template
-   const value_type*
_M_data_ptr(_Ptr __ptr) const
-   { return empty() ? (const value_type*)0 : __ptr.operator->(); }
+   { return empty() ? (value_type*)0 : __ptr.operator->(); }
 #endif
 };
 
-- 
2.46.2



Re: [PATCH 1/7] libstdc++: Refactor std::uninitialized_{copy, fill, fill_n} algos [PR68350]

2024-10-18 Thread Jonathan Wakely

On 18/10/24 10:41 +0100, Jonathan Wakely wrote:

On 16/10/24 21:39 -0400, Patrick Palka wrote:

On Tue, 15 Oct 2024, Jonathan Wakely wrote:

+#if __cplusplus < 201103L
+
+  // True if we can unwrap _Iter to get a pointer by using std::__niter_base.
+  template
+struct __unwrappable_niter
+{
+  template struct __is_ptr { enum { __value = 0 }; };
+  template struct __is_ptr<_Tp*> { enum { __value = 1 }; };
+
+  typedef __decltype(std::__niter_base(*(_Iter*)0)) _Base;
+
+  enum { __value = __is_ptr<_Base>::__value };
+};


It might be slightly cheaper to define this without the nested class
template as:

template
struct __unwrappable_niter
{ enum { __value = false }; };

template
struct __unwrappable_niter<_Iter, _Tp*>
{ enum { __value = true }; };


Nice. I think after spending a while failing to make any C++98
metaprogramming work for __memcpyable in cpp_type_traits.h I was not
in the mood for fighting C++98 any more :-) But this works well.


+
+  // Use template specialization for C++98 when 'if constexpr' can't be used.
+  template
struct __uninitialized_copy
{
  template
@@ -186,53 +172,150 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  template<>
struct __uninitialized_copy
{
+  // Overload for generic iterators.
  template
static _ForwardIterator
__uninit_copy(_InputIterator __first, _InputIterator __last,
  _ForwardIterator __result)
-{ return std::copy(__first, __last, __result); }
-};
+   {
+ if (__unwrappable_niter<_InputIterator>::__value
+   && __unwrappable_niter<_ForwardIterator>::__value)
+   {
+ __uninit_copy(std::__niter_base(__first),
+   std::__niter_base(__last),
+   std::__niter_base(__result));
+ std::advance(__result, std::distance(__first, __last));
+ return __result;
+   }
+ else
+   return std::__do_uninit_copy(__first, __last, __result);
+   }

+  // Overload for pointers.
+  template
+   static _Up*
+   __uninit_copy(_Tp* __first, _Tp* __last, _Up* __result)
+   {
+ // Ensure that we don't successfully memcpy in cases that should be
+ // ill-formed because is_constructible<_Up, _Tp&> is false.
+ typedef __typeof__(static_cast<_Up>(*__first)) __check
+   __attribute__((__unused__));
+
+ if (const ptrdiff_t __n = __last - __first)


Do we have to worry about the __n == 1 case here like in the C++11 code path?


Actually I think we don't need to worry about it in either case.

C++20 had a note in [specialized.algorithms.general]/3 that said:

 [Note 1: When invoked on ranges of potentially-overlapping subobjects
 ([intro.object]), the algorithms specified in [specialized.algorithms]
 result in undefined behavior. — end note]

The reason is that the uninitialized algos create new objects at the
specified storage locations, and creating new objects reuses storage,
which ends the lifetime of any other objects in that storage. That
includes any objects that were in tail padding within that storage.

See Casey's Feb 2023 comment at
https://github.com/cplusplus/draft/issues/6143

That note was removed for C++23 (which is unfortunate IMHO), but the
algos still reuse storage by creating new objects, and so still end
the lifetime of potentially-overlapping subobjects within that
storage.

For std::copy there are no new objects created, and the effects are
specified in terms of assignment, which does not reuse storage. A
compiler-generated trivial copy assignment operator is careful to not
overwrite tail padding, so we can't use memmove if it would produce
different effects.

tl;dr I think I can remove the __n == 1 handling from the C++11 paths.



I actually had `if (__n > 0)` in an earlier version, and then looked
at it before posting the patch and "fixed" it to check __n > 1 and
then handle the __n == 1 case. But that's not nexcessary here, I'd
just been spending too much time looking at std::copy and got
confused.




Re: [PATCH 1/7] libstdc++: Refactor std::uninitialized_{copy, fill, fill_n} algos [PR68350]

2024-10-18 Thread Jonathan Wakely

On 16/10/24 21:39 -0400, Patrick Palka wrote:

On Tue, 15 Oct 2024, Jonathan Wakely wrote:

+#if __cplusplus < 201103L
+
+  // True if we can unwrap _Iter to get a pointer by using std::__niter_base.
+  template
+struct __unwrappable_niter
+{
+  template struct __is_ptr { enum { __value = 0 }; };
+  template struct __is_ptr<_Tp*> { enum { __value = 1 }; };
+
+  typedef __decltype(std::__niter_base(*(_Iter*)0)) _Base;
+
+  enum { __value = __is_ptr<_Base>::__value };
+};


It might be slightly cheaper to define this without the nested class
template as:

 template
 struct __unwrappable_niter
 { enum { __value = false }; };

 template
 struct __unwrappable_niter<_Iter, _Tp*>
 { enum { __value = true }; };


Nice. I think after spending a while failing to make any C++98
metaprogramming work for __memcpyable in cpp_type_traits.h I was not
in the mood for fighting C++98 any more :-) But this works well.


+
+  // Use template specialization for C++98 when 'if constexpr' can't be used.
+  template
 struct __uninitialized_copy
 {
   template
@@ -186,53 +172,150 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<>
 struct __uninitialized_copy
 {
+  // Overload for generic iterators.
   template
 static _ForwardIterator
 __uninit_copy(_InputIterator __first, _InputIterator __last,
  _ForwardIterator __result)
-{ return std::copy(__first, __last, __result); }
-};
+   {
+ if (__unwrappable_niter<_InputIterator>::__value
+   && __unwrappable_niter<_ForwardIterator>::__value)
+   {
+ __uninit_copy(std::__niter_base(__first),
+   std::__niter_base(__last),
+   std::__niter_base(__result));
+ std::advance(__result, std::distance(__first, __last));
+ return __result;
+   }
+ else
+   return std::__do_uninit_copy(__first, __last, __result);
+   }

+  // Overload for pointers.
+  template
+   static _Up*
+   __uninit_copy(_Tp* __first, _Tp* __last, _Up* __result)
+   {
+ // Ensure that we don't successfully memcpy in cases that should be
+ // ill-formed because is_constructible<_Up, _Tp&> is false.
+ typedef __typeof__(static_cast<_Up>(*__first)) __check
+   __attribute__((__unused__));
+
+ if (const ptrdiff_t __n = __last - __first)


Do we have to worry about the __n == 1 case here like in the C++11 code path?


Actually I think we don't need to worry about it in either case.

C++20 had a note in [specialized.algorithms.general]/3 that said:

  [Note 1: When invoked on ranges of potentially-overlapping subobjects
  ([intro.object]), the algorithms specified in [specialized.algorithms]
  result in undefined behavior. — end note]

The reason is that the uninitialized algos create new objects at the
specified storage locations, and creating new objects reuses storage,
which ends the lifetime of any other objects in that storage. That
includes any objects that were in tail padding within that storage.

See Casey's Feb 2023 comment at
https://github.com/cplusplus/draft/issues/6143

That note was removed for C++23 (which is unfortunate IMHO), but the
algos still reuse storage by creating new objects, and so still end
the lifetime of potentially-overlapping subobjects within that
storage.

For std::copy there are no new objects created, and the effects are
specified in terms of assignment, which does not reuse storage. A
compiler-generated trivial copy assignment operator is careful to not
overwrite tail padding, so we can't use memmove if it would produce
different effects.

tl;dr I think I can remove the __n == 1 handling from the C++11 paths.


+   {
+ __builtin_memcpy(__result, __first, __n * sizeof(_Tp));
+ __result += __n;
+   }
+ return __result;
+   }
+};
+#endif
   /// @endcond

+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wc++17-extensions"
   /**
*  @brief Copies the range [first,last) into result.
*  @param  __first  An input iterator.
*  @param  __last   An input iterator.
-   *  @param  __result An output iterator.
-   *  @return   __result + (__first - __last)
+   *  @param  __result A forward iterator.
+   *  @return   __result + (__last - __first)
*
-   *  Like copy(), but does not require an initialized output range.
+   *  Like std::copy, but does not require an initialized output range.
   */
   template
 inline _ForwardIterator
 uninitialized_copy(_InputIterator __first, _InputIterator __last,
   _ForwardIterator __result)
 {
+  // We can use memcpy to copy the ranges under these conditions:
+  //
+  // _ForwardIterator and _InputIterator are both contiguous iterators

Re: [PATCH] Add fancy pointer support in std::map/set

2024-10-17 Thread Jonathan Wakely
On Thu, 17 Oct 2024 at 21:39, Jonathan Wakely  wrote:

>
>
> On Thu, 17 Oct 2024 at 20:52, François Dumont 
> wrote:
>
>> Here is an updated version that compiles, I think, all your feedbacks.
>> It's much cleaner indeed.
>>
>
> Thanks, I'll take a look tomorrow.
>
>
>> It's also tested in C++98/17/23.
>>
>> I'm surprised that we do not need to consider potential
>> allocator::const_pointer.
>>
> Do you mean consider the case where Alloc::const_pointer is not the same
> type as rebinding 'pointer' to a const element type?
>
> We don't need to consider that because we never get a 'const_pointer' from
> the allocator, and we never need to pass a 'const_pointer' to the
> allocator. The allocator's 'allocate' and 'deallocate' members both work
> with the 'pointer' type, so we only need to use that type when interacting
> with the allocator. For all the other uses, such as _Const_Node_ptr, what
> we need is a pointer-to-const that's compatible with the allocator's
> pointer type. It doesn't actually matter if it's the same type as
> allocator_traits::const_pointer, because we don't need
>

Sorry, I sent the email before finishing that thought!

... we don't need to pass a const_pointer to anything, we only need it for
the container's own purposes.

But thinking about it some more, do we even need a const-pointer for the
container?  Currently the const_iterator stores a const-pointer, and some
members like _M_root() and _M_leftmost() return a const-pointer. But they
don't need to. The nodes are all pointed to by a non-const _Base_ptr, none
of the storage managed by the container is const. We could just use the
non-const pointers everywhere, which would make things much simpler!

The const_iterator stores a const_pointer, and returns a const-pointer from
operator->(), so maybe _Rb_tree_const_piterator should take the allocator's
const_pointer as its template argument, instead of the non-const ValPtr. So
the trait would take two pointer types, but the const one would only be
used for the const iterator:

template
  struct _Rb_tree_node_traits
  {
using _Node_base = _Rb_tree_pnode_base<_ValPtr>;
using _Node_type = _Rb_tree_pnode<_ValPtr>;
using _Header_t = _Rb_tree_pheader<_Node_base>;
using _Iterator_t = _Rb_tree_piterator<_ValPtr>;
using _Const_iterator_t = _Rb_tree_const_piterator<_CValPtr>;
  };

Would that work? I can experiment with that if you like.



>
>
>> Is there a plan to deprecate it ?
>>
>
> No, although I think that would be possible. Nothing in the allocator
> requirements ever uses that type or cares what it is, as long as it's
> convertible to  'const_void_pointer', and 'pointer' is convertible to
> 'const_pointer'.
>
>
>> And if not, should not alloc traits const_pointer be per default a rebind
>> of pointer for const element_type like in the __add_const_to_ptr you made
>> me add ? I can try to work on a patch for that if needed.
>>
>
> No, allocator_traits is defined correctly as the standard requires. If an
> allocator A defines a 'A::const_pointer' typedef, then that is used. If
> not, then 'allocator_traits::const_pointer' defaults to rebinding the
> non-const 'allocator_traits::pointer' type.
>
>
>


Re: [PATCH] Add fancy pointer support in std::map/set

2024-10-17 Thread Jonathan Wakely
On Thu, 17 Oct 2024 at 20:52, François Dumont  wrote:

> Here is an updated version that compiles, I think, all your feedbacks.
> It's much cleaner indeed.
>

Thanks, I'll take a look tomorrow.


> It's also tested in C++98/17/23.
>
> I'm surprised that we do not need to consider potential
> allocator::const_pointer.
>
Do you mean consider the case where Alloc::const_pointer is not the same
type as rebinding 'pointer' to a const element type?

We don't need to consider that because we never get a 'const_pointer' from
the allocator, and we never need to pass a 'const_pointer' to the
allocator. The allocator's 'allocate' and 'deallocate' members both work
with the 'pointer' type, so we only need to use that type when interacting
with the allocator. For all the other uses, such as _Const_Node_ptr, what
we need is a pointer-to-const that's compatible with the allocator's
pointer type. It doesn't actually matter if it's the same type as
allocator_traits::const_pointer, because we don't need


> Is there a plan to deprecate it ?
>

No, although I think that would be possible. Nothing in the allocator
requirements ever uses that type or cares what it is, as long as it's
convertible to  'const_void_pointer', and 'pointer' is convertible to
'const_pointer'.


> And if not, should not alloc traits const_pointer be per default a rebind
> of pointer for const element_type like in the __add_const_to_ptr you made
> me add ? I can try to work on a patch for that if needed.
>

No, allocator_traits is defined correctly as the standard requires. If an
allocator A defines a 'A::const_pointer' typedef, then that is used. If
not, then 'allocator_traits::const_pointer' defaults to rebinding the
non-const 'allocator_traits::pointer' type.


[PATCH] libstdc++: Move std::__niter_base and std::__niter_wrap to stl_iterator.h

2024-10-17 Thread Jonathan Wakely
I've split this out of "Refactor std::uninitialized_{copy, fill, fill_n}"
because this part can be done separately. Call it [PATCH -1/7] if you
like :-)

This fixes the ordering problem that Patrick noticed in [PATCH 1/7], and
adds a test for it. It also updates the comments as was previously done
in [PATCH 2/7], which Patrick noted could have been done when moving the
functions into stl_iterator.h.

Note that the __niter_base overloads for reverse_iterator and
move_iterator call __niter_base unqualified, which means that in
contrast to all other uses of __niter_base they *do* use ADL to find the
next __niter_base to call. I think that's necessary so that it works for
both reverse_iterator> and the inverse order,
move_iterator>. I haven't changed that here, they
still use unqualified calls.

As a further change in this area, I think it would be possible (and
maybe nice) to remove __miter_base and replace the uses of it in
std::move_backward(I,I,O) and std::move(I,I,O). That's left for another
day.

Tested x86_64-linux.

-- >8 --

Move the functions for unwrapping and rewrapping __normal_iterator
objects to the same file as the definition of __normal_iterator itself.

This will allow a later commit to make use of std::__niter_base in other
headers without having to include all of .

libstdc++-v3/ChangeLog:

* include/bits/stl_algobase.h (__niter_base, __niter_wrap): Move
to ...
* include/bits/stl_iterator.h: ... here.
(__niter_base, __miter_base): Move all overloads to the end of
the header.
* testsuite/24_iterators/normal_iterator/wrapping.cc: New test.
---
 libstdc++-v3/include/bits/stl_algobase.h  |  45 --
 libstdc++-v3/include/bits/stl_iterator.h  | 138 +-
 .../24_iterators/normal_iterator/wrapping.cc  |  29 
 3 files changed, 132 insertions(+), 80 deletions(-)
 create mode 100644 
libstdc++-v3/testsuite/24_iterators/normal_iterator/wrapping.cc

diff --git a/libstdc++-v3/include/bits/stl_algobase.h 
b/libstdc++-v3/include/bits/stl_algobase.h
index 384e5fdcdc9..751b7ad119b 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -308,51 +308,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   return __a;
 }
 
-  // Fallback implementation of the function in bits/stl_iterator.h used to
-  // remove the __normal_iterator wrapper. See copy, fill, ...
-  template
-_GLIBCXX20_CONSTEXPR
-inline _Iterator
-__niter_base(_Iterator __it)
-_GLIBCXX_NOEXCEPT_IF(std::is_nothrow_copy_constructible<_Iterator>::value)
-{ return __it; }
-
-#if __cplusplus < 201103L
-  template
-_Ite
-__niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq,
-std::random_access_iterator_tag>&);
-
- template
-_Ite
-__niter_base(const ::__gnu_debug::_Safe_iterator<
-::__gnu_cxx::__normal_iterator<_Ite, _Cont>, _Seq,
-std::random_access_iterator_tag>&);
-#else
-  template
-_GLIBCXX20_CONSTEXPR
-decltype(std::__niter_base(std::declval<_Ite>()))
-__niter_base(const ::__gnu_debug::_Safe_iterator<_Ite, _Seq,
-std::random_access_iterator_tag>&)
-noexcept(std::is_nothrow_copy_constructible<_Ite>::value);
-#endif
-
-  // Reverse the __niter_base transformation to get a
-  // __normal_iterator back again (this assumes that __normal_iterator
-  // is only used to wrap random access iterators, like pointers).
-  template
-_GLIBCXX20_CONSTEXPR
-inline _From
-__niter_wrap(_From __from, _To __res)
-{ return __from + (std::__niter_base(__res) - std::__niter_base(__from)); }
-
-  // No need to wrap, iterator already has the right type.
-  template
-_GLIBCXX20_CONSTEXPR
-inline _Iterator
-__niter_wrap(const _Iterator&, _Iterator __res)
-{ return __res; }
-
   // All of these auxiliary structs serve two purposes.  (1) Replace
   // calls to copy with memmove whenever possible.  (Memmove, not memcpy,
   // because the input and output ranges are permitted to overlap.)
diff --git a/libstdc++-v3/include/bits/stl_iterator.h 
b/libstdc++-v3/include/bits/stl_iterator.h
index 28a600c81cb..be3fa6f7a34 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -654,24 +654,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #  endif // C++20
 # endif // __glibcxx_make_reverse_iterator
 
-  template
-_GLIBCXX20_CONSTEXPR
-auto
-__niter_base(reverse_iterator<_Iterator> __it)
--> decltype(__make_reverse_iterator(__niter_base(__it.base(
-{ return __make_reverse_iterator(__niter_base(__it.base())); }
-
   template
 struct __is_move_iterator >
   : __is_move_iterator<_Iterator>
 { };
-
-  template
-_GLIBCXX20_CONSTEXPR
-auto
-__miter_base(reverse_iterator<_Iterator> __it)
--> decltype(__make_reverse_iterator(__miter_base(__it.base(
-{ return __make_reverse_iterator(__miter_base(__it.base())); }
 #endif // C++11

Re: [PATCH 1/7] libstdc++: Refactor std::uninitialized_{copy, fill, fill_n} algos [PR68350]

2024-10-17 Thread Jonathan Wakely
On Thu, 17 Oct 2024 at 11:12, Jonathan Wakely  wrote:
>
> On Thu, 17 Oct 2024 at 02:39, Patrick Palka  wrote:
> >
> > On Tue, 15 Oct 2024, Jonathan Wakely wrote:
> >
> > > This is v2 of
> > > https://gcc.gnu.org/pipermail/gcc-patches/2024-October/665246.html
> > > fixing some thinkos in uninitialized_{fill,fill_n}. We don't need to
> > > worry about overwriting tail-padding in those algos, because we only use
> > > memset for 1-byte integer types. So they have no tail padding that can
> > > be reused anyway! So this changes __n > 1 to __n > 0 in a few places
> > > (which fixes the problem that it was not actually filling anything for
> > > the n==1 cases).
> > >
> > > Also simplify std::__to_address(__result++) to just __result++ because
> > > we already have a pointer, and use std::to_address(result++) for a C++20
> > > std::contiguous_iterator case, instead of addressof(*result++).
> > >
> > > Tested x86_64-linux.
> > >
> > > -- >8 --
> > >
> > > This refactors the std::uninitialized_copy, std::uninitialized_fill and
> > > std::uninitialized_fill_n algorithms to directly perform memcpy/memset
> > > optimizations instead of dispatching to std::copy/std::fill/std::fill_n.
> > >
> > > The reasons for this are:
> > >
> > > - Use 'if constexpr' to simplify and optimize compilation throughput, so
> > >   dispatching to specialized class templates is only needed for C++98
> > >   mode.
> > > - Relax the conditions for using memcpy/memset, because the C++20 rules
> > >   on implicit-lifetime types mean that we can rely on memcpy to begin
> > >   lifetimes of trivially copyable types.  We don't need to require
> > >   trivially default constructible, so don't need to limit the
> > >   optimization to trivial types. See PR 68350 for more details.
> > > - The conditions on non-overlapping ranges are stronger for
> > >   std::uninitialized_copy than for std::copy so we can use memcpy instead
> > >   of memmove, which might be a minor optimization.
> > > - Avoid including  in .
> > >   It only needs some iterator utilities from that file now, which belong
> > >   in  anyway, so this moves them there.
> > >
> > > Several tests need changes to the diagnostics matched by dg-error
> > > because we no longer use the __constructible() function that had a
> > > static assert in. Now we just get straightforward errors for attempting
> > > to use a deleted constructor.
> > >
> > > Two tests needed more signficant changes to the actual expected results
> > > of executing the tests, because they were checking for old behaviour
> > > which was incorrect according to the standard.
> > > 20_util/specialized_algorithms/uninitialized_copy/64476.cc was expecting
> > > std::copy to be used for a call to std::uninitialized_copy involving two
> > > trivially copyable types. That was incorrect behaviour, because a
> > > non-trivial constructor should have been used, but using std::copy used
> > > trivial default initialization followed by assignment.
> > > 20_util/specialized_algorithms/uninitialized_fill_n/sizes.cc was testing
> > > the behaviour with a non-integral Size passed to uninitialized_fill_n,
> > > but I wrote the test looking at the requirements of uninitialized_copy_n
> > > which are not the same as uninitialized_fill_n. The former uses --n and
> > > tests n > 0, but the latter just tests n-- (which will never be false
> > > for a floating-point value with a fractional part).
> > >
> > > libstdc++-v3/ChangeLog:
> > >
> > >   PR libstdc++/68350
> > >   PR libstdc++/93059
> > >   * include/bits/stl_algobase.h (__niter_base, __niter_wrap): Move
> > >   to ...
> > >   * include/bits/stl_iterator.h: ... here.
> > >   * include/bits/stl_uninitialized.h (__check_constructible)
> > >   (_GLIBCXX_USE_ASSIGN_FOR_INIT): Remove.
> > >   [C++98] (__unwrappable_niter): New trait.
> > >   (__uninitialized_copy): Replace use of std::copy.
> > >   (uninitialized_copy): Fix Doxygen comments. Open-code memcpy
> > >   optimization for C++11 and later.
> > >   (__uninitialized_fill): Replace use of std::fill.
> > >   (uninitialized_fill): Fix Doxygen comments. Open-code memset
> > >   optimization for C++11 and later.
> > >   (__uninitialized_fill_n): Replace us

Re: [PATCH 1/7] libstdc++: Refactor std::uninitialized_{copy, fill, fill_n} algos [PR68350]

2024-10-17 Thread Jonathan Wakely
On Thu, 17 Oct 2024 at 02:39, Patrick Palka  wrote:
>
> On Tue, 15 Oct 2024, Jonathan Wakely wrote:
>
> > This is v2 of
> > https://gcc.gnu.org/pipermail/gcc-patches/2024-October/665246.html
> > fixing some thinkos in uninitialized_{fill,fill_n}. We don't need to
> > worry about overwriting tail-padding in those algos, because we only use
> > memset for 1-byte integer types. So they have no tail padding that can
> > be reused anyway! So this changes __n > 1 to __n > 0 in a few places
> > (which fixes the problem that it was not actually filling anything for
> > the n==1 cases).
> >
> > Also simplify std::__to_address(__result++) to just __result++ because
> > we already have a pointer, and use std::to_address(result++) for a C++20
> > std::contiguous_iterator case, instead of addressof(*result++).
> >
> > Tested x86_64-linux.
> >
> > -- >8 --
> >
> > This refactors the std::uninitialized_copy, std::uninitialized_fill and
> > std::uninitialized_fill_n algorithms to directly perform memcpy/memset
> > optimizations instead of dispatching to std::copy/std::fill/std::fill_n.
> >
> > The reasons for this are:
> >
> > - Use 'if constexpr' to simplify and optimize compilation throughput, so
> >   dispatching to specialized class templates is only needed for C++98
> >   mode.
> > - Relax the conditions for using memcpy/memset, because the C++20 rules
> >   on implicit-lifetime types mean that we can rely on memcpy to begin
> >   lifetimes of trivially copyable types.  We don't need to require
> >   trivially default constructible, so don't need to limit the
> >   optimization to trivial types. See PR 68350 for more details.
> > - The conditions on non-overlapping ranges are stronger for
> >   std::uninitialized_copy than for std::copy so we can use memcpy instead
> >   of memmove, which might be a minor optimization.
> > - Avoid including  in .
> >   It only needs some iterator utilities from that file now, which belong
> >   in  anyway, so this moves them there.
> >
> > Several tests need changes to the diagnostics matched by dg-error
> > because we no longer use the __constructible() function that had a
> > static assert in. Now we just get straightforward errors for attempting
> > to use a deleted constructor.
> >
> > Two tests needed more signficant changes to the actual expected results
> > of executing the tests, because they were checking for old behaviour
> > which was incorrect according to the standard.
> > 20_util/specialized_algorithms/uninitialized_copy/64476.cc was expecting
> > std::copy to be used for a call to std::uninitialized_copy involving two
> > trivially copyable types. That was incorrect behaviour, because a
> > non-trivial constructor should have been used, but using std::copy used
> > trivial default initialization followed by assignment.
> > 20_util/specialized_algorithms/uninitialized_fill_n/sizes.cc was testing
> > the behaviour with a non-integral Size passed to uninitialized_fill_n,
> > but I wrote the test looking at the requirements of uninitialized_copy_n
> > which are not the same as uninitialized_fill_n. The former uses --n and
> > tests n > 0, but the latter just tests n-- (which will never be false
> > for a floating-point value with a fractional part).
> >
> > libstdc++-v3/ChangeLog:
> >
> >   PR libstdc++/68350
> >   PR libstdc++/93059
> >   * include/bits/stl_algobase.h (__niter_base, __niter_wrap): Move
> >   to ...
> >   * include/bits/stl_iterator.h: ... here.
> >   * include/bits/stl_uninitialized.h (__check_constructible)
> >   (_GLIBCXX_USE_ASSIGN_FOR_INIT): Remove.
> >   [C++98] (__unwrappable_niter): New trait.
> >   (__uninitialized_copy): Replace use of std::copy.
> >   (uninitialized_copy): Fix Doxygen comments. Open-code memcpy
> >   optimization for C++11 and later.
> >   (__uninitialized_fill): Replace use of std::fill.
> >   (uninitialized_fill): Fix Doxygen comments. Open-code memset
> >   optimization for C++11 and later.
> >   (__uninitialized_fill_n): Replace use of std::fill_n.
> >   (uninitialized_fill_n): Fix Doxygen comments. Open-code memset
> >   optimization for C++11 and later.
> >   * 
> > testsuite/20_util/specialized_algorithms/uninitialized_copy/64476.cc:
> >   Adjust expected behaviour to match what the standard specifies.
> >   * 
> > testsuite/20_util/specialized_algorithms/uninitialized_fill_n/sizes.cc:
> >   Likewise.
&g

Re: [PATCH 3/7] libstdc++: Inline memmove optimizations for std::copy etc. [PR115444]

2024-10-17 Thread Jonathan Wakely
On Thu, 17 Oct 2024, 03:04 Patrick Palka,  wrote:

> On Tue, 15 Oct 2024, Jonathan Wakely wrote:
>
> > This is a slightly different approach to C++98 compatibility than used
> > in patch 1/1 of this series for the uninitialized algos. It worked out a
> > bit cleaner this way for these algos, I think.
> >
> > Tested x86_64-linux.
> >
> > -- >8 --
> >
> > This removes all the __copy_move class template specializations that
> > decide how to optimize std::copy and std::copy_n. We can inline those
> > optimizations into the algorithms, using if-constexpr (and macros for
> > C++98 compatibility) and remove the code dispatching to the various
> > class template specializations.
> >
> > Doing this means we implement the optimization directly for std::copy_n
> > instead of deferring to std::copy, That avoids the unwanted consequence
> > of advancing the iterator in copy_n only to take the difference later to
> > get back to the length that we already had in copy_n originally (as
> > described in PR 115444).
> >
> > With the new flattened implementations, we can also lower contiguous
> > iterators to pointers in std::copy/std::copy_n/std::copy_backwards, so
> > that they benefit from the same memmove optimizations as pointers.
> > There's a subtlety though: contiguous iterators can potentially throw
> > exceptions to exit the algorithm early.  So we can only transform the
> > loop to memmove if dereferencing the iterator is noexcept. We don't
> > check that incrementing the iterator is noexcept because we advance the
> > contiguous iterators before using memmove, so that if incrementing would
> > throw, that happens first. I am writing a proposal (P3249R0) which would
> > make this unnecessary, so I hope we can drop the nothrow requirements
> > later.
> >
> > This change also solves PR 114817 by checking is_trivially_assignable
> > before optimizing copy/copy_n etc. to memmove. It's not enough to check
> > that the types are trivially copyable (a precondition for using memmove
> > at all), we also need to check that the specific assignment that would
> > be performed by the algorithm is also trivial. Replacing a non-trivial
> > assignment with memmove would be observable, so not allowed.
> >
> > libstdc++-v3/ChangeLog:
> >
> >   PR libstdc++/115444
> >   PR libstdc++/114817
> >   * include/bits/stl_algo.h (__copy_n): Remove generic overload
> >   and overload for random access iterators.
> >   (copy_n): Inline generic version of __copy_n here. Do not defer
> >   to std::copy for random access iterators.
> >   * include/bits/stl_algobase.h (__copy_move): Remove.
> >   (__nothrow_contiguous_iterator, __memcpyable_iterators): New
> >   concepts.
> >   (__assign_one, _GLIBCXX_TO_ADDR, _GLIBCXX_ADVANCE): New helpers.
> >   (__copy_move_a2): Inline __copy_move logic and conditional
> >   memmove optimization into the most generic overload.
> >   (__copy_n_a): Likewise.
> >   (__copy_move_backward): Remove.
> >   (__copy_move_backward_a2): Inline __copy_move_backward logic and
> >   memmove optimization into the most generic overload.
> >   *
> testsuite/20_util/specialized_algorithms/uninitialized_copy/114817.cc:
> >   New test.
> >   *
> testsuite/20_util/specialized_algorithms/uninitialized_copy_n/114817.cc:
> >   New test.
> >   * testsuite/25_algorithms/copy/114817.cc: New test.
> >   * testsuite/25_algorithms/copy/115444.cc: New test.
> >   * testsuite/25_algorithms/copy_n/114817.cc: New test.
> > ---
> >  libstdc++-v3/include/bits/stl_algo.h  |  24 +-
> >  libstdc++-v3/include/bits/stl_algobase.h  | 426 +-
> >  .../uninitialized_copy/114817.cc  |  39 ++
> >  .../uninitialized_copy_n/114817.cc|  39 ++
> >  .../testsuite/25_algorithms/copy/114817.cc|  38 ++
> >  .../testsuite/25_algorithms/copy/115444.cc|  93 
> >  .../testsuite/25_algorithms/copy_n/114817.cc  |  38 ++
> >  7 files changed, 469 insertions(+), 228 deletions(-)
> >  create mode 100644
> libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/114817.cc
> >  create mode 100644
> libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy_n/114817.cc
> >  create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy/114817.cc
> >  create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy/115444.cc
> >  create mode 100644 libstdc++-v3/testsuite/25

Re: [PATCH 2/7] libstdc++: Make __normal_iterator constexpr, always_inline, nodiscard

2024-10-16 Thread Jonathan Wakely
On Thu, 17 Oct 2024, 03:33 Patrick Palka,  wrote:

> On Tue, 15 Oct 2024, Jonathan Wakely wrote:
>
> > Tested x86_64-linux.
> >
> > -- >8 --
> >
> > The __gnu_cxx::__normal_iterator type we use for std::vector::iterator
> > is not specified by the standard, it's an implementation detail. This
> > means it's not constrained by the rule that forbids strengthening
> > constexpr. We can make it meet the constexpr iterator requirements for
> > older standards, not only when it's required to be for C++20.
> >
> > For the non-const member functions they can't be constexpr in C++11, so
> > use _GLIBCXX14_CONSTEXPR for those. For all constructors, const members
> > and non-member operator overloads, use _GLIBCXX_CONSTEXPR or just
> > constexpr.
> >
> > We can also liberally add [[nodiscard]] and [[gnu::always_inline]]
> > attributes to those functions.
> >
> > Also change some internal helpers for std::move_iterator which can be
> > unconditionally constexpr and marked nodiscard.
> >
> > libstdc++-v3/ChangeLog:
> >
> >   * include/bits/stl_iterator.h (__normal_iterator): Make all
> >   members and overloaded operators constexpr before C++20.
> >   (__niter_base, __niter_wrap, __to_address): Add nodiscard
> >   and always_inline attributes.
> >   (__make_move_if_noexcept_iterator, __miter_base): Add nodiscard
> >   and make unconditionally constexpr.
> > ---
> >  libstdc++-v3/include/bits/stl_iterator.h | 125 ++-
> >  1 file changed, 76 insertions(+), 49 deletions(-)
> >
> > diff --git a/libstdc++-v3/include/bits/stl_iterator.h
> b/libstdc++-v3/include/bits/stl_iterator.h
> > index 85b9861..3cc10a160bd 100644
> > --- a/libstdc++-v3/include/bits/stl_iterator.h
> > +++ b/libstdc++-v3/include/bits/stl_iterator.h
> > @@ -656,7 +656,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >
> >template
> >  _GLIBCXX20_CONSTEXPR
> > -auto
> > +inline auto
> >  __niter_base(reverse_iterator<_Iterator> __it)
> >  -> decltype(__make_reverse_iterator(__niter_base(__it.base(
> >  { return __make_reverse_iterator(__niter_base(__it.base())); }
> > @@ -668,7 +668,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >
> >template
> >  _GLIBCXX20_CONSTEXPR
> > -auto
> > +inline auto
>
> These 'inline' additions aren't mentioned in the ChangeLog it seems.


Good point.

Is
> the intent of these inlines solely as a compiler hint?
>

Yes, but they do a little more work than the really trivial ones, and are
less important, less frequently used, so I didn't think always_inline was
justified.


> >  __miter_base(reverse_iterator<_Iterator> __it)
> >  -> decltype(__make_reverse_iterator(__miter_base(__it.base(
> >  { return __make_reverse_iterator(__miter_base(__it.base())); }
> > @@ -1060,23 +1060,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >using iterator_concept = std::__detail::__iter_concept<_Iterator>;
> >  #endif
> >
> > -  _GLIBCXX_CONSTEXPR __normal_iterator() _GLIBCXX_NOEXCEPT
> > -  : _M_current(_Iterator()) { }
> > +  __attribute__((__always_inline__))
> > +  _GLIBCXX_CONSTEXPR
> > +  __normal_iterator() _GLIBCXX_NOEXCEPT
> > +  : _M_current() { }
> >
> > -  explicit _GLIBCXX20_CONSTEXPR
> > +  __attribute__((__always_inline__))
> > +  explicit _GLIBCXX_CONSTEXPR
> >__normal_iterator(const _Iterator& __i) _GLIBCXX_NOEXCEPT
> >: _M_current(__i) { }
> >
> >// Allow iterator to const_iterator conversion
> >  #if __cplusplus >= 201103L
> >template>
> > - _GLIBCXX20_CONSTEXPR
> > + [[__gnu__::__always_inline__]]
> > + constexpr
> >   __normal_iterator(const __normal_iterator<_Iter, _Container>& __i)
> >   noexcept
> >  #else
> >// N.B. _Container::pointer is not actually in container
> requirements,
> >// but is present in std::vector and std::basic_string.
> >template
> > + __attribute__((__always_inline__))
> >  __normal_iterator(const __normal_iterator<_Iter,
> > typename __enable_if<
> >  (std::__are_same<_Iter, typename
> _Container::pointer>::__value),
> > @@ -1085,17 +1090,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >  : _M_current(__i.base()) { }
> >
> >// Forward iterator requirements
> > -  

Re: [committed] libstdc++: Fix Python deprecation warning in printers.py

2024-10-16 Thread Jonathan Wakely
On Wed, 16 Oct 2024 at 16:58, Tom Tromey  wrote:
>
> >>>>> "Jonathan" == Jonathan Wakely  writes:
>
> Jonathan> Using a keyword argument for count only became possible with Python 
> 3.1
> Jonathan> so introduce a new function to do the substitution.
>
> gdb docs are inconsistent on this, but at least one spot says that the
> minimum supported Python version is 3.2.  Plus, I know we agreed that
> the minimum should be 3.4, and I'll be sending a patch to this effect
> soon.
>
> Anyway, I think it would be reasonably safe to just assume 3.1 if you
> want to do that.

We still have a few places in the printers.py file that check for
Python 3 vs Python 2, so I did so here too.

For the Python 3 case, I'm assuming 3.1 or later, because I can
imagine some people might be stuck on Python 2 for some reason (and
also unable to build GDB with Python 3? ... maybe unlikely) but nobody
should be stuck on 3.0 and unable to replace that with 3.12 or so.

So the condition is Python 2x, or Python 3.1+, and Python 3.0 is unsupported.

If we no longer care about Python 2 there are a few places in that
file we could clean up.



Re: [PATCH 3/7] libstdc++: Inline memmove optimizations for std::copy etc. [PR115444]

2024-10-16 Thread Jonathan Wakely
On Tue, 15 Oct 2024 at 15:29, Jonathan Wakely  wrote:
>
> This is a slightly different approach to C++98 compatibility than used
> in patch 1/1 of this series for the uninitialized algos. It worked out a
> bit cleaner this way for these algos, I think.
>
> Tested x86_64-linux.
>
> -- >8 --
>
> This removes all the __copy_move class template specializations that
> decide how to optimize std::copy and std::copy_n. We can inline those
> optimizations into the algorithms, using if-constexpr (and macros for
> C++98 compatibility) and remove the code dispatching to the various
> class template specializations.
>
> Doing this means we implement the optimization directly for std::copy_n
> instead of deferring to std::copy, That avoids the unwanted consequence
> of advancing the iterator in copy_n only to take the difference later to
> get back to the length that we already had in copy_n originally (as
> described in PR 115444).
>
> With the new flattened implementations, we can also lower contiguous
> iterators to pointers in std::copy/std::copy_n/std::copy_backwards, so
> that they benefit from the same memmove optimizations as pointers.
> There's a subtlety though: contiguous iterators can potentially throw
> exceptions to exit the algorithm early.  So we can only transform the
> loop to memmove if dereferencing the iterator is noexcept. We don't
> check that incrementing the iterator is noexcept because we advance the
> contiguous iterators before using memmove, so that if incrementing would
> throw, that happens first. I am writing a proposal (P3249R0) which would

Oops, got my own paper number wrong, I've fixed that locally.
The paper is online now:
https://isocpp.org/files/papers/P3349R0.html

> make this unnecessary, so I hope we can drop the nothrow requirements
> later.
>
> This change also solves PR 114817 by checking is_trivially_assignable
> before optimizing copy/copy_n etc. to memmove. It's not enough to check
> that the types are trivially copyable (a precondition for using memmove
> at all), we also need to check that the specific assignment that would
> be performed by the algorithm is also trivial. Replacing a non-trivial
> assignment with memmove would be observable, so not allowed.
>
> libstdc++-v3/ChangeLog:
>
> PR libstdc++/115444
> PR libstdc++/114817
> * include/bits/stl_algo.h (__copy_n): Remove generic overload
> and overload for random access iterators.
> (copy_n): Inline generic version of __copy_n here. Do not defer
> to std::copy for random access iterators.
> * include/bits/stl_algobase.h (__copy_move): Remove.
> (__nothrow_contiguous_iterator, __memcpyable_iterators): New
> concepts.
> (__assign_one, _GLIBCXX_TO_ADDR, _GLIBCXX_ADVANCE): New helpers.
> (__copy_move_a2): Inline __copy_move logic and conditional
> memmove optimization into the most generic overload.
> (__copy_n_a): Likewise.
> (__copy_move_backward): Remove.
> (__copy_move_backward_a2): Inline __copy_move_backward logic and
> memmove optimization into the most generic overload.
> * 
> testsuite/20_util/specialized_algorithms/uninitialized_copy/114817.cc:
> New test.
> * 
> testsuite/20_util/specialized_algorithms/uninitialized_copy_n/114817.cc:
> New test.
> * testsuite/25_algorithms/copy/114817.cc: New test.
> * testsuite/25_algorithms/copy/115444.cc: New test.
> * testsuite/25_algorithms/copy_n/114817.cc: New test.
> ---
>  libstdc++-v3/include/bits/stl_algo.h  |  24 +-
>  libstdc++-v3/include/bits/stl_algobase.h  | 426 +-
>  .../uninitialized_copy/114817.cc  |  39 ++
>  .../uninitialized_copy_n/114817.cc|  39 ++
>  .../testsuite/25_algorithms/copy/114817.cc|  38 ++
>  .../testsuite/25_algorithms/copy/115444.cc|  93 
>  .../testsuite/25_algorithms/copy_n/114817.cc  |  38 ++
>  7 files changed, 469 insertions(+), 228 deletions(-)
>  create mode 100644 
> libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/114817.cc
>  create mode 100644 
> libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy_n/114817.cc
>  create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy/114817.cc
>  create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy/115444.cc
>  create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy_n/114817.cc
>
> diff --git a/libstdc++-v3/include/bits/stl_algo.h 
> b/libstdc++-v3/include/bits/stl_algo.h
> index a1ef665506d..489ce7e14d2 100644
> --- a/libstdc++-v3/include/bits/stl_algo.h
> +++ b/libstdc++-v3/include/bits/stl_algo.h
>

[committed] libstdc++: Fix Python deprecation warning in printers.py

2024-10-16 Thread Jonathan Wakely
Tested x86_64-linux with gdb-15.1 and Python 3.12.

Pushed to trunk, backports to follow.

-- >8 --

python/libstdcxx/v6/printers.py:1355: DeprecationWarning: 'count' is passed as 
positional argument

The Python docs say:

  Deprecated since version 3.13: Passing count and flags as positional
  arguments is deprecated. In future Python versions they will be
  keyword-only parameters.

Using a keyword argument for count only became possible with Python 3.1
so introduce a new function to do the substitution.

libstdc++-v3/ChangeLog:

* python/libstdcxx/v6/printers.py (strip_fundts_namespace): New.
(StdExpAnyPrinter, StdExpOptionalPrinter): Use it.
---
 libstdc++-v3/python/libstdcxx/v6/printers.py | 19 +--
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py 
b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 92104937862..d05b79762fd 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -220,6 +220,16 @@ def strip_versioned_namespace(typename):
 return typename.replace(_versioned_namespace, '')
 
 
+def strip_fundts_namespace(typ):
+"""Remove "fundamentals_vN" inline namespace from qualified type name."""
+pattern = r'^std::experimental::fundamentals_v\d::'
+repl = 'std::experimental::'
+if sys.version_info[0] == 2:
+return re.sub(pattern, repl, typ, 1)
+else: # Technically this needs Python 3.1 but nobody should be using 3.0
+return re.sub(pattern, repl, typ, count=1)
+
+
 def strip_inline_namespaces(type_str):
 """Remove known inline namespaces from the canonical name of a type."""
 type_str = strip_versioned_namespace(type_str)
@@ -1355,8 +1365,7 @@ class StdExpAnyPrinter(SingleObjContainerPrinter):
 
 def __init__(self, typename, val):
 self._typename = strip_versioned_namespace(typename)
-self._typename = re.sub(r'^std::experimental::fundamentals_v\d::',
-'std::experimental::', self._typename, 1)
+self._typename = strip_fundts_namespace(self._typename)
 self._val = val
 self._contained_type = None
 contained_value = None
@@ -1449,10 +1458,8 @@ class StdExpOptionalPrinter(SingleObjContainerPrinter):
 """Print a std::optional or std::experimental::optional."""
 
 def __init__(self, typename, val):
-typename = strip_versioned_namespace(typename)
-self._typename = re.sub(
-r'^std::(experimental::|)(fundamentals_v\d::|)(.*)',
-r'std::\1\3', typename, 1)
+self._typename = strip_versioned_namespace(typename)
+self._typename = strip_fundts_namespace(self._typename)
 payload = val['_M_payload']
 if self._typename.startswith('std::experimental'):
 engaged = val['_M_engaged']
-- 
2.46.2



Re: [PATCH 4/7] libstdc++: Remove indirection to __find_if in std::find etc.

2024-10-15 Thread Jonathan Wakely

On 15/10/24 15:20 +0100, Jonathan Wakely wrote:

Tested x86_64-linux.

-- >8 --

There doesn't seem to be a lot of benefit in reusing __find_if with
__gnu_cxx::__ops predicates, since they aren't going to actually
instantiate any less code if we use different predicates every time
(e.g. __ops::__negate, or __ops::__iter_equals_val, or
__ops::__pred_iter).

And now that std::find no longer calls __find_if (because it just does a
loop directly), we can make the _Iter_equals_val case of __find_if call
std::find, to take advantage of its memchr optimization. This benefits
other algos like search_n which use __find_if with _Iter_equals_val.


Hmm, I wonder if inverting the relationship below (__find_if calls
find, instead of vice versa) can cause an ABI problem if one TU has an
instantiation of the old find that calls __find_if, and another TU has
an instantiation of the new __find_if that calls find, and they end up
calling each other recursively until the stack overflows.

We might need to mangle one of them differently.


-  /**
-   *  @brief Find the first occurrence of a value in a sequence.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first  An input iterator.
-   *  @param  __last   An input iterator.
-   *  @param  __valThe value to find.
-   *  @return   The first iterator @c i in the range @p [__first,__last)
-   *  such that @c *i == @p __val, or @p __last if no such iterator exists.
-  */
-  template
-_GLIBCXX20_CONSTEXPR
-inline _InputIterator
-find(_InputIterator __first, _InputIterator __last, const _Tp& __val)
-{
-  // concept requirements
-  __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-  __glibcxx_function_requires(_EqualOpConcept<
-   typename iterator_traits<_InputIterator>::value_type, _Tp>)
-  __glibcxx_requires_valid_range(__first, __last);
-
-#if __cpp_if_constexpr && __glibcxx_type_trait_variable_templates
-  using _ValT = typename iterator_traits<_InputIterator>::value_type;
-  if constexpr (__can_use_memchr_for_find<_ValT, _Tp>)
-   if constexpr (is_pointer_v
-#if __cpp_lib_concepts
-   || contiguous_iterator<_InputIterator>
-#endif
-)
- {
-   // If conversion to the 1-byte value_type alters the value,
-   // it would not be found by std::find using equality comparison.
-   // We need to check this here, because otherwise something like
-   // memchr("a", 'a'+256, 1) would give a false positive match.
-   if (!(static_cast<_ValT>(__val) == __val))
- return __last;
-   else if (!__is_constant_evaluated())
- {
-   const void* __p0 = std::__to_address(__first);
-   const int __ival = static_cast(__val);
-   if (auto __n = std::distance(__first, __last); __n > 0)
- if (auto __p1 = __builtin_memchr(__p0, __ival, __n))
-   return __first + ((const char*)__p1 - (const char*)__p0);
-   return __last;
- }
- }
-#endif
-
-  return std::__find_if(__first, __last,
-   __gnu_cxx::__ops::__iter_equals_val(__val));
-}


[...]


+  // When the predicate is just comparing to a value we can use std::find,
+  // which is optimized to memchr for some types.
+  template
+_GLIBCXX20_CONSTEXPR
+inline _Iterator
+__find_if(_Iterator __first, _Iterator __last,
+ __gnu_cxx::__ops::_Iter_equals_val<_Value> __pred)
+{ return _GLIBCXX_STD_A::find(__first, __last, __pred._M_value); }
+
  template
_GLIBCXX20_CONSTEXPR
typename iterator_traits<_InputIterator>::difference_type
--
2.46.2





[PATCH 6/7] libstdc++: Add always_inline to some one-liners in

2024-10-15 Thread Jonathan Wakely
Tested x86_64-linux.

-- >8 --

We implement std::copy, std::fill etc. as a series of calls to other
overloads which incrementally peel off layers of iterator wrappers. This
adds a high abstraction penalty for -O0 and potentially even -O1. Add
the always_inline attribute to several functions that are just a single
return statement (and maybe a static_assert, or some concept-checking
assertions which are disabled by default).

libstdc++-v3/ChangeLog:

* include/bits/stl_algobase.h (__copy_move_a1, __copy_move_a)
(__copy_move_backward_a1, __copy_move_backward_a, move_backward)
(__fill_a1, __fill_a, fill, __fill_n_a, fill_n, __equal_aux):
Add always_inline attribute to one-line forwarding functions.
---
 libstdc++-v3/include/bits/stl_algobase.h | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/libstdc++-v3/include/bits/stl_algobase.h 
b/libstdc++-v3/include/bits/stl_algobase.h
index d9d1d00b113..b2f5b96d46e 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -500,12 +500,14 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
 __copy_move_a1(_II, _II, _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>);
 
   template
+__attribute__((__always_inline__))
 _GLIBCXX20_CONSTEXPR
 inline _OI
 __copy_move_a1(_II __first, _II __last, _OI __result)
 { return std::__copy_move_a2<_IsMove>(__first, __last, __result); }
 
   template
+__attribute__((__always_inline__))
 _GLIBCXX20_CONSTEXPR
 inline _OI
 __copy_move_a(_II __first, _II __last, _OI __result)
@@ -757,6 +759,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
 #undef _GLIBCXX_ADVANCE
 
   template
+__attribute__((__always_inline__))
 _GLIBCXX20_CONSTEXPR
 inline _BI2
 __copy_move_backward_a1(_BI1 __first, _BI1 __last, _BI2 __result)
@@ -785,6 +788,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>);
 
   template
+__attribute__((__always_inline__))
 _GLIBCXX20_CONSTEXPR
 inline _OI
 __copy_move_backward_a(_II __first, _II __last, _OI __result)
@@ -840,6 +844,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
*  that the start of the output range may overlap [first,last).
   */
   template
+__attribute__((__always_inline__))
 _GLIBCXX20_CONSTEXPR
 inline _BI2
 copy_backward(_BI1 __first, _BI1 __last, _BI2 __result)
@@ -875,6 +880,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
*  that the start of the output range may overlap [first,last).
   */
   template
+__attribute__((__always_inline__))
 _GLIBCXX20_CONSTEXPR
 inline _BI2
 move_backward(_BI1 __first, _BI1 __last, _BI2 __result)
@@ -958,6 +964,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
 }
 
   template
+__attribute__((__always_inline__))
 _GLIBCXX20_CONSTEXPR
 inline void
 __fill_a1(::__gnu_cxx::__normal_iterator<_Ite, _Cont> __first,
@@ -977,6 +984,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
const bool&);
 
   template
+__attribute__((__always_inline__))
 _GLIBCXX20_CONSTEXPR
 inline void
 __fill_a(_FIte __first, _FIte __last, const _Tp& __value)
@@ -1002,6 +1010,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
*  to @c memset or @c wmemset.
   */
   template
+__attribute__((__always_inline__))
 _GLIBCXX20_CONSTEXPR
 inline void
 fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value)
@@ -1108,6 +1117,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
   std::input_iterator_tag);
 
   template
+__attribute__((__always_inline__))
 _GLIBCXX20_CONSTEXPR
 inline _OutputIterator
 __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value,
@@ -1120,6 +1130,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
 }
 
   template
+__attribute__((__always_inline__))
 _GLIBCXX20_CONSTEXPR
 inline _OutputIterator
 __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value,
@@ -1132,6 +1143,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
 }
 
   template
+__attribute__((__always_inline__))
 _GLIBCXX20_CONSTEXPR
 inline _OutputIterator
 __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value,
@@ -1167,6 +1179,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
   // DR 865. More algorithms that throw away information
   // DR 426. search_n(), fill_n(), and generate_n() with negative n
   template
+__attribute__((__always_inline__))
 _GLIBCXX20_CONSTEXPR
 inline _OI
 fill_n(_OI __first, _Size __n, const _Tp& __value)
@@ -1246,6 +1259,7 @@ _GLIBCXX_END_NAMESPACE_CONTAINER
 }
 
   template
+__attribute__((__always_inline__))
 _GLIBCXX20_CONSTEXPR
 inline bool
 __equal_aux(_II1 __first1, _II1 __last1, _II2 __first2)
-- 
2.46.2



[PATCH 3/7] libstdc++: Inline memmove optimizations for std::copy etc. [PR115444]

2024-10-15 Thread Jonathan Wakely
This is a slightly different approach to C++98 compatibility than used
in patch 1/1 of this series for the uninitialized algos. It worked out a
bit cleaner this way for these algos, I think.

Tested x86_64-linux.

-- >8 --

This removes all the __copy_move class template specializations that
decide how to optimize std::copy and std::copy_n. We can inline those
optimizations into the algorithms, using if-constexpr (and macros for
C++98 compatibility) and remove the code dispatching to the various
class template specializations.

Doing this means we implement the optimization directly for std::copy_n
instead of deferring to std::copy, That avoids the unwanted consequence
of advancing the iterator in copy_n only to take the difference later to
get back to the length that we already had in copy_n originally (as
described in PR 115444).

With the new flattened implementations, we can also lower contiguous
iterators to pointers in std::copy/std::copy_n/std::copy_backwards, so
that they benefit from the same memmove optimizations as pointers.
There's a subtlety though: contiguous iterators can potentially throw
exceptions to exit the algorithm early.  So we can only transform the
loop to memmove if dereferencing the iterator is noexcept. We don't
check that incrementing the iterator is noexcept because we advance the
contiguous iterators before using memmove, so that if incrementing would
throw, that happens first. I am writing a proposal (P3249R0) which would
make this unnecessary, so I hope we can drop the nothrow requirements
later.

This change also solves PR 114817 by checking is_trivially_assignable
before optimizing copy/copy_n etc. to memmove. It's not enough to check
that the types are trivially copyable (a precondition for using memmove
at all), we also need to check that the specific assignment that would
be performed by the algorithm is also trivial. Replacing a non-trivial
assignment with memmove would be observable, so not allowed.

libstdc++-v3/ChangeLog:

PR libstdc++/115444
PR libstdc++/114817
* include/bits/stl_algo.h (__copy_n): Remove generic overload
and overload for random access iterators.
(copy_n): Inline generic version of __copy_n here. Do not defer
to std::copy for random access iterators.
* include/bits/stl_algobase.h (__copy_move): Remove.
(__nothrow_contiguous_iterator, __memcpyable_iterators): New
concepts.
(__assign_one, _GLIBCXX_TO_ADDR, _GLIBCXX_ADVANCE): New helpers.
(__copy_move_a2): Inline __copy_move logic and conditional
memmove optimization into the most generic overload.
(__copy_n_a): Likewise.
(__copy_move_backward): Remove.
(__copy_move_backward_a2): Inline __copy_move_backward logic and
memmove optimization into the most generic overload.
* testsuite/20_util/specialized_algorithms/uninitialized_copy/114817.cc:
New test.
* 
testsuite/20_util/specialized_algorithms/uninitialized_copy_n/114817.cc:
New test.
* testsuite/25_algorithms/copy/114817.cc: New test.
* testsuite/25_algorithms/copy/115444.cc: New test.
* testsuite/25_algorithms/copy_n/114817.cc: New test.
---
 libstdc++-v3/include/bits/stl_algo.h  |  24 +-
 libstdc++-v3/include/bits/stl_algobase.h  | 426 +-
 .../uninitialized_copy/114817.cc  |  39 ++
 .../uninitialized_copy_n/114817.cc|  39 ++
 .../testsuite/25_algorithms/copy/114817.cc|  38 ++
 .../testsuite/25_algorithms/copy/115444.cc|  93 
 .../testsuite/25_algorithms/copy_n/114817.cc  |  38 ++
 7 files changed, 469 insertions(+), 228 deletions(-)
 create mode 100644 
libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/114817.cc
 create mode 100644 
libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy_n/114817.cc
 create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy/114817.cc
 create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy/115444.cc
 create mode 100644 libstdc++-v3/testsuite/25_algorithms/copy_n/114817.cc

diff --git a/libstdc++-v3/include/bits/stl_algo.h 
b/libstdc++-v3/include/bits/stl_algo.h
index a1ef665506d..489ce7e14d2 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -665,25 +665,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   return __result;
 }
 
-  template
-_GLIBCXX20_CONSTEXPR
-_OutputIterator
-__copy_n(_InputIterator __first, _Size __n,
-_OutputIterator __result, input_iterator_tag)
-{
-  return std::__niter_wrap(__result,
-  __copy_n_a(__first, __n,
- std::__niter_base(__result), true));
-}
-
-  template
-_GLIBCXX20_CONSTEXPR
-inline _OutputIterator
-__copy_n(_RandomAccessIterator __first, _Size __n,
-_OutputIterator __result, random_access_iterator_tag)
-{ return std

[PATCH 1/7] libstdc++: Refactor std::uninitialized_{copy, fill, fill_n} algos [PR68350]

2024-10-15 Thread Jonathan Wakely
This is v2 of
https://gcc.gnu.org/pipermail/gcc-patches/2024-October/665246.html
fixing some thinkos in uninitialized_{fill,fill_n}. We don't need to
worry about overwriting tail-padding in those algos, because we only use
memset for 1-byte integer types. So they have no tail padding that can
be reused anyway! So this changes __n > 1 to __n > 0 in a few places
(which fixes the problem that it was not actually filling anything for
the n==1 cases).

Also simplify std::__to_address(__result++) to just __result++ because
we already have a pointer, and use std::to_address(result++) for a C++20
std::contiguous_iterator case, instead of addressof(*result++).

Tested x86_64-linux.

-- >8 --

This refactors the std::uninitialized_copy, std::uninitialized_fill and
std::uninitialized_fill_n algorithms to directly perform memcpy/memset
optimizations instead of dispatching to std::copy/std::fill/std::fill_n.

The reasons for this are:

- Use 'if constexpr' to simplify and optimize compilation throughput, so
  dispatching to specialized class templates is only needed for C++98
  mode.
- Relax the conditions for using memcpy/memset, because the C++20 rules
  on implicit-lifetime types mean that we can rely on memcpy to begin
  lifetimes of trivially copyable types.  We don't need to require
  trivially default constructible, so don't need to limit the
  optimization to trivial types. See PR 68350 for more details.
- The conditions on non-overlapping ranges are stronger for
  std::uninitialized_copy than for std::copy so we can use memcpy instead
  of memmove, which might be a minor optimization.
- Avoid including  in .
  It only needs some iterator utilities from that file now, which belong
  in  anyway, so this moves them there.

Several tests need changes to the diagnostics matched by dg-error
because we no longer use the __constructible() function that had a
static assert in. Now we just get straightforward errors for attempting
to use a deleted constructor.

Two tests needed more signficant changes to the actual expected results
of executing the tests, because they were checking for old behaviour
which was incorrect according to the standard.
20_util/specialized_algorithms/uninitialized_copy/64476.cc was expecting
std::copy to be used for a call to std::uninitialized_copy involving two
trivially copyable types. That was incorrect behaviour, because a
non-trivial constructor should have been used, but using std::copy used
trivial default initialization followed by assignment.
20_util/specialized_algorithms/uninitialized_fill_n/sizes.cc was testing
the behaviour with a non-integral Size passed to uninitialized_fill_n,
but I wrote the test looking at the requirements of uninitialized_copy_n
which are not the same as uninitialized_fill_n. The former uses --n and
tests n > 0, but the latter just tests n-- (which will never be false
for a floating-point value with a fractional part).

libstdc++-v3/ChangeLog:

PR libstdc++/68350
PR libstdc++/93059
* include/bits/stl_algobase.h (__niter_base, __niter_wrap): Move
to ...
* include/bits/stl_iterator.h: ... here.
* include/bits/stl_uninitialized.h (__check_constructible)
(_GLIBCXX_USE_ASSIGN_FOR_INIT): Remove.
[C++98] (__unwrappable_niter): New trait.
(__uninitialized_copy): Replace use of std::copy.
(uninitialized_copy): Fix Doxygen comments. Open-code memcpy
optimization for C++11 and later.
(__uninitialized_fill): Replace use of std::fill.
(uninitialized_fill): Fix Doxygen comments. Open-code memset
optimization for C++11 and later.
(__uninitialized_fill_n): Replace use of std::fill_n.
(uninitialized_fill_n): Fix Doxygen comments. Open-code memset
optimization for C++11 and later.
* testsuite/20_util/specialized_algorithms/uninitialized_copy/64476.cc:
Adjust expected behaviour to match what the standard specifies.
* 
testsuite/20_util/specialized_algorithms/uninitialized_fill_n/sizes.cc:
Likewise.
* testsuite/20_util/specialized_algorithms/uninitialized_copy/1.cc:
Adjust dg-error directives.
* testsuite/20_util/specialized_algorithms/uninitialized_copy/89164.cc:
Likewise.
* 
testsuite/20_util/specialized_algorithms/uninitialized_copy_n/89164.cc:
Likewise.
* testsuite/20_util/specialized_algorithms/uninitialized_fill/89164.cc:
Likewise.
* 
testsuite/20_util/specialized_algorithms/uninitialized_fill_n/89164.cc:
Likewise.
* testsuite/23_containers/vector/cons/89164.cc: Likewise.
* testsuite/23_containers/vector/cons/89164_c++17.cc: Likewise.
---
 libstdc++-v3/include/bits/stl_algobase.h  |  45 --
 libstdc++-v3/include/bits/stl_iterator.h  |  54 +++
 libstdc++-v3/include/bits/stl_uninitialized.h | 385 +-
 .../uninitialized_copy/1.cc   |   3 +-
 .../uninitialized_copy/64476.cc  

[PATCH 2/7] libstdc++: Make __normal_iterator constexpr, always_inline, nodiscard

2024-10-15 Thread Jonathan Wakely
Tested x86_64-linux.

-- >8 --

The __gnu_cxx::__normal_iterator type we use for std::vector::iterator
is not specified by the standard, it's an implementation detail. This
means it's not constrained by the rule that forbids strengthening
constexpr. We can make it meet the constexpr iterator requirements for
older standards, not only when it's required to be for C++20.

For the non-const member functions they can't be constexpr in C++11, so
use _GLIBCXX14_CONSTEXPR for those. For all constructors, const members
and non-member operator overloads, use _GLIBCXX_CONSTEXPR or just
constexpr.

We can also liberally add [[nodiscard]] and [[gnu::always_inline]]
attributes to those functions.

Also change some internal helpers for std::move_iterator which can be
unconditionally constexpr and marked nodiscard.

libstdc++-v3/ChangeLog:

* include/bits/stl_iterator.h (__normal_iterator): Make all
members and overloaded operators constexpr before C++20.
(__niter_base, __niter_wrap, __to_address): Add nodiscard
and always_inline attributes.
(__make_move_if_noexcept_iterator, __miter_base): Add nodiscard
and make unconditionally constexpr.
---
 libstdc++-v3/include/bits/stl_iterator.h | 125 ++-
 1 file changed, 76 insertions(+), 49 deletions(-)

diff --git a/libstdc++-v3/include/bits/stl_iterator.h 
b/libstdc++-v3/include/bits/stl_iterator.h
index 85b9861..3cc10a160bd 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -656,7 +656,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
 _GLIBCXX20_CONSTEXPR
-auto
+inline auto
 __niter_base(reverse_iterator<_Iterator> __it)
 -> decltype(__make_reverse_iterator(__niter_base(__it.base(
 { return __make_reverse_iterator(__niter_base(__it.base())); }
@@ -668,7 +668,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   template
 _GLIBCXX20_CONSTEXPR
-auto
+inline auto
 __miter_base(reverse_iterator<_Iterator> __it)
 -> decltype(__make_reverse_iterator(__miter_base(__it.base(
 { return __make_reverse_iterator(__miter_base(__it.base())); }
@@ -1060,23 +1060,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   using iterator_concept = std::__detail::__iter_concept<_Iterator>;
 #endif
 
-  _GLIBCXX_CONSTEXPR __normal_iterator() _GLIBCXX_NOEXCEPT
-  : _M_current(_Iterator()) { }
+  __attribute__((__always_inline__))
+  _GLIBCXX_CONSTEXPR
+  __normal_iterator() _GLIBCXX_NOEXCEPT
+  : _M_current() { }
 
-  explicit _GLIBCXX20_CONSTEXPR
+  __attribute__((__always_inline__))
+  explicit _GLIBCXX_CONSTEXPR
   __normal_iterator(const _Iterator& __i) _GLIBCXX_NOEXCEPT
   : _M_current(__i) { }
 
   // Allow iterator to const_iterator conversion
 #if __cplusplus >= 201103L
   template>
-   _GLIBCXX20_CONSTEXPR
+   [[__gnu__::__always_inline__]]
+   constexpr
__normal_iterator(const __normal_iterator<_Iter, _Container>& __i)
noexcept
 #else
   // N.B. _Container::pointer is not actually in container requirements,
   // but is present in std::vector and std::basic_string.
   template
+   __attribute__((__always_inline__))
 __normal_iterator(const __normal_iterator<_Iter,
  typename __enable_if<
   (std::__are_same<_Iter, typename _Container::pointer>::__value),
@@ -1085,17 +1090,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 : _M_current(__i.base()) { }
 
   // Forward iterator requirements
-  _GLIBCXX20_CONSTEXPR
+
+  __attribute__((__always_inline__)) _GLIBCXX_NODISCARD
+  _GLIBCXX_CONSTEXPR
   reference
   operator*() const _GLIBCXX_NOEXCEPT
   { return *_M_current; }
 
-  _GLIBCXX20_CONSTEXPR
+  __attribute__((__always_inline__)) _GLIBCXX_NODISCARD
+  _GLIBCXX_CONSTEXPR
   pointer
   operator->() const _GLIBCXX_NOEXCEPT
   { return _M_current; }
 
-  _GLIBCXX20_CONSTEXPR
+  __attribute__((__always_inline__))
+  _GLIBCXX14_CONSTEXPR
   __normal_iterator&
   operator++() _GLIBCXX_NOEXCEPT
   {
@@ -1103,13 +1112,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this;
   }
 
-  _GLIBCXX20_CONSTEXPR
+  __attribute__((__always_inline__))
+  _GLIBCXX14_CONSTEXPR
   __normal_iterator
   operator++(int) _GLIBCXX_NOEXCEPT
   { return __normal_iterator(_M_current++); }
 
   // Bidirectional iterator requirements
-  _GLIBCXX20_CONSTEXPR
+
+  __attribute__((__always_inline__))
+  _GLIBCXX14_CONSTEXPR
   __normal_iterator&
   operator--() _GLIBCXX_NOEXCEPT
   {
@@ -1117,38 +1129,46 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this;
   }
 
-  _GLIBCXX20_CONSTEXPR
+  __attribute__((__always_inline__))
+  _GLIBCXX14_CONSTEXPR
   __normal_iterator
   operator--(int) _GLIBCXX_NOEXCEPT
   { return __normal_iterator(_M_current--); }
 
   // Ra

[PATCH 4/7] libstdc++: Remove indirection to __find_if in std::find etc.

2024-10-15 Thread Jonathan Wakely
Tested x86_64-linux.

-- >8 --

There doesn't seem to be a lot of benefit in reusing __find_if with
__gnu_cxx::__ops predicates, since they aren't going to actually
instantiate any less code if we use different predicates every time
(e.g. __ops::__negate, or __ops::__iter_equals_val, or
__ops::__pred_iter).

And now that std::find no longer calls __find_if (because it just does a
loop directly), we can make the _Iter_equals_val case of __find_if call
std::find, to take advantage of its memchr optimization. This benefits
other algos like search_n which use __find_if with _Iter_equals_val.

libstdc++-v3/ChangeLog:

* include/bits/stl_algo.h (__find_if_not): Do loop here instead
of using __find_if with __gnu_cxx::__ops predicate.
(find_if): Likewise.
(find): Move to ...
* include/bits/stl_algobase.h (find): ... here.
(__find_if): Overload for _Iter_equals_val predicate.
---
 libstdc++-v3/include/bits/stl_algo.h | 63 +++-
 libstdc++-v3/include/bits/stl_algobase.h | 61 +++
 2 files changed, 68 insertions(+), 56 deletions(-)

diff --git a/libstdc++-v3/include/bits/stl_algo.h 
b/libstdc++-v3/include/bits/stl_algo.h
index 489ce7e14d2..05c1dbd07b6 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -105,15 +105,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
std::iter_swap(__result, __b);
 }
 
-  /// Provided for stable_partition to use.
+  // Used by std::find_if_not and __stable_partition.
   template
 _GLIBCXX20_CONSTEXPR
 inline _InputIterator
 __find_if_not(_InputIterator __first, _InputIterator __last,
  _Predicate __pred)
 {
-  return std::__find_if(__first, __last,
-   __gnu_cxx::__ops::__negate(__pred));
+  while (__first != __last && __pred(__first))
+   ++__first;
+  return __first;
 }
 
   /// Like find_if_not(), but uses and updates a count of the
@@ -3810,57 +3811,6 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
 }
 #endif // C++17
 
-  /**
-   *  @brief Find the first occurrence of a value in a sequence.
-   *  @ingroup non_mutating_algorithms
-   *  @param  __first  An input iterator.
-   *  @param  __last   An input iterator.
-   *  @param  __valThe value to find.
-   *  @return   The first iterator @c i in the range @p [__first,__last)
-   *  such that @c *i == @p __val, or @p __last if no such iterator exists.
-  */
-  template
-_GLIBCXX20_CONSTEXPR
-inline _InputIterator
-find(_InputIterator __first, _InputIterator __last, const _Tp& __val)
-{
-  // concept requirements
-  __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
-  __glibcxx_function_requires(_EqualOpConcept<
-   typename iterator_traits<_InputIterator>::value_type, _Tp>)
-  __glibcxx_requires_valid_range(__first, __last);
-
-#if __cpp_if_constexpr && __glibcxx_type_trait_variable_templates
-  using _ValT = typename iterator_traits<_InputIterator>::value_type;
-  if constexpr (__can_use_memchr_for_find<_ValT, _Tp>)
-   if constexpr (is_pointer_v
-#if __cpp_lib_concepts
-   || contiguous_iterator<_InputIterator>
-#endif
-)
- {
-   // If conversion to the 1-byte value_type alters the value,
-   // it would not be found by std::find using equality comparison.
-   // We need to check this here, because otherwise something like
-   // memchr("a", 'a'+256, 1) would give a false positive match.
-   if (!(static_cast<_ValT>(__val) == __val))
- return __last;
-   else if (!__is_constant_evaluated())
- {
-   const void* __p0 = std::__to_address(__first);
-   const int __ival = static_cast(__val);
-   if (auto __n = std::distance(__first, __last); __n > 0)
- if (auto __p1 = __builtin_memchr(__p0, __ival, __n))
-   return __first + ((const char*)__p1 - (const char*)__p0);
-   return __last;
- }
- }
-#endif
-
-  return std::__find_if(__first, __last,
-   __gnu_cxx::__ops::__iter_equals_val(__val));
-}
-
   /**
*  @brief Find the first element in a sequence for which a
* predicate is true.
@@ -3883,8 +3833,9 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
  typename iterator_traits<_InputIterator>::value_type>)
   __glibcxx_requires_valid_range(__first, __last);
 
-  return std::__find_if(__first, __last,
-   __gnu_cxx::__ops::__pred_iter(__pred));
+  while (__first != __last && !__pred(*__first))
+   ++__first;
+  return __first;
 }
 
   /**
diff --git a/libstdc++-v3/include/bits/stl_algobase.h 
b/libstdc++-v3/include/bits/stl_algobase.h
index 5f77b00be9b..34e1cf7322f 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase

[PATCH 7/7] libstdc++: Reuse std::__assign_one in

2024-10-15 Thread Jonathan Wakely
Tested x86_64-linux.

-- >8 --

Use std::__assign_one instead of ranges::__assign_one. Adjust the uses,
because std::__assign_one has the arguments in the opposite order (the
same order as an assignment expression).

libstdc++-v3/ChangeLog:

* include/bits/ranges_algobase.h (ranges::__assign_one): Remove.
(__copy_or_move, __copy_or_move_backward): Use std::__assign_one
instead of ranges::__assign_one.
---
 libstdc++-v3/include/bits/ranges_algobase.h | 22 ++---
 1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/libstdc++-v3/include/bits/ranges_algobase.h 
b/libstdc++-v3/include/bits/ranges_algobase.h
index 0345ea850a4..df4e770e7a6 100644
--- a/libstdc++-v3/include/bits/ranges_algobase.h
+++ b/libstdc++-v3/include/bits/ranges_algobase.h
@@ -225,16 +225,6 @@ namespace ranges
  copy_backward_result<_Iter, _Out>>
 __copy_or_move_backward(_Iter __first, _Sent __last, _Out __result);
 
-  template
-constexpr void
-__assign_one(_Iter& __iter, _Out& __result)
-{
-  if constexpr (_IsMove)
- *__result = std::move(*__iter);
-  else
- *__result = *__iter;
-}
-
   template _Sent,
   weakly_incrementable _Out>
@@ -294,14 +284,14 @@ namespace ranges
__builtin_memmove(__result, __first,
  sizeof(_ValueTypeI) * __num);
  else if (__num == 1)
-   ranges::__assign_one<_IsMove>(__first, __result);
+   std::__assign_one<_IsMove>(__result, __first);
  return {__first + __num, __result + __num};
}
}
 
  for (auto __n = __last - __first; __n > 0; --__n)
{
- ranges::__assign_one<_IsMove>(__first, __result);
+ std::__assign_one<_IsMove>(__result, __first);
  ++__first;
  ++__result;
}
@@ -311,7 +301,7 @@ namespace ranges
{
  while (__first != __last)
{
- ranges::__assign_one<_IsMove>(__first, __result);
+ std::__assign_one<_IsMove>(__result, __first);
  ++__first;
  ++__result;
}
@@ -423,7 +413,7 @@ namespace ranges
__builtin_memmove(__result, __first,
  sizeof(_ValueTypeI) * __num);
  else if (__num == 1)
-   ranges::__assign_one<_IsMove>(__first, __result);
+   std::__assign_one<_IsMove>(__result, __first);
  return {__first + __num, __result};
}
}
@@ -435,7 +425,7 @@ namespace ranges
{
  --__tail;
  --__result;
- ranges::__assign_one<_IsMove>(__tail, __result);
+ std::__assign_one<_IsMove>(__result, __tail);
}
  return {std::move(__lasti), std::move(__result)};
}
@@ -448,7 +438,7 @@ namespace ranges
{
  --__tail;
  --__result;
- ranges::__assign_one<_IsMove>(__tail, __result);
+ std::__assign_one<_IsMove>(__result, __tail);
}
  return {std::move(__lasti), std::move(__result)};
}
-- 
2.46.2



[PATCH 5/7] libstdc++: Add nodiscard to std::find

2024-10-15 Thread Jonathan Wakely
Tested x86_64-linux.

-- >8 --

libstdc++-v3/ChangeLog:

* include/bits/stl_algobase.h (find): Add nodiscard.
---
 libstdc++-v3/include/bits/stl_algobase.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libstdc++-v3/include/bits/stl_algobase.h 
b/libstdc++-v3/include/bits/stl_algobase.h
index 34e1cf7322f..d9d1d00b113 100644
--- a/libstdc++-v3/include/bits/stl_algobase.h
+++ b/libstdc++-v3/include/bits/stl_algobase.h
@@ -2087,7 +2087,7 @@ _GLIBCXX_BEGIN_NAMESPACE_ALGO
*  such that @c *i == @p __val, or @p __last if no such iterator exists.
   */
   template
-_GLIBCXX20_CONSTEXPR
+_GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR
 inline _InputIterator
 find(_InputIterator __first, _InputIterator __last, const _Tp& __val)
 {
-- 
2.46.2



Re: [PATCH] libstdc++: Implement LWG 3798 for range adaptors [PR106676]

2024-10-15 Thread Jonathan Wakely
On Tue, 15 Oct 2024 at 14:30, Patrick Palka  wrote:
>
> On Mon, 14 Oct 2024, Jonathan Wakely wrote:
>
> > Tested x86_64-linux.
> >
> > -- >8 --
> >
> > LWG 3798 modified the iterator_category of the iterator types for
> > transform_view, join_with_view, zip_transform_view and
> > adjacent_transform_view, to allow the iterator's reference type to be an
> > rvalue reference.
> >
> > libstdc++-v3/ChangeLog:
> >
> >   PR libstdc++/106676
> >   * include/bits/iterator_concepts.h (__cpp17_fwd_iterator): Use
> >   is_reference instead of is_value_reference.
> >   rvalue references.
> >   * include/std/ranges (transform_view:__iter_cat::_S_iter_cat):
> >   Likewise.
> >   (zip_transform_view::__iter_cat::_S_iter_cat): Likewise.
> >   (adjacent_transform_view::__iter_cat::_S_iter_cat): Likewise.
> >   (join_with_view::__iter_cat::_S_iter_cat): Likewise.
> >   * testsuite/std/ranges/adaptors/transform.cc: Check
> >   iterator_category when the transformation function returns an
> >   rvalue reference type.
> > ---
> >  libstdc++-v3/include/bits/iterator_concepts.h|  4 +++-
> >  libstdc++-v3/include/std/ranges  | 16 
> >  .../testsuite/std/ranges/adaptors/transform.cc   | 16 
> >  3 files changed, 31 insertions(+), 5 deletions(-)
> >
> > diff --git a/libstdc++-v3/include/bits/iterator_concepts.h 
> > b/libstdc++-v3/include/bits/iterator_concepts.h
> > index 490a362cdf1..669d3ddfd1e 100644
> > --- a/libstdc++-v3/include/bits/iterator_concepts.h
> > +++ b/libstdc++-v3/include/bits/iterator_concepts.h
> > @@ -333,10 +333,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >   typename incrementable_traits<_Iter>::difference_type>;
> >   };
> >
> > +// _GLIBCXX_RESOLVE_LIB_DEFECTS
> > +// 3798. Rvalue reference and iterator_category
> >  template
> >concept __cpp17_fwd_iterator = __cpp17_input_iterator<_Iter>
> >   && constructible_from<_Iter>
> > - && is_lvalue_reference_v>
> > + && is_reference_v>
> >   && same_as>,
> >  typename indirectly_readable_traits<_Iter>::value_type>
> >   && requires(_Iter __it)
> > diff --git a/libstdc++-v3/include/std/ranges 
> > b/libstdc++-v3/include/std/ranges
> > index f0d81cbea0c..941189d65c3 100644
> > --- a/libstdc++-v3/include/std/ranges
> > +++ b/libstdc++-v3/include/std/ranges
> > @@ -1892,7 +1892,9 @@ namespace views::__adaptor
> >   using _Fpc = __detail::__maybe_const_t<_Const, _Fp>;
> >   using _Base = transform_view::_Base<_Const>;
> >   using _Res = invoke_result_t<_Fpc&, range_reference_t<_Base>>;
> > - if constexpr (is_lvalue_reference_v<_Res>)
> > + // _GLIBCXX_RESOLVE_LIB_DEFECTS
> > + // 3798. Rvalue reference and iterator_category
> > + if constexpr (is_reference_v<_Res>)
> > {
> >   using _Cat
> > = typename 
> > iterator_traits>::iterator_category;
> > @@ -5047,7 +5049,9 @@ namespace views::__adaptor
> > using __detail::__range_iter_cat;
> > using _Res = invoke_result_t<__maybe_const_t<_Const, _Fp>&,
> >  
> > range_reference_t<__maybe_const_t<_Const, _Vs>>...>;
> > -   if constexpr (!is_lvalue_reference_v<_Res>)
> > +   // _GLIBCXX_RESOLVE_LIB_DEFECTS
> > +   // 3798. Rvalue reference and iterator_category
> > +   if constexpr (!is_reference_v<_Res>)
> >   return input_iterator_tag{};
> > else if constexpr ((derived_from<__range_iter_cat<_Vs, _Const>,
> >  random_access_iterator_tag> && 
> > ...))
> > @@ -5820,7 +5824,9 @@ namespace views::__adaptor
> >using _Res = invoke_result_t<__unarize<__maybe_const_t<_Const, 
> > _Fp>&, _Nm>,
> >  range_reference_t<_Base>>;
> >using _Cat = typename 
> > iterator_traits>::iterator_category;
> > -  if constexpr (!is_lvalue_reference_v<_Res>)
> > +  // _GLIBCXX_RESOLVE_LIB_DEFECTS
> > +  // 3798. Rvalue reference and iterator_category
> > +  if constexpr (!is_reference_v<_Res>)
> >   return input_iterator_tag{};
> >   

[committed] libstdc++: Populate generic std::time_get's wide %c format [PR117135]

2024-10-14 Thread Jonathan Wakely
Tested x86_64-linux. Pushed to trunk.

-- >8 --

I missed out the __timepunct specialization for the "generic"
implementation when defining the %c format in r15-4016-gc534e37faccf48.

libstdc++-v3/ChangeLog:

PR libstdc++/117135
* config/locale/generic/time_members.cc
(__timepunct::_M_initialize_timepunc): Set
_M_date_time_format for C locale. Set %Ex formats to the same
values as the %x formats.
---
 libstdc++-v3/config/locale/generic/time_members.cc | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libstdc++-v3/config/locale/generic/time_members.cc 
b/libstdc++-v3/config/locale/generic/time_members.cc
index 6619f0ca881..5012a270dd1 100644
--- a/libstdc++-v3/config/locale/generic/time_members.cc
+++ b/libstdc++-v3/config/locale/generic/time_members.cc
@@ -150,11 +150,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_M_data = new __timepunct_cache;
 
   _M_data->_M_date_format = L"%m/%d/%y";
-  _M_data->_M_date_era_format = L"%m/%d/%y";
+  _M_data->_M_date_era_format = _M_data->_M_date_format;
   _M_data->_M_time_format = L"%H:%M:%S";
-  _M_data->_M_time_era_format = L"%H:%M:%S";
-  _M_data->_M_date_time_format = L"";
-  _M_data->_M_date_time_era_format = L"";
+  _M_data->_M_time_era_format = _M_data->_M_time_format;
+  _M_data->_M_date_time_format = L"%a %b %e %T %Y";
+  _M_data->_M_date_time_era_format = _M_data->_M_date_time_format;
   _M_data->_M_am = L"AM";
   _M_data->_M_pm = L"PM";
   _M_data->_M_am_pm_format = L"%I:%M:%S %p";
-- 
2.46.2



[committed] libstdc++: Constrain std::expected comparisons (P3379R0)

2024-10-14 Thread Jonathan Wakely
Tested x86_64-linux. Pushed to trunk.

-- >8 --

This proposal of mine has been approved by LEWG and forwarded to LWG. I
expect it to be voted into the draft without significant changes.

libstdc++-v3/ChangeLog:

* include/bits/version.def (constrained_equality): Bump value.
* include/bits/version.h: Regenerate.
* include/std/expected (operator==): Add constraints and
noexcept specifiers.
* testsuite/20_util/optional/relops/constrained.cc: Adjust
check for feature test macro.
* testsuite/20_util/pair/comparison_operators/constrained.cc:
Likewise.
* testsuite/20_util/tuple/comparison_operators/constrained.cc:
Likewise.
* testsuite/20_util/variant/relops/constrained.cc: Likewise.
* testsuite/20_util/expected/equality_constrained.cc: New test.
---
 libstdc++-v3/include/bits/version.def |   2 +-
 libstdc++-v3/include/bits/version.h   |   4 +-
 libstdc++-v3/include/std/expected |  31 ++-
 .../20_util/expected/equality_constrained.cc  | 181 ++
 .../20_util/optional/relops/constrained.cc|   2 +-
 .../pair/comparison_operators/constrained.cc  |   2 +-
 .../tuple/comparison_operators/constrained.cc |   2 +-
 .../20_util/variant/relops/constrained.cc |   2 +-
 8 files changed, 213 insertions(+), 13 deletions(-)
 create mode 100644 
libstdc++-v3/testsuite/20_util/expected/equality_constrained.cc

diff --git a/libstdc++-v3/include/bits/version.def 
b/libstdc++-v3/include/bits/version.def
index 477651f358a..4fa820a5a4a 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -1256,7 +1256,7 @@ ftms = {
 ftms = {
   name = constrained_equality;
   values = {
-v = 202403;
+v = 202411; // FIXME: 202403 for P2944R3, ??? for P3379R0
 cxxmin = 20;
 extra_cond = "__glibcxx_three_way_comparison";
   };
diff --git a/libstdc++-v3/include/bits/version.h 
b/libstdc++-v3/include/bits/version.h
index 342ee6b4c7a..fdbee8161d9 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -1392,9 +1392,9 @@
 
 #if !defined(__cpp_lib_constrained_equality)
 # if (__cplusplus >= 202002L) && (__glibcxx_three_way_comparison)
-#  define __glibcxx_constrained_equality 202403L
+#  define __glibcxx_constrained_equality 202411L
 #  if defined(__glibcxx_want_all) || 
defined(__glibcxx_want_constrained_equality)
-#   define __cpp_lib_constrained_equality 202403L
+#   define __cpp_lib_constrained_equality 202411L
 #  endif
 # endif
 #endif /* !defined(__cpp_lib_constrained_equality) && 
defined(__glibcxx_want_constrained_equality) */
diff --git a/libstdc++-v3/include/std/expected 
b/libstdc++-v3/include/std/expected
index d4a4bc17541..7de2aeffc70 100644
--- a/libstdc++-v3/include/std/expected
+++ b/libstdc++-v3/include/std/expected
@@ -35,6 +35,7 @@
 
 #define __glibcxx_want_expected
 #define __glibcxx_want_freestanding_expected
+#define __glibcxx_want_constrained_equality
 #include 
 
 #ifdef __cpp_lib_expected // C++ >= 23 && __cpp_concepts >= 202002L
@@ -1152,10 +1153,15 @@ namespace __expected
 
   template
requires (!is_void_v<_Up>)
+ && requires (const _Tp& __t, const _Up& __u,
+  const _Er& __e, const _Er2& __e2) {
+   { __t == __u } -> convertible_to;
+   { __e == __e2 } -> convertible_to;
+ }
friend constexpr bool
operator==(const expected& __x, const expected<_Up, _Er2>& __y)
-   // FIXME: noexcept(noexcept(bool(*__x == *__y))
- // && noexcept(bool(__x.error() == __y.error(
+   noexcept(noexcept(bool(*__x == *__y))
+ && noexcept(bool(__x.error() == __y.error(
{
  if (__x.has_value())
return __y.has_value() && bool(*__x == *__y);
@@ -1164,15 +1170,22 @@ namespace __expected
}
 
   template
+   requires (!__expected::__is_expected<_Up>)
+ && requires (const _Tp& __t, const _Up& __u) {
+   { __t == __u } -> convertible_to;
+ }
friend constexpr bool
operator==(const expected& __x, const _Up& __v)
-   // FIXME: noexcept(noexcept(bool(*__x == __v)))
+   noexcept(noexcept(bool(*__x == __v)))
{ return __x.has_value() && bool(*__x == __v); }
 
   template
+   requires requires (const _Er& __e, const _Er2& __e2) {
+ { __e == __e2 } -> convertible_to;
+   }
friend constexpr bool
operator==(const expected& __x, const unexpected<_Er2>& __e)
-   // FIXME: noexcept(noexcept(bool(__x.error() == __e.error(
+   noexcept(noexcept(bool(__x.error() == __e.error(
{ return !__x.has_value() && bool(__x.error() == __e.error()); }
 
   friend constexpr void
@@ -1819,9 +1832,12 @@ namespace __expected
 
   template
requires is_void_v<_Up>
+ && requires (const _Er& __e, const _Er2& __e2) {
+   { __e == __e2 } -> convert

Re: [PATCH] libstdc++: Refactor std::uninitialized_{copy, fill, fill_n} algos [PR68350]

2024-10-14 Thread Jonathan Wakely
On Mon, 14 Oct 2024 at 14:59, Jonathan Wakely  wrote:
>
> This causes some codegen regressions on (at least) aarch64 and power64:
>
> FAIL: g++.dg/pr104547.C  -std=gnu++11  scan-tree-dump-not vrp2
> "_M_default_append"
> FAIL: g++.dg/pr104547.C  -std=gnu++17  scan-tree-dump-not vrp2
> "_M_default_append"
>
> For some reason the PR 104547 fix to stop the unused _M_default_append
> function being emitted in the assembly code no longer works.
>
> I also see new bogus stringop-overflow warnings for these tests:
>
> FAIL: 27_io/basic_ios/imbue/14072.cc  -std=gnu++17 (test for excess errors)
> FAIL: 27_io/basic_istream/extractors_character/char/9826.cc
> -std=gnu++17 (test for excess errors)
> FAIL: 27_io/basic_stringbuf/requirements/explicit_instantiation/2.cc
> -std=gnu++17 (test for excess errors)
> FAIL: 27_io/basic_stringstream/requirements/explicit_instantiation.cc
> -std=gnu++17 (test for excess errors)

Actually the bogus -Wstringop-overflow warnings are due to a different
patch I'm testing locally.

The FAIL: g++.dg/pr104547.C regression is caused by this one though.


>
>
>
>
> On Mon, 14 Oct 2024 at 00:53, Jonathan Wakely  wrote:
> >
> > Tested x86_64-linux.
> >
> > -- >8 --
> >
> > This refactors the std::uninitialized_copy, std::uninitialized_fill and
> > std::uninitialized_fill_n algorithms to directly perform memcpy/memset
> > optimizations instead of dispatching to std::copy/std::fill/std::fill_n.
> >
> > The reasons for this are:
> >
> > - Use 'if constexpr' to simplify and optimize compilation throughput, so
> >   dispatching to specialized class templates is only needed for C++98
> >   mode.
> > - Relax the conditions for using memcpy/memset, because the C++20 rules
> >   on implicit-lifetime types mean that we can rely on memcpy to begin
> >   lifetimes of trivially copyable types.  We don't need to require
> >   trivially default constructible, so don't need to limit the
> >   optimization to trivial types. See PR 68350 for more details.
> > - The conditions on non-overlapping ranges are stronger for
> >   std::uninitialized_copy than for std::copy so we can use memcpy instead
> >   of memmove, which might be a minor optimization.
> > - Avoid including  in .
> >   It only needs some iterator utilities from that file now, which belong
> >   in  anyway, so this moves them there.
> >
> > Several tests need changes to the diagnostics matched by dg-error
> > because we no longer use the __constructible() function that had a
> > static assert in. Now we just get straightforward errors for attempting
> > to use a deleted constructor.
> >
> > Two tests needed more signficant changes to the actual expected results
> > of executing the tests, because they were checking for old behaviour
> > which was incorrect according to the standard.
> > 20_util/specialized_algorithms/uninitialized_copy/64476.cc was expecting
> > std::copy to be used for a call to std::uninitialized_copy involving two
> > trivially copyable types. That was incorrect behaviour, because a
> > non-trivial constructor should have been used, but using std::copy used
> > trivial default initialization followed by assignment.
> > 20_util/specialized_algorithms/uninitialized_fill_n/sizes.cc was testing
> > the behaviour with a non-integral Size passed to uninitialized_fill_n,
> > but I wrote the test looking at the requirements of uninitialized_copy_n
> > which are not the same as uninitialized_fill_n. The former uses --n and
> > tests n > 0, but the latter just tests n-- (which will never be false
> > for a floating-point value with a fractional part).
> >
> > libstdc++-v3/ChangeLog:
> >
> > PR libstdc++/68350
> > PR libstdc++/93059
> > * include/bits/stl_algobase.h (__niter_base, __niter_wrap): Move
> > to ...
> > * include/bits/stl_iterator.h: ... here.
> > * include/bits/stl_uninitialized.h (__check_constructible)
> > (_GLIBCXX_USE_ASSIGN_FOR_INIT): Remove.
> > [C++98] (__unwrappable_niter): New trait.
> > (__uninitialized_copy): Replace use of std::copy.
> > (uninitialized_copy): Fix Doxygen comments. Open-code memcpy
> > optimization for C++11 and later.
> > (__uninitialized_fill): Replace use of std::fill.
> > (uninitialized_fill): Fix Doxygen comments. Open-code memset
> > optimization for C++11 and later.
> > (__uninitialized_fill_n): Replace use of std::fill_n.
> > (uninitialized_fill_n): Fix Doxyg

Re: [PATCH] libstdc++: Refactor std::uninitialized_{copy, fill, fill_n} algos [PR68350]

2024-10-14 Thread Jonathan Wakely
This causes some codegen regressions on (at least) aarch64 and power64:

FAIL: g++.dg/pr104547.C  -std=gnu++11  scan-tree-dump-not vrp2
"_M_default_append"
FAIL: g++.dg/pr104547.C  -std=gnu++17  scan-tree-dump-not vrp2
"_M_default_append"

For some reason the PR 104547 fix to stop the unused _M_default_append
function being emitted in the assembly code no longer works.

I also see new bogus stringop-overflow warnings for these tests:

FAIL: 27_io/basic_ios/imbue/14072.cc  -std=gnu++17 (test for excess errors)
FAIL: 27_io/basic_istream/extractors_character/char/9826.cc
-std=gnu++17 (test for excess errors)
FAIL: 27_io/basic_stringbuf/requirements/explicit_instantiation/2.cc
-std=gnu++17 (test for excess errors)
FAIL: 27_io/basic_stringstream/requirements/explicit_instantiation.cc
-std=gnu++17 (test for excess errors)





On Mon, 14 Oct 2024 at 00:53, Jonathan Wakely  wrote:
>
> Tested x86_64-linux.
>
> -- >8 --
>
> This refactors the std::uninitialized_copy, std::uninitialized_fill and
> std::uninitialized_fill_n algorithms to directly perform memcpy/memset
> optimizations instead of dispatching to std::copy/std::fill/std::fill_n.
>
> The reasons for this are:
>
> - Use 'if constexpr' to simplify and optimize compilation throughput, so
>   dispatching to specialized class templates is only needed for C++98
>   mode.
> - Relax the conditions for using memcpy/memset, because the C++20 rules
>   on implicit-lifetime types mean that we can rely on memcpy to begin
>   lifetimes of trivially copyable types.  We don't need to require
>   trivially default constructible, so don't need to limit the
>   optimization to trivial types. See PR 68350 for more details.
> - The conditions on non-overlapping ranges are stronger for
>   std::uninitialized_copy than for std::copy so we can use memcpy instead
>   of memmove, which might be a minor optimization.
> - Avoid including  in .
>   It only needs some iterator utilities from that file now, which belong
>   in  anyway, so this moves them there.
>
> Several tests need changes to the diagnostics matched by dg-error
> because we no longer use the __constructible() function that had a
> static assert in. Now we just get straightforward errors for attempting
> to use a deleted constructor.
>
> Two tests needed more signficant changes to the actual expected results
> of executing the tests, because they were checking for old behaviour
> which was incorrect according to the standard.
> 20_util/specialized_algorithms/uninitialized_copy/64476.cc was expecting
> std::copy to be used for a call to std::uninitialized_copy involving two
> trivially copyable types. That was incorrect behaviour, because a
> non-trivial constructor should have been used, but using std::copy used
> trivial default initialization followed by assignment.
> 20_util/specialized_algorithms/uninitialized_fill_n/sizes.cc was testing
> the behaviour with a non-integral Size passed to uninitialized_fill_n,
> but I wrote the test looking at the requirements of uninitialized_copy_n
> which are not the same as uninitialized_fill_n. The former uses --n and
> tests n > 0, but the latter just tests n-- (which will never be false
> for a floating-point value with a fractional part).
>
> libstdc++-v3/ChangeLog:
>
> PR libstdc++/68350
> PR libstdc++/93059
> * include/bits/stl_algobase.h (__niter_base, __niter_wrap): Move
> to ...
> * include/bits/stl_iterator.h: ... here.
> * include/bits/stl_uninitialized.h (__check_constructible)
> (_GLIBCXX_USE_ASSIGN_FOR_INIT): Remove.
> [C++98] (__unwrappable_niter): New trait.
> (__uninitialized_copy): Replace use of std::copy.
> (uninitialized_copy): Fix Doxygen comments. Open-code memcpy
> optimization for C++11 and later.
> (__uninitialized_fill): Replace use of std::fill.
> (uninitialized_fill): Fix Doxygen comments. Open-code memset
> optimization for C++11 and later.
> (__uninitialized_fill_n): Replace use of std::fill_n.
> (uninitialized_fill_n): Fix Doxygen comments. Open-code memset
> optimization for C++11 and later.
> * 
> testsuite/20_util/specialized_algorithms/uninitialized_copy/64476.cc:
> Adjust expected behaviour to match what the standard specifies.
> * 
> testsuite/20_util/specialized_algorithms/uninitialized_fill_n/sizes.cc:
> Likewise.
> * testsuite/20_util/specialized_algorithms/uninitialized_copy/1.cc:
> Adjust dg-error directives.
> * 
> testsuite/20_util/specialized_algorithms/uninitialized_copy/89164.cc:
> Likewise.
> * 
> testsuite/20_util/specialized_algorithms/unin

Re: [PATCH] aarch64: libstdc++: Use shufflevector instead of shuffle in opt_random.h

2024-10-14 Thread Jonathan Wakely
On Mon, 14 Oct 2024 at 14:36, Kyrylo Tkachov  wrote:
>
>
>
> > On 14 Oct 2024, at 15:28, Ricardo Jesus  wrote:
> >
> > External email: Use caution opening links or attachments
> >
> >
> > This patch modifies the implementation of the vectorized mersenne
> > twister random number generator to use __builtin_shufflevector instead
> > of __builtin_shuffle. This makes it (almost) compatible with Clang.
> >
> > To make the implementation fully compatible with Clang, Clang will need
> > to support internal Neon types like __Uint8x16_t and __Uint32x4_t, which
> > currently it does not. This looks like an oversight in Clang and so will
> > be addressed separately.
> >
> > I see no codegen change with this patch.
>
> FWIW the change looks ok to me from an aarch64 perspective.
> The only potential problem could have been a compile error so as long as the 
> CI buildbots are happy I think this would be safe to take.

OK thanks for looking. I'll wait to see that CI is green (thanks for
resubmitting it, Ricardo!) and then push it.


> Thanks,
> Kyrill
>
> >
> > Bootstrapped and tested on aarch64-none-linux-gnu.
> >
> > Signed-off-by: Ricardo Jesus 
> >
> > 2024-09-05  Ricardo Jesus  
> >
> >* config/cpu/aarch64/opt/ext/opt_random.h (__VEXT): Replace uses
> >of __builtin_shuffle with __builtin_shufflevector.
> >(__aarch64_lsl_128): Move shift amount to a template parameter.
> >(__aarch64_lsr_128): Move shift amount to a template parameter.
> >(__aarch64_recursion): Update call sites of __aarch64_lsl_128
> >and __aarch64_lsr_128.
> > ---
> > .../config/cpu/aarch64/opt/ext/opt_random.h   | 28 +++
> > 1 file changed, 16 insertions(+), 12 deletions(-)
> >
> > diff --git a/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h 
> > b/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h
> > index 7f756d1572f..7eb816abcd0 100644
> > --- a/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h
> > +++ b/libstdc++-v3/config/cpu/aarch64/opt/ext/opt_random.h
> > @@ -35,13 +35,13 @@
> > #ifdef __ARM_NEON
> >
> > #ifdef __ARM_BIG_ENDIAN
> > -# define __VEXT(_A,_B,_C) __builtin_shuffle (_A, _B, (__Uint8x16_t) \
> > -{16-_C, 17-_C, 18-_C, 19-_C, 20-_C, 21-_C, 22-_C, 23-_C, \
> > - 24-_C, 25-_C, 26-_C, 27-_C, 28-_C, 29-_C, 30-_C, 31-_C})
> > +# define __VEXT(_A,_B,_C) __builtin_shufflevector (_A, _B, \
> > +16-_C, 17-_C, 18-_C, 19-_C, 20-_C, 21-_C, 22-_C, 23-_C, \
> > +24-_C, 25-_C, 26-_C, 27-_C, 28-_C, 29-_C, 30-_C, 31-_C)
> > #else
> > -# define __VEXT(_A,_B,_C) __builtin_shuffle (_B, _A, (__Uint8x16_t) \
> > -{_C, _C+1, _C+2, _C+3, _C+4, _C+5, _C+6, _C+7, \
> > - _C+8, _C+9, _C+10, _C+11, _C+12, _C+13, _C+14, _C+15})
> > +# define __VEXT(_A,_B,_C) __builtin_shufflevector (_B, _A, \
> > +_C, _C+1, _C+2, _C+3, _C+4, _C+5, _C+6, _C+7, \
> > +_C+8, _C+9, _C+10, _C+11, _C+12, _C+13, _C+14, _C+15)
> > #endif
> >
> > #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
> > @@ -52,9 +52,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >   namespace {
> > // Logical Shift right 128-bits by c * 8 bits
> >
> > -__extension__ extern __inline __Uint32x4_t
> > +__extension__
> > +template
> > +extern __inline __Uint32x4_t
> > __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> > -__aarch64_lsr_128 (__Uint8x16_t __a, __const int __c)
> > +__aarch64_lsr_128 (__Uint8x16_t __a)
> > {
> >   const __Uint8x16_t __zero = {0, 0, 0, 0, 0, 0, 0, 0,
> >   0, 0, 0, 0, 0, 0, 0, 0};
> > @@ -64,9 +66,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >
> > // Logical Shift left 128-bits by c * 8 bits
> >
> > -__extension__ extern __inline __Uint32x4_t
> > +__extension__
> > +template
> > +extern __inline __Uint32x4_t
> > __attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
> > -__aarch64_lsl_128 (__Uint8x16_t __a, __const int __c)
> > +__aarch64_lsl_128 (__Uint8x16_t __a)
> > {
> >   const __Uint8x16_t __zero = {0, 0, 0, 0, 0, 0, 0, 0,
> >   0, 0, 0, 0, 0, 0, 0, 0};
> > @@ -82,14 +86,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> >   __Uint32x4_t __e)
> > {
> >   __Uint32x4_t __y = (__b >> __sr1);
> > -  __Uint32x4_t __z = __aarch64_lsr_128 ((__Uint8x16_t) __c, __sr2);
> > +  __Uint32x4_t __z = __aarch64_lsr_128<__sr2> ((__Uint8x16_t) __c);
> >
> >   __Uint32x4_t __v = __d << __sl1;
> >
> >   __z = __z ^ __a;
> >   __z = __z ^ __v;
> >
> > -  __Uint32x4_t __x = __aarch64_lsl_128 ((__Uint8x16_t) __a, __sl2);
> > +  __Uint32x4_t __x = __aarch64_lsl_128<__sl2> ((__Uint8x16_t) __a);
> >
> >   __y = __y & __e;
> >   __z = __z ^ __x;
> > --
> > 2.44.0
> >
>



Re: libstdc++ fetch_add & fenv -- ecosystem questions

2024-10-14 Thread Jonathan Wakely
On Mon, 14 Oct 2024 at 14:35, Jonathan Wakely  wrote:
>
> N.B. please CC the libstdc++ list for libstdc++ topics.
>
> On Mon, 14 Oct 2024 at 14:00, Matthew Malcomson  wrote:
> >
> > After getting GCC to handle floating point exceptions I'm now noticing that 
> > the `targetm.atomic_assign_expand_fenv` hook tends to use the library 
> > function `__atomic_feraiseexcept`.
> > This requires adding -latomic to the command line where it wasn't needed 
> > before.
> > I also notice that the inline CAS loop for libstdc++ `atomic::fetch_add` 
> > on floating point types doesn't handle these floating point exceptions.
>
> Right, Joseph made the C front-end handle them for _Atomic but I
> didn't do that for std::atomic.
>
> > For context, clang (which has already implemented floating point fetch_add 
> > for floating point types) is not emitting anything to handle the floating 
> > point environment.

I'm not sure if C++ users really care about fenv. I think most don't.


> >
> > I expect that the eventual goal should be (please do correct if you 
> > disagree)
> >
> > Update the existing libstdc++ CAS loop to handle floating point exceptions.
> > Suggest to clang that the fetch_add builtin should handle floating point 
> > exceptions.
> > GCC builtin handles floating point exceptions.
> > __atomic_feraiseexcept should be a builtin to avoid previously unnecessary 
> > requirement to link libatomic.
> >
> > However I'm uncertain we could sort all that out for GCC 15.
> > Would it be reasonable to require linking with libatomic for the GCC 15 
> > release?
>
> That would be a regression for anybody using
> std::atomic today.
>
> > Alternatively is there some other intermediate step that people would 
> > prefer?
> > Similarly — maybe there's something I'm missing — maybe about differences 
> > between C/C++?
> >
> > Another option is to aim for implementing the functionality of 
> > __atomic_feraiseexcept inline in the fetch_add GCC 15 (a bit tight on 
> > time), to use it in the new fetch_add builtin overload, but not use it in 
> > the CAS loop.
> > That way no compiler & floating point type combination would need linking 
> > libatomic, current clang would not handle floating point exception 
> > information, while current gcc would handle that information.
> >
> > What are your thoughts?
>
> If making it Just Work without a new libatomic requirement is
> possible, I'd prefer that.
>
> > Regards,
> > Matthew
> >
> > 
> > From: Joseph Myers 
> > Sent: 19 September 2024 10:38 PM
> > To: Matthew Malcomson 
> > Cc: gcc-patches@gcc.gnu.org ; Jonathan Wakely 
> > ; Richard Biener 
> > Subject: Re: [PATCH 0/8] [RFC] Introduce floating point fetch_add builtins
> >
> > External email: Use caution opening links or attachments
> >
> >
> > On Thu, 19 Sep 2024, mmalcom...@nvidia.com wrote:
> >
> > > 6) Anything special about floating point maths that I'm tripping up on?
> >
> > Correct atomic operations with floating-point operands should ensure that
> > exceptions raised exactly correspond to the operands for which the
> > operation succeeded, and not to the operands for any previous attempts
> > where the compare-exchange failed.  There is a lengthy note in the C
> > standard (in C11 it's a footnote in 6.5.16.2, in C17 it's a Note in
> > 6.5.16.2 and in C23 that subclause has become 6.5.17.3) that discusses
> > appropriate code sequences to achieve this.  In GCC the implementation of
> > this is in c-typeck.cc:build_atomic_assign, which in turn calls
> > targetm.atomic_assign_expand_fenv (note that we have the complication for
> > C of not introducing libm dependencies in code that only uses standard
> > language features and not ,  or , so direct use
> > of  functions is inappropriate here).
> >
> > I would expect such built-in functions to follow the same semantics for
> > floating-point exceptions as _Atomic compound assignment does.  (Note that
> > _Atomic compound assignment is more general in the allowed operands,
> > because compound assignment is a heterogeneous operation - for example,
> > the special floating-point logic in build_atomic_assign includes the case
> > where the LHS of the compound assignment is of atomic integer type but the
> > RHS is of floating type.  However, built-in functions allow memory orders
> > other than seq_cst to be used, whereas _Atomic compound assignment is
> > limited

Re: libstdc++ fetch_add & fenv -- ecosystem questions

2024-10-14 Thread Jonathan Wakely
N.B. please CC the libstdc++ list for libstdc++ topics.

On Mon, 14 Oct 2024 at 14:00, Matthew Malcomson  wrote:
>
> After getting GCC to handle floating point exceptions I'm now noticing that 
> the `targetm.atomic_assign_expand_fenv` hook tends to use the library 
> function `__atomic_feraiseexcept`.
> This requires adding -latomic to the command line where it wasn't needed 
> before.
> I also notice that the inline CAS loop for libstdc++ `atomic::fetch_add` 
> on floating point types doesn't handle these floating point exceptions.

Right, Joseph made the C front-end handle them for _Atomic but I
didn't do that for std::atomic.

> For context, clang (which has already implemented floating point fetch_add 
> for floating point types) is not emitting anything to handle the floating 
> point environment.
>
> I expect that the eventual goal should be (please do correct if you disagree)
>
> Update the existing libstdc++ CAS loop to handle floating point exceptions.
> Suggest to clang that the fetch_add builtin should handle floating point 
> exceptions.
> GCC builtin handles floating point exceptions.
> __atomic_feraiseexcept should be a builtin to avoid previously unnecessary 
> requirement to link libatomic.
>
> However I'm uncertain we could sort all that out for GCC 15.
> Would it be reasonable to require linking with libatomic for the GCC 15 
> release?

That would be a regression for anybody using
std::atomic today.

> Alternatively is there some other intermediate step that people would prefer?
> Similarly — maybe there's something I'm missing — maybe about differences 
> between C/C++?
>
> Another option is to aim for implementing the functionality of 
> __atomic_feraiseexcept inline in the fetch_add GCC 15 (a bit tight on time), 
> to use it in the new fetch_add builtin overload, but not use it in the CAS 
> loop.
> That way no compiler & floating point type combination would need linking 
> libatomic, current clang would not handle floating point exception 
> information, while current gcc would handle that information.
>
> What are your thoughts?

If making it Just Work without a new libatomic requirement is
possible, I'd prefer that.

> Regards,
> Matthew
>
> 
> From: Joseph Myers 
> Sent: 19 September 2024 10:38 PM
> To: Matthew Malcomson 
> Cc: gcc-patches@gcc.gnu.org ; Jonathan Wakely 
> ; Richard Biener 
> Subject: Re: [PATCH 0/8] [RFC] Introduce floating point fetch_add builtins
>
> External email: Use caution opening links or attachments
>
>
> On Thu, 19 Sep 2024, mmalcom...@nvidia.com wrote:
>
> > 6) Anything special about floating point maths that I'm tripping up on?
>
> Correct atomic operations with floating-point operands should ensure that
> exceptions raised exactly correspond to the operands for which the
> operation succeeded, and not to the operands for any previous attempts
> where the compare-exchange failed.  There is a lengthy note in the C
> standard (in C11 it's a footnote in 6.5.16.2, in C17 it's a Note in
> 6.5.16.2 and in C23 that subclause has become 6.5.17.3) that discusses
> appropriate code sequences to achieve this.  In GCC the implementation of
> this is in c-typeck.cc:build_atomic_assign, which in turn calls
> targetm.atomic_assign_expand_fenv (note that we have the complication for
> C of not introducing libm dependencies in code that only uses standard
> language features and not ,  or , so direct use
> of  functions is inappropriate here).
>
> I would expect such built-in functions to follow the same semantics for
> floating-point exceptions as _Atomic compound assignment does.  (Note that
> _Atomic compound assignment is more general in the allowed operands,
> because compound assignment is a heterogeneous operation - for example,
> the special floating-point logic in build_atomic_assign includes the case
> where the LHS of the compound assignment is of atomic integer type but the
> RHS is of floating type.  However, built-in functions allow memory orders
> other than seq_cst to be used, whereas _Atomic compound assignment is
> limited to the seq_cst case.)
>
> So it would seem appropriate for the implementation of such built-in
> functions to make use of targetm.atomic_assign_expand_fenv for
> floating-point environment handling, and for testcases to include tests
> analogous to c11-atomic-exec-5.c that exceptions are being handled
> correctly.
>
> Cf. N2329 which suggested such operations for C in  (but
> tried to do to many things in one paper to be accepted into C); it didn't
> go into the floating-point exceptions semantics but simple correctness
> would indicate avoiding spurious exceptions from discarded computations.
>
> --
> Joseph S. Myers
> josmy...@redhat.com
>



[PATCH] libstdc++: debug output in 22_locale/time_get/get/wchar_t/5.cc [PR117135]

2024-10-14 Thread Jonathan Wakely
This is not going to be committed.

This is just for arm-none-eabi CI testing, re PR 117135.

libstdc++-v3/ChangeLog:

* testsuite/22_locale/time_get/get/wchar_t/5.cc: Dump debugging
info.
---
 .../testsuite/22_locale/time_get/get/wchar_t/5.cc   | 13 +
 1 file changed, 13 insertions(+)

diff --git a/libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/5.cc 
b/libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/5.cc
index 254ae96acd1..79c8a56f04a 100644
--- a/libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/5.cc
+++ b/libstdc++-v3/testsuite/22_locale/time_get/get/wchar_t/5.cc
@@ -11,7 +11,20 @@ int main()
   std::wistringstream ss(L"Fri Jul 5 14:58:21 2019");
   std::ios::iostate err = std::ios::goodbit;
   std::tm tm = {};
+
+  const auto& punct = 
std::use_facet>(std::locale::classic());
+  const wchar_t* formats[2];
+  punct._M_date_time_formats(formats);
+  __builtin_printf("Wide D_T_FMT for C locale: ");
+  std::wstring fmt(formats[0]);
+  for (wchar_t c : fmt)
+__builtin_printf("%c", (char)c);
+  __builtin_puts("");
+
   fac.get(ss, Facet::iter_type(), ss, err, &tm, 'c');
+  __builtin_printf("eofbit: %d failbit: %d badbit: %d\n",
+  (int)(err & std::ios::eofbit), (int)(err & std::ios::failbit),
+  (int)(err & std::ios::badbit));
   VERIFY( err == std::ios::eofbit );
   VERIFY( tm.tm_year == 119 );
   VERIFY( tm.tm_mon == 6 );
-- 
2.46.2



  1   2   3   4   5   6   7   8   9   10   >