Re: [PATCH] libstdc++: Make __gnu_debug::vector usable in constant expressions [PR109536]
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]
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]
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]
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]
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]
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]
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