[libcxx] Use custom allocator's construct in C++03 when available.
Makes libc++ behavior consistent between C++03 and C++11. Can use `decltype` in C++03 because `include/__config` defines a macro when `decltype` is not available. Reviewers: mclow.lists, EricWF, erik.pilkington, ldionne Reviewed By: ldionne Subscribers: dexonsmith, cfe-commits, howard.hinnant, ldionne, christof, jkorous, Quuxplusone Differential Revision: https://reviews.llvm.org/D48753 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@349676 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -1460,29 +1460,21 @@ struct __has_select_on_container_copy_construction
|
|||||||
|
|
||||||
#else // _LIBCPP_CXX03_LANG
|
#else // _LIBCPP_CXX03_LANG
|
||||||
|
|
||||||
#ifndef _LIBCPP_HAS_NO_VARIADICS
|
template <class _Alloc, class _Pointer, class _Tp, class = void>
|
||||||
|
struct __has_construct : std::false_type {};
|
||||||
|
|
||||||
template <class _Alloc, class _Pointer, class ..._Args>
|
template <class _Alloc, class _Pointer, class _Tp>
|
||||||
struct __has_construct
|
struct __has_construct<_Alloc, _Pointer, _Tp, typename __void_t<
|
||||||
: false_type
|
decltype(_VSTD::declval<_Alloc>().construct(_VSTD::declval<_Pointer>(), _VSTD::declval<_Tp>()))
|
||||||
{
|
>::type> : std::true_type {};
|
||||||
};
|
|
||||||
|
|
||||||
#else // _LIBCPP_HAS_NO_VARIADICS
|
template <class _Alloc, class _Pointer, class = void>
|
||||||
|
struct __has_destroy : false_type {};
|
||||||
template <class _Alloc, class _Pointer, class _Args>
|
|
||||||
struct __has_construct
|
|
||||||
: false_type
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
|
||||||
|
|
||||||
template <class _Alloc, class _Pointer>
|
template <class _Alloc, class _Pointer>
|
||||||
struct __has_destroy
|
struct __has_destroy<_Alloc, _Pointer, typename __void_t<
|
||||||
: false_type
|
decltype(_VSTD::declval<_Alloc>().destroy(_VSTD::declval<_Pointer>()))
|
||||||
{
|
>::type> : std::true_type {};
|
||||||
};
|
|
||||||
|
|
||||||
template <class _Alloc>
|
template <class _Alloc>
|
||||||
struct __has_max_size
|
struct __has_max_size
|
||||||
@@ -1571,9 +1563,10 @@ struct _LIBCPP_TEMPLATE_VIS allocator_traits
|
|||||||
}
|
}
|
||||||
template <class _Tp, class _A0>
|
template <class _Tp, class _A0>
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
static void construct(allocator_type&, _Tp* __p, const _A0& __a0)
|
static void construct(allocator_type& __a, _Tp* __p, const _A0& __a0)
|
||||||
{
|
{
|
||||||
::new ((void*)__p) _Tp(__a0);
|
__construct(__has_construct<allocator_type, _Tp*, const _A0&>(),
|
||||||
|
__a, __p, __a0);
|
||||||
}
|
}
|
||||||
template <class _Tp, class _A0, class _A1>
|
template <class _Tp, class _A0, class _A1>
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
@@ -1721,6 +1714,19 @@ private:
|
|||||||
{
|
{
|
||||||
::new ((void*)__p) _Tp(_VSTD::forward<_Args>(__args)...);
|
::new ((void*)__p) _Tp(_VSTD::forward<_Args>(__args)...);
|
||||||
}
|
}
|
||||||
|
#else // _LIBCPP_HAS_NO_VARIADICS
|
||||||
|
template <class _Tp, class _A0>
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
static void __construct(true_type, allocator_type& __a, _Tp* __p,
|
||||||
|
const _A0& __a0)
|
||||||
|
{__a.construct(__p, __a0);}
|
||||||
|
template <class _Tp, class _A0>
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
static void __construct(false_type, allocator_type&, _Tp* __p,
|
||||||
|
const _A0& __a0)
|
||||||
|
{
|
||||||
|
::new ((void*)__p) _Tp(__a0);
|
||||||
|
}
|
||||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||||
|
|
||||||
template <class _Tp>
|
template <class _Tp>
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// <vector>
|
||||||
|
|
||||||
|
// template <class InputIter> vector(InputIter first, InputIter last);
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "min_allocator.h"
|
||||||
|
|
||||||
|
void test_ctor_under_alloc() {
|
||||||
|
int arr1[] = {42};
|
||||||
|
int arr2[] = {1, 101, 42};
|
||||||
|
{
|
||||||
|
typedef std::vector<int, cpp03_allocator<int> > C;
|
||||||
|
typedef C::allocator_type Alloc;
|
||||||
|
{
|
||||||
|
Alloc::construct_called = false;
|
||||||
|
C v(arr1, arr1 + 1);
|
||||||
|
assert(Alloc::construct_called);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Alloc::construct_called = false;
|
||||||
|
C v(arr2, arr2 + 3);
|
||||||
|
assert(Alloc::construct_called);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::vector<int, cpp03_overload_allocator<int> > C;
|
||||||
|
typedef C::allocator_type Alloc;
|
||||||
|
{
|
||||||
|
Alloc::construct_called = false;
|
||||||
|
C v(arr1, arr1 + 1);
|
||||||
|
assert(Alloc::construct_called);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Alloc::construct_called = false;
|
||||||
|
C v(arr2, arr2 + 3);
|
||||||
|
assert(Alloc::construct_called);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
test_ctor_under_alloc();
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// <vector>
|
||||||
|
|
||||||
|
// template <class InputIter> vector(InputIter first, InputIter last,
|
||||||
|
// const allocator_type& a);
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "min_allocator.h"
|
||||||
|
|
||||||
|
void test_ctor_under_alloc() {
|
||||||
|
int arr1[] = {42};
|
||||||
|
int arr2[] = {1, 101, 42};
|
||||||
|
{
|
||||||
|
typedef std::vector<int, cpp03_allocator<int> > C;
|
||||||
|
typedef C::allocator_type Alloc;
|
||||||
|
Alloc a;
|
||||||
|
{
|
||||||
|
Alloc::construct_called = false;
|
||||||
|
C v(arr1, arr1 + 1, a);
|
||||||
|
assert(Alloc::construct_called);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Alloc::construct_called = false;
|
||||||
|
C v(arr2, arr2 + 3, a);
|
||||||
|
assert(Alloc::construct_called);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::vector<int, cpp03_overload_allocator<int> > C;
|
||||||
|
typedef C::allocator_type Alloc;
|
||||||
|
Alloc a;
|
||||||
|
{
|
||||||
|
Alloc::construct_called = false;
|
||||||
|
C v(arr1, arr1 + 1, a);
|
||||||
|
assert(Alloc::construct_called);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Alloc::construct_called = false;
|
||||||
|
C v(arr2, arr2 + 3, a);
|
||||||
|
assert(Alloc::construct_called);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
test_ctor_under_alloc();
|
||||||
|
}
|
||||||
@@ -73,7 +73,7 @@ int main()
|
|||||||
std::aligned_storage<sizeof(VT)>::type store;
|
std::aligned_storage<sizeof(VT)>::type store;
|
||||||
std::allocator_traits<Alloc>::destroy(a, (VT*)&store);
|
std::allocator_traits<Alloc>::destroy(a, (VT*)&store);
|
||||||
}
|
}
|
||||||
#if TEST_STD_VER >= 11
|
#if defined(_LIBCPP_VERSION) || TEST_STD_VER >= 11
|
||||||
{
|
{
|
||||||
A0::count = 0;
|
A0::count = 0;
|
||||||
b_destroy = 0;
|
b_destroy = 0;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <climits>
|
||||||
|
|
||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
|
|
||||||
@@ -131,6 +132,59 @@ public:
|
|||||||
friend bool operator!=(malloc_allocator x, malloc_allocator y) {return !(x == y);}
|
friend bool operator!=(malloc_allocator x, malloc_allocator y) {return !(x == y);}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct cpp03_allocator : bare_allocator<T>
|
||||||
|
{
|
||||||
|
typedef T value_type;
|
||||||
|
typedef value_type* pointer;
|
||||||
|
|
||||||
|
static bool construct_called;
|
||||||
|
|
||||||
|
// Returned value is not used but it's not prohibited.
|
||||||
|
pointer construct(pointer p, const value_type& val)
|
||||||
|
{
|
||||||
|
::new(p) value_type(val);
|
||||||
|
construct_called = true;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t max_size() const
|
||||||
|
{
|
||||||
|
return UINT_MAX / sizeof(T);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template <class T> bool cpp03_allocator<T>::construct_called = false;
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct cpp03_overload_allocator : bare_allocator<T>
|
||||||
|
{
|
||||||
|
typedef T value_type;
|
||||||
|
typedef value_type* pointer;
|
||||||
|
|
||||||
|
static bool construct_called;
|
||||||
|
|
||||||
|
void construct(pointer p, const value_type& val)
|
||||||
|
{
|
||||||
|
construct(p, val, std::is_class<T>());
|
||||||
|
}
|
||||||
|
void construct(pointer p, const value_type& val, std::true_type)
|
||||||
|
{
|
||||||
|
::new(p) value_type(val);
|
||||||
|
construct_called = true;
|
||||||
|
}
|
||||||
|
void construct(pointer p, const value_type& val, std::false_type)
|
||||||
|
{
|
||||||
|
::new(p) value_type(val);
|
||||||
|
construct_called = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t max_size() const
|
||||||
|
{
|
||||||
|
return UINT_MAX / sizeof(T);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
template <class T> bool cpp03_overload_allocator<T>::construct_called = false;
|
||||||
|
|
||||||
|
|
||||||
#if TEST_STD_VER >= 11
|
#if TEST_STD_VER >= 11
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user