https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116641
Bug ID: 116641 Summary: [12/13/14/15 Regression] std::string move assignment incorrectly depends on POCCA Product: gcc Version: 15.0 Status: UNCONFIRMED Keywords: wrong-code Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: redi at gcc dot gnu.org CC: oliver.rosten at googlemail dot com Target Milestone: --- Oliver Rosten noticed this bug: #include <string> template<typename T> struct Alloc { using value_type = T; using propagate_on_container_swap = std::false_type; using propagate_on_container_copy_assignment = std::true_type; using propagate_on_container_move_assignment = std::false_type; Alloc(int id) : id(id) { } template<typename U> Alloc(const Alloc<U>& a) : id(a.id) { } T* allocate(unsigned long n) { return std::allocator<T>().allocate(n); } void deallocate(T* p, unsigned long n) { std::allocator<T>().deallocate(p, n); } Alloc& operator=(const Alloc&) { throw; } bool operator==(const Alloc& a) const { return id == a.id; } bool operator!=(const Alloc& a) const { return id != a.id; } int id; }; void test_move_assign() { Alloc<char> a1(1), a2(2); std::basic_string<char, std::char_traits<char>, Alloc<char>> s1(a1), s2(a2); s1 = "sooooooooooooooooooooooooooooooo long"; s2 = std::move(s1); } int main() { test_move_assign(); } There should be no allocator assignment here, but since r10-327-gdb33efde17932f string::assign considers POCCA (propagate_on_container_copy_assignment) and so when operator=(basic_string&&) calls assign to do a deep copy, it also ends up propagating the allocator. That shouldn't happen, because POCMA is false here. The fix should be as simple as changing operator= to call _M_assign instead of assign.