diff mbox series

[committed] libstdc++: Fix debug containers for constant evaluation [PR117962]

Message ID 20241209151911.1842356-1-jwakely@redhat.com
State New
Headers show
Series [committed] libstdc++: Fix debug containers for constant evaluation [PR117962] | expand

Commit Message

Jonathan Wakely Dec. 9, 2024, 3:18 p.m. UTC
Using a stateful allocator with std::vector would fail in Debug Mode,
because the allocator-extended move constructor tries to swap all the
attached safe iterators, but that uses a non-inline function which isn't
constexpr. We don't actually need to swap any iterators in constant
expressions, because we never attach them to the container in the first
place.

This bug went unnoticed because the tests for constexpr std::vector were
using a stateful allocator with a std::allocator base class, but were
failing to override the inherited is_always_equal trait from
std::allocator. That meant that the allocators took the always-equal
code paths, and didn't try to use the buggy constructor. In C++26 the
std::allocator::is_always_equal trait goes away, and so the tests
changed behaviour, revealing the bug.

libstdc++-v3/ChangeLog:

	PR libstdc++/117962
	* include/debug/safe_container.h: Make allocator-extended move
	constructor a no-op during constant evaluation.
---

Tested x86_64-linux. Pushed to trunk. I'll backport this too.

 libstdc++-v3/include/debug/safe_container.h | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/libstdc++-v3/include/debug/safe_container.h b/libstdc++-v3/include/debug/safe_container.h
index 9a6c4f7ba74..75c6834bfae 100644
--- a/libstdc++-v3/include/debug/safe_container.h
+++ b/libstdc++-v3/include/debug/safe_container.h
@@ -64,10 +64,13 @@  namespace __gnu_debug
       _Safe_container(_Safe_container&& __x, const _Alloc& __a, std::false_type)
       : _Safe_container()
       {
-	if (__x._M_cont().get_allocator() == __a)
-	  _Base::_M_swap(__x);
-	else if (!std::__is_constant_evaluated())
-	  __x._M_invalidate_all();
+	if (!std::__is_constant_evaluated())
+	  {
+	    if (__x._M_cont().get_allocator() == __a)
+	      _Base::_M_swap(__x);
+	    else
+	      __x._M_invalidate_all();
+	  }
       }
 
     protected: