[libc++] Fix PR35491 - std::array of zero-size doesn't work with non-default constructible types.
Summary: This patch fixes llvm.org/PR35491 and LWG2157 (https://cplusplus.github.io/LWG/issue2157) The fix attempts to maintain ABI compatibility by replacing the array with a instance of `aligned_storage`. Reviewers: mclow.lists, EricWF Reviewed By: EricWF Subscribers: lichray, cfe-commits Differential Revision: https://reviews.llvm.org/D41223 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@324526 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -793,8 +793,13 @@ namespace std {
|
|||||||
# if !defined(_LIBCPP_DEBUG)
|
# if !defined(_LIBCPP_DEBUG)
|
||||||
# error cannot use _LIBCPP_DEBUG_USE_EXCEPTIONS unless _LIBCPP_DEBUG is defined
|
# error cannot use _LIBCPP_DEBUG_USE_EXCEPTIONS unless _LIBCPP_DEBUG is defined
|
||||||
# endif
|
# endif
|
||||||
# define _NOEXCEPT_DEBUG noexcept(false)
|
# ifdef _LIBCPP_HAS_NO_NOEXCEPT
|
||||||
# define _NOEXCEPT_DEBUG_(x) noexcept(false)
|
# define _NOEXCEPT_DEBUG
|
||||||
|
# define _NOEXCEPT_DEBUG_(x)
|
||||||
|
# else
|
||||||
|
# define _NOEXCEPT_DEBUG noexcept(false)
|
||||||
|
# define _NOEXCEPT_DEBUG_(x) noexcept(false)
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
# define _NOEXCEPT_DEBUG _NOEXCEPT
|
# define _NOEXCEPT_DEBUG _NOEXCEPT
|
||||||
# define _NOEXCEPT_DEBUG_(x) _NOEXCEPT_(x)
|
# define _NOEXCEPT_DEBUG_(x) _NOEXCEPT_(x)
|
||||||
|
|||||||
167
include/array
167
include/array
@@ -108,6 +108,8 @@ template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexce
|
|||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <cstdlib> // for _LIBCPP_UNREACHABLE
|
||||||
|
#include <__debug>
|
||||||
|
|
||||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||||
#pragma GCC system_header
|
#pragma GCC system_header
|
||||||
@@ -117,6 +119,7 @@ template <size_t I, class T, size_t N> const T&& get(const array<T, N>&&) noexce
|
|||||||
|
|
||||||
_LIBCPP_BEGIN_NAMESPACE_STD
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||||
|
|
||||||
|
|
||||||
template <class _Tp, size_t _Size>
|
template <class _Tp, size_t _Size>
|
||||||
struct _LIBCPP_TEMPLATE_VIS array
|
struct _LIBCPP_TEMPLATE_VIS array
|
||||||
{
|
{
|
||||||
@@ -134,31 +137,27 @@ struct _LIBCPP_TEMPLATE_VIS array
|
|||||||
typedef std::reverse_iterator<iterator> reverse_iterator;
|
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||||
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||||
|
|
||||||
value_type __elems_[_Size > 0 ? _Size : 1];
|
_Tp __elems_[_Size];
|
||||||
|
|
||||||
// No explicit construct/copy/destroy for aggregate type
|
// No explicit construct/copy/destroy for aggregate type
|
||||||
_LIBCPP_INLINE_VISIBILITY void fill(const value_type& __u)
|
_LIBCPP_INLINE_VISIBILITY void fill(const value_type& __u) {
|
||||||
{_VSTD::fill_n(__elems_, _Size, __u);}
|
_VSTD::fill_n(__elems_, _Size, __u);
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
}
|
||||||
void swap(array& __a) _NOEXCEPT_(_Size == 0 || __is_nothrow_swappable<_Tp>::value)
|
|
||||||
{ __swap_dispatch((std::integral_constant<bool, _Size == 0>()), __a); }
|
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
void __swap_dispatch(std::true_type, array&) {}
|
void swap(array& __a) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value) {
|
||||||
|
std::swap_ranges(__elems_, __elems_ + _Size, __a.__elems_);
|
||||||
_LIBCPP_INLINE_VISIBILITY
|
}
|
||||||
void __swap_dispatch(std::false_type, array& __a)
|
|
||||||
{ _VSTD::swap_ranges(__elems_, __elems_ + _Size, __a.__elems_);}
|
|
||||||
|
|
||||||
// iterators:
|
// iterators:
|
||||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||||
iterator begin() _NOEXCEPT {return iterator(__elems_);}
|
iterator begin() _NOEXCEPT {return iterator(data());}
|
||||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||||
const_iterator begin() const _NOEXCEPT {return const_iterator(__elems_);}
|
const_iterator begin() const _NOEXCEPT {return const_iterator(data());}
|
||||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||||
iterator end() _NOEXCEPT {return iterator(__elems_ + _Size);}
|
iterator end() _NOEXCEPT {return iterator(data() + _Size);}
|
||||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||||
const_iterator end() const _NOEXCEPT {return const_iterator(__elems_ + _Size);}
|
const_iterator end() const _NOEXCEPT {return const_iterator(data() + _Size);}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||||
reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());}
|
reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());}
|
||||||
@@ -184,7 +183,7 @@ struct _LIBCPP_TEMPLATE_VIS array
|
|||||||
_LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
_LIBCPP_CONSTEXPR size_type max_size() const _NOEXCEPT {return _Size;}
|
_LIBCPP_CONSTEXPR size_type max_size() const _NOEXCEPT {return _Size;}
|
||||||
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
|
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
|
||||||
_LIBCPP_CONSTEXPR bool empty() const _NOEXCEPT {return _Size == 0;}
|
_LIBCPP_CONSTEXPR bool empty() const _NOEXCEPT {return false; }
|
||||||
|
|
||||||
// element access:
|
// element access:
|
||||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||||
@@ -197,8 +196,8 @@ struct _LIBCPP_TEMPLATE_VIS array
|
|||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reference front() {return __elems_[0];}
|
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reference front() {return __elems_[0];}
|
||||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference front() const {return __elems_[0];}
|
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference front() const {return __elems_[0];}
|
||||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reference back() {return __elems_[_Size > 0 ? _Size-1 : 0];}
|
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14 reference back() {return __elems_[_Size - 1];}
|
||||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference back() const {return __elems_[_Size > 0 ? _Size-1 : 0];}
|
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11 const_reference back() const {return __elems_[_Size - 1];}
|
||||||
|
|
||||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||||
value_type* data() _NOEXCEPT {return __elems_;}
|
value_type* data() _NOEXCEPT {return __elems_;}
|
||||||
@@ -206,6 +205,7 @@ struct _LIBCPP_TEMPLATE_VIS array
|
|||||||
const value_type* data() const _NOEXCEPT {return __elems_;}
|
const value_type* data() const _NOEXCEPT {return __elems_;}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <class _Tp, size_t _Size>
|
template <class _Tp, size_t _Size>
|
||||||
_LIBCPP_CONSTEXPR_AFTER_CXX14
|
_LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||||
typename array<_Tp, _Size>::reference
|
typename array<_Tp, _Size>::reference
|
||||||
@@ -227,12 +227,138 @@ array<_Tp, _Size>::at(size_type __n) const
|
|||||||
return __elems_[__n];
|
return __elems_[__n];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class _Tp>
|
||||||
|
struct _LIBCPP_TEMPLATE_VIS array<_Tp, 0>
|
||||||
|
{
|
||||||
|
// types:
|
||||||
|
typedef array __self;
|
||||||
|
typedef _Tp value_type;
|
||||||
|
typedef value_type& reference;
|
||||||
|
typedef const value_type& const_reference;
|
||||||
|
typedef value_type* iterator;
|
||||||
|
typedef const value_type* const_iterator;
|
||||||
|
typedef value_type* pointer;
|
||||||
|
typedef const value_type* const_pointer;
|
||||||
|
typedef size_t size_type;
|
||||||
|
typedef ptrdiff_t difference_type;
|
||||||
|
typedef std::reverse_iterator<iterator> reverse_iterator;
|
||||||
|
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
|
||||||
|
|
||||||
|
|
||||||
|
typedef typename conditional<is_const<_Tp>::value, const char,
|
||||||
|
char>::type _CharType;
|
||||||
|
_ALIGNAS(alignment_of<_Tp[1]>::value) _CharType __elems_[sizeof(_Tp[1])];
|
||||||
|
|
||||||
|
// No explicit construct/copy/destroy for aggregate type
|
||||||
|
_LIBCPP_INLINE_VISIBILITY void fill(const value_type&) {
|
||||||
|
static_assert(!is_const<_Tp>::value,
|
||||||
|
"cannot fill zero-sized array of type 'const T'");
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
void swap(array&) _NOEXCEPT {
|
||||||
|
static_assert(!is_const<_Tp>::value,
|
||||||
|
"cannot swap zero-sized array of type 'const T'");
|
||||||
|
}
|
||||||
|
|
||||||
|
// iterators:
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
iterator begin() _NOEXCEPT {return iterator(data());}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
const_iterator begin() const _NOEXCEPT {return const_iterator(data());}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
iterator end() _NOEXCEPT {return iterator(data());}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
const_iterator end() const _NOEXCEPT {return const_iterator(data());}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
const_reverse_iterator rbegin() const _NOEXCEPT {return const_reverse_iterator(end());}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
reverse_iterator rend() _NOEXCEPT {return reverse_iterator(begin());}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
const_reverse_iterator rend() const _NOEXCEPT {return const_reverse_iterator(begin());}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
const_iterator cbegin() const _NOEXCEPT {return begin();}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
const_iterator cend() const _NOEXCEPT {return end();}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
const_reverse_iterator crbegin() const _NOEXCEPT {return rbegin();}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
const_reverse_iterator crend() const _NOEXCEPT {return rend();}
|
||||||
|
|
||||||
|
// capacity:
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
_LIBCPP_CONSTEXPR size_type size() const _NOEXCEPT {return 0; }
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
_LIBCPP_CONSTEXPR size_type max_size() const _NOEXCEPT {return 0;}
|
||||||
|
_LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
|
||||||
|
_LIBCPP_CONSTEXPR bool empty() const _NOEXCEPT {return true;}
|
||||||
|
|
||||||
|
// element access:
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
reference operator[](size_type) {
|
||||||
|
_LIBCPP_ASSERT(false, "cannot call array<T, 0>::operator[] on a zero-sized array");
|
||||||
|
_LIBCPP_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
|
||||||
|
const_reference operator[](size_type) const {
|
||||||
|
_LIBCPP_ASSERT(false, "cannot call array<T, 0>::operator[] on a zero-sized array");
|
||||||
|
_LIBCPP_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
reference at(size_type) {
|
||||||
|
__throw_out_of_range("array<T, 0>::at");
|
||||||
|
_LIBCPP_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
const_reference at(size_type) const {
|
||||||
|
__throw_out_of_range("array<T, 0>::at");
|
||||||
|
_LIBCPP_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
reference front() {
|
||||||
|
_LIBCPP_ASSERT(false, "cannot call array<T, 0>::front() on a zero-sized array");
|
||||||
|
_LIBCPP_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
const_reference front() const {
|
||||||
|
_LIBCPP_ASSERT(false, "cannot call array<T, 0>::front() on a zero-sized array");
|
||||||
|
_LIBCPP_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
reference back() {
|
||||||
|
_LIBCPP_ASSERT(false, "cannot call array<T, 0>::back() on a zero-sized array");
|
||||||
|
_LIBCPP_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
const_reference back() const {
|
||||||
|
_LIBCPP_ASSERT(false, "cannot call array<T, 0>::back() on a zero-sized array");
|
||||||
|
_LIBCPP_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
value_type* data() _NOEXCEPT {return reinterpret_cast<value_type*>(__elems_);}
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
const value_type* data() const _NOEXCEPT {return reinterpret_cast<const value_type*>(__elems_);}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
template <class _Tp, size_t _Size>
|
template <class _Tp, size_t _Size>
|
||||||
inline _LIBCPP_INLINE_VISIBILITY
|
inline _LIBCPP_INLINE_VISIBILITY
|
||||||
bool
|
bool
|
||||||
operator==(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
|
operator==(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
|
||||||
{
|
{
|
||||||
return _VSTD::equal(__x.__elems_, __x.__elems_ + _Size, __y.__elems_);
|
return _VSTD::equal(__x.begin(), __x.end(), __y.begin());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class _Tp, size_t _Size>
|
template <class _Tp, size_t _Size>
|
||||||
@@ -248,7 +374,8 @@ inline _LIBCPP_INLINE_VISIBILITY
|
|||||||
bool
|
bool
|
||||||
operator<(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
|
operator<(const array<_Tp, _Size>& __x, const array<_Tp, _Size>& __y)
|
||||||
{
|
{
|
||||||
return _VSTD::lexicographical_compare(__x.__elems_, __x.__elems_ + _Size, __y.__elems_, __y.__elems_ + _Size);
|
return _VSTD::lexicographical_compare(__x.begin(), __x.end(),
|
||||||
|
__y.begin(), __y.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class _Tp, size_t _Size>
|
template <class _Tp, size_t _Size>
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: libcpp-no-exceptions
|
||||||
|
// MODULES_DEFINES: _LIBCPP_DEBUG=1
|
||||||
|
// MODULES_DEFINES: _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||||
|
|
||||||
|
// Can't test the system lib because this test enables debug mode
|
||||||
|
// UNSUPPORTED: with_system_cxx_lib
|
||||||
|
|
||||||
|
// test array<T, 0>::front() throws a debug exception.
|
||||||
|
|
||||||
|
#define _LIBCPP_DEBUG 1
|
||||||
|
#define _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
template <class Array>
|
||||||
|
inline bool CheckDebugThrows(Array& Arr) {
|
||||||
|
try {
|
||||||
|
Arr.back();
|
||||||
|
} catch (std::__libcpp_debug_exception const&) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
typedef std::array<int, 0> C;
|
||||||
|
C c = {};
|
||||||
|
C const& cc = c;
|
||||||
|
assert(CheckDebugThrows(c));
|
||||||
|
assert(CheckDebugThrows(cc));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::array<const int, 0> C;
|
||||||
|
C c = {{}};
|
||||||
|
C const& cc = c;
|
||||||
|
assert(CheckDebugThrows(c));
|
||||||
|
assert(CheckDebugThrows(cc));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: libcpp-no-exceptions
|
||||||
|
// MODULES_DEFINES: _LIBCPP_DEBUG=1
|
||||||
|
// MODULES_DEFINES: _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||||
|
|
||||||
|
// Can't test the system lib because this test enables debug mode
|
||||||
|
// UNSUPPORTED: with_system_cxx_lib
|
||||||
|
|
||||||
|
// test array<T, 0>::front() throws a debug exception.
|
||||||
|
|
||||||
|
#define _LIBCPP_DEBUG 1
|
||||||
|
#define _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
template <class Array>
|
||||||
|
inline bool CheckDebugThrows(Array& Arr) {
|
||||||
|
try {
|
||||||
|
Arr.front();
|
||||||
|
} catch (std::__libcpp_debug_exception const&) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
typedef std::array<int, 0> C;
|
||||||
|
C c = {};
|
||||||
|
C const& cc = c;
|
||||||
|
assert(CheckDebugThrows(c));
|
||||||
|
assert(CheckDebugThrows(cc));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::array<const int, 0> C;
|
||||||
|
C c = {{}};
|
||||||
|
C const& cc = c;
|
||||||
|
assert(CheckDebugThrows(c));
|
||||||
|
assert(CheckDebugThrows(cc));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: libcpp-no-exceptions
|
||||||
|
// MODULES_DEFINES: _LIBCPP_DEBUG=1
|
||||||
|
// MODULES_DEFINES: _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||||
|
|
||||||
|
// Can't test the system lib because this test enables debug mode
|
||||||
|
// UNSUPPORTED: with_system_cxx_lib
|
||||||
|
|
||||||
|
// test array<T, 0>::operator[] throws a debug exception.
|
||||||
|
|
||||||
|
#define _LIBCPP_DEBUG 1
|
||||||
|
#define _LIBCPP_DEBUG_USE_EXCEPTIONS
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
template <class Array>
|
||||||
|
inline bool CheckDebugThrows(Array& Arr, size_t Index) {
|
||||||
|
try {
|
||||||
|
Arr[Index];
|
||||||
|
} catch (std::__libcpp_debug_exception const&) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
typedef std::array<int, 0> C;
|
||||||
|
C c = {};
|
||||||
|
C const& cc = c;
|
||||||
|
assert(CheckDebugThrows(c, 0));
|
||||||
|
assert(CheckDebugThrows(c, 1));
|
||||||
|
assert(CheckDebugThrows(cc, 0));
|
||||||
|
assert(CheckDebugThrows(cc, 1));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::array<const int, 0> C;
|
||||||
|
C c = {{}};
|
||||||
|
C const& cc = c;
|
||||||
|
assert(CheckDebugThrows(c, 0));
|
||||||
|
assert(CheckDebugThrows(c, 1));
|
||||||
|
assert(CheckDebugThrows(cc, 0));
|
||||||
|
assert(CheckDebugThrows(cc, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,6 +14,14 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
|
// std::array is explicitly allowed to be initialized with A a = { init-list };.
|
||||||
|
// Disable the missing braces warning for this reason.
|
||||||
|
#include "disable_missing_braces_warning.h"
|
||||||
|
|
||||||
|
struct NoDefault {
|
||||||
|
NoDefault(int) {}
|
||||||
|
};
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -28,4 +36,13 @@ int main()
|
|||||||
C c;
|
C c;
|
||||||
assert(c.size() == 0);
|
assert(c.size() == 0);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
typedef std::array<NoDefault, 0> C;
|
||||||
|
C c;
|
||||||
|
assert(c.size() == 0);
|
||||||
|
C c1 = {};
|
||||||
|
assert(c1.size() == 0);
|
||||||
|
C c2 = {{}};
|
||||||
|
assert(c2.size() == 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// <array>
|
||||||
|
|
||||||
|
// implicitly generated array constructors / assignment operators
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <cassert>
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
// std::array is explicitly allowed to be initialized with A a = { init-list };.
|
||||||
|
// Disable the missing braces warning for this reason.
|
||||||
|
#include "disable_missing_braces_warning.h"
|
||||||
|
|
||||||
|
// In C++03 the copy assignment operator is not deleted when the implicitly
|
||||||
|
// generated operator would be ill-formed; like in the case of a struct with a
|
||||||
|
// const member.
|
||||||
|
#if TEST_STD_VER < 11
|
||||||
|
#define TEST_NOT_COPY_ASSIGNABLE(T) ((void)0)
|
||||||
|
#else
|
||||||
|
#define TEST_NOT_COPY_ASSIGNABLE(T) static_assert(!std::is_copy_assignable<T>::value, "")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct NoDefault {
|
||||||
|
NoDefault(int) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
{
|
||||||
|
typedef double T;
|
||||||
|
typedef std::array<T, 3> C;
|
||||||
|
C c = {1.1, 2.2, 3.3};
|
||||||
|
C c2 = c;
|
||||||
|
c2 = c;
|
||||||
|
static_assert(std::is_copy_constructible<C>::value, "");
|
||||||
|
static_assert(std::is_copy_assignable<C>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef double T;
|
||||||
|
typedef std::array<const T, 3> C;
|
||||||
|
C c = {1.1, 2.2, 3.3};
|
||||||
|
C c2 = c;
|
||||||
|
((void)c2);
|
||||||
|
static_assert(std::is_copy_constructible<C>::value, "");
|
||||||
|
TEST_NOT_COPY_ASSIGNABLE(C);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef double T;
|
||||||
|
typedef std::array<T, 0> C;
|
||||||
|
C c = {};
|
||||||
|
C c2 = c;
|
||||||
|
c2 = c;
|
||||||
|
static_assert(std::is_copy_constructible<C>::value, "");
|
||||||
|
static_assert(std::is_copy_assignable<C>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// const arrays of size 0 should disable the implicit copy assignment operator.
|
||||||
|
typedef double T;
|
||||||
|
typedef std::array<const T, 0> C;
|
||||||
|
C c = {{}};
|
||||||
|
C c2 = c;
|
||||||
|
((void)c2);
|
||||||
|
static_assert(std::is_copy_constructible<C>::value, "");
|
||||||
|
TEST_NOT_COPY_ASSIGNABLE(C);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef NoDefault T;
|
||||||
|
typedef std::array<T, 0> C;
|
||||||
|
C c = {};
|
||||||
|
C c2 = c;
|
||||||
|
c2 = c;
|
||||||
|
static_assert(std::is_copy_constructible<C>::value, "");
|
||||||
|
static_assert(std::is_copy_assignable<C>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef NoDefault T;
|
||||||
|
typedef std::array<const T, 0> C;
|
||||||
|
C c = {{}};
|
||||||
|
C c2 = c;
|
||||||
|
((void)c2);
|
||||||
|
static_assert(std::is_copy_constructible<C>::value, "");
|
||||||
|
TEST_NOT_COPY_ASSIGNABLE(C);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
// std::array is explicitly allowed to be initialized with A a = { init-list };.
|
// std::array is explicitly allowed to be initialized with A a = { init-list };.
|
||||||
// Disable the missing braces warning for this reason.
|
// Disable the missing braces warning for this reason.
|
||||||
@@ -34,6 +35,33 @@ int main()
|
|||||||
typedef std::array<T, 0> C;
|
typedef std::array<T, 0> C;
|
||||||
C c = {};
|
C c = {};
|
||||||
T* p = c.data();
|
T* p = c.data();
|
||||||
(void)p; // to placate scan-build
|
assert(p != nullptr);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef double T;
|
||||||
|
typedef std::array<const T, 0> C;
|
||||||
|
C c = {{}};
|
||||||
|
const T* p = c.data();
|
||||||
|
static_assert((std::is_same<decltype(c.data()), const T*>::value), "");
|
||||||
|
assert(p != nullptr);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::max_align_t T;
|
||||||
|
typedef std::array<T, 0> C;
|
||||||
|
const C c = {};
|
||||||
|
const T* p = c.data();
|
||||||
|
assert(p != nullptr);
|
||||||
|
std::uintptr_t pint = reinterpret_cast<std::uintptr_t>(p);
|
||||||
|
assert(pint % TEST_ALIGNOF(std::max_align_t) == 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
struct NoDefault {
|
||||||
|
NoDefault(int) {}
|
||||||
|
};
|
||||||
|
typedef NoDefault T;
|
||||||
|
typedef std::array<T, 0> C;
|
||||||
|
C c = {};
|
||||||
|
T* p = c.data();
|
||||||
|
assert(p != nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,6 +38,25 @@ int main()
|
|||||||
const T* p = c.data();
|
const T* p = c.data();
|
||||||
(void)p; // to placate scan-build
|
(void)p; // to placate scan-build
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
struct NoDefault {
|
||||||
|
NoDefault(int) {}
|
||||||
|
};
|
||||||
|
typedef NoDefault T;
|
||||||
|
typedef std::array<T, 0> C;
|
||||||
|
const C c = {};
|
||||||
|
const T* p = c.data();
|
||||||
|
assert(p != nullptr);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef std::max_align_t T;
|
||||||
|
typedef std::array<T, 0> C;
|
||||||
|
const C c = {};
|
||||||
|
const T* p = c.data();
|
||||||
|
assert(p != nullptr);
|
||||||
|
std::uintptr_t pint = reinterpret_cast<std::uintptr_t>(p);
|
||||||
|
assert(pint % TEST_ALIGNOF(std::max_align_t) == 0);
|
||||||
|
}
|
||||||
#if TEST_STD_VER > 14
|
#if TEST_STD_VER > 14
|
||||||
{
|
{
|
||||||
typedef std::array<int, 5> C;
|
typedef std::array<int, 5> C;
|
||||||
|
|||||||
29
test/std/containers/sequences/array/array.fill/fill.fail.cpp
Normal file
29
test/std/containers/sequences/array/array.fill/fill.fail.cpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// <array>
|
||||||
|
|
||||||
|
// void fill(const T& u);
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
// std::array is explicitly allowed to be initialized with A a = { init-list };.
|
||||||
|
// Disable the missing braces warning for this reason.
|
||||||
|
#include "disable_missing_braces_warning.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
{
|
||||||
|
typedef double T;
|
||||||
|
typedef std::array<const T, 0> C;
|
||||||
|
C c = {};
|
||||||
|
// expected-error-re@array:* {{static_assert failed {{.*}} "cannot fill zero-sized array of type 'const T'"}}
|
||||||
|
c.fill(5.5); // expected-note {{requested here}}
|
||||||
|
}
|
||||||
|
}
|
||||||
30
test/std/containers/sequences/array/array.swap/swap.fail.cpp
Normal file
30
test/std/containers/sequences/array/array.swap/swap.fail.cpp
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// <array>
|
||||||
|
|
||||||
|
// void swap(array& a);
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
// std::array is explicitly allowed to be initialized with A a = { init-list };.
|
||||||
|
// Disable the missing braces warning for this reason.
|
||||||
|
#include "disable_missing_braces_warning.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
{
|
||||||
|
typedef double T;
|
||||||
|
typedef std::array<const T, 0> C;
|
||||||
|
C c = {};
|
||||||
|
C c2 = {};
|
||||||
|
// expected-error-re@array:* {{static_assert failed {{.*}} "cannot swap zero-sized array of type 'const T'"}}
|
||||||
|
c.swap(c2); // expected-note {{requested here}}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -56,6 +56,26 @@ int main()
|
|||||||
catch (const std::out_of_range &) {}
|
catch (const std::out_of_range &) {}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||||
|
{
|
||||||
|
typedef double T;
|
||||||
|
typedef std::array<T, 0> C;
|
||||||
|
C c = {};
|
||||||
|
C const& cc = c;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TEST_IGNORE_NODISCARD c.at(0);
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
catch (const std::out_of_range &) {}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
TEST_IGNORE_NODISCARD cc.at(0);
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
catch (const std::out_of_range &) {}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
typedef double T;
|
typedef double T;
|
||||||
typedef std::array<T, 3> C;
|
typedef std::array<T, 3> C;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
// Disable the missing braces warning for this reason.
|
// Disable the missing braces warning for this reason.
|
||||||
#include "disable_missing_braces_warning.h"
|
#include "disable_missing_braces_warning.h"
|
||||||
|
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -31,4 +32,13 @@ int main()
|
|||||||
*i = 5.5;
|
*i = 5.5;
|
||||||
assert(c[0] == 5.5);
|
assert(c[0] == 5.5);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
struct NoDefault {
|
||||||
|
NoDefault(int) {}
|
||||||
|
};
|
||||||
|
typedef NoDefault T;
|
||||||
|
typedef std::array<T, 0> C;
|
||||||
|
C c = {};
|
||||||
|
assert(c.begin() == c.end());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
71
test/std/containers/sequences/array/compare.fail.cpp
Normal file
71
test/std/containers/sequences/array/compare.fail.cpp
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// <array>
|
||||||
|
|
||||||
|
// bool operator==(array<T, N> const&, array<T, N> const&);
|
||||||
|
// bool operator!=(array<T, N> const&, array<T, N> const&);
|
||||||
|
// bool operator<(array<T, N> const&, array<T, N> const&);
|
||||||
|
// bool operator<=(array<T, N> const&, array<T, N> const&);
|
||||||
|
// bool operator>(array<T, N> const&, array<T, N> const&);
|
||||||
|
// bool operator>=(array<T, N> const&, array<T, N> const&);
|
||||||
|
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <vector>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
// std::array is explicitly allowed to be initialized with A a = { init-list };.
|
||||||
|
// Disable the missing braces warning for this reason.
|
||||||
|
#include "disable_missing_braces_warning.h"
|
||||||
|
|
||||||
|
template <class Array>
|
||||||
|
void test_compare(const Array& LHS, const Array& RHS) {
|
||||||
|
typedef std::vector<typename Array::value_type> Vector;
|
||||||
|
const Vector LHSV(LHS.begin(), LHS.end());
|
||||||
|
const Vector RHSV(RHS.begin(), RHS.end());
|
||||||
|
assert((LHS == RHS) == (LHSV == RHSV));
|
||||||
|
assert((LHS != RHS) == (LHSV != RHSV));
|
||||||
|
assert((LHS < RHS) == (LHSV < RHSV));
|
||||||
|
assert((LHS <= RHS) == (LHSV <= RHSV));
|
||||||
|
assert((LHS > RHS) == (LHSV > RHSV));
|
||||||
|
assert((LHS >= RHS) == (LHSV >= RHSV));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <int Dummy> struct NoCompare {};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
typedef NoCompare<0> T;
|
||||||
|
typedef std::array<T, 3> C;
|
||||||
|
C c1 = {{}};
|
||||||
|
// expected-error@algorithm:* 2 {{invalid operands to binary expression}}
|
||||||
|
TEST_IGNORE_NODISCARD (c1 == c1);
|
||||||
|
TEST_IGNORE_NODISCARD (c1 < c1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef NoCompare<1> T;
|
||||||
|
typedef std::array<T, 3> C;
|
||||||
|
C c1 = {{}};
|
||||||
|
// expected-error@algorithm:* 2 {{invalid operands to binary expression}}
|
||||||
|
TEST_IGNORE_NODISCARD (c1 != c1);
|
||||||
|
TEST_IGNORE_NODISCARD (c1 > c1);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef NoCompare<2> T;
|
||||||
|
typedef std::array<T, 0> C;
|
||||||
|
C c1 = {{}};
|
||||||
|
// expected-error@algorithm:* 2 {{invalid operands to binary expression}}
|
||||||
|
TEST_IGNORE_NODISCARD (c1 == c1);
|
||||||
|
TEST_IGNORE_NODISCARD (c1 < c1);
|
||||||
|
}
|
||||||
|
}
|
||||||
63
test/std/containers/sequences/array/compare.pass.cpp
Normal file
63
test/std/containers/sequences/array/compare.pass.cpp
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// <array>
|
||||||
|
|
||||||
|
// bool operator==(array<T, N> const&, array<T, N> const&);
|
||||||
|
// bool operator!=(array<T, N> const&, array<T, N> const&);
|
||||||
|
// bool operator<(array<T, N> const&, array<T, N> const&);
|
||||||
|
// bool operator<=(array<T, N> const&, array<T, N> const&);
|
||||||
|
// bool operator>(array<T, N> const&, array<T, N> const&);
|
||||||
|
// bool operator>=(array<T, N> const&, array<T, N> const&);
|
||||||
|
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <vector>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
// std::array is explicitly allowed to be initialized with A a = { init-list };.
|
||||||
|
// Disable the missing braces warning for this reason.
|
||||||
|
#include "disable_missing_braces_warning.h"
|
||||||
|
|
||||||
|
template <class Array>
|
||||||
|
void test_compare(const Array& LHS, const Array& RHS) {
|
||||||
|
typedef std::vector<typename Array::value_type> Vector;
|
||||||
|
const Vector LHSV(LHS.begin(), LHS.end());
|
||||||
|
const Vector RHSV(RHS.begin(), RHS.end());
|
||||||
|
assert((LHS == RHS) == (LHSV == RHSV));
|
||||||
|
assert((LHS != RHS) == (LHSV != RHSV));
|
||||||
|
assert((LHS < RHS) == (LHSV < RHSV));
|
||||||
|
assert((LHS <= RHS) == (LHSV <= RHSV));
|
||||||
|
assert((LHS > RHS) == (LHSV > RHSV));
|
||||||
|
assert((LHS >= RHS) == (LHSV >= RHSV));
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
typedef int T;
|
||||||
|
typedef std::array<T, 3> C;
|
||||||
|
C c1 = {1, 2, 3};
|
||||||
|
C c2 = {1, 2, 3};
|
||||||
|
C c3 = {3, 2, 1};
|
||||||
|
C c4 = {1, 2, 1};
|
||||||
|
test_compare(c1, c2);
|
||||||
|
test_compare(c1, c3);
|
||||||
|
test_compare(c1, c4);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef int T;
|
||||||
|
typedef std::array<T, 0> C;
|
||||||
|
C c1 = {};
|
||||||
|
C c2 = {};
|
||||||
|
test_compare(c1, c2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,6 +23,9 @@
|
|||||||
|
|
||||||
int main ()
|
int main ()
|
||||||
{
|
{
|
||||||
|
|
||||||
std::array<int, 1> c;
|
std::array<int, 1> c;
|
||||||
c.empty(); // expected-error {{ignoring return value of function declared with 'nodiscard' attribute}}
|
c.empty(); // expected-error {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||||
|
std::array<int, 0> c0;
|
||||||
|
c0.empty(); // expected-error {{ignoring return value of function declared with 'nodiscard' attribute}}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,7 +64,38 @@ int main()
|
|||||||
C::const_reference r2 = c.back();
|
C::const_reference r2 = c.back();
|
||||||
assert(r2 == 3.5);
|
assert(r2 == 3.5);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
typedef double T;
|
||||||
|
typedef std::array<T, 0> C;
|
||||||
|
C c = {};
|
||||||
|
C const& cc = c;
|
||||||
|
static_assert((std::is_same<decltype(c.front()), T &>::value), "");
|
||||||
|
static_assert((std::is_same<decltype(cc.front()), const T &>::value), "");
|
||||||
|
static_assert((std::is_same<decltype(c.back()), T &>::value), "");
|
||||||
|
static_assert((std::is_same<decltype(cc.back()), const T &>::value), "");
|
||||||
|
if (c.size() > (0)) { // always false
|
||||||
|
TEST_IGNORE_NODISCARD c.front();
|
||||||
|
TEST_IGNORE_NODISCARD c.back();
|
||||||
|
TEST_IGNORE_NODISCARD cc.front();
|
||||||
|
TEST_IGNORE_NODISCARD cc.back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
typedef double T;
|
||||||
|
typedef std::array<const T, 0> C;
|
||||||
|
C c = {{}};
|
||||||
|
C const& cc = c;
|
||||||
|
static_assert((std::is_same<decltype(c.front()), const T &>::value), "");
|
||||||
|
static_assert((std::is_same<decltype(cc.front()), const T &>::value), "");
|
||||||
|
static_assert((std::is_same<decltype(c.back()), const T &>::value), "");
|
||||||
|
static_assert((std::is_same<decltype(cc.back()), const T &>::value), "");
|
||||||
|
if (c.size() > (0)) {
|
||||||
|
TEST_IGNORE_NODISCARD c.front();
|
||||||
|
TEST_IGNORE_NODISCARD c.back();
|
||||||
|
TEST_IGNORE_NODISCARD cc.front();
|
||||||
|
TEST_IGNORE_NODISCARD cc.back();
|
||||||
|
}
|
||||||
|
}
|
||||||
#if TEST_STD_VER > 11
|
#if TEST_STD_VER > 11
|
||||||
{
|
{
|
||||||
typedef double T;
|
typedef double T;
|
||||||
|
|||||||
@@ -56,7 +56,34 @@ int main()
|
|||||||
C::const_reference r2 = c[2];
|
C::const_reference r2 = c[2];
|
||||||
assert(r2 == 3.5);
|
assert(r2 == 3.5);
|
||||||
}
|
}
|
||||||
|
{ // Test operator[] "works" on zero sized arrays
|
||||||
|
typedef double T;
|
||||||
|
typedef std::array<T, 0> C;
|
||||||
|
C c = {};
|
||||||
|
C const& cc = c;
|
||||||
|
static_assert((std::is_same<decltype(c[0]), T &>::value), "");
|
||||||
|
static_assert((std::is_same<decltype(cc[0]), const T &>::value), "");
|
||||||
|
if (c.size() > (0)) { // always false
|
||||||
|
C::reference r1 = c[0];
|
||||||
|
C::const_reference r2 = cc[0];
|
||||||
|
((void)r1);
|
||||||
|
((void)r2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{ // Test operator[] "works" on zero sized arrays
|
||||||
|
typedef double T;
|
||||||
|
typedef std::array<const T, 0> C;
|
||||||
|
C c = {{}};
|
||||||
|
C const& cc = c;
|
||||||
|
static_assert((std::is_same<decltype(c[0]), const T &>::value), "");
|
||||||
|
static_assert((std::is_same<decltype(cc[0]), const T &>::value), "");
|
||||||
|
if (c.size() > (0)) { // always false
|
||||||
|
C::reference r1 = c[0];
|
||||||
|
C::const_reference r2 = cc[0];
|
||||||
|
((void)r1);
|
||||||
|
((void)r2);
|
||||||
|
}
|
||||||
|
}
|
||||||
#if TEST_STD_VER > 11
|
#if TEST_STD_VER > 11
|
||||||
{
|
{
|
||||||
typedef double T;
|
typedef double T;
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// <array>
|
||||||
|
|
||||||
|
// template <class T, size_t N >
|
||||||
|
// struct array
|
||||||
|
|
||||||
|
// Test the size and alignment matches that of an array of a given type.
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <iterator>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
template <class T, size_t Size>
|
||||||
|
void test() {
|
||||||
|
typedef T CArrayT[Size == 0 ? 1 : Size];
|
||||||
|
typedef std::array<T, Size> ArrayT;
|
||||||
|
static_assert(sizeof(CArrayT) == sizeof(ArrayT), "");
|
||||||
|
static_assert(TEST_ALIGNOF(CArrayT) == TEST_ALIGNOF(ArrayT), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void test_type() {
|
||||||
|
test<T, 1>();
|
||||||
|
test<T, 42>();
|
||||||
|
test<T, 0>();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TEST_ALIGNAS(TEST_ALIGNOF(std::max_align_t) * 2) TestType1 {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TEST_ALIGNAS(TEST_ALIGNOF(std::max_align_t) * 2) TestType2 {
|
||||||
|
char data[1000];
|
||||||
|
};
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
test_type<char>();
|
||||||
|
test_type<int>();
|
||||||
|
test_type<double>();
|
||||||
|
test_type<long double>();
|
||||||
|
test_type<std::max_align_t>();
|
||||||
|
test_type<TestType1>();
|
||||||
|
test_type<TestType2>();
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user