libstdc++: Fix non-reserved name in std::allocator base class [PR64135]
The possible base classes of std::allocator are new_allocator and malloc_allocator, which both cause a non-reserved name to be declared in every program that includes the definition of std::allocator. This is non-conforming. This change replaces __gnu_cxx::new_allocator with std::__new_allocator which is identical except for using a reserved name. The non-standard extension __gnu_cxx::new_allocator is preserved as a thin wrapper over std::__new_allocator. There is no problem with the extension using a non-reserved name now that it's not included by default in other headers. The same change could be done to __gnu_cxx::malloc_allocator but as it's not the default configuration it can wait. libstdc++-v3/ChangeLog: PR libstdc++/64135 * config/allocator/new_allocator_base.h: Include <bits/new_allocator.h> instead of <ext/new_allocator.h>. (__allocator_base): Use std::__new_allocator instead of __gnu_cxx::new_allocator. * doc/xml/manual/allocator.xml: Document new default base class for std::allocator. * doc/xml/manual/evolution.xml: Likewise. * doc/html/*: Regenerate. * include/Makefile.am: Add bits/new_allocator.h. * include/Makefile.in: Regenerate. * include/experimental/memory_resource (new_delete_resource): Use std::__new_allocator instead of __gnu_cxx::new_allocator. * include/ext/new_allocator.h (new_allocator): Derive from std::__new_allocator. Move implementation to ... * include/bits/new_allocator.h: New file. * testsuite/20_util/allocator/64135.cc: New test.
This commit is contained in:
parent
f157c5362b
commit
fe9571a35d
|
@ -30,7 +30,7 @@
|
|||
#ifndef _GLIBCXX_CXX_ALLOCATOR_H
|
||||
#define _GLIBCXX_CXX_ALLOCATOR_H 1
|
||||
|
||||
#include <ext/new_allocator.h>
|
||||
#include <bits/new_allocator.h>
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
namespace std
|
||||
|
@ -38,18 +38,17 @@ namespace std
|
|||
/**
|
||||
* @brief An alias to the base class for std::allocator.
|
||||
*
|
||||
* Used to set the std::allocator base class to
|
||||
* __gnu_cxx::new_allocator.
|
||||
* Used to set the std::allocator base class to std::__new_allocator.
|
||||
*
|
||||
* @ingroup allocators
|
||||
* @tparam _Tp Type of allocated object.
|
||||
*/
|
||||
template<typename _Tp>
|
||||
using __allocator_base = __gnu_cxx::new_allocator<_Tp>;
|
||||
using __allocator_base = __new_allocator<_Tp>;
|
||||
}
|
||||
#else
|
||||
// Define new_allocator as the base class to std::allocator.
|
||||
# define __allocator_base __gnu_cxx::new_allocator
|
||||
// Define __new_allocator as the base class to std::allocator.
|
||||
# define __allocator_base __new_allocator
|
||||
#endif
|
||||
|
||||
#ifndef _GLIBCXX_SANITIZE_STD_ALLOCATOR
|
||||
|
|
|
@ -447,4 +447,7 @@ Dynamic exception specifications should be replaced with <code class="code">noex
|
|||
</p><p>
|
||||
The <code class="literal">bitmap</code>, <code class="literal">mt</code>, and <code class="literal">pool</code>
|
||||
options for <code class="option">--enable-libstdcxx-allocator</code> were removed.
|
||||
For the <code class="literal">new</code> option, <code class="classname">std::allocator</code>
|
||||
no longer derives from <code class="classname">__gnu_cxx::new_allocator</code>;
|
||||
they both derive from <code class="classname">std::__new_allocator</code> instead.
|
||||
</p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="abi.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="appendix_porting.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="backwards.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">ABI Policy and Guidelines </td><td width="20%" align="center"><a accesskey="h" href="../index.html">Home</a></td><td width="40%" align="right" valign="top"> Backwards Compatibility</td></tr></table></div></body></html>
|
|
@ -140,9 +140,11 @@
|
|||
<a class="link" href="http://gcc.gnu.org/viewcvs/gcc/trunk/libstdc++-v3/testsuite/performance/23_containers/producer_consumer/associative.cc?view=markup" target="_top">associative</a>
|
||||
containers.
|
||||
</p></li></ol></div><p>
|
||||
The current default choice for
|
||||
Since GCC 12 the default choice for
|
||||
<code class="classname">allocator</code> is
|
||||
<code class="classname">__gnu_cxx::new_allocator</code>.
|
||||
<code class="classname">std::__new_allocator</code>.
|
||||
Before GCC 12 it was the <code class="classname">__gnu_cxx::new_allocator</code>
|
||||
extension (which has identical behaviour).
|
||||
</p></div><div class="section"><div class="titlepage"><div><div><h5 class="title"><a id="allocator.caching"></a>Disabling Memory Caching</h5></div></div></div><p>
|
||||
In use, <code class="classname">allocator</code> may allocate and
|
||||
deallocate using implementation-specific strategies and
|
||||
|
|
|
@ -219,9 +219,11 @@
|
|||
</orderedlist>
|
||||
|
||||
<para>
|
||||
The current default choice for
|
||||
Since GCC 12 the default choice for
|
||||
<classname>allocator</classname> is
|
||||
<classname>__gnu_cxx::new_allocator</classname>.
|
||||
<classname>std::__new_allocator</classname>.
|
||||
Before GCC 12 it was the <classname>__gnu_cxx::new_allocator</classname>
|
||||
extension (which has identical behaviour).
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
|
|
@ -1036,6 +1036,9 @@ Dynamic exception specifications should be replaced with <code>noexcept</code>.
|
|||
<para>
|
||||
The <literal>bitmap</literal>, <literal>mt</literal>, and <literal>pool</literal>
|
||||
options for <option>--enable-libstdcxx-allocator</option> were removed.
|
||||
For the <literal>new</literal> option, <classname>std::allocator</classname>
|
||||
no longer derives from <classname>__gnu_cxx::new_allocator</classname>;
|
||||
they both derive from <classname>std::__new_allocator</classname> instead.
|
||||
</para>
|
||||
|
||||
</section>
|
||||
|
|
|
@ -159,6 +159,7 @@ bits_headers = \
|
|||
${bits_srcdir}/mofunc_impl.h \
|
||||
${bits_srcdir}/move.h \
|
||||
${bits_srcdir}/move_only_function.h \
|
||||
${bits_srcdir}/new_allocator.h \
|
||||
${bits_srcdir}/node_handle.h \
|
||||
${bits_srcdir}/ostream.tcc \
|
||||
${bits_srcdir}/ostream_insert.h \
|
||||
|
|
|
@ -509,6 +509,7 @@ bits_headers = \
|
|||
${bits_srcdir}/mofunc_impl.h \
|
||||
${bits_srcdir}/move.h \
|
||||
${bits_srcdir}/move_only_function.h \
|
||||
${bits_srcdir}/new_allocator.h \
|
||||
${bits_srcdir}/node_handle.h \
|
||||
${bits_srcdir}/ostream.tcc \
|
||||
${bits_srcdir}/ostream_insert.h \
|
||||
|
|
|
@ -0,0 +1,223 @@
|
|||
// Allocator that wraps operator new -*- C++ -*-
|
||||
|
||||
// Copyright (C) 2001-2021 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
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
/** @file bits/new_allocator.h
|
||||
* This is an internal header file, included by other library headers.
|
||||
* Do not attempt to use it directly. @headername{memory}
|
||||
*/
|
||||
|
||||
#ifndef _STD_NEW_ALLOCATOR_H
|
||||
#define _STD_NEW_ALLOCATOR_H 1
|
||||
|
||||
#include <bits/c++config.h>
|
||||
#include <new>
|
||||
#include <bits/functexcept.h>
|
||||
#include <bits/move.h>
|
||||
#if __cplusplus >= 201103L
|
||||
#include <type_traits>
|
||||
#endif
|
||||
|
||||
namespace std _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
_GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
/**
|
||||
* @brief An allocator that uses global new, as per C++03 [20.4.1].
|
||||
* @ingroup allocators
|
||||
*
|
||||
* This is precisely the allocator defined in the C++ Standard.
|
||||
* - all allocation calls operator new
|
||||
* - all deallocation calls operator delete
|
||||
*
|
||||
* @tparam _Tp Type of allocated object.
|
||||
*/
|
||||
template<typename _Tp>
|
||||
class __new_allocator
|
||||
{
|
||||
public:
|
||||
typedef _Tp value_type;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
#if __cplusplus <= 201703L
|
||||
typedef _Tp* pointer;
|
||||
typedef const _Tp* const_pointer;
|
||||
typedef _Tp& reference;
|
||||
typedef const _Tp& const_reference;
|
||||
|
||||
template<typename _Tp1>
|
||||
struct rebind
|
||||
{ typedef __new_allocator<_Tp1> other; };
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 2103. propagate_on_container_move_assignment
|
||||
typedef std::true_type propagate_on_container_move_assignment;
|
||||
#endif
|
||||
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
__new_allocator() _GLIBCXX_USE_NOEXCEPT { }
|
||||
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
__new_allocator(const __new_allocator&) _GLIBCXX_USE_NOEXCEPT { }
|
||||
|
||||
template<typename _Tp1>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
__new_allocator(const __new_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { }
|
||||
|
||||
#if __cplusplus <= 201703L
|
||||
~__new_allocator() _GLIBCXX_USE_NOEXCEPT { }
|
||||
|
||||
pointer
|
||||
address(reference __x) const _GLIBCXX_NOEXCEPT
|
||||
{ return std::__addressof(__x); }
|
||||
|
||||
const_pointer
|
||||
address(const_reference __x) const _GLIBCXX_NOEXCEPT
|
||||
{ return std::__addressof(__x); }
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin_operator_new) >= 201802L
|
||||
# define _GLIBCXX_OPERATOR_NEW __builtin_operator_new
|
||||
# define _GLIBCXX_OPERATOR_DELETE __builtin_operator_delete
|
||||
#else
|
||||
# define _GLIBCXX_OPERATOR_NEW ::operator new
|
||||
# define _GLIBCXX_OPERATOR_DELETE ::operator delete
|
||||
#endif
|
||||
|
||||
// NB: __n is permitted to be 0. The C++ standard says nothing
|
||||
// about what the return value is when __n == 0.
|
||||
_GLIBCXX_NODISCARD _Tp*
|
||||
allocate(size_type __n, const void* = static_cast<const void*>(0))
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 3308. std::allocator<void>().allocate(n)
|
||||
static_assert(sizeof(_Tp) != 0, "cannot allocate incomplete types");
|
||||
#endif
|
||||
|
||||
if (__builtin_expect(__n > this->_M_max_size(), false))
|
||||
{
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 3190. allocator::allocate sometimes returns too little storage
|
||||
if (__n > (std::size_t(-1) / sizeof(_Tp)))
|
||||
std::__throw_bad_array_new_length();
|
||||
std::__throw_bad_alloc();
|
||||
}
|
||||
|
||||
#if __cpp_aligned_new
|
||||
if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
|
||||
{
|
||||
std::align_val_t __al = std::align_val_t(alignof(_Tp));
|
||||
return static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__n * sizeof(_Tp),
|
||||
__al));
|
||||
}
|
||||
#endif
|
||||
return static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__n * sizeof(_Tp)));
|
||||
}
|
||||
|
||||
// __p is not permitted to be a null pointer.
|
||||
void
|
||||
deallocate(_Tp* __p, size_type __n __attribute__ ((__unused__)))
|
||||
{
|
||||
#if __cpp_sized_deallocation
|
||||
# define _GLIBCXX_SIZED_DEALLOC(p, n) (p), (n) * sizeof(_Tp)
|
||||
#else
|
||||
# define _GLIBCXX_SIZED_DEALLOC(p, n) (p)
|
||||
#endif
|
||||
|
||||
#if __cpp_aligned_new
|
||||
if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
|
||||
{
|
||||
_GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n),
|
||||
std::align_val_t(alignof(_Tp)));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
_GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n));
|
||||
}
|
||||
|
||||
#undef _GLIBCXX_SIZED_DEALLOC
|
||||
#undef _GLIBCXX_OPERATOR_DELETE
|
||||
#undef _GLIBCXX_OPERATOR_NEW
|
||||
|
||||
#if __cplusplus <= 201703L
|
||||
size_type
|
||||
max_size() const _GLIBCXX_USE_NOEXCEPT
|
||||
{ return _M_max_size(); }
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _Up, typename... _Args>
|
||||
void
|
||||
construct(_Up* __p, _Args&&... __args)
|
||||
noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
|
||||
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
|
||||
|
||||
template<typename _Up>
|
||||
void
|
||||
destroy(_Up* __p)
|
||||
noexcept(std::is_nothrow_destructible<_Up>::value)
|
||||
{ __p->~_Up(); }
|
||||
#else
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 402. wrong new expression in [some_] allocator::construct
|
||||
void
|
||||
construct(pointer __p, const _Tp& __val)
|
||||
{ ::new((void *)__p) _Tp(__val); }
|
||||
|
||||
void
|
||||
destroy(pointer __p) { __p->~_Tp(); }
|
||||
#endif
|
||||
#endif // ! C++20
|
||||
|
||||
template<typename _Up>
|
||||
friend _GLIBCXX20_CONSTEXPR bool
|
||||
operator==(const __new_allocator&, const __new_allocator<_Up>&)
|
||||
_GLIBCXX_NOTHROW
|
||||
{ return true; }
|
||||
|
||||
#if __cpp_impl_three_way_comparison < 201907L
|
||||
template<typename _Up>
|
||||
friend _GLIBCXX20_CONSTEXPR bool
|
||||
operator!=(const __new_allocator&, const __new_allocator<_Up>&)
|
||||
_GLIBCXX_NOTHROW
|
||||
{ return false; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
_GLIBCXX_CONSTEXPR size_type
|
||||
_M_max_size() const _GLIBCXX_USE_NOEXCEPT
|
||||
{
|
||||
#if __PTRDIFF_MAX__ < __SIZE_MAX__
|
||||
return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp);
|
||||
#else
|
||||
return std::size_t(-1) / sizeof(_Tp);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
} // namespace
|
||||
|
||||
#endif
|
|
@ -40,7 +40,7 @@
|
|||
#include <atomic> // atomic
|
||||
#include <new> // placement new
|
||||
#include <cstddef> // max_align_t
|
||||
#include <ext/new_allocator.h>
|
||||
#include <bits/new_allocator.h>
|
||||
#include <debug/assertions.h>
|
||||
|
||||
/// @cond
|
||||
|
@ -503,7 +503,7 @@ namespace pmr {
|
|||
inline memory_resource*
|
||||
new_delete_resource() noexcept
|
||||
{
|
||||
using type = resource_adaptor<__gnu_cxx::new_allocator<char>>;
|
||||
using type = resource_adaptor<std::__new_allocator<char>>;
|
||||
alignas(type) static unsigned char __buf[sizeof(type)];
|
||||
static type* __r = new(__buf) type;
|
||||
return __r;
|
||||
|
|
|
@ -29,13 +29,7 @@
|
|||
#ifndef _NEW_ALLOCATOR_H
|
||||
#define _NEW_ALLOCATOR_H 1
|
||||
|
||||
#include <bits/c++config.h>
|
||||
#include <new>
|
||||
#include <bits/functexcept.h>
|
||||
#include <bits/move.h>
|
||||
#if __cplusplus >= 201103L
|
||||
#include <type_traits>
|
||||
#endif
|
||||
#include <bits/new_allocator.h>
|
||||
|
||||
namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
|
||||
{
|
||||
|
@ -52,168 +46,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
* @tparam _Tp Type of allocated object.
|
||||
*/
|
||||
template<typename _Tp>
|
||||
class new_allocator
|
||||
class new_allocator : public std::__new_allocator<_Tp>
|
||||
{
|
||||
public:
|
||||
typedef _Tp value_type;
|
||||
typedef std::size_t size_type;
|
||||
typedef std::ptrdiff_t difference_type;
|
||||
#if __cplusplus <= 201703L
|
||||
typedef _Tp* pointer;
|
||||
typedef const _Tp* const_pointer;
|
||||
typedef _Tp& reference;
|
||||
typedef const _Tp& const_reference;
|
||||
|
||||
template<typename _Tp1>
|
||||
struct rebind
|
||||
{ typedef new_allocator<_Tp1> other; };
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 2103. propagate_on_container_move_assignment
|
||||
typedef std::true_type propagate_on_container_move_assignment;
|
||||
#endif
|
||||
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
new_allocator() _GLIBCXX_USE_NOEXCEPT { }
|
||||
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
new_allocator(const new_allocator&) _GLIBCXX_USE_NOEXCEPT { }
|
||||
|
||||
template<typename _Tp1>
|
||||
_GLIBCXX20_CONSTEXPR
|
||||
new_allocator(const new_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { }
|
||||
|
||||
#if __cplusplus <= 201703L
|
||||
~new_allocator() _GLIBCXX_USE_NOEXCEPT { }
|
||||
|
||||
pointer
|
||||
address(reference __x) const _GLIBCXX_NOEXCEPT
|
||||
{ return std::__addressof(__x); }
|
||||
|
||||
const_pointer
|
||||
address(const_reference __x) const _GLIBCXX_NOEXCEPT
|
||||
{ return std::__addressof(__x); }
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin_operator_new) >= 201802L
|
||||
# define _GLIBCXX_OPERATOR_NEW __builtin_operator_new
|
||||
# define _GLIBCXX_OPERATOR_DELETE __builtin_operator_delete
|
||||
#else
|
||||
# define _GLIBCXX_OPERATOR_NEW ::operator new
|
||||
# define _GLIBCXX_OPERATOR_DELETE ::operator delete
|
||||
#endif
|
||||
|
||||
// NB: __n is permitted to be 0. The C++ standard says nothing
|
||||
// about what the return value is when __n == 0.
|
||||
_GLIBCXX_NODISCARD _Tp*
|
||||
allocate(size_type __n, const void* = static_cast<const void*>(0))
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 3308. std::allocator<void>().allocate(n)
|
||||
static_assert(sizeof(_Tp) != 0, "cannot allocate incomplete types");
|
||||
#endif
|
||||
|
||||
if (__builtin_expect(__n > this->_M_max_size(), false))
|
||||
{
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 3190. allocator::allocate sometimes returns too little storage
|
||||
if (__n > (std::size_t(-1) / sizeof(_Tp)))
|
||||
std::__throw_bad_array_new_length();
|
||||
std::__throw_bad_alloc();
|
||||
}
|
||||
|
||||
#if __cpp_aligned_new
|
||||
if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
|
||||
{
|
||||
std::align_val_t __al = std::align_val_t(alignof(_Tp));
|
||||
return static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__n * sizeof(_Tp),
|
||||
__al));
|
||||
}
|
||||
#endif
|
||||
return static_cast<_Tp*>(_GLIBCXX_OPERATOR_NEW(__n * sizeof(_Tp)));
|
||||
}
|
||||
|
||||
// __p is not permitted to be a null pointer.
|
||||
void
|
||||
deallocate(_Tp* __p, size_type __n __attribute__ ((__unused__)))
|
||||
{
|
||||
#if __cpp_sized_deallocation
|
||||
# define _GLIBCXX_SIZED_DEALLOC(p, n) (p), (n) * sizeof(_Tp)
|
||||
#else
|
||||
# define _GLIBCXX_SIZED_DEALLOC(p, n) (p)
|
||||
#endif
|
||||
|
||||
#if __cpp_aligned_new
|
||||
if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
|
||||
{
|
||||
_GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n),
|
||||
std::align_val_t(alignof(_Tp)));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
_GLIBCXX_OPERATOR_DELETE(_GLIBCXX_SIZED_DEALLOC(__p, __n));
|
||||
}
|
||||
|
||||
#undef _GLIBCXX_SIZED_DEALLOC
|
||||
#undef _GLIBCXX_OPERATOR_DELETE
|
||||
#undef _GLIBCXX_OPERATOR_NEW
|
||||
|
||||
#if __cplusplus <= 201703L
|
||||
size_type
|
||||
max_size() const _GLIBCXX_USE_NOEXCEPT
|
||||
{ return _M_max_size(); }
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename _Up, typename... _Args>
|
||||
void
|
||||
construct(_Up* __p, _Args&&... __args)
|
||||
noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
|
||||
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
|
||||
|
||||
template<typename _Up>
|
||||
void
|
||||
destroy(_Up* __p)
|
||||
noexcept(std::is_nothrow_destructible<_Up>::value)
|
||||
{ __p->~_Up(); }
|
||||
#else
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 402. wrong new expression in [some_] allocator::construct
|
||||
void
|
||||
construct(pointer __p, const _Tp& __val)
|
||||
{ ::new((void *)__p) _Tp(__val); }
|
||||
|
||||
void
|
||||
destroy(pointer __p) { __p->~_Tp(); }
|
||||
#endif
|
||||
#endif // ! C++20
|
||||
|
||||
template<typename _Up>
|
||||
friend _GLIBCXX20_CONSTEXPR bool
|
||||
operator==(const new_allocator&, const new_allocator<_Up>&)
|
||||
_GLIBCXX_NOTHROW
|
||||
{ return true; }
|
||||
|
||||
#if __cpp_impl_three_way_comparison < 201907L
|
||||
template<typename _Up>
|
||||
friend _GLIBCXX20_CONSTEXPR bool
|
||||
operator!=(const new_allocator&, const new_allocator<_Up>&)
|
||||
_GLIBCXX_NOTHROW
|
||||
{ return false; }
|
||||
#endif
|
||||
|
||||
private:
|
||||
_GLIBCXX_CONSTEXPR size_type
|
||||
_M_max_size() const _GLIBCXX_USE_NOEXCEPT
|
||||
{
|
||||
#if __PTRDIFF_MAX__ < __SIZE_MAX__
|
||||
return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp);
|
||||
#else
|
||||
return std::size_t(-1) / sizeof(_Tp);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
_GLIBCXX_END_NAMESPACE_VERSION
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
// { dg-do compile { target std_allocator_new } }
|
||||
// { dg-add-options no_pch }
|
||||
|
||||
// PR libstdc++/64135
|
||||
|
||||
#define new_allocator 1
|
||||
#define malloc_allocator 1
|
||||
#define bitmap_allocator 1
|
||||
#include <memory>
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#define STATIC_ASSERT(X) static_assert((X), #X)
|
||||
#else
|
||||
#define PASTE2(X, Y) X##Y
|
||||
#define PASTE(X, Y) PASTE2(X, Y)
|
||||
#define STATIC_ASSERT(X) char PASTE(_assertion_, __LINE__) [(X) ? 1 : -1]
|
||||
#endif
|
||||
|
||||
#undef new_allocator
|
||||
#undef malloc_allocator
|
||||
#include <ext/new_allocator.h>
|
||||
#include <ext/malloc_allocator.h>
|
||||
|
||||
struct N : __gnu_cxx::new_allocator<char> { };
|
||||
|
||||
struct A : std::allocator<char>, N { };
|
||||
struct B : std::allocator<char> { N n; };
|
||||
|
||||
// Verify that layout was not changed by removing std::allocator inheritance
|
||||
// from __gnu_cxx::new_allocator:
|
||||
STATIC_ASSERT( sizeof(A) == 2 );
|
||||
STATIC_ASSERT( sizeof(B) == 2 );
|
||||
|
||||
struct M : __gnu_cxx::malloc_allocator<char> { };
|
||||
struct C : N, M { };
|
||||
|
||||
// Verify that malloc_allocator can be an overlapping subobject with
|
||||
// __new_allocator:
|
||||
STATIC_ASSERT( sizeof(M) == 1 );
|
||||
STATIC_ASSERT( sizeof(C) == 1 );
|
||||
|
||||
struct D : std::allocator<char>, M { };
|
||||
|
||||
// This test uses { target std_allocator_new } so this is true too:
|
||||
STATIC_ASSERT( sizeof(D) == 1 );
|
Loading…
Reference in New Issue