mirror of
https://github.com/llvm-mirror/libcxx.git
synced 2025-10-24 03:32:35 +08:00
[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)
|
||||
# error cannot use _LIBCPP_DEBUG_USE_EXCEPTIONS unless _LIBCPP_DEBUG is defined
|
||||
# endif
|
||||
# ifdef _LIBCPP_HAS_NO_NOEXCEPT
|
||||
# define _NOEXCEPT_DEBUG
|
||||
# define _NOEXCEPT_DEBUG_(x)
|
||||
# else
|
||||
# define _NOEXCEPT_DEBUG noexcept(false)
|
||||
# define _NOEXCEPT_DEBUG_(x) noexcept(false)
|
||||
#endif
|
||||
#else
|
||||
# define _NOEXCEPT_DEBUG _NOEXCEPT
|
||||
# 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 <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <cstdlib> // for _LIBCPP_UNREACHABLE
|
||||
#include <__debug>
|
||||
|
||||
#if !defined(_LIBCPP_HAS_NO_PRAGMA_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
|
||||
|
||||
|
||||
template <class _Tp, size_t _Size>
|
||||
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<const_iterator> const_reverse_iterator;
|
||||
|
||||
value_type __elems_[_Size > 0 ? _Size : 1];
|
||||
_Tp __elems_[_Size];
|
||||
|
||||
// No explicit construct/copy/destroy for aggregate type
|
||||
_LIBCPP_INLINE_VISIBILITY void fill(const value_type& __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 void fill(const value_type& __u) {
|
||||
_VSTD::fill_n(__elems_, _Size, __u);
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __swap_dispatch(std::true_type, array&) {}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __swap_dispatch(std::false_type, array& __a)
|
||||
{ _VSTD::swap_ranges(__elems_, __elems_ + _Size, __a.__elems_);}
|
||||
void swap(array& __a) _NOEXCEPT_(__is_nothrow_swappable<_Tp>::value) {
|
||||
std::swap_ranges(__elems_, __elems_ + _Size, __a.__elems_);
|
||||
}
|
||||
|
||||
// iterators:
|
||||
_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
|
||||
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
|
||||
iterator end() _NOEXCEPT {return iterator(__elems_ + _Size);}
|
||||
iterator end() _NOEXCEPT {return iterator(data() + _Size);}
|
||||
_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
|
||||
reverse_iterator rbegin() _NOEXCEPT {return reverse_iterator(end());}
|
||||
@@ -184,7 +183,7 @@ struct _LIBCPP_TEMPLATE_VIS array
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_CONSTEXPR size_type max_size() const _NOEXCEPT {return _Size;}
|
||||
_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:
|
||||
_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_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_CXX11 const_reference back() const {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 - 1];}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||
value_type* data() _NOEXCEPT {return __elems_;}
|
||||
@@ -206,6 +205,7 @@ struct _LIBCPP_TEMPLATE_VIS array
|
||||
const value_type* data() const _NOEXCEPT {return __elems_;}
|
||||
};
|
||||
|
||||
|
||||
template <class _Tp, size_t _Size>
|
||||
_LIBCPP_CONSTEXPR_AFTER_CXX14
|
||||
typename array<_Tp, _Size>::reference
|
||||
@@ -227,12 +227,138 @@ array<_Tp, _Size>::at(size_type __n) const
|
||||
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>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
bool
|
||||
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>
|
||||
@@ -248,7 +374,8 @@ inline _LIBCPP_INLINE_VISIBILITY
|
||||
bool
|
||||
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>
|
||||
|
||||
@@ -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 <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()
|
||||
{
|
||||
{
|
||||
@@ -28,4 +36,13 @@ int main()
|
||||
C c;
|
||||
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 <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.
|
||||
@@ -34,6 +35,33 @@ int main()
|
||||
typedef std::array<T, 0> C;
|
||||
C c = {};
|
||||
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();
|
||||
(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
|
||||
{
|
||||
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 &) {}
|
||||
#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 std::array<T, 3> C;
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
// Disable the missing braces warning for this reason.
|
||||
#include "disable_missing_braces_warning.h"
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
@@ -31,4 +32,13 @@ int main()
|
||||
*i = 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 ()
|
||||
{
|
||||
|
||||
std::array<int, 1> c;
|
||||
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();
|
||||
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
|
||||
{
|
||||
typedef double T;
|
||||
|
||||
@@ -56,7 +56,34 @@ int main()
|
||||
C::const_reference r2 = c[2];
|
||||
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
|
||||
{
|
||||
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