From patchwork Wed Jun 25 20:56:24 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 364152 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 9BBED1400AA for ; Thu, 26 Jun 2014 06:56:38 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=l2oz+Z4TolLoOjiCzGbgGfbebDO2BgTt5cIc+CrLw/NyOl+dASzEq XifAfm/bNkqelzQp9ExpcBA9j6xYJV+5N3+eeqLrPo0Vfm80mkHIP2fJrY7O4/wK Cpe66cUXdklF2BNACWJMz3ustllcGvbxqjNU3eEdI1v1MWgOUvbCnc= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=IlGdZiTTA3ZHpGNkh0HU8ZSTAAY=; b=M6t1u+0DnAr/qEMFgGQ0 6edw3TewEqDqhKmc266mVpqDa+ZGtmYnAlA0WFq9wDBy+kslxKETOSs/238oYk8o aIcPc833K0NKN5AOVz9kqsDbUwG/snGUT1hOSmTQce5X5HDUJ5sEqYt3k4OisKPX MVNKR+7YA8BzTkrCxWIzcq4= Received: (qmail 17285 invoked by alias); 25 Jun 2014 20:56:30 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 17264 invoked by uid 89); 25 Jun 2014 20:56:30 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.0 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-Spam-User: qpsmtpd, 2 recipients X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Wed, 25 Jun 2014 20:56:27 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id s5PKuQlb005034 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 25 Jun 2014 16:56:26 -0400 Received: from localhost (vpn1-6-161.ams2.redhat.com [10.36.6.161]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id s5PKuOx0031513; Wed, 25 Jun 2014 16:56:25 -0400 Date: Wed, 25 Jun 2014 21:56:24 +0100 From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [patch] Simplify allocator use Message-ID: <20140625205624.GD2711@redhat.com> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.23 (2014-03-12) A couple of related patches that came out of some work on std::list and std::string which is not ready yet. One adds an alias template to simplify rebinding allocators. The other adds an RAII type to help manage pointers obtained from allocators. The new type means I can remove several ugly try-catch blocks that are all very similar in structure and have been bothering me for some time. The new type also makes it trivial to support allocators with fancy pointers, fixing long-standing (but not very important) bugs in std::promise and std::shared_ptr. Tested x86_64-linux, committed to trunk. commit 6339d3559931228c0c3e4ce6e0cebcb0b0b0265d Author: Jonathan Wakely Date: Wed Jun 25 16:03:52 2014 +0100 * include/Makefile.am: Add new header. * include/Makefile.in: Regenerate. * include/bits/allocated_ptr.h (__allocated_ptr, __allocate_guarded): New RAII utilities for working with allocators. * include/bits/shared_ptr_base.h (_Sp_counted_deleter): Define __allocator_type typedef and use new __allocated_ptr type. (_Sp_counted_ptr_inplace): Likewise. (__shared_count::__shared_count, __shared_ptr::__shared_ptr): Use __allocate_guarded to to simplify exception handling. * include/experimental/any (any::_Manager_alloc::_S_alloc): Likewise. * include/std/future (_Result_alloc::_M_destroy): Likewise. (_Result_alloc::_S_allocate_result): Likewise. * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust line number. * testsuite/20_util/shared_ptr/cons/void_neg.cc: Likewise. * testsuite/20_util/shared_ptr/creation/no_rtti.cc: New. * testsuite/20_util/shared_ptr/creation/alloc.cc: Test allocator with fancy pointer. * testsuite/30_threads/promise/cons/alloc.cc: Likewise. diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index 8fe82da..e469586 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -80,6 +80,7 @@ bits_builddir = ./bits bits_headers = \ ${bits_srcdir}/algorithmfwd.h \ ${bits_srcdir}/alloc_traits.h \ + ${bits_srcdir}/allocated_ptr.h \ ${bits_srcdir}/allocator.h \ ${bits_srcdir}/atomic_base.h \ ${bits_srcdir}/basic_ios.h \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index 51fde97..34ae1d1 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -347,6 +347,7 @@ bits_builddir = ./bits bits_headers = \ ${bits_srcdir}/algorithmfwd.h \ ${bits_srcdir}/alloc_traits.h \ + ${bits_srcdir}/allocated_ptr.h \ ${bits_srcdir}/allocator.h \ ${bits_srcdir}/atomic_base.h \ ${bits_srcdir}/basic_ios.h \ diff --git a/libstdc++-v3/include/bits/allocated_ptr.h b/libstdc++-v3/include/bits/allocated_ptr.h new file mode 100644 index 0000000..5cdce20 --- /dev/null +++ b/libstdc++-v3/include/bits/allocated_ptr.h @@ -0,0 +1,104 @@ +// Guarded Allocation -*- C++ -*- + +// Copyright (C) 2014 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/allocated_ptr.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _ALLOCATED_PTR_H +#define _ALLOCATED_PTR_H 1 + +#if __cplusplus < 201103L +# include +#else +# include +# include +# include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// Non-standard RAII type for managing pointers obtained from allocators. + template + struct __allocated_ptr + { + using pointer = typename allocator_traits<_Alloc>::pointer; + using value_type = typename allocator_traits<_Alloc>::value_type; + + /// Take ownership of __ptr + __allocated_ptr(_Alloc& __a, pointer __ptr) noexcept + : _M_alloc(&__a), _M_ptr(__ptr) + { } + + /// Convert __ptr to allocator's pointer type and take ownership of it + template>> + __allocated_ptr(_Alloc& __a, _Ptr __ptr) + : _M_alloc(&__a), _M_ptr(pointer_traits::pointer_to(*__ptr)) + { } + + /// Transfer ownership of the owned pointer + __allocated_ptr(__allocated_ptr&& __gd) noexcept + : _M_alloc(__gd._M_alloc), _M_ptr(__gd._M_ptr) + { __gd._M_ptr = nullptr; } + + /// Deallocate the owned pointer + ~__allocated_ptr() + { + if (_M_ptr != nullptr) + std::allocator_traits<_Alloc>::deallocate(*_M_alloc, _M_ptr, 1); + } + + /// Release ownership of the owned pointer + __allocated_ptr& operator=(std::nullptr_t) noexcept { _M_ptr = nullptr; } + + /// Get the address that the owned pointer refers to. + value_type* get() { return _S_raw_ptr(_M_ptr); } + + private: + value_type* _S_raw_ptr(value_type* __ptr) { return __ptr; } + + template + auto _S_raw_ptr(_Ptr __ptr) -> decltype(_S_raw_ptr(__ptr.operator->())) + { return _S_raw_ptr(__ptr.operator->()); } + + _Alloc* _M_alloc; + pointer _M_ptr; + }; + + /// Allocate space for a single object using __a + template + __allocated_ptr<_Alloc> + __allocate_guarded(_Alloc& __a) + { + return { __a, std::allocator_traits<_Alloc>::allocate(__a, 1) }; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif +#endif diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h index c25157f..590a8d3 100644 --- a/libstdc++-v3/include/bits/shared_ptr_base.h +++ b/libstdc++-v3/include/bits/shared_ptr_base.h @@ -49,6 +49,7 @@ #ifndef _SHARED_PTR_BASE_H #define _SHARED_PTR_BASE_H 1 +#include #include namespace std _GLIBCXX_VISIBILITY(default) @@ -448,6 +449,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; public: + using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_deleter>; + // __d(__p) must not throw. _Sp_counted_deleter(_Ptr __p, _Deleter __d) noexcept : _M_impl(__p, __d, _Alloc()) { } @@ -465,11 +468,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION virtual void _M_destroy() noexcept { - typedef typename allocator_traits<_Alloc>::template - rebind_traits<_Sp_counted_deleter> _Alloc_traits; - typename _Alloc_traits::allocator_type __a(_M_impl._M_alloc()); - _Alloc_traits::destroy(__a, this); - _Alloc_traits::deallocate(__a, this, 1); + __allocator_type __a(_M_impl._M_alloc()); + __allocated_ptr<__allocator_type> __guard_ptr{ __a, this }; + this->~_Sp_counted_deleter(); } virtual void* @@ -506,6 +507,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; public: + using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_ptr_inplace>; + template _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args) : _M_impl(__a) @@ -528,11 +531,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION virtual void _M_destroy() noexcept { - typedef typename allocator_traits<_Alloc>::template - rebind_traits<_Sp_counted_ptr_inplace> _Alloc_traits; - typename _Alloc_traits::allocator_type __a(_M_impl._M_alloc()); - _Alloc_traits::destroy(__a, this); - _Alloc_traits::deallocate(__a, this, 1); + __allocator_type __a(_M_impl._M_alloc()); + __allocated_ptr<__allocator_type> __guard_ptr{ __a, this }; + this->~_Sp_counted_ptr_inplace(); } // Sneaky trick so __shared_ptr can get the managed pointer @@ -584,22 +585,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0) { typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type; - typedef typename allocator_traits<_Alloc>::template - rebind_traits<_Sp_cd_type> _Alloc_traits; - typename _Alloc_traits::allocator_type __a2(__a); - _Sp_cd_type* __mem = 0; __try { - __mem = _Alloc_traits::allocate(__a2, 1); - _Alloc_traits::construct(__a2, __mem, - __p, std::move(__d), std::move(__a)); + typename _Sp_cd_type::__allocator_type __a2(__a); + auto __guard = std::__allocate_guarded(__a2); + _Sp_cd_type* __mem = __guard.get(); + ::new (__mem) _Sp_cd_type(__p, std::move(__d), std::move(__a)); _M_pi = __mem; + __guard = nullptr; } __catch(...) { __d(__p); // Call _Deleter on __p. - if (__mem) - _Alloc_traits::deallocate(__a2, __mem, 1); __throw_exception_again; } } @@ -610,21 +607,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION : _M_pi(0) { typedef _Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp> _Sp_cp_type; - typedef typename allocator_traits<_Alloc>::template - rebind_traits<_Sp_cp_type> _Alloc_traits; - typename _Alloc_traits::allocator_type __a2(__a); - _Sp_cp_type* __mem = _Alloc_traits::allocate(__a2, 1); - __try - { - _Alloc_traits::construct(__a2, __mem, std::move(__a), - std::forward<_Args>(__args)...); - _M_pi = __mem; - } - __catch(...) - { - _Alloc_traits::deallocate(__a2, __mem, 1); - __throw_exception_again; - } + typename _Sp_cp_type::__allocator_type __a2(__a); + auto __guard = std::__allocate_guarded(__a2); + _Sp_cp_type* __mem = __guard.get(); + ::new (__mem) _Sp_cp_type(std::move(__a), + std::forward<_Args>(__args)...); + _M_pi = __mem; + __guard = nullptr; } #if _GLIBCXX_USE_DEPRECATED @@ -1096,11 +1085,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct _Deleter { - void operator()(_Tp* __ptr) + void operator()(typename _Alloc::pointer __ptr) { - typedef allocator_traits<_Alloc> _Alloc_traits; - _Alloc_traits::destroy(_M_alloc, __ptr); - _Alloc_traits::deallocate(_M_alloc, __ptr, 1); + __allocated_ptr<_Alloc> __guard{ _M_alloc, __ptr }; + allocator_traits<_Alloc>::destroy(_M_alloc, __guard.get()); } _Alloc _M_alloc; }; @@ -1109,27 +1097,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a, _Args&&... __args) : _M_ptr(), _M_refcount() - { - typedef typename _Alloc::template rebind<_Tp>::other _Alloc2; - _Deleter<_Alloc2> __del = { _Alloc2(__a) }; - typedef allocator_traits<_Alloc2> __traits; - _M_ptr = __traits::allocate(__del._M_alloc, 1); - __try - { - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2070. allocate_shared should use allocator_traits::construct - __traits::construct(__del._M_alloc, _M_ptr, - std::forward<_Args>(__args)...); - } - __catch(...) - { - __traits::deallocate(__del._M_alloc, _M_ptr, 1); - __throw_exception_again; - } - __shared_count<_Lp> __count(_M_ptr, __del, __del._M_alloc); - _M_refcount._M_swap(__count); + { + typedef typename allocator_traits<_Alloc>::template + rebind_traits<_Tp> __traits; + _Deleter __del = { __a }; + auto __guard = std::__allocate_guarded(__del._M_alloc); + _M_ptr = __guard.get(); + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2070. allocate_shared should use allocator_traits::construct + __traits::construct(__del._M_alloc, _M_ptr, + std::forward<_Args>(__args)...); + __guard = nullptr; + __shared_count<_Lp> __count(_M_ptr, __del, __del._M_alloc); + _M_refcount._M_swap(__count); __enable_shared_from_this_helper(_M_refcount, _M_ptr, _M_ptr); - } + } #endif template struct _Manager_alloc; // creates contained object using an allocator - template::template rebind_alloc<_Tp>> + template> using _ManagerAlloc = conditional_t<_Internal<_Tp>::value, _Manager_internal<_Tp>, _Manager_alloc<_Tp, _TpAlloc>>; @@ -501,19 +501,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _S_alloc(const _Alloc& __a, _Up&& __value) { typename _Traits::allocator_type __a2(__a); - auto __ptr = _Traits::allocate(__a2, 1); - __try - { - any::_Storage __storage; - __storage._M_ptr = std::__addressof(*__ptr); - ::new(__storage._M_ptr) _Data{__a, std::forward<_Up>(__value)}; - return __storage; - } - __catch(...) - { - _Traits::deallocate(__a2, __ptr, 1); - __throw_exception_again; - } + auto __guard = std::__allocate_guarded(__a2); + any::_Storage __storage; + __storage._M_ptr = __guard.get(); + ::new(__storage._M_ptr) _Data{__a, std::forward<_Up>(__value)}; + __guard = nullptr; + return __storage; } #endif @@ -591,11 +584,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION break; case _Op_destroy: { - using _PtrTr = pointer_traits; - typename _Traits::allocator_type __a(__ptr->_M_alloc()); - auto __alloc_ptr = _PtrTr::pointer_to(*const_cast<_Data*>(__ptr)); + using _Alloc2 = typename _Traits::allocator_type; + _Alloc2 __a(__ptr->_M_alloc()); + __allocated_ptr<_Alloc2> __guard{__a, const_cast<_Data*>(__ptr)}; __ptr->~_Data(); - _Traits::deallocate(__a, __alloc_ptr, 1); } break; } diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future index 0949144..be2ed96 100644 --- a/libstdc++-v3/include/std/future +++ b/libstdc++-v3/include/std/future @@ -45,7 +45,7 @@ #include #include #include -#include +#include #include namespace std _GLIBCXX_VISIBILITY(default) @@ -251,42 +251,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct _Result_alloc final : _Result<_Res>, _Alloc { - typedef typename allocator_traits<_Alloc>::template - rebind_alloc<_Result_alloc> __allocator_type; + using __allocator_type = __alloc_rebind<_Alloc, _Result_alloc>; explicit _Result_alloc(const _Alloc& __a) : _Result<_Res>(), _Alloc(__a) - { } + { } private: void _M_destroy() - { - typedef allocator_traits<__allocator_type> __traits; - __allocator_type __a(*this); - __traits::destroy(__a, this); - __traits::deallocate(__a, this, 1); - } + { + __allocator_type __a(*this); + __allocated_ptr<__allocator_type> __guard_ptr{ __a, this }; + this->~_Result_alloc(); + } }; template static _Ptr<_Result_alloc<_Res, _Allocator>> _S_allocate_result(const _Allocator& __a) { - typedef _Result_alloc<_Res, _Allocator> __result_type; - typedef allocator_traits - __traits; - typename __traits::allocator_type __a2(__a); - __result_type* __p = __traits::allocate(__a2, 1); - __try - { - __traits::construct(__a2, __p, __a); - } - __catch(...) - { - __traits::deallocate(__a2, __p, 1); - __throw_exception_again; - } - return _Ptr<__result_type>(__p); + using __result_type = _Result_alloc<_Res, _Allocator>; + typename __result_type::__allocator_type __a2(__a); + auto __guard = std::__allocate_guarded(__a2); + __result_type* __p = ::new((void*)__guard.get()) __result_type{__a}; + __guard = nullptr; + return _Ptr<__result_type>(__p); } template diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc index fbd8ccd..dff0402 100644 --- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc @@ -32,7 +32,7 @@ void test01() { X* px = 0; std::shared_ptr p1(px); // { dg-error "here" } - // { dg-error "incomplete" "" { target *-*-* } 875 } + // { dg-error "incomplete" "" { target *-*-* } 864 } std::shared_ptr p9(ap()); // { dg-error "here" } // { dg-error "incomplete" "" { target *-*-* } 307 } diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc index 3f93a5e..1ea114c 100644 --- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc @@ -25,5 +25,5 @@ void test01() { std::shared_ptr p((void*)nullptr); // { dg-error "here" } - // { dg-error "incomplete" "" { target *-*-* } 874 } + // { dg-error "incomplete" "" { target *-*-* } 863 } } diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/creation/alloc.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/creation/alloc.cc index cd2712a..402c612 100644 --- a/libstdc++-v3/testsuite/20_util/shared_ptr/creation/alloc.cc +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/creation/alloc.cc @@ -101,10 +101,25 @@ test02() == tracker_allocator_counter::get_deallocation_count() ); } +template + struct Pointer : __gnu_test::PointerBase, T> + { + using __gnu_test::PointerBase, T>::PointerBase; + }; + +void +test03() +{ + __gnu_test::CustomPointerAlloc> alloc; + auto p = std::allocate_shared(alloc, 1); + VERIFY( *p == 1 ); +} + int main() { test01(); test02(); + test03(); return 0; } diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/creation/no_rtti.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/creation/no_rtti.cc new file mode 100644 index 0000000..127bafb --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/shared_ptr/creation/no_rtti.cc @@ -0,0 +1,41 @@ +// { dg-options "-std=gnu++11 -fno-rtti" } +// { dg-do compile } + +// Copyright (C) 2014 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// 20.8.2.2 Class template shared_ptr [util.smartptr.shared] + +#include +#include + +struct X { }; + +// 20.8.2.2.6 shared_ptr creation [util.smartptr.shared.create] + +// test allocate_shared with no RTTI + +template + struct Pointer : __gnu_test::PointerBase, T> + { + using __gnu_test::PointerBase, T>::PointerBase; + }; + +__gnu_test::CustomPointerAlloc> alloc; + +auto p = std::allocate_shared(alloc); + diff --git a/libstdc++-v3/testsuite/30_threads/promise/cons/alloc.cc b/libstdc++-v3/testsuite/30_threads/promise/cons/alloc.cc index ac8fb13..c45e646 100644 --- a/libstdc++-v3/testsuite/30_threads/promise/cons/alloc.cc +++ b/libstdc++-v3/testsuite/30_threads/promise/cons/alloc.cc @@ -27,14 +27,27 @@ #include #include +using std::promise; +using std::allocator_arg; + void test01() { - using std::promise; - using std::allocator_arg; - using __gnu_test::uneq_allocator; + __gnu_test::uneq_allocator alloc(99); + promise p1(allocator_arg, alloc); + p1.set_value(5); + VERIFY( p1.get_future().get() == 5 ); +} - uneq_allocator alloc(99); +template + struct Pointer : __gnu_test::PointerBase, T> + { + using __gnu_test::PointerBase, T>::PointerBase; + }; +void +test02() +{ + __gnu_test::CustomPointerAlloc> alloc; promise p1(allocator_arg, alloc); p1.set_value(5); VERIFY( p1.get_future().get() == 5 ); @@ -43,5 +56,6 @@ void test01() int main() { test01(); + test02(); return 0; }