From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6809 invoked by alias); 29 Jan 2015 17:22:04 -0000 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 Received: (qmail 6576 invoked by uid 48); 29 Jan 2015 17:21:54 -0000 From: "Casey at Carter dot net" To: gcc-bugs@gcc.gnu.org Subject: [Bug libstdc++/64865] New: std::allocator::construct/destroy not called for specialization of std::allocator Date: Thu, 29 Jan 2015 17:22: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-Version: 5.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: minor X-Bugzilla-Who: Casey at Carter dot net X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-SW-Source: 2015-01/txt/msg03427.txt.bz2 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64865 Bug ID: 64865 Summary: std::allocator::construct/destroy not called for specialization of std::allocator Product: gcc Version: 5.0 Status: UNCONFIRMED Severity: minor Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: Casey at Carter dot net Per N4296 [container.requirements.general]/3: For the components affected by this subclause that declare an allocator_type, objects stored in these components shall be constructed using the allocator_traits::construct function and destroyed using the allocator_traits::destroy function (20.7.8.2). libstdc++ optimizes out calls to `construct` and `destroy` for types with trivial construction/destruction when the allocator type is a specialization of std::allocator: see implementation of __uninitialized_copy_a(InputIterator, InputIterator, ForwardIterator, allocator<>&) in bits/stl_uninitialized.h, and _Destroy(ForwardIterator, ForwardIterator, allocator<>&) in bits/stl_construct.h. However, not every instance of std::allocator necessarily has side-effect free implementation of construct/destruct, since [namespace.std]/1 allows users to specialize templates in the standard namespace if the declaration depends on a user-defined type. For example, this program: #include #include #include struct mytype { int value; mytype(int v) : value{v} {} operator int() const { return value; } }; int constructions = 0, destructions = 0; namespace std { template <> struct allocator<::mytype> { using value_type = mytype; allocator() = default; template allocator(const allocator&) {} mytype* allocate(std::size_t n) { return static_cast(::operator new(n * sizeof(mytype))); } void deallocate(mytype* ptr, std::size_t) noexcept { ::operator delete(ptr); } template void construct(U* ptr, Args&&...args) { ::new ((void*)ptr) U(std::forward(args)...); ++::constructions; } template void destroy(U* ptr) noexcept { ++::destructions; ptr->~U(); } friend constexpr bool operator == (const allocator&, const allocator&) noexcept { return true; } friend constexpr bool operator != (const allocator&, const allocator&) noexcept { return false; } }; } // namespace std int main() { { std::vector{1,2,3}; // assert(constructions == 3); // assert would fire } // assert(destructions == 3); // assert would fire return constructions != 3 || destructions != 3; } always returns non-zero, and either of the asserts will fire if uncommented. Some possible solutions: * Change all such optimizations in the library to presume that specializations of std::allocator are the "default allocator" only if they are derived from __allocator_base. This is the case for the base template definition as implemented in bits/allocator.h. * Remove all such optimizations from the library, and let the compiler optimize away trivial construction and destruction. This has the unfortunate side effect of slowing down debug builds of user programs. * Close this bug report as WONTFIX since it is horrible design to specialize std::allocator instead of declaring a new allocator type; given that container implementations are free to rebind to a different specialization, there is no guarantee that functionality added to a user-defined specialization will even be used.