Re: [PATCH] libstdc++: Make __gnu_debug::vector usable in constant expressions [PR109536]

2023-12-16 Thread Jonathan Wakely
On Sat, 16 Dec 2023 at 16:26, Patrick Palka  wrote:
>
> On Sat, 16 Dec 2023, Jonathan Wakely wrote:
>
> > On Sat, 16 Dec 2023 at 09:14, Jonathan Wakely wrote:
> > >
> > > On Sat, 16 Dec 2023 at 00:27, Patrick Palka wrote:
> > > >
> > > > On Wed, 6 Dec 2023, Jonathan Wakely wrote:
> > > >
> > > > > Any comments on this approach?
> > > > >
> > > > > -- >8 --
> > > > >
> > > > > This makes constexpr std::vector (mostly) work in Debug Mode. All safe
> > > > > iterator instrumentation and checking is disabled during constant
> > > > > evaluation, because it requires mutex locks and calls to non-inline
> > > > > functions defined in libstdc++.so. It should be OK to disable the 
> > > > > safety
> > > > > checks, because most UB should be detected during constant evaluation
> > > > > anyway.
> > > > >
> > > > > We could try to enable the full checking in constexpr, but it would 
> > > > > mean
> > > > > wrapping all the non-inline functions like _M_attach with an inline
> > > > > _M_constexpr_attach that does the iterator housekeeping inline without
> > > > > mutex locks when calling for constant evaluation, and calls the
> > > > > non-inline function at runtime. That could be done in future if we 
> > > > > find
> > > > > that we've lost safety or useful checking by disabling the safe
> > > > > iterators.
> > > > >
> > > > > There are a few test failures in C++20 mode, which I'm unable to
> > > > > explain. The _Safe_iterator::operator++() member gives errors for 
> > > > > using
> > > > > non-constexpr functions during constant evaluation, even though those
> > > > > functions are guarded by std::is_constant_evaluated() checks. The same
> > > > > code works fine for C++23 and up.
> > > >
> > > > AFAICT these C++20 test failures are really due to the variable
> > > > definition of non-literal type
> > > >
> > > > 381__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
> > > >
> > > > which were prohibited in a constexpr function (even if that code was
> > > > never executed) until C++23's P2242R3.
> > >
> > > Ah, I figured it was a core change but I couldn't recall which one. 
> > > Thanks.
>
> Yeah the diagnostic blaming the non-constexpr call to _M_incrementable
> was outright wrong and misleading, I filed PR113041 about that.
>
> > >
> > > > We can use an immediately invoked lambda to work around this:
> > > >
> > > > 381[this] {
> > > > 382  __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
> > > > 383  ++base();
> > > > 384}();
> > > > 385return *this;
> > >
> > > We'd need some #if as this code has to work for C++98. But that's doable.
> >
> > The attached patch seems simpler, I'm testing it now.
>
> Would the operator+=, operator-= and the copy assign operator= also need
> adjustment?

Maybe ... which suggest we have missing tests for constexpr vector
(which is probably the case).


>
> We could somewhat cleanly encapsulate the lambda workaround with a pair
> of macros surrounding the problematic variable, something like:
>
> diff --git a/libstdc++-v3/include/debug/safe_iterator.h 
> b/libstdc++-v3/include/debug/safe_iterator.h
> index 26f008982f8..df3b4d33f04 100644
> --- a/libstdc++-v3/include/debug/safe_iterator.h
> +++ b/libstdc++-v3/include/debug/safe_iterator.h
> @@ -360,6 +360,14 @@ namespace __gnu_debug
> return base().operator->();
>}
>
> +#if __cplusplus >= 202002L && __cpp_constexpr < 202110L
> +# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN [&] { do
> +# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END while(false); }()
> +#else
> +# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN do
> +# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END while(false)

I think for the limited uses in this file, we don't even need the
do-while, as the code we're enclosing is not a single statement
anyway.


> +#endif
> +
>// -- Input iterator requirements --
>/**
> *  @brief Iterator preincrement
> @@ -378,8 +386,10 @@ namespace __gnu_debug
> _GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
>   _M_message(__msg_bad_inc)
>   ._M_iterator(*this, "this"));
> -   __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
> -   ++base();
> +   _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN {
> + __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
> + ++base();
> +   } _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END;
> return *this;
>}
>

Yeah, I'll check if other operators need it, and if it's more than
just the two places in my patch I'll go with that.

If I don't get around to it (as I'm meant to have stopped work for the
year yesterday) then feel free to do that.


Re: [PATCH] libstdc++: Make __gnu_debug::vector usable in constant expressions [PR109536]

2023-12-16 Thread Patrick Palka
On Sat, 16 Dec 2023, Jonathan Wakely wrote:

> On Sat, 16 Dec 2023 at 09:14, Jonathan Wakely wrote:
> >
> > On Sat, 16 Dec 2023 at 00:27, Patrick Palka wrote:
> > >
> > > On Wed, 6 Dec 2023, Jonathan Wakely wrote:
> > >
> > > > Any comments on this approach?
> > > >
> > > > -- >8 --
> > > >
> > > > This makes constexpr std::vector (mostly) work in Debug Mode. All safe
> > > > iterator instrumentation and checking is disabled during constant
> > > > evaluation, because it requires mutex locks and calls to non-inline
> > > > functions defined in libstdc++.so. It should be OK to disable the safety
> > > > checks, because most UB should be detected during constant evaluation
> > > > anyway.
> > > >
> > > > We could try to enable the full checking in constexpr, but it would mean
> > > > wrapping all the non-inline functions like _M_attach with an inline
> > > > _M_constexpr_attach that does the iterator housekeeping inline without
> > > > mutex locks when calling for constant evaluation, and calls the
> > > > non-inline function at runtime. That could be done in future if we find
> > > > that we've lost safety or useful checking by disabling the safe
> > > > iterators.
> > > >
> > > > There are a few test failures in C++20 mode, which I'm unable to
> > > > explain. The _Safe_iterator::operator++() member gives errors for using
> > > > non-constexpr functions during constant evaluation, even though those
> > > > functions are guarded by std::is_constant_evaluated() checks. The same
> > > > code works fine for C++23 and up.
> > >
> > > AFAICT these C++20 test failures are really due to the variable
> > > definition of non-literal type
> > >
> > > 381__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
> > >
> > > which were prohibited in a constexpr function (even if that code was
> > > never executed) until C++23's P2242R3.
> >
> > Ah, I figured it was a core change but I couldn't recall which one. Thanks.

Yeah the diagnostic blaming the non-constexpr call to _M_incrementable
was outright wrong and misleading, I filed PR113041 about that.

> >
> > > We can use an immediately invoked lambda to work around this:
> > >
> > > 381[this] {
> > > 382  __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
> > > 383  ++base();
> > > 384}();
> > > 385return *this;
> >
> > We'd need some #if as this code has to work for C++98. But that's doable.
> 
> The attached patch seems simpler, I'm testing it now.

Would the operator+=, operator-= and the copy assign operator= also need
adjustment?

We could somewhat cleanly encapsulate the lambda workaround with a pair
of macros surrounding the problematic variable, something like:

diff --git a/libstdc++-v3/include/debug/safe_iterator.h 
b/libstdc++-v3/include/debug/safe_iterator.h
index 26f008982f8..df3b4d33f04 100644
--- a/libstdc++-v3/include/debug/safe_iterator.h
+++ b/libstdc++-v3/include/debug/safe_iterator.h
@@ -360,6 +360,14 @@ namespace __gnu_debug
return base().operator->();
   }
 
+#if __cplusplus >= 202002L && __cpp_constexpr < 202110L
+# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN [&] { do
+# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END while(false); }()
+#else
+# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN do
+# define _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END while(false)
+#endif
+
   // -- Input iterator requirements --
   /**
*  @brief Iterator preincrement
@@ -378,8 +386,10 @@ namespace __gnu_debug
_GLIBCXX_DEBUG_VERIFY(this->_M_incrementable(),
  _M_message(__msg_bad_inc)
  ._M_iterator(*this, "this"));
-   __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
-   ++base();
+   _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_BEGIN {
+ __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
+ ++base();
+   } _GLIBCXX20_CONSTEXPR_NON_LITERAL_SCOPE_END;
return *this;
   }
 



Re: [PATCH] libstdc++: Make __gnu_debug::vector usable in constant expressions [PR109536]

2023-12-16 Thread Jonathan Wakely
On Sat, 16 Dec 2023 at 09:14, Jonathan Wakely wrote:
>
> On Sat, 16 Dec 2023 at 00:27, Patrick Palka wrote:
> >
> > On Wed, 6 Dec 2023, Jonathan Wakely wrote:
> >
> > > Any comments on this approach?
> > >
> > > -- >8 --
> > >
> > > This makes constexpr std::vector (mostly) work in Debug Mode. All safe
> > > iterator instrumentation and checking is disabled during constant
> > > evaluation, because it requires mutex locks and calls to non-inline
> > > functions defined in libstdc++.so. It should be OK to disable the safety
> > > checks, because most UB should be detected during constant evaluation
> > > anyway.
> > >
> > > We could try to enable the full checking in constexpr, but it would mean
> > > wrapping all the non-inline functions like _M_attach with an inline
> > > _M_constexpr_attach that does the iterator housekeeping inline without
> > > mutex locks when calling for constant evaluation, and calls the
> > > non-inline function at runtime. That could be done in future if we find
> > > that we've lost safety or useful checking by disabling the safe
> > > iterators.
> > >
> > > There are a few test failures in C++20 mode, which I'm unable to
> > > explain. The _Safe_iterator::operator++() member gives errors for using
> > > non-constexpr functions during constant evaluation, even though those
> > > functions are guarded by std::is_constant_evaluated() checks. The same
> > > code works fine for C++23 and up.
> >
> > AFAICT these C++20 test failures are really due to the variable
> > definition of non-literal type
> >
> > 381__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
> >
> > which were prohibited in a constexpr function (even if that code was
> > never executed) until C++23's P2242R3.
>
> Ah, I figured it was a core change but I couldn't recall which one. Thanks.
>
> > We can use an immediately invoked lambda to work around this:
> >
> > 381[this] {
> > 382  __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
> > 383  ++base();
> > 384}();
> > 385return *this;
>
> We'd need some #if as this code has to work for C++98. But that's doable.

The attached patch seems simpler, I'm testing it now.
commit 5d70c6c2965647077749a869e9cdbf7e91dba4c7
Author: Jonathan Wakely 
Date:   Sat Dec 16 09:31:40 2023

libstdc++: Fix errors for constexpr __gnu_debug::vector in C++23 [PR109536]

In the commit log for r14-6553-g7d00a59229ee17 I noted some tests FAIL
in C++20 mode. Patrick identified that they were due to the variable
definitions of non-literal type __scoped_lock, which were prohibited in
a constexpr function (even if that code was never executed) until
C++23's P2242R3.

We can move the problematic code into new non-constexpr functions that
are not called during constant evaluation.

There's also a warning about a constexpr _M_swap function which is never
defined. That's simply because I added the _GLIBCXX20_CONSTEXPR macro on
a member that doesn't need it.

libstdc++-v3/ChangeLog:

PR libstdc++/109536
* include/debug/safe_base.h (_Safe_sequence_base::_M_swap):
Remove _GLIBCXX20_CONSTEXPR from non-inline member function.
* include/debug/safe_iterator.h (_Safe_iterator::_M_move_assign)

diff --git a/libstdc++-v3/include/debug/safe_base.h 
b/libstdc++-v3/include/debug/safe_base.h
index d9c17b52b48..1519ad809a4 100644
--- a/libstdc++-v3/include/debug/safe_base.h
+++ b/libstdc++-v3/include/debug/safe_base.h
@@ -268,7 +268,6 @@ namespace __gnu_debug
  *  operation is complete all iterators that originally referenced
  *  one container now reference the other container.
  */
-_GLIBCXX20_CONSTEXPR
 void
 _M_swap(_Safe_sequence_base& __x) _GLIBCXX_USE_NOEXCEPT;
 
diff --git a/libstdc++-v3/include/debug/safe_iterator.h 
b/libstdc++-v3/include/debug/safe_iterator.h
index 26f008982f8..bde34e1f99c 100644
--- a/libstdc++-v3/include/debug/safe_iterator.h
+++ b/libstdc++-v3/include/debug/safe_iterator.h
@@ -295,7 +295,13 @@ namespace __gnu_debug
base() = __x.base();
return *this;
  }
+   _M_move_assign(std::move(__x));
+   return *this;
+  }
 
+  void
+  _M_move_assign(_Safe_iterator&& __x) noexcept
+  {
_GLIBCXX_DEBUG_VERIFY(!__x._M_singular()
  || __x._M_value_initialized(),
  _M_message(__msg_copy_singular)
@@ -303,7 +309,7 @@ namespace __gnu_debug
  ._M_iterator(__x, "other"));
 
if (std::__addressof(__x) == this)
- return *this;
+ return;
 
if (this->_M_sequence && this->_M_sequence == __x._M_sequence)
  {
@@ -320,7 +326,6 @@ namespace __gnu_debug
 
__x._M_detach();
__x.base() = _Iterator();
-   return *this;
   }
 #endif
 
@@ -370,17 +375,20 @@ namespace __gnu_debug
   operator++() _GLIBCXX_NOEXCEPT
   {
if 

Re: [PATCH] libstdc++: Make __gnu_debug::vector usable in constant expressions [PR109536]

2023-12-16 Thread Jonathan Wakely
On Sat, 16 Dec 2023 at 00:27, Patrick Palka wrote:
>
> On Wed, 6 Dec 2023, Jonathan Wakely wrote:
>
> > Any comments on this approach?
> >
> > -- >8 --
> >
> > This makes constexpr std::vector (mostly) work in Debug Mode. All safe
> > iterator instrumentation and checking is disabled during constant
> > evaluation, because it requires mutex locks and calls to non-inline
> > functions defined in libstdc++.so. It should be OK to disable the safety
> > checks, because most UB should be detected during constant evaluation
> > anyway.
> >
> > We could try to enable the full checking in constexpr, but it would mean
> > wrapping all the non-inline functions like _M_attach with an inline
> > _M_constexpr_attach that does the iterator housekeeping inline without
> > mutex locks when calling for constant evaluation, and calls the
> > non-inline function at runtime. That could be done in future if we find
> > that we've lost safety or useful checking by disabling the safe
> > iterators.
> >
> > There are a few test failures in C++20 mode, which I'm unable to
> > explain. The _Safe_iterator::operator++() member gives errors for using
> > non-constexpr functions during constant evaluation, even though those
> > functions are guarded by std::is_constant_evaluated() checks. The same
> > code works fine for C++23 and up.
>
> AFAICT these C++20 test failures are really due to the variable
> definition of non-literal type
>
> 381__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
>
> which were prohibited in a constexpr function (even if that code was
> never executed) until C++23's P2242R3.

Ah, I figured it was a core change but I couldn't recall which one. Thanks.

> We can use an immediately invoked lambda to work around this:
>
> 381[this] {
> 382  __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
> 383  ++base();
> 384}();
> 385return *this;

We'd need some #if as this code has to work for C++98. But that's doable.



> >
> > libstdc++-v3/ChangeLog:
> >
> >   PR libstdc++/109536
> >   * include/bits/c++config (__glibcxx_constexpr_assert): Remove
> >   macro.
> >   * include/bits/stl_algobase.h (__niter_base, __copy_move_a)
> >   (__copy_move_backward_a, __fill_a, __fill_n_a, __equal_aux)
> >   (__lexicographical_compare_aux): Add constexpr to overloads for
> >   debug mode iterators.
> >   * include/debug/helper_functions.h (__unsafe): Add constexpr.
> >   * include/debug/macros.h (_GLIBCXX_DEBUG_VERIFY_COND_AT): Remove
> >   macro, folding it into ...
> >   (_GLIBCXX_DEBUG_VERIFY_AT_F): ... here. Do not use
> >   __glibcxx_constexpr_assert.
> >   * include/debug/safe_base.h (_Safe_iterator_base): Add constexpr
> >   to some member functions. Omit attaching, detaching and checking
> >   operations during constant evaluation.
> >   * include/debug/safe_container.h (_Safe_container): Likewise.
> >   * include/debug/safe_iterator.h (_Safe_iterator): Likewise.
> >   * include/debug/safe_iterator.tcc (__niter_base, __copy_move_a)
> >   (__copy_move_backward_a, __fill_a, __fill_n_a, __equal_aux)
> >   (__lexicographical_compare_aux): Add constexpr.
> >   * include/debug/vector (_Safe_vector, vector): Add constexpr.
> >   Omit safe iterator operations during constant evaluation.
> >   * testsuite/23_containers/vector/bool/capacity/constexpr.cc:
> >   Remove dg-xfail-if for debug mode.
> >   * testsuite/23_containers/vector/bool/cmp_c++20.cc: Likewise.
> >   * testsuite/23_containers/vector/bool/cons/constexpr.cc:
> >   Likewise.
> >   * testsuite/23_containers/vector/bool/element_access/1.cc:
> >   Likewise.
> >   * testsuite/23_containers/vector/bool/element_access/constexpr.cc:
> >   Likewise.
> >   * testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc:
> >   Likewise.
> >   * testsuite/23_containers/vector/bool/modifiers/constexpr.cc:
> >   Likewise.
> >   * testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc:
> >   Likewise.
> >   * testsuite/23_containers/vector/capacity/constexpr.cc:
> >   Likewise.
> >   * testsuite/23_containers/vector/cmp_c++20.cc: Likewise.
> >   * testsuite/23_containers/vector/cons/constexpr.cc: Likewise.
> >   * testsuite/23_containers/vector/data_access/constexpr.cc:
> >   Likewise.
> >   * testsuite/23_containers/vector/element_access/constexpr.cc:
> >   Likewise.
> >   * testsuite/23_containers/vector/modifiers/assign/constexpr.cc:
> >   Likewise.
> >   * testsuite/23_containers/vector/modifiers/constexpr.cc:
> >   Likewise.
> >   * testsuite/23_containers/vector/modifiers/swap/constexpr.cc:
> >   Likewise.
> > ---
> >  libstdc++-v3/include/bits/c++config   |   9 -
> >  libstdc++-v3/include/bits/stl_algobase.h  |  15 ++
> >  libstdc++-v3/include/debug/helper_functions.h |   1 +
> >  libstdc++-v3/include/debug/macros.h   

Re: [PATCH] libstdc++: Make __gnu_debug::vector usable in constant expressions [PR109536]

2023-12-15 Thread Patrick Palka
On Wed, 6 Dec 2023, Jonathan Wakely wrote:

> Any comments on this approach?
> 
> -- >8 --
> 
> This makes constexpr std::vector (mostly) work in Debug Mode. All safe
> iterator instrumentation and checking is disabled during constant
> evaluation, because it requires mutex locks and calls to non-inline
> functions defined in libstdc++.so. It should be OK to disable the safety
> checks, because most UB should be detected during constant evaluation
> anyway.
> 
> We could try to enable the full checking in constexpr, but it would mean
> wrapping all the non-inline functions like _M_attach with an inline
> _M_constexpr_attach that does the iterator housekeeping inline without
> mutex locks when calling for constant evaluation, and calls the
> non-inline function at runtime. That could be done in future if we find
> that we've lost safety or useful checking by disabling the safe
> iterators.
> 
> There are a few test failures in C++20 mode, which I'm unable to
> explain. The _Safe_iterator::operator++() member gives errors for using
> non-constexpr functions during constant evaluation, even though those
> functions are guarded by std::is_constant_evaluated() checks. The same
> code works fine for C++23 and up.

AFAICT these C++20 test failures are really due to the variable
definition of non-literal type

381__gnu_cxx::__scoped_lock __l(this->_M_get_mutex());

which were prohibited in a constexpr function (even if that code was
never executed) until C++23's P2242R3.

We can use an immediately invoked lambda to work around this:

381[this] {
382  __gnu_cxx::__scoped_lock __l(this->_M_get_mutex());
383  ++base();
384}();
385return *this;

> 
> libstdc++-v3/ChangeLog:
> 
>   PR libstdc++/109536
>   * include/bits/c++config (__glibcxx_constexpr_assert): Remove
>   macro.
>   * include/bits/stl_algobase.h (__niter_base, __copy_move_a)
>   (__copy_move_backward_a, __fill_a, __fill_n_a, __equal_aux)
>   (__lexicographical_compare_aux): Add constexpr to overloads for
>   debug mode iterators.
>   * include/debug/helper_functions.h (__unsafe): Add constexpr.
>   * include/debug/macros.h (_GLIBCXX_DEBUG_VERIFY_COND_AT): Remove
>   macro, folding it into ...
>   (_GLIBCXX_DEBUG_VERIFY_AT_F): ... here. Do not use
>   __glibcxx_constexpr_assert.
>   * include/debug/safe_base.h (_Safe_iterator_base): Add constexpr
>   to some member functions. Omit attaching, detaching and checking
>   operations during constant evaluation.
>   * include/debug/safe_container.h (_Safe_container): Likewise.
>   * include/debug/safe_iterator.h (_Safe_iterator): Likewise.
>   * include/debug/safe_iterator.tcc (__niter_base, __copy_move_a)
>   (__copy_move_backward_a, __fill_a, __fill_n_a, __equal_aux)
>   (__lexicographical_compare_aux): Add constexpr.
>   * include/debug/vector (_Safe_vector, vector): Add constexpr.
>   Omit safe iterator operations during constant evaluation.
>   * testsuite/23_containers/vector/bool/capacity/constexpr.cc:
>   Remove dg-xfail-if for debug mode.
>   * testsuite/23_containers/vector/bool/cmp_c++20.cc: Likewise.
>   * testsuite/23_containers/vector/bool/cons/constexpr.cc:
>   Likewise.
>   * testsuite/23_containers/vector/bool/element_access/1.cc:
>   Likewise.
>   * testsuite/23_containers/vector/bool/element_access/constexpr.cc:
>   Likewise.
>   * testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc:
>   Likewise.
>   * testsuite/23_containers/vector/bool/modifiers/constexpr.cc:
>   Likewise.
>   * testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc:
>   Likewise.
>   * testsuite/23_containers/vector/capacity/constexpr.cc:
>   Likewise.
>   * testsuite/23_containers/vector/cmp_c++20.cc: Likewise.
>   * testsuite/23_containers/vector/cons/constexpr.cc: Likewise.
>   * testsuite/23_containers/vector/data_access/constexpr.cc:
>   Likewise.
>   * testsuite/23_containers/vector/element_access/constexpr.cc:
>   Likewise.
>   * testsuite/23_containers/vector/modifiers/assign/constexpr.cc:
>   Likewise.
>   * testsuite/23_containers/vector/modifiers/constexpr.cc:
>   Likewise.
>   * testsuite/23_containers/vector/modifiers/swap/constexpr.cc:
>   Likewise.
> ---
>  libstdc++-v3/include/bits/c++config   |   9 -
>  libstdc++-v3/include/bits/stl_algobase.h  |  15 ++
>  libstdc++-v3/include/debug/helper_functions.h |   1 +
>  libstdc++-v3/include/debug/macros.h   |   9 +-
>  libstdc++-v3/include/debug/safe_base.h|  35 +++-
>  libstdc++-v3/include/debug/safe_container.h   |  15 +-
>  libstdc++-v3/include/debug/safe_iterator.h| 186 +++---
>  libstdc++-v3/include/debug/safe_iterator.tcc  |  15 ++
>  libstdc++-v3/include/debug/vector | 146 --
>  .../vector/bool/capacity/constexpr.cc |   1 -
>  

Re: [PATCH] libstdc++: Make __gnu_debug::vector usable in constant expressions [PR109536]

2023-12-14 Thread Jonathan Wakely
On Wed, 6 Dec 2023 at 14:30, Jonathan Wakely wrote:
>
> Any comments on this approach?

Pushed to trunk now.

>
> -- >8 --
>
> This makes constexpr std::vector (mostly) work in Debug Mode. All safe
> iterator instrumentation and checking is disabled during constant
> evaluation, because it requires mutex locks and calls to non-inline
> functions defined in libstdc++.so. It should be OK to disable the safety
> checks, because most UB should be detected during constant evaluation
> anyway.
>
> We could try to enable the full checking in constexpr, but it would mean
> wrapping all the non-inline functions like _M_attach with an inline
> _M_constexpr_attach that does the iterator housekeeping inline without
> mutex locks when calling for constant evaluation, and calls the
> non-inline function at runtime. That could be done in future if we find
> that we've lost safety or useful checking by disabling the safe
> iterators.
>
> There are a few test failures in C++20 mode, which I'm unable to
> explain. The _Safe_iterator::operator++() member gives errors for using
> non-constexpr functions during constant evaluation, even though those
> functions are guarded by std::is_constant_evaluated() checks. The same
> code works fine for C++23 and up.
>
> libstdc++-v3/ChangeLog:
>
> PR libstdc++/109536
> * include/bits/c++config (__glibcxx_constexpr_assert): Remove
> macro.
> * include/bits/stl_algobase.h (__niter_base, __copy_move_a)
> (__copy_move_backward_a, __fill_a, __fill_n_a, __equal_aux)
> (__lexicographical_compare_aux): Add constexpr to overloads for
> debug mode iterators.
> * include/debug/helper_functions.h (__unsafe): Add constexpr.
> * include/debug/macros.h (_GLIBCXX_DEBUG_VERIFY_COND_AT): Remove
> macro, folding it into ...
> (_GLIBCXX_DEBUG_VERIFY_AT_F): ... here. Do not use
> __glibcxx_constexpr_assert.
> * include/debug/safe_base.h (_Safe_iterator_base): Add constexpr
> to some member functions. Omit attaching, detaching and checking
> operations during constant evaluation.
> * include/debug/safe_container.h (_Safe_container): Likewise.
> * include/debug/safe_iterator.h (_Safe_iterator): Likewise.
> * include/debug/safe_iterator.tcc (__niter_base, __copy_move_a)
> (__copy_move_backward_a, __fill_a, __fill_n_a, __equal_aux)
> (__lexicographical_compare_aux): Add constexpr.
> * include/debug/vector (_Safe_vector, vector): Add constexpr.
> Omit safe iterator operations during constant evaluation.
> * testsuite/23_containers/vector/bool/capacity/constexpr.cc:
> Remove dg-xfail-if for debug mode.
> * testsuite/23_containers/vector/bool/cmp_c++20.cc: Likewise.
> * testsuite/23_containers/vector/bool/cons/constexpr.cc:
> Likewise.
> * testsuite/23_containers/vector/bool/element_access/1.cc:
> Likewise.
> * testsuite/23_containers/vector/bool/element_access/constexpr.cc:
> Likewise.
> * testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc:
> Likewise.
> * testsuite/23_containers/vector/bool/modifiers/constexpr.cc:
> Likewise.
> * testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc:
> Likewise.
> * testsuite/23_containers/vector/capacity/constexpr.cc:
> Likewise.
> * testsuite/23_containers/vector/cmp_c++20.cc: Likewise.
> * testsuite/23_containers/vector/cons/constexpr.cc: Likewise.
> * testsuite/23_containers/vector/data_access/constexpr.cc:
> Likewise.
> * testsuite/23_containers/vector/element_access/constexpr.cc:
> Likewise.
> * testsuite/23_containers/vector/modifiers/assign/constexpr.cc:
> Likewise.
> * testsuite/23_containers/vector/modifiers/constexpr.cc:
> Likewise.
> * testsuite/23_containers/vector/modifiers/swap/constexpr.cc:
> Likewise.
> ---
>  libstdc++-v3/include/bits/c++config   |   9 -
>  libstdc++-v3/include/bits/stl_algobase.h  |  15 ++
>  libstdc++-v3/include/debug/helper_functions.h |   1 +
>  libstdc++-v3/include/debug/macros.h   |   9 +-
>  libstdc++-v3/include/debug/safe_base.h|  35 +++-
>  libstdc++-v3/include/debug/safe_container.h   |  15 +-
>  libstdc++-v3/include/debug/safe_iterator.h| 186 +++---
>  libstdc++-v3/include/debug/safe_iterator.tcc  |  15 ++
>  libstdc++-v3/include/debug/vector | 146 --
>  .../vector/bool/capacity/constexpr.cc |   1 -
>  .../23_containers/vector/bool/cmp_c++20.cc|   1 -
>  .../vector/bool/cons/constexpr.cc |   1 -
>  .../vector/bool/element_access/1.cc   |   1 -
>  .../vector/bool/element_access/constexpr.cc   |   1 -
>  .../vector/bool/modifiers/assign/constexpr.cc |   1 -
>  .../vector/bool/modifiers/constexpr.cc|   1 

[PATCH] libstdc++: Make __gnu_debug::vector usable in constant expressions [PR109536]

2023-12-06 Thread Jonathan Wakely
Any comments on this approach?

-- >8 --

This makes constexpr std::vector (mostly) work in Debug Mode. All safe
iterator instrumentation and checking is disabled during constant
evaluation, because it requires mutex locks and calls to non-inline
functions defined in libstdc++.so. It should be OK to disable the safety
checks, because most UB should be detected during constant evaluation
anyway.

We could try to enable the full checking in constexpr, but it would mean
wrapping all the non-inline functions like _M_attach with an inline
_M_constexpr_attach that does the iterator housekeeping inline without
mutex locks when calling for constant evaluation, and calls the
non-inline function at runtime. That could be done in future if we find
that we've lost safety or useful checking by disabling the safe
iterators.

There are a few test failures in C++20 mode, which I'm unable to
explain. The _Safe_iterator::operator++() member gives errors for using
non-constexpr functions during constant evaluation, even though those
functions are guarded by std::is_constant_evaluated() checks. The same
code works fine for C++23 and up.

libstdc++-v3/ChangeLog:

PR libstdc++/109536
* include/bits/c++config (__glibcxx_constexpr_assert): Remove
macro.
* include/bits/stl_algobase.h (__niter_base, __copy_move_a)
(__copy_move_backward_a, __fill_a, __fill_n_a, __equal_aux)
(__lexicographical_compare_aux): Add constexpr to overloads for
debug mode iterators.
* include/debug/helper_functions.h (__unsafe): Add constexpr.
* include/debug/macros.h (_GLIBCXX_DEBUG_VERIFY_COND_AT): Remove
macro, folding it into ...
(_GLIBCXX_DEBUG_VERIFY_AT_F): ... here. Do not use
__glibcxx_constexpr_assert.
* include/debug/safe_base.h (_Safe_iterator_base): Add constexpr
to some member functions. Omit attaching, detaching and checking
operations during constant evaluation.
* include/debug/safe_container.h (_Safe_container): Likewise.
* include/debug/safe_iterator.h (_Safe_iterator): Likewise.
* include/debug/safe_iterator.tcc (__niter_base, __copy_move_a)
(__copy_move_backward_a, __fill_a, __fill_n_a, __equal_aux)
(__lexicographical_compare_aux): Add constexpr.
* include/debug/vector (_Safe_vector, vector): Add constexpr.
Omit safe iterator operations during constant evaluation.
* testsuite/23_containers/vector/bool/capacity/constexpr.cc:
Remove dg-xfail-if for debug mode.
* testsuite/23_containers/vector/bool/cmp_c++20.cc: Likewise.
* testsuite/23_containers/vector/bool/cons/constexpr.cc:
Likewise.
* testsuite/23_containers/vector/bool/element_access/1.cc:
Likewise.
* testsuite/23_containers/vector/bool/element_access/constexpr.cc:
Likewise.
* testsuite/23_containers/vector/bool/modifiers/assign/constexpr.cc:
Likewise.
* testsuite/23_containers/vector/bool/modifiers/constexpr.cc:
Likewise.
* testsuite/23_containers/vector/bool/modifiers/swap/constexpr.cc:
Likewise.
* testsuite/23_containers/vector/capacity/constexpr.cc:
Likewise.
* testsuite/23_containers/vector/cmp_c++20.cc: Likewise.
* testsuite/23_containers/vector/cons/constexpr.cc: Likewise.
* testsuite/23_containers/vector/data_access/constexpr.cc:
Likewise.
* testsuite/23_containers/vector/element_access/constexpr.cc:
Likewise.
* testsuite/23_containers/vector/modifiers/assign/constexpr.cc:
Likewise.
* testsuite/23_containers/vector/modifiers/constexpr.cc:
Likewise.
* testsuite/23_containers/vector/modifiers/swap/constexpr.cc:
Likewise.
---
 libstdc++-v3/include/bits/c++config   |   9 -
 libstdc++-v3/include/bits/stl_algobase.h  |  15 ++
 libstdc++-v3/include/debug/helper_functions.h |   1 +
 libstdc++-v3/include/debug/macros.h   |   9 +-
 libstdc++-v3/include/debug/safe_base.h|  35 +++-
 libstdc++-v3/include/debug/safe_container.h   |  15 +-
 libstdc++-v3/include/debug/safe_iterator.h| 186 +++---
 libstdc++-v3/include/debug/safe_iterator.tcc  |  15 ++
 libstdc++-v3/include/debug/vector | 146 --
 .../vector/bool/capacity/constexpr.cc |   1 -
 .../23_containers/vector/bool/cmp_c++20.cc|   1 -
 .../vector/bool/cons/constexpr.cc |   1 -
 .../vector/bool/element_access/1.cc   |   1 -
 .../vector/bool/element_access/constexpr.cc   |   1 -
 .../vector/bool/modifiers/assign/constexpr.cc |   1 -
 .../vector/bool/modifiers/constexpr.cc|   1 -
 .../vector/bool/modifiers/swap/constexpr.cc   |   3 +-
 .../vector/capacity/constexpr.cc  |   1 -
 .../23_containers/vector/cmp_c++20.cc |   1 -
 .../23_containers/vector/cons/constexpr.cc|   1 -
 .../vector/data_access/constexpr.cc