From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5498 invoked by alias); 13 Mar 2013 13:33:17 -0000 Received: (qmail 5289 invoked by uid 48); 13 Mar 2013 13:32:29 -0000 From: "redi at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug libstdc++/56613] New: [4.8 Regression] map::operator[](key_type&&) fails with custom allocator Date: Wed, 13 Mar 2013 13:33:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: libstdc++ X-Bugzilla-Keywords: rejects-valid X-Bugzilla-Severity: normal X-Bugzilla-Who: redi at gcc dot gnu.org X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Changed-Fields: Message-ID: X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated Content-Type: text/plain; charset="UTF-8" MIME-Version: 1.0 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org X-SW-Source: 2013-03/txt/msg01038.txt.bz2 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56613 Bug #: 56613 Summary: [4.8 Regression] map::operator[](key_type&&) fails with custom allocator Classification: Unclassified Product: gcc Version: 4.8.0 Status: UNCONFIRMED Keywords: rejects-valid Severity: normal Priority: P3 Component: libstdc++ AssignedTo: unassigned@gcc.gnu.org ReportedBy: redi@gcc.gnu.org This program is valid in C++03 and C++11 but can't be compiled with trunk using -std=c++11 #include template struct alloc { typedef T value_type; typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; typedef unsigned size_type; typedef int difference_type; template struct rebind { typedef alloc other; }; alloc() { } template alloc(const alloc&) { } pointer allocate(size_type n, const void* = 0) { return std::allocator().allocate(n); } void deallocate(pointer p, size_type n) { std::allocator().deallocate(p, n); } size_type max_size() const { return -1; } void construct(pointer p, const T& t) { new ((void*) p) T(t); } void destroy(pointer p) { p->~T(); } }; template bool operator==(alloc, alloc) { return true; } template bool operator!=(alloc, alloc) { return false; } int main() { std::map, alloc > m; m[1]; } $ g++-4.8 -std=c++11 map.cc In file included from /home/redi/gcc/4.x/include/c++/4.8.0/map:60:0, from map.cc:1: /home/redi/gcc/4.x/include/c++/4.8.0/bits/stl_tree.h: In instantiation of 'std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_create_node(_Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple, std::tuple<>}; _Key = int; _Val = std::pair; _KeyOfValue = std::_Select1st >; _Compare = std::less; _Alloc = alloc >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node >*]': /home/redi/gcc/4.x/include/c++/4.8.0/bits/stl_tree.h:1662:64: required from 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_emplace_hint_unique(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator, _Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple, std::tuple<>}; _Key = int; _Val = std::pair; _KeyOfValue = std::_Select1st >; _Compare = std::less; _Alloc = alloc >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator >]' /home/redi/gcc/4.x/include/c++/4.8.0/bits/stl_map.h:484:8: required from 'std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](std::map<_Key, _Tp, _Compare, _Alloc>::key_type&&) [with _Key = int; _Tp = int; _Compare = std::less; _Alloc = alloc; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = int; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = int]' map.cc:41:8: required from here /home/redi/gcc/4.x/include/c++/4.8.0/bits/stl_tree.h:403:8: error: no matching function for call to 'alloc > >::construct(std::_Rb_tree_node >*&, const std::piecewise_construct_t&, std::tuple, std::tuple<>)' _M_get_Node_allocator().construct(__tmp, ^ /home/redi/gcc/4.x/include/c++/4.8.0/bits/stl_tree.h:403:8: note: candidate is: map.cc:28:10: note: void alloc::construct(alloc::pointer, const T&) [with T = std::_Rb_tree_node >; alloc::pointer = std::_Rb_tree_node >*] void construct(pointer p, const T& t) { new ((void*) p) T(t); } ^ map.cc:28:10: note: candidate expects 2 arguments, 4 provided The problem is that stl_map.h uses piecewise construction for the pair object, which calls alloc::construct with four arguments, incorrectly assuming that all allocators in C++11 have a variadic construct() member. It's easily fixed by changing the C++11 version of _M_create_node to use allocator_traits::construct: std::allocator_traits<_Node_allocator>:: construct(_M_get_Node_allocator(), __tmp, std::forward<_Args>(__args)...); (For 4.9 I was going to make all the RB-trees allocator-aware, but this regression needs to be fixed for 4.8 without the rest of the allocator changes)