Index: include/experimental/any =================================================================== --- /dev/null +++ include/experimental/any @@ -0,0 +1,659 @@ +// -*- C++ -*- +#ifndef _LIBCPP_EXPERIMENTAL_ANY +#define _LIBCPP_EXPERIMENTAL_ANY + +/** + any synopsis + + +// C++1y +namespace std { namespace experimental { inline namespace fundamentals_v1 { + class bad_any_cast : public bad_cast + { + public: + virtual const char* what() const noexcept; + }; + + class any + { + public: + // construct/destruct + any() noexcept; + + any(const any& other); + any(any&& x) noexcept; + + template + any(ValueType&& value); + + template + any(allocator_arg_t, const Allocator& a) noexcept; + template + any(allocator_arg_t, const Allocator& a, ValueType&& value); + template + any(allocator_arg_t, const Allocator& a, const any& other); + template + any(allocator_arg_t, const Allocator& a, any&& other) noexcept; + + ~any(); + + // assignments + any& operator=(const any& rhs); + any& operator=(any&& rhs) noexcept; + + template + any& operator=(ValueType&& rhs); + + // modifiers + void clear() noexcept; + void swap(any& rhs) noexcept; + + // observers + bool empty() const noexcept; + const type_info& type() const noexcept; + }; + + void swap(any& x, any& y) noexcept; + + template + ValueType any_cast(const any& operand); + template + ValueType any_cast(any& operand); + template + ValueType any_cast(any&& operand); + + template + const ValueType* any_cast(const any* operand) noexcept; + template + ValueType* any_cast(any* operand) noexcept; +}}} // std::experimental::fundamentals_v1 + +*/ + +# include +# include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL + +// Get bad_any_cast into the dylib even if not compiling for C++1y +class _LIBCPP_EXCEPTION_ABI bad_any_cast + : public bad_cast +{ +public: + virtual const char* what() const _NOEXCEPT; + + // TODO Destructor not specified + virtual ~bad_any_cast() _NOEXCEPT; +}; + +_LIBCPP_END_NAMESPACE_EXPERIMENTAL + +#if _LIBCPP_STD_VER > 11 + +// Feature checking macro encouraged in the fundamentals-ts +#define __cpp_lib_experimental_any + +#include +#include +#include +#include /* placement new */ +#include <__functional_base> /* allocator_arg_t */ + +_LIBCPP_BEGIN_NAMESPACE_LFTS + + namespace __any + { + + /** The buffer type used for the small object optimization. */ + typedef typename _VSTD::aligned_storage<3*sizeof(void*)>::type __buffer; + + /** The predicate to check if an object can be stored locally. + * 1. sizeof(T) <= sizeof(Buffer) + * 2. Alignment + * 3. It must be nothrow move constructible. + */ + template + struct __is_small_object + : public integral_constant::value + % alignment_of<_Storage>::value == 0 + && is_nothrow_move_constructible< + typename _Storage::_ValueType + >::value + > + {}; + + + class __storage_base + { + __storage_base(__storage_base const &); + __storage_base & operator=(__storage_base const &); + + public: + _LIBCPP_INLINE_VISIBILITY __storage_base() {} + _LIBCPP_INLINE_VISIBILITY virtual ~__storage_base() {} + virtual __storage_base* __copy() const = 0; + virtual __storage_base* __copy(void*) const = 0; + virtual __storage_base* __move(void*) = 0; + + /** __destroy() handles both deallocation and destruction, since + * it knows if an object is stored on the stack or the heap + * Thats one less virtual overload needed vs the extra + * __destroy_deallocate() that std::function has. + * TODO: is that worth it? + */ + virtual void __destroy() _NOEXCEPT = 0; + + virtual void const* __target(type_info const &) const _NOEXCEPT = 0; + virtual type_info const & __target_type() const _NOEXCEPT = 0; + }; + + template + class __storage : public __storage_base + { + __compressed_pair<_Tp, _Alloc> __store_; + + public: + + typedef _Tp _ValueType; + + template + _LIBCPP_INLINE_VISIBILITY + explicit __storage(_Up && __v, _Alloc const & __a) + : __store_(piecewise_construct + , _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__v)) + , _VSTD::forward_as_tuple(__a)) + {} + + /** Not uses allocator construction. */ + template + explicit __storage( + integral_constant, _Alloc const & __a, _Up && __v) + : __store_(piecewise_construct + , _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__v)) + , _VSTD::forward_as_tuple(__a)) + {} + + /** Uses allocator construction: _Tp(allocator_arg_t, Alloc, _Up) */ + template + explicit __storage( + integral_constant, _Alloc const & __a, _Up && __v) + : __store_(piecewise_construct + , _VSTD::forward_as_tuple( + allocator_arg_t(), __a, _VSTD::forward<_Up>(__v)) + , _VSTD::forward_as_tuple(__a)) + {} + + /** Uses allocator construction: _Tp(_Up, _Alloc) */ + template + explicit __storage( + integral_constant, _Alloc const & __a, _Up && __v) + : __store_(piecewise_construct + , _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__v), __a) + , _VSTD::forward_as_tuple(__a)) + {} + + /** Allocate and copy construct */ + virtual __storage_base* __copy() const; + + /** Copy construct into storage */ + virtual __storage_base* __copy(void*) const; + + /** Move construct into storage */ + virtual __storage_base* __move(void*); + + /** Destroy or destroy && deallocate depending on if it stores a + * small type. */ + virtual void __destroy() _NOEXCEPT; + + /** Return a pointer to the stored value if given the correct type. + * nullptr otherwise. */ + virtual void const *__target(type_info const &) const _NOEXCEPT; + + /** Return the stored values type */ + virtual type_info const & __target_type() const _NOEXCEPT; + }; + + template + __storage_base* + __storage<_Tp, _Alloc>::__copy() const + { + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __alloc_traits::template +#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES + rebind_traits<__storage> +#else + rebind_traits<__storage>::other +#endif + _BaseTraits; + typedef typename _BaseTraits::allocator_type _Ap; + + _Ap __a(__store_.second()); + typedef __allocator_destructor<_Ap> _Dp; + unique_ptr<__storage, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + + _BaseTraits::construct( + __a, __hold.get() + , __store_.first(), _VSTD::move(__a) + ); + return __hold.release(); + } + + template + __storage_base* + __storage<_Tp, _Alloc>::__copy(void *__dest) const + { + return ::new (__dest) __storage(__store_.first(), __store_.second()); + } + + template + __storage_base* + __storage<_Tp, _Alloc>::__move(void *__dest) + { + return ::new(__dest) __storage( + _VSTD::move(__store_.first()) + , _VSTD::move(__store_.second()) + ); + } + + template + void + __storage<_Tp, _Alloc>::__destroy() _NOEXCEPT + { + typedef allocator_traits<_Alloc> __alloc_traits; + typedef typename __alloc_traits::template +#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES + rebind_alloc<__storage> +#else + rebind_alloc<__storage>::other +#endif + _Ap; + + if (!__is_small_object<__storage>::value) { + _Ap __a(__store_.second()); + __store_.~__compressed_pair<_Tp, _Alloc>(); + __a.deallocate(this, 1); + } else { + __store_.~__compressed_pair<_Tp, _Alloc>(); + } + + } + + template + void const * + __storage<_Tp, _Alloc>::__target(type_info const & __info) const _NOEXCEPT + { + if (__info == typeid(_Tp)) { + return _VSTD::addressof(__store_.first()); + } else { + return static_cast(nullptr); + } + } + + template + type_info const & + __storage<_Tp, _Alloc>::__target_type() const _NOEXCEPT + { + return typeid(_Tp); + } + } // namespace __any + + class _LIBCPP_TYPE_VIS_ONLY any + { + typedef __any::__buffer __buffer; + typedef __any::__storage_base __base; + __buffer __buf_; + __base* __base_; + public: + + // constructors + _LIBCPP_INLINE_VISIBILITY + any() _NOEXCEPT : __base_(nullptr) {} + + any(any const &); + + any(any &&) _NOEXCEPT; + + /** Remarks: This constructor shall not participate in overload resolution + * if decay::type is the same type as std::any. */ + // TODO: I really wish this constructor was explicit. File a defect report? + template ::type, any>::value + >::type + > + any(_Tp && __v); + + // TODO Can delegating constructors be used? + template + _LIBCPP_INLINE_VISIBILITY + any(allocator_arg_t, _Alloc const &) _NOEXCEPT + : __base_(nullptr) + {} + + // TODO Can delegating constructors be used? + // NOTE: No support until polymorphic allocators. + template + _LIBCPP_INLINE_VISIBILITY + any(allocator_arg_t, _Alloc const &, any const & __other) + : any(__other) + {} + + // TODO Can delegating constructors be used? + // NOTE: No support until polymorphic allocators. + template + _LIBCPP_INLINE_VISIBILITY + any(allocator_arg_t, _Alloc const &, any && __other) _NOEXCEPT + : any(_VSTD::move(__other)) + {} + + /** Remarks: This constructor shall not participate in overload resolution + * if decay::type is the same type as std::any. */ + template < + class _Alloc, class _Tp + , class = typename enable_if::type + , any + >::value>::type + > + any(allocator_arg_t, _Alloc const & __a0, _Tp && __v); + + // destructor + _LIBCPP_INLINE_VISIBILITY + ~any() { clear(); } + + // assignments + + /** Effects: any(rhs).swap(*this), however, no effects if an exception + * is thrown. */ + _LIBCPP_INLINE_VISIBILITY + any & operator=(any const & __other) + { + any(__other).swap(*this); + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + any & operator=(any && __other) _NOEXCEPT + { + any(_VSTD::move(__other)).swap(*this); + return *this; + } + + /** Remarks: This operator shall not participate in overload resolution + * if decay::type is the same type as std::any. */ + template < + class _Tp + , class = typename enable_if< + !is_same::type, any>::value + >::type + > + _LIBCPP_INLINE_VISIBILITY + any & operator=(_Tp && __v) + { + typedef typename decay<_Tp>::type _ValueType; + static_assert( + is_copy_constructible<_ValueType>::value + , "ValueType must be copy constructible" + ); + any(_VSTD::forward<_Tp>(__v)).swap(*this); + return *this; + } + + // modifiers + void clear() _NOEXCEPT; + void swap(any &) _NOEXCEPT; + + // observers + _LIBCPP_INLINE_VISIBILITY + bool empty() const _NOEXCEPT + { return __base_ == nullptr; } + + _LIBCPP_INLINE_VISIBILITY + type_info const & type() const _NOEXCEPT + { return __base_ ? __base_->__target_type() : typeid(void); } + + private: + template friend + typename add_pointer::type>::type + any_cast(any const *) _NOEXCEPT; + + template friend + typename add_pointer<_Tp>::type + any_cast(any *) _NOEXCEPT; + }; // class any + + inline _LIBCPP_INLINE_VISIBILITY + any::any(any const & __other) + { + if (__other.__base_ == nullptr) { + __base_ = nullptr; + } + else if (__other.__base_ == (__base const*) &__other.__buf_) { + __base_ = (__base*) &__buf_; + __other.__base_->__copy(__base_); + } else { + __base_ = __other.__base_->__copy(); + } + } + + inline _LIBCPP_INLINE_VISIBILITY + any::any(any && __other) _NOEXCEPT + { + if (__other.__base_ == (__base*) &__other.__buf_) { + __base_ = (__base*) &__buf_; + __other.__base_->__move(__base_); + } else { + __base_ = __other.__base_; + __other.__base_ = nullptr; + } + } + + template + any::any(_Tp && __v) + { + typedef typename decay<_Tp>::type _Value; + static_assert( + is_copy_constructible<_Value>::value + , "Construction of any with a non-copyable type is ill-formed." + ); + + typedef allocator<_Value> _Ap; + typedef __any::__storage<_Value, _Ap> _Store; + + if (__any::__is_small_object<_Store>::value) { + __base_ = ::new ((void*)&__buf_) _Store( + _VSTD::forward<_Tp>(__v), _Ap() + ); + } else { + typedef allocator<_Store> _Ap; + _Ap __a; + typedef __allocator_destructor<_Ap> _Dp; + unique_ptr<_Store, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + ::new ((void*)__hold.get()) _Store( + _VSTD::forward<_Tp>(__v) + , allocator<_Value>(__a) + ); + __base_ = __hold.release(); + } + } + + template + any::any(allocator_arg_t, _Alloc const & __a0, _Tp && __v) + { + typedef typename remove_reference<_Tp>::type _Value; + typedef allocator_traits<_Alloc> __alloc_traits; + typedef __any::__storage<_Value, _Alloc> _Store; + + if (__any::__is_small_object<_Store>::value) { + __base_ = ::new ((void*) &__buf_) _Store( + _VSTD::forward<_Tp>(__v), _Alloc(__a0) + ); + } else { + typedef typename __alloc_traits::template +#ifndef _LIBCPP_HAS_NO_TEMPLATE_ALIASES + rebind_traits<_Store> +#else + rebind_traits<_Store>::other +#endif + _BaseAlloc; + typedef typename _BaseAlloc::allocator_type _Ap; + _Ap __a(__a0); + typedef __allocator_destructor<_Ap> _Dp; + unique_ptr<_Store, _Dp> __hold(__a.allocate(1), _Dp(__a, 1)); + _BaseAlloc::construct( + __a, __hold.get() + , typename __uses_alloc_ctor<_Value, _Alloc, _Tp>::type() + , _Alloc(__a), _VSTD::forward<_Tp>(__v) + ); + __base_ = __hold.release(); + } + } + + inline _LIBCPP_INLINE_VISIBILITY + void any::clear() _NOEXCEPT + { + if (__base_) { + __base_->__destroy(); + } + __base_ = nullptr; + } + + inline void any::swap(any & __other) _NOEXCEPT + { + // Both objects stored locally + if (__base_ == (__base*) &__buf_ + && __other.__base_ == (__base*) &__other.__buf_) + { + __buffer __tmp; + __base* __tmp_base = __base_->__move(&__tmp); + __base_->__destroy(); + + __base_ = __other.__base_->__move(&__buf_); + __other.__base_->__destroy(); + + __other.__base_ = __tmp_base->__move(&__other.__buf_); + __tmp_base->__destroy(); + } + // Other's object is remote or null + else if (__base_ == (__base*) &__buf_) + { + __base* __tmp_base = __other.__base_; + __other.__base_ = __base_->__move(&__other.__buf_); + __base_->__destroy(); + __base_ = __tmp_base; + } + // Our object is remote or null + else if (__other.__base_ == (__base*) &__other.__buf_) { + __base* __tmp_base = __base_; + __base_ = __other.__base_->__move(&__buf_); + __other.__base_->__destroy(); + __other.__base_ = __tmp_base; + } + // Both objects are remote + else { + _VSTD::swap(__base_, __other.__base_); + } + } + + + inline _LIBCPP_INLINE_VISIBILITY + void swap(any & __lhs, any & __rhs) _NOEXCEPT + { + __lhs.swap(__rhs); + } + + /** NOTE: The return type has to be calculated using traits. + * If it is specified as: "_Tp const *" then substitution failure will + * occur when _Tp = T &. The add_pointer trait seems to handle this case + * by removing the reference and applying the pointer. + * The nasty thing about that bug is that it would cause the pointer overloads + * to drop out of the candidates set. Then the compiler will apply any's + * converting constructor "template any(T &&)". + * The end result was essentially "any_cast(any(__any_ptr))". + */ + template + _LIBCPP_INLINE_VISIBILITY + typename add_pointer::type>::type + any_cast(any const* __a) _NOEXCEPT + { + typedef typename add_pointer::type>::type _RetType; + return __a && __a->__base_ + ? static_cast<_RetType>(__a->__base_->__target(typeid(_Tp))) + : nullptr; + } + + template + _LIBCPP_INLINE_VISIBILITY + typename add_pointer<_Tp>::type + any_cast(any * __a) _NOEXCEPT + { + typedef typename add_pointer<_Tp>::type _RetType; + return __a && __a->__base_ + ? static_cast<_RetType>(const_cast( + __a->__base_->__target(typeid(_Tp)) + )) + : nullptr; + } + + template + _LIBCPP_INLINE_VISIBILITY + _Tp any_cast(any const & __a) + { + static_assert( + is_reference<_Tp>::value || is_copy_constructible<_Tp>::value + , "ValueType must be a reference or copy constructible" + ); + static_assert( + !is_reference<_Tp>::value + || is_const::type>::value + , "Returning a reference to non-const violates const correctness" + ); + typedef typename add_const::type>::type + _CastType; + _CastType * __ret = any_cast<_CastType>(&__a); +#ifndef _LIBCPP_NO_EXCEPTIONS + if (__ret == nullptr) { + throw bad_any_cast(); + } +#endif /* _LIBCPP_NO_EXCEPTIONS */ + return *__ret; + } + + template + _LIBCPP_INLINE_VISIBILITY + _Tp any_cast(any & __a) + { + static_assert( + is_reference<_Tp>::value || is_copy_constructible<_Tp>::value + , "ValueType must be a reference or copy constructible" + ); + + typedef typename remove_reference<_Tp>::type _CastType; + _CastType * __ret = any_cast<_CastType>(&__a); +#ifndef _LIBCPP_NO_EXCEPTIONS + if (__ret == nullptr) { + throw bad_any_cast(); + } +#endif /* _LIBCPP_NO_EXCEPTIONS */ + return *__ret; + } + + template + _LIBCPP_INLINE_VISIBILITY + _Tp any_cast(any && __a) + { + return any_cast<_Tp>(static_cast(__a)); + } + + +_LIBCPP_END_NAMESPACE_LFTS + +#endif // _LIBCPP_STD_VER > 11 + +#endif // _LIBCPP_EXPERIMENTAL_ANY \ No newline at end of file Index: src/any.cpp =================================================================== --- /dev/null +++ src/any.cpp @@ -0,0 +1,29 @@ +//===------------------------ any.cpp -------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#include "experimental/any" + +_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL + +#ifdef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS + +bad_any_cast::~bad_any_cast() _NOEXCEPT {} + +#else + +bad_any_cast::~bad_any_cast() _NOEXCEPT = default; + +#endif + +const char* bad_any_cast::what() const _NOEXCEPT +{ + return "bad any cast"; +} + +_LIBCPP_END_NAMESPACE_EXPERIMENTAL Index: test/experimental/any/any.class/any.assign/copy_large_throws.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.assign/copy_large_throws.pass.cpp @@ -0,0 +1,149 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any& operator=(any const &); + +// Test throwing from a stored values copy constructor during copy assignment. + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +struct my_exception {}; + +struct throws_on_copy +{ + static int count; + + throws_on_copy() + { + data[0] = 0; + ++count; + } + + throws_on_copy(throws_on_copy const &) + { + throw my_exception(); + } + + throws_on_copy(throws_on_copy &&) + { + ++count; + } + + ~throws_on_copy() { --count; } + +private: + int data[10]; +}; + +int throws_on_copy::count = 0; + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // const lvalue to empty + { + any a; + any const a2((throws_on_copy())); + assert(throws_on_copy::count == 1); + + try { + a = a2; + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(a.empty()); + assert(a.type() == typeid(void)); + + assert(!a2.empty()); + assert(a2.type() == typeid(throws_on_copy)); + + assert(throws_on_copy::count == 1); + assert(new_called == 1); + assert(delete_called == 1); + } + assert(new_called == 0); + assert(throws_on_copy::count == 0); + delete_called = 0; + // const lvalue to small + { + small const s(1); + any a(s); + any const a2((throws_on_copy())); + assert(throws_on_copy::count == 1); + + try { + a = a2; + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + assert(small::count == 2); + + assert(!a2.empty()); + assert(a2.type() == typeid(throws_on_copy)); + assert(throws_on_copy::count == 1); + + assert(new_called == 1); + assert(delete_called == 1); + } + assert(small::count == 0); + assert(throws_on_copy::count == 0); + assert(new_called == 0); + delete_called = 0; + // const lvalue to large + { + large const s(1); + any a(s); + any const a2((throws_on_copy())); + assert(throws_on_copy::count == 1); + + try { + a = a2; + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == s); + assert(large::count == 2); + + assert(!a2.empty()); + assert(a2.type() == typeid(throws_on_copy)); + assert(throws_on_copy::count == 1); + + assert(new_called == 2); + assert(delete_called == 1); + } + assert(large::count == 0); + assert(throws_on_copy::count == 0); + assert(new_called == 0); +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.assign/copy_self.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.assign/copy_self.pass.cpp @@ -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. +// +//===----------------------------------------------------------------------===// + +// + +// any& operator=(any const &); + +// Test self copy assignment. + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // empty + { + any a; + a = a; + assert(a.empty()); + assert(a.type() == typeid(void)); + assert(new_called == 0); + } + assert(new_called == 0); + // small + { + small const s(1); + any a(s); + a = a; + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + assert(small::count == 2); + assert(new_called == 0); + } + assert(small::count == 0); + assert(new_called == 0); + // large + { + large const s(1); + any a(s); + a = a; + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == s); + assert(large::count == 2); + assert(new_called == 1); + } + assert(large::count == 0); + assert(new_called == 0); +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.assign/copy_small_throws.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.assign/copy_small_throws.pass.cpp @@ -0,0 +1,144 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any& operator=(any const &); + +// Test throwing from a "small" values copy constructor during copy assignment. + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +struct my_exception {}; + +struct throws_on_copy +{ + static int count; + + throws_on_copy() { ++count; } + + throws_on_copy(throws_on_copy const &) + { + throw my_exception(); + } + + throws_on_copy(throws_on_copy &&) throw() + { + ++count; + } + + ~throws_on_copy() { --count; } +}; + +int throws_on_copy::count = 0; + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // const lvalue to empty + { + any a; + any const a2((throws_on_copy())); + assert(throws_on_copy::count == 1); + + try { + a = a2; + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(a.empty()); + assert(a.type() == typeid(void)); + + assert(!a2.empty()); + assert(a2.type() == typeid(throws_on_copy)); + + assert(throws_on_copy::count == 1); + assert(new_called == 0); + assert(delete_called == 0); + } + assert(new_called == 0); + assert(throws_on_copy::count == 0); + delete_called = 0; + // const lvalue to small + { + small const s(1); + any a(s); + any const a2((throws_on_copy())); + assert(throws_on_copy::count == 1); + + try { + a = a2; + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + assert(small::count == 2); + + assert(!a2.empty()); + assert(a2.type() == typeid(throws_on_copy)); + assert(throws_on_copy::count == 1); + + assert(new_called == 0); + assert(delete_called == 0); + } + assert(small::count == 0); + assert(throws_on_copy::count == 0); + assert(new_called == 0); + delete_called = 0; + // const lvalue to large + { + large const s(1); + any a(s); + any const a2((throws_on_copy())); + assert(throws_on_copy::count == 1); + + try { + a = a2; + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == s); + assert(large::count == 2); + + assert(!a2.empty()); + assert(a2.type() == typeid(throws_on_copy)); + assert(throws_on_copy::count == 1); + + assert(new_called == 1); + assert(delete_called == 0); + } + assert(large::count == 0); + assert(throws_on_copy::count == 0); + assert(new_called == 0); + delete_called = 0; + +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.assign/copy_to_empty.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.assign/copy_to_empty.pass.cpp @@ -0,0 +1,83 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any& operator=(any const &); + +// Test copy assignment to an empty any. + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" + +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // empty + { + any a; + any const a2; + a = a2; + assert(a.empty()); + assert(a.type() == typeid(void)); + assert(a2.empty()); + assert(a2.type() == typeid(void)); + assert(new_called == 0); + } + assert(new_called == 0); + // small + { + any a; + small const s(1); + any const a2(s); + + a = a2; + + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + + assert(!a2.empty()); + assert(a2.type() == typeid(small)); + assert(any_cast(a2) == s); + + assert(small::count == 3); + assert(new_called == 0); + } + assert(small::count == 0); + assert(new_called == 0); + // large + { + any a; + large const s(1); + any const a2(s); + + a = a2; + + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == s); + + assert(!a2.empty()); + assert(a2.type() == typeid(large)); + assert(any_cast(a2) == s); + + assert(large::count == 3); + assert(new_called == 2); + } + assert(large::count == 0); + assert(new_called == 0); +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.assign/copy_to_large.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.assign/copy_to_large.pass.cpp @@ -0,0 +1,95 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any& operator=(any const &); + +// Test copy assignment to an any instance storing a large value. + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // empty + { + large1 const s1(1); + any a(s1); + any const a2; + + a = a2; + + assert(a.empty()); + assert(a.type() == typeid(void)); + assert(a2.empty()); + assert(a2.type() == typeid(void)); + + assert(large1::count == 1); + assert(new_called == 0); + } + assert(new_called == 0); + // small + { + large1 const s1(1); + any a(s1); + small const s2(2); + any const a2(s2); + + a = a2; + + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s2); + + assert(!a2.empty()); + assert(a2.type() == typeid(small)); + assert(any_cast(a2) == s2); + + assert(large1::count == 1); + assert(small::count == 3); + assert(new_called == 0); + } + assert(large1::count == 0); + assert(small::count == 0); + assert(new_called == 0); + delete_called = 0; + // large + { + large1 const s1(1); + any a(s1); + large2 const l(1); + any const a2(l); + + a = a2; + + assert(!a.empty()); + assert(a.type() == typeid(large2)); + assert(any_cast(a) == l); + + assert(!a2.empty()); + assert(a2.type() == typeid(large2)); + assert(any_cast(a2) == l); + + assert(large1::count == 1); + assert(large2::count == 3); + assert(new_called == 2); + assert(delete_called == 1); + } + assert(large1::count == 0); + assert(large2::count == 0); + assert(new_called == 0); +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.assign/copy_to_small.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.assign/copy_to_small.pass.cpp @@ -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. +// +//===----------------------------------------------------------------------===// + +// + +// any& operator=(any const &); + +// Test copy assignment to an any instance storing a small value. + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // empty + { + small1 const s1(1); + any a(s1); + any const a2; + + a = a2; + + assert(a.empty()); + assert(a.type() == typeid(void)); + assert(a2.empty()); + assert(a2.type() == typeid(void)); + + assert(small1::count == 1); + assert(new_called == 0); + } + assert(new_called == 0); + // small + { + small1 const s1(1); + any a(s1); + small2 const s2(2); + any const a2(s2); + + a = a2; + + assert(!a.empty()); + assert(a.type() == typeid(small2)); + assert(any_cast(a) == s2); + + assert(!a2.empty()); + assert(a2.type() == typeid(small2)); + assert(any_cast(a2) == s2); + + assert(small1::count == 1); + assert(small2::count == 3); + assert(new_called == 0); + } + assert(small1::count == 0); + assert(small2::count == 0); + assert(new_called == 0); + // large + { + small1 const s1(1); + any a(s1); + large const l(1); + any const a2(l); + + a = a2; + + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == l); + + assert(!a2.empty()); + assert(a2.type() == typeid(large)); + assert(any_cast(a2) == l); + + assert(small1::count == 1); + assert(large::count == 3); + assert(new_called == 2); + } + assert(small1::count == 0); + assert(large::count == 0); + assert(new_called == 0); +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.assign/large_value_copy_throws.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.assign/large_value_copy_throws.pass.cpp @@ -0,0 +1,143 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// any& operator=(Value&&); + +// Test throwing an exception during value copy assignment of a "large" value. + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +struct my_exception {}; + +struct throws_on_copy +{ + static int count; + + throws_on_copy() + { + data[0] = 0; + ++count; + } + + throws_on_copy(throws_on_copy const &) + { + throw my_exception(); + } + + throws_on_copy(throws_on_copy &&) + { + ++count; + } + + ~throws_on_copy() { --count; } + +private: + int data[10]; +}; + +int throws_on_copy::count = 0; + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // const lvalue to empty + { + any a; + throws_on_copy v; + assert(throws_on_copy::count == 1); + + try { + a = v; + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(a.empty()); + assert(a.type() == typeid(void)); + + assert(throws_on_copy::count == 1); + assert(new_called == 0); + assert(delete_called == 1); + } + assert(new_called == 0); + assert(throws_on_copy::count == 0); + delete_called = 0; + // const lvalue to small + { + small const s(1); + any a(s); + throws_on_copy v; + assert(throws_on_copy::count == 1); + + try { + a = v; + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + assert(small::count == 2); + + assert(throws_on_copy::count == 1); + assert(new_called == 0); + assert(delete_called == 1); + } + assert(small::count == 0); + assert(throws_on_copy::count == 0); + assert(new_called == 0); + delete_called = 0; + // const lvalue to large + { + large const s(1); + any a(s); + throws_on_copy v; + assert(throws_on_copy::count == 1); + + try { + a = v; + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == s); + assert(large::count == 2); + + assert(throws_on_copy::count == 1); + assert(new_called == 1); + assert(delete_called == 1); + } + assert(large::count == 0); + assert(throws_on_copy::count == 0); + assert(new_called == 0); + delete_called = 0; + +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.assign/move_noexcept.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.assign/move_noexcept.pass.cpp @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any& operator=(any &&) noexcept; + +#include +#include + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + any a1; + any a2; + static_assert( + noexcept(a1 = std::move(a2)) + , "any & operator=(any &&) must be noexcept" + ); +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.assign/move_self.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.assign/move_self.pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any& operator=(any &&); + +// Test self move assignment + +#include +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // empty + { + any a; + a = std::move(a); + assert(a.empty()); + assert(a.type() == typeid(void)); + assert(new_called == 0); + } + assert(new_called == 0); + // small + { + small const s(1); + any a(s); + a = std::move(a); + + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + + assert(small::count == 2); + assert(new_called == 0); + } + assert(small::count == 0); + assert(new_called == 0); + // large + { + large const s(1); + any a(s); + + a = std::move(a); + + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == s); + + assert(large::count == 2); + assert(new_called == 1); + } + assert(large::count == 0); + assert(new_called == 0); + +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.assign/move_to_empty.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.assign/move_to_empty.pass.cpp @@ -0,0 +1,75 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any& operator=(any &&); + +// Test move assignment to an empty any object. + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // empty + { + any a; + any a2; + + a = std::move(a2); + + assert(a.empty()); + assert(a.type() == typeid(void)); + assert(new_called == 0); + } + assert(new_called == 0); + // small + { + any a; + small const s(1); + any a2(s); + + a = std::move(a2); + + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + + assert(small::count == 2 || small::count == 3); + assert(new_called == 0); + } + assert(small::count == 0); + assert(new_called == 0); + // large + { + any a; + large const s(1); + any a2(s); + + a = std::move(a2); + + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == s); + + assert(large::count == 2 || large::count == 3); + assert(new_called == 1); + } + assert(large::count == 0); + assert(new_called == 0); + +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.assign/move_to_large.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.assign/move_to_large.pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any& operator=(any &&) noexcept + +// Test move assignment to an any instance storing a large value. + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // empty + { + large1 const s1(1); + any a(s1); + any a2; + + a = std::move(a2); + + assert(a.empty()); + assert(a.type() == typeid(void)); + assert(large1::count == 1); + assert(new_called == 0); + } + assert(new_called == 0); + // small + { + large1 const s1(1); + any a(s1); + small const s2(2); + any a2(s2); + + a = std::move(a2); + + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s2); + + assert(large1::count == 1); + assert(small::count == 2 || small::count == 3); + assert(new_called == 0); + } + assert(large1::count == 0); + assert(small::count == 0); + assert(new_called == 0); + delete_called = 0; + // large + { + large1 const s1(1); + any a(s1); + large2 const l(1); + any a2(l); + + a = std::move(a2); + + assert(!a.empty()); + assert(a.type() == typeid(large2)); + assert(any_cast(a) == l); + + assert(large1::count == 1); + assert(large2::count == 2 || large2::count == 3); + assert(new_called == 1); + assert(delete_called == 1); + } + assert(large1::count == 0); + assert(large2::count == 0); + assert(new_called == 0); +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.assign/move_to_small.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.assign/move_to_small.pass.cpp @@ -0,0 +1,84 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any& operator=(any &&) noexcept + +// Test move assignment to an any instance storing a small value. + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // empty + { + small1 const s1(1); + any a(s1); + any a2; + + a = std::move(a2); + + assert(a.empty()); + assert(a.type() == typeid(void)); + + assert(small1::count == 1); + assert(new_called == 0); + } + assert(new_called == 0); + // small + { + small1 const s1(1); + any a(s1); + small2 const s2(2); + any a2(s2); + + a = std::move(a2); + + assert(!a.empty()); + assert(a.type() == typeid(small2)); + assert(any_cast(a) == s2); + + assert(small1::count == 1); + assert(small2::count == 2 || small2::count == 3); + assert(new_called == 0); + } + assert(small1::count == 0); + assert(small2::count == 0); + assert(new_called == 0); + // large + { + small1 const s1(1); + any a(s1); + large const l(1); + any a2(l); + + a = std::move(a2); + + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == l); + + assert(small1::count == 1); + assert(large::count == 2 || large::count == 3); + assert(new_called == 1); + } + assert(small1::count == 0); + assert(large::count == 0); + assert(new_called == 0); + +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.assign/small_value_copy_throws.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.assign/small_value_copy_throws.pass.cpp @@ -0,0 +1,136 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// any& operator=(Value&&); + +// Test throwing during the value copy assignment of a "small" object. + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +struct my_exception {}; + +struct throws_on_copy +{ + static int count; + + throws_on_copy() { ++count; } + + throws_on_copy(throws_on_copy const &) + { + throw my_exception(); + } + + throws_on_copy(throws_on_copy &&) throw() + { + ++count; + } + + ~throws_on_copy() { --count; } +}; + +int throws_on_copy::count = 0; + + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // const lvalue to empty + { + any a; + throws_on_copy v; + assert(throws_on_copy::count == 1); + + try { + a = v; + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(a.empty()); + assert(a.type() == typeid(void)); + + assert(throws_on_copy::count == 1); + assert(new_called == 0); + assert(delete_called == 0); + } + assert(new_called == 0); + assert(throws_on_copy::count == 0); + delete_called = 0; + // const lvalue to small + { + small const s(1); + any a(s); + throws_on_copy v; + assert(throws_on_copy::count == 1); + + try { + a = v; + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + assert(small::count == 2); + + assert(throws_on_copy::count == 1); + assert(new_called == 0); + assert(delete_called == 0); + } + assert(small::count == 0); + assert(throws_on_copy::count == 0); + assert(new_called == 0); + delete_called = 0; + // const lvalue to large + { + large const s(1); + any a(s); + throws_on_copy v; + assert(throws_on_copy::count == 1); + + try { + a = v; + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == s); + assert(large::count == 2); + + assert(throws_on_copy::count == 1); + assert(new_called == 1); + assert(delete_called == 0); + } + assert(large::count == 0); + assert(throws_on_copy::count == 0); + assert(new_called == 0); + delete_called = 0; +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.assign/value_move_throws.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.assign/value_move_throws.pass.cpp @@ -0,0 +1,136 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// any& operator=(Value&&); + +// Test throwing an exception during value move assignment. + +#include +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +struct my_exception {}; + +struct throws_on_move +{ + static int count; + + throws_on_move() { ++count; } + + throws_on_move(throws_on_move const &) + { + ++count; + } + + throws_on_move(throws_on_move &&) + { + throw my_exception(); + } + + ~throws_on_move() { --count; } +}; + +int throws_on_move::count = 0; + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // const lvalue to empty + { + any a; + throws_on_move v; + assert(throws_on_move::count == 1); + + try { + a = std::move(v); + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(a.empty()); + assert(a.type() == typeid(void)); + + assert(throws_on_move::count == 1); + assert(new_called == 0); + assert(delete_called == 1); + } + assert(new_called == 0); + assert(throws_on_move::count == 0); + delete_called = 0; + // const lvalue to small + { + small const s(1); + any a(s); + throws_on_move v; + assert(throws_on_move::count == 1); + + try { + a = std::move(v); + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + assert(small::count == 2); + + assert(throws_on_move::count == 1); + assert(new_called == 0); + assert(delete_called == 1); + } + assert(small::count == 0); + assert(throws_on_move::count == 0); + assert(new_called == 0); + delete_called = 0; + // const lvalue to large + { + large const s(1); + any a(s); + throws_on_move v; + assert(throws_on_move::count == 1); + + try { + a = std::move(v); + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == s); + assert(large::count == 2); + + assert(throws_on_move::count == 1); + assert(new_called == 1); + assert(delete_called == 1); + } + assert(large::count == 0); + assert(throws_on_move::count == 0); + assert(new_called == 0); + delete_called = 0; +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.assign/value_non_copyable_assign.fail.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.assign/value_non_copyable_assign.fail.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// any& operator=(Value &&); + +// Instantiate the value assignment operator with a non-copyable type. + +#include + +class non_copyable +{ + non_copyable(non_copyable const &); + +public: + non_copyable() {} + non_copyable(non_copyable &&) {} +}; + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + non_copyable nc; + any a; + a = static_cast(nc); +#else +# error +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.assign/value_to_empty.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.assign/value_to_empty.pass.cpp @@ -0,0 +1,96 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// any& operator=(Value &&); + +// Test value assignment into an empty any instance. + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // small const lvalue + { + any a; + small const s(1); + + a = s; + + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + assert(small::count == 2); + assert(new_called == 0); + } + assert(small::count == 0); + assert(new_called == 0); + // small non-const rvalue + { + any a; + small s(1); + + a = std::move(s); + + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a).value == 1); + + assert(s.value == 0); + + assert(small::count == 2); + assert(new_called == 0); + } + assert(small::count == 0); + assert(new_called == 0); + // large const lvalue + { + any a; + large const s(1); + + a = s; + + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == s); + + assert(large::count == 2); + assert(new_called == 1); + } + assert(large::count == 0); + assert(new_called == 0); + // large non-const rvalue + { + any a; + large s(1); + + a = std::move(s); + + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a).value == 1); + + assert(s.value == 0); + + assert(large::count == 2); + assert(new_called == 1); + } + assert(large::count == 0); + assert(new_called == 0); +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.assign/value_to_large.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.assign/value_to_large.pass.cpp @@ -0,0 +1,114 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// any& operator=(Value&&); + +// Test value assignment into an any object storing an instance of a "large" +// object. + + +#include +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // small const lvalue + { + large1 const s1(1); + any a(s1); + small const s2(2); + + a = s2; + + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s2); + + assert(large1::count == 1); + assert(small::count == 2); + assert(new_called == 0); + } + // small non-const rvalue + { + large1 const s1(1); + any a(s1); + small s2(2); + + a = std::move(s2); + + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a).value == 2); + + assert(s2.value == 0); + + assert(large1::count == 1); + assert(small::count == 2); + assert(new_called == 0); + } + assert(large1::count == 0); + assert(small::count == 0); + assert(new_called == 0); + delete_called = 0; + // large const lvalue + { + large1 const s1(1); + any a(s1); + large2 const l(1); + + a = l; + + assert(!a.empty()); + assert(a.type() == typeid(large2)); + assert(any_cast(a) == l); + + assert(large1::count == 1); + assert(large2::count == 2); + assert(new_called == 1); + assert(delete_called == 1); + } + assert(large1::count == 0); + assert(large2::count == 0); + assert(new_called == 0); + delete_called = 0; + // large non-const rvalue + { + large1 const s1(1); + any a(s1); + large2 l(1); + + a = std::move(l); + + assert(!a.empty()); + assert(a.type() == typeid(large2)); + assert(any_cast(a).value == 1); + + assert(l.value == 0); + + assert(large1::count == 1); + assert(large2::count == 2); + assert(new_called == 1); + assert(delete_called == 1); + } + assert(large1::count == 0); + assert(large2::count == 0); + assert(new_called == 0); + delete_called = 0; +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.assign/value_to_small.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.assign/value_to_small.pass.cpp @@ -0,0 +1,112 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// any & operator=(Value &&); + +// Test value assignment into an any object storing an instance of a "small" +// object. + +#include +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // small const lvalue + { + small1 const s1(1); + any a(s1); + small2 const s2(2); + + a = s2; + + assert(!a.empty()); + assert(a.type() == typeid(small2)); + assert(any_cast(a) == s2); + + assert(small1::count == 1); + assert(small2::count == 2); + assert(new_called == 0); + } + assert(small1::count == 0); + assert(small2::count == 0); + assert(new_called == 0); + // small non-const rvalue + { + small1 const s1(1); + any a(s1); + small2 s2(2); + + a = std::move(s2); + + assert(!a.empty()); + assert(a.type() == typeid(small2)); + assert(any_cast(a).value == 2); + + assert(s2.value == 0); + + assert(small1::count == 1); + assert(small2::count == 2); + assert(new_called == 0); + } + assert(small1::count == 0); + assert(small2::count == 0); + assert(new_called == 0); + // large const lvalue + { + small1 const s1(1); + any a(s1); + large const l(2); + + a = l; + + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == l); + + assert(small1::count == 1); + assert(large::count == 2); + assert(new_called == 1); + } + assert(small1::count == 0); + assert(large::count == 0); + assert(new_called == 0); + // large non-const rvalue + { + small1 const s1(1); + any a(s1); + large l(2); + + a = std::move(l); + + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a).value == 2); + + assert(l.value == 0); + + assert(small1::count == 1); + assert(large::count == 2); + assert(new_called == 1); + } + assert(small1::count == 0); + assert(large::count == 0); + assert(new_called == 0); + +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.cons/alloc.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/alloc.pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::any(allocator_arg_t, Alloc); + +#include +#include +#include +#include "test_allocator.h" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::allocator_arg; + { + static_assert( + std::is_nothrow_constructible< + any, std::allocator_arg_t, test_allocator + >::value + , "Must be nothrow constructible" + ); + } + { + any a(std::allocator_arg, test_allocator()); + assert(a.empty()); + assert(a.type() == typeid(void)); + assert(test_alloc_base::alloc_count == 0); + } + assert(test_alloc_base::alloc_count == 0); +#endif /* _LIBCPP_STD_VER > 11 */ +} \ No newline at end of file Index: test/experimental/any/any.class/any.cons/alloc_copy.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/alloc_copy.pass.cpp @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::any(allocator_arg_t, Alloc const &, any const &); + +#include +#include +#include "../../small_type.hpp" +#include "../../large_type.hpp" +#include "test_allocator.h" + + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + //empty + { + any const a1; + + any const a2(std::allocator_arg, test_allocator(), a1); + + assert(a2.empty()); + assert(a2.type() == typeid(void)); + assert(test_alloc_base::alloc_count == 0); + } + assert(test_alloc_base::alloc_count == 0); + // small type + { + small const s(1); + any const a1(s); + + any const a2(std::allocator_arg, test_allocator(), a1); + assert(!a2.empty()); + assert(a2.type() == typeid(small)); + assert(any_cast(a2) == s); + assert(small::count == 3); + assert(small::copied == 2); + assert(small::moved == 0); + + assert(!a1.empty()); + assert(a1.type() == typeid(small)); + assert(any_cast(a1) == s); + + assert(test_alloc_base::alloc_count == 0); + } + assert(small::count == 0); + assert(test_alloc_base::alloc_count == 0); + // large type + { + large const l(1); + any const a1(l); + + any const a2(std::allocator_arg, test_allocator(), a1); + assert(!a2.empty()); + assert(a2.type() == typeid(large)); + assert(any_cast(a2) == l); + assert(large::count == 3); + assert(large::copied == 2); + assert(large::moved == 0); + + assert(!a1.empty()); + assert(a1.type() == typeid(large)); + assert(any_cast(a1) == l); + + assert(test_alloc_base::alloc_count == 0); + } + assert(large::count == 0); + assert(test_alloc_base::alloc_count == 0); +#endif +} Index: test/experimental/any/any.class/any.cons/alloc_copy_throws.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/alloc_copy_throws.pass.cpp @@ -0,0 +1,125 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template any(allocator_arg_t, Alloc const &, any const &); + +// Test throwing an exception from the stored objects copy constructor. + +#include +#include +#include "../../count_new.hpp" +#include "test_allocator.h" + +struct my_exception {}; + + +struct small_throws_on_copy +{ + static int count; + + small_throws_on_copy() { ++count; } + + small_throws_on_copy(small_throws_on_copy const &) + { + throw my_exception(); + } + + small_throws_on_copy(small_throws_on_copy &&) throw() + { + ++count; + } + + ~small_throws_on_copy() { --count; } +}; + +int small_throws_on_copy::count = 0; + + +struct large_throws_on_copy +{ + static int count; + + large_throws_on_copy() + { + data[0] = 0; + ++count; + } + + large_throws_on_copy(large_throws_on_copy const &) + { + throw my_exception(); + } + + large_throws_on_copy(large_throws_on_copy &&) throw() + { + ++count; + } + + ~large_throws_on_copy() { --count; } + +private: + int data[10]; +}; + +int large_throws_on_copy::count = 0; + +int main() +{ +# if _LIBCPP_STD_VER > 11 + using std::experimental::any; + { + any const a((small_throws_on_copy())); + assert(small_throws_on_copy::count == 1); + try { + any const a2(std::allocator_arg + , test_allocator(), a); + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(small_throws_on_copy::count == 1); + assert(new_called == 0); + + // check that we didn't try and allocate. + assert(test_alloc_base::alloc_count == 0); + assert(test_alloc_base::count == 0); + } + assert(small_throws_on_copy::count == 0); + assert(new_called == 0); + assert(test_alloc_base::alloc_count == 0); + assert(test_alloc_base::count == 0); + { + any const a((large_throws_on_copy())); + assert(large_throws_on_copy::count == 1); + assert(new_called == 1); + try { + any const a2(std::allocator_arg + , test_allocator(), a); + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(large_throws_on_copy::count == 1); + assert(new_called == 1); + + assert(test_alloc_base::alloc_count == 0); + assert(test_alloc_base::count == 0); + } + assert(new_called == 0); + assert(large_throws_on_copy::count == 0); + assert(test_alloc_base::alloc_count == 0); + assert(test_alloc_base::count == 0); +#endif /* _LIBCPP_STD_VER > 11 */ +} \ No newline at end of file Index: test/experimental/any/any.class/any.cons/alloc_move.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/alloc_move.pass.cpp @@ -0,0 +1,80 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::any(allocator_arg_t, Alloc const &, any &&); + +#include +#include +#include +#include +#include "../../small_type.hpp" +#include "../../large_type.hpp" +#include "test_allocator.h" + + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + { + static_assert( + std::is_nothrow_constructible< + any, std::allocator_arg_t, test_allocator const &, any && + >::value + , "Must be nothrow constructible" + ); + } + //empty + { + any a1; + + any const a2(std::allocator_arg, test_allocator(), std::move(a1)); + + assert(a2.empty()); + assert(a2.type() == typeid(void)); + assert(test_alloc_base::alloc_count == 0); + } + assert(test_alloc_base::alloc_count == 0); + // small type + { + small const s(1); + any a1(s); + + any const a2(std::allocator_arg, test_allocator(), std::move(a1)); + + assert(!a2.empty()); + assert(a2.type() == typeid(small)); + assert(any_cast(a2) == s); + assert(small::count == 3); + assert(small::copied == 1); + assert(small::moved == 1); + assert(test_alloc_base::alloc_count == 0); + } + assert(small::count == 0); + assert(test_alloc_base::alloc_count == 0); + // large type + { + large const l(1); + any a1(l); + + any const a2(std::allocator_arg, test_allocator(), std::move(a1)); + + assert(!a2.empty()); + assert(a2.type() == typeid(large)); + assert(any_cast(a2) == l); + // NOTE: we can't check A::count since we just do a pointer swap. + assert(test_alloc_base::alloc_count == 0); + } + assert(large::count == 0); + assert(test_alloc_base::alloc_count == 0); +#endif +} Index: test/experimental/any/any.class/any.cons/alloc_move_throws.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/alloc_move_throws.pass.cpp @@ -0,0 +1,77 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template any(allocator_arg_t, Alloc, any &&) noexcept + +// Test moving an any object that holds a value that throws on move. +// NOTE: no move should be performed on the value. + +#include +#include +#include "../../count_new.hpp" +#include "test_allocator.h" + +struct my_exception {}; + +struct throws_on_move +{ + static int count; + + throws_on_move() { ++count; } + + throws_on_move(throws_on_move const &) + { + ++count; + } + + throws_on_move(throws_on_move &&) + { + throw my_exception(); + } + + ~throws_on_move() { --count; } +}; + +int throws_on_move::count = 0; + + +int main() +{ +# if _LIBCPP_STD_VER > 11 + using std::experimental::any; + { + throws_on_move v; + any a(v); + assert(throws_on_move::count == 2); + + // Check that we put a throws-on-move type on the heap. + assert(new_called == 1); + assert(total_new == 1); + + // Moves are always noexcept. + try { + any const a2(std::allocator_arg + , test_allocator(), std::move(a)); + assert(new_called == 1); + assert(a2.type() == typeid(throws_on_move)); + assert(test_alloc_base::alloc_count == 0); + } catch (...) { + assert(false); + } + assert(test_alloc_base::alloc_count == 0); + // Assert that we didn't allocate again. + assert(total_new == 1); + } + assert(throws_on_move::count == 0); + assert(new_called == 0); + assert(test_alloc_base::alloc_count == 0); +#endif /* _LIBCPP_STD_VER > 11 */ +} \ No newline at end of file Index: test/experimental/any/any.class/any.cons/alloc_non_copyable_value.fail.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/alloc_non_copyable_value.fail.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::any(allocator_arg_t, Alloc const &, Value &&) + +// Test constructing any with a non-copyable type from the allocator_arg_t +// constructor. + +#include +#include +#include "test_allocator.h" + +class non_copyable +{ + non_copyable(non_copyable const &); + +public: + non_copyable() {} + non_copyable(non_copyable &&) {} +}; + +int main() +{ +# if _LIBCPP_STD_VER > 11 + using std::experimental::any; + any a(std::allocator_arg, test_allocator(), non_copyable()); +#else +# error +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.cons/alloc_value.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/alloc_value.pass.cpp @@ -0,0 +1,120 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::any(allocator_arg_t, Alloc const &, Value &&); + +// Test the allocator_arg_t signature on value types that do not support uses +// allocator construction. + +#include +#include +#include +#include "../../small_type.hpp" +#include "../../large_type.hpp" +#include "test_allocator.h" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // small const lvalue + { + small const s(1); + any const a(std::allocator_arg, test_allocator(), s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + assert(test_alloc_base::alloc_count == 0); + assert(small::count == 2); + assert(small::copied == 1); + } + assert(small::count == 0); + small::reset(); + assert(test_alloc_base::alloc_count == 0); + // small non-const lvalue + { + small s(1); + any const a(std::allocator_arg, test_allocator(), s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + assert(test_alloc_base::alloc_count == 0); + assert(small::count == 2); + assert(small::copied == 1); + assert(small::moved == 0); + } + assert(small::count == 0); + small::reset(); + assert(test_alloc_base::alloc_count == 0); + // small non-const rvalue + { + small s(1); + any const a(std::allocator_arg, test_allocator(), std::move(s)); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(s.value == 0); + assert(any_cast(a).value == 1); + assert(small::count == 2); + assert(small::copied == 0); + assert(small::moved == 1); + assert(test_alloc_base::alloc_count == 0); + } + assert(small::count == 0); + small::copied = 0; + small::moved = 0; + assert(test_alloc_base::alloc_count == 0); + // large const lvalue + { + large const s(1); + any const a(std::allocator_arg, test_allocator(), s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == s); + assert(test_alloc_base::alloc_count == 1); + assert(large::count == 2); + assert(large::copied == 1); + assert(large::moved == 0); + } + assert(large::count == 0); + large::reset(); + assert(test_alloc_base::alloc_count == 0); + // large non-const lvalue + { + large s(1); + any const a(std::allocator_arg, test_allocator(), s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == s); + assert(test_alloc_base::alloc_count == 1); + assert(large::count == 2); + assert(large::copied == 1); + assert(large::moved == 0); + } + assert(large::count == 0); + large::reset(); + assert(test_alloc_base::alloc_count == 0); + // large non-const rvalue + { + large s(1); + any const a(std::allocator_arg, test_allocator(), std::move(s)); + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a).value == 1); + assert(s.value == 0); + assert(large::count == 2); + assert(large::moved == 1); + assert(test_alloc_base::alloc_count == 1); + } + assert(large::count == 0); + assert(test_alloc_base::alloc_count == 0); +#endif /* _LIBCPP_STD_VER > 11 */ +} \ No newline at end of file Index: test/experimental/any/any.class/any.cons/alloc_value_alloc_throws.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/alloc_value_alloc_throws.pass.cpp @@ -0,0 +1,73 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::any(allocator_arg_t, Alloc const &, Value &&); + +// Test throwing an exception during the allocation of memory using an allocator. + +#include +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" +#include "test_allocator.h" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // small value copy throws + test_alloc_base::throw_after = 0; + { + small const v(42); + assert(small::count == 1); + + try { + any const a(std::allocator_arg + , test_allocator(), v); + assert(small::count == 2); + assert(test_alloc_base::alloc_count == 0); + assert(test_alloc_base::count == 1); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == v); + } catch (...) { + assert(false); + } + + assert(small::count == 1); + assert(test_alloc_base::alloc_count == 0); + assert(test_alloc_base::count == 0); + } + assert(small::count == 0); + { + large const v(42); + assert(large::count == 1); + + try { + any const a(std::allocator_arg + , test_allocator(), v); + assert(false); + } catch (std::bad_alloc const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(large::count == 1); + assert(test_alloc_base::alloc_count == 0); + assert(test_alloc_base::count == 0); + } + assert(large::count == 0); +#endif /* _LIBCPP_STD_VER > 11 */ +} \ No newline at end of file Index: test/experimental/any/any.class/any.cons/alloc_value_throws.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/alloc_value_throws.pass.cpp @@ -0,0 +1,126 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::any(allocator_arg_t, Alloc const &, Value &&); + +// Test throwing an exception from the constructor of a value type. + +#include +#include +#include +#include "../../count_new.hpp" +#include "test_allocator.h" + + +struct my_exception {}; + +struct small_throws_on_copy +{ + static int count; + small_throws_on_copy() { ++count; } + small_throws_on_copy(small_throws_on_copy const &) { throw my_exception(); } + small_throws_on_copy(small_throws_on_copy &&) throw() { ++count; } + ~small_throws_on_copy() { --count; } +}; + +int small_throws_on_copy::count = 0; + + +struct large_throws_on_copy +{ + static int count; + large_throws_on_copy() { data[0] = 0; ++count; } + large_throws_on_copy(large_throws_on_copy const &) { throw my_exception(); } + large_throws_on_copy(large_throws_on_copy &&) throw() { ++count; } + ~large_throws_on_copy() { --count; } +private: + int data[10]; +}; + +int large_throws_on_copy::count = 0; + +struct throws_on_move +{ + static int count; + throws_on_move() { ++count; } + throws_on_move(throws_on_move const &) { ++count; } + throws_on_move(throws_on_move &&) { throw my_exception(); } + ~throws_on_move() { --count; } +}; + +int throws_on_move::count = 0; + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // small value copy throws + { + small_throws_on_copy const v; + assert(small_throws_on_copy::count == 1); + + try { + any const a(std::allocator_arg + , test_allocator(), v); + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(small_throws_on_copy::count == 1); + assert(test_alloc_base::alloc_count == 0); + assert(test_alloc_base::count == 0); + } + assert(small_throws_on_copy::count == 0); + { + large_throws_on_copy const v; + assert(large_throws_on_copy::count == 1); + + try { + any const a(std::allocator_arg + , test_allocator(), v); + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(large_throws_on_copy::count == 1); + assert(test_alloc_base::alloc_count == 0); + assert(test_alloc_base::count == 0); + } + assert(large_throws_on_copy::count == 0); + assert(new_called == 0); + { + throws_on_move v; + assert(throws_on_move::count == 1); + + try { + any const a(std::allocator_arg + , test_allocator(), std::move(v)); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(throws_on_move::count == 1); + assert(test_alloc_base::alloc_count == 0); + assert(test_alloc_base::count == 0); + } + assert(total_new == 0); + assert(delete_called == 0); +#endif /* _LIBCPP_STD_VER > 11 */ +} \ No newline at end of file Index: test/experimental/any/any.class/any.cons/copy.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/copy.pass.cpp @@ -0,0 +1,75 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any(any const &); + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // empty + { + any const a1; + + any const a2(a1); + + assert(a2.empty()); + assert(a2.type() == typeid(void)); + assert(new_called == 0); + } + assert(new_called == 0); + // small value + { + small const s(1); + any const a(s); + + any a2(a); + + assert(!a2.empty()); + assert(a2.type() == typeid(small)); + assert(any_cast(a2) == s); + + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + + assert(small::count == 3); + assert(new_called == 0); + } + assert(new_called == 0); + // large value + { + large const l(1); + any const a(l); + + any a2(a); + + assert(!a2.empty()); + assert(a2.type() == typeid(large)); + assert(any_cast(a2) == l); + + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == l); + + assert(large::count == 3); + assert(new_called == 2); + } + assert(new_called == 0); +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.cons/copy_throws.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/copy_throws.pass.cpp @@ -0,0 +1,114 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template any(any const &); + +// Test throwing an exception during copy construction. + +#include +#include +#include "../../count_new.hpp" + +struct my_exception {}; + + +struct small_throws_on_copy +{ + static int count; + + small_throws_on_copy() { ++count; } + + small_throws_on_copy(small_throws_on_copy const &) + { + throw my_exception(); + } + + small_throws_on_copy(small_throws_on_copy &&) throw() + { + ++count; + } + + ~small_throws_on_copy() { --count; } +}; + +int small_throws_on_copy::count = 0; + + +struct large_throws_on_copy +{ + static int count; + + large_throws_on_copy() + { + data[0] = 0; + ++count; + } + + large_throws_on_copy(large_throws_on_copy const &) + { + throw my_exception(); + } + + large_throws_on_copy(large_throws_on_copy &&) throw() + { + ++count; + } + + ~large_throws_on_copy() { --count; } + +private: + int data[10]; +}; + +int large_throws_on_copy::count = 0; + +int main() +{ +# if _LIBCPP_STD_VER > 11 + using std::experimental::any; + { + any const a((small_throws_on_copy())); + assert(small_throws_on_copy::count == 1); + try { + any const a2(a); + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(small_throws_on_copy::count == 1); + assert(new_called == 0); + + // check that we didn't try and allocate. + assert(total_new == 0); + } + assert(small_throws_on_copy::count == 0); + assert(new_called == 0); + { + any const a((large_throws_on_copy())); + assert(large_throws_on_copy::count == 1); + assert(new_called == 1); + try { + any const a2(a); + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(large_throws_on_copy::count == 1); + assert(new_called == 1); + } + assert(new_called == 0); + assert(large_throws_on_copy::count == 0); +#endif /* _LIBCPP_STD_VER > 11 */ +} \ No newline at end of file Index: test/experimental/any/any.class/any.cons/default.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/default.pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any() noexcept; + +#include +#include +#include +#include "../../count_new.hpp" + + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + { + static_assert( + std::is_nothrow_default_constructible::value + , "Must be default constructible" + ); + } + { + any const a; + assert(a.empty()); + assert(a.type() == typeid(void)); + assert(new_called == 0); + } + assert(new_called == 0); +#endif // _LIBCPP_STD_VER > 11 +} \ No newline at end of file Index: test/experimental/any/any.class/any.cons/move.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/move.pass.cpp @@ -0,0 +1,78 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any(any &&) noexcept; + +#include +#include +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // noexcept test + { + static_assert( + std::is_nothrow_move_constructible::value + , "any must be nothrow move constructible" + ); + } + // empty object + { + any a1; + + any a2(std::move(a1)); + + assert(a2.empty()); + assert(a2.type() == typeid(void)); + assert(new_called == 0); + } + assert(new_called == 0); + // small object + { + small s(1); + any a1(s); + + any a2(std::move(a1)); + + assert(!a2.empty()); + assert(a2.type() == typeid(small)); + assert(any_cast(a2) == s); + assert(small::copied == 1); + assert(small::moved == 1); + assert(new_called == 0); + } + assert(small::count == 0); + assert(new_called == 0); + // large object + { + large l(1); + any a1(l); + + any a2(std::move(a1)); + + assert(!a2.empty()); + assert(a2.type() == typeid(large)); + assert(any_cast(a2) == l); + // NOTE: We cannot check the count of large + // since we just do a pointer swap + assert(new_called == 1); + } + assert(large::count == 0); + assert(new_called == 0); +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.cons/move_throws.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/move_throws.pass.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any(any &&) noexcept + +// Test throwing an exception during move construction. + +#include +#include +#include "../../count_new.hpp" + +struct my_exception {}; + +struct throws_on_move +{ + static int count; + + throws_on_move() { ++count; } + + throws_on_move(throws_on_move const &) + { + ++count; + } + + throws_on_move(throws_on_move &&) + { + throw my_exception(); + } + + ~throws_on_move() { --count; } +}; + +int throws_on_move::count = 0; + + +int main() +{ +# if _LIBCPP_STD_VER > 11 + using std::experimental::any; + { + throws_on_move v; + any a(v); + assert(throws_on_move::count == 2); + + // Check that we put a throws-on-move type on the heap. + assert(new_called == 1); + assert(total_new == 1); + + // Moves are always noexcept. + try { + any const a2(std::move(a)); + assert(new_called == 1); + assert(a2.type() == typeid(throws_on_move)); + } catch (...) { + assert(false); + } + + // Assert that we didn't allocate again. + assert(total_new == 1); + } + assert(throws_on_move::count == 0); + assert(new_called == 0); +#endif /* _LIBCPP_STD_VER > 11 */ +} \ No newline at end of file Index: test/experimental/any/any.class/any.cons/non_copyable_value.fail.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/non_copyable_value.fail.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::any(Value &&) + +// Attempt to construct any with a non-copyable type. + +#include + +#if _LIBCPP_STD_VER > 11 +class non_copyable +{ + non_copyable(non_copyable const &); + +public: + non_copyable() {} + non_copyable(non_copyable &&) {} +}; + +int main() +{ + using std::experimental::any; + non_copyable nc; + any a(static_cast(nc)); +} +#else /* _LIBCPP_STD_VER <= 11 */ +int main() +{ +# error +} +#endif /* _LIBCPP_STD_VER > 11 */ \ No newline at end of file Index: test/experimental/any/any.class/any.cons/uses_allocator_alloc_at_end.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/uses_allocator_alloc_at_end.pass.cpp @@ -0,0 +1,252 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::any(allocator_arg_t, Alloc const &, any const &); + +// Test uses allocator construction on a value type that takes the allocator as +// as the last argument. + +#include +#include +#include +#include +#include "test_allocator.h" + +struct small +{ + static int count; + static int copied; + static int moved; + + char value; + + typedef test_allocator allocator_type; + + small(char val) + : value(val) + { + ++count; + } + + small(small const & other) throw() + { + value = other.value; + ++count; + ++copied; + } + + small(small && other) throw() + { + value = other.value; + other.value = 0; + ++count; + ++moved; + } + + small(std::allocator_arg_t, test_allocator const &, small const & other) + { + assert(false); + } + + small(std::allocator_arg_t, test_allocator const &, small && other) + { + assert(false); + } + + + ~small() + { + value = 0; + --count; + } +}; + +int small::count = 0; +int small::copied = 0; +int small::moved = 0; + +inline bool operator==(small const & lhs, small const & rhs) +{ + return lhs.value == rhs.value; +} + +inline bool operator!=(small const & lhs, small const & rhs) +{ + return lhs.value != rhs.value; +} + +struct large +{ + static int count; + static int alloc_copied; + static int alloc_moved; + + char value; + + typedef test_allocator allocator_type; + + large(char val) : value(val) + { + ++count; + data[0] = 0; + } + + large(large const & other) + { + assert(false); + } + + large(large && other) + { + assert(false); + } + + large(large const & other, test_allocator const &) + { + value = other.value; + ++count; + ++alloc_copied; + } + + + large(large && other, test_allocator const &) + { + value = other.value; + other.value = 0; + ++count; + ++alloc_moved; + } + + ~large() + { + value = 0; + --count; + } +private: + int data[10]; +}; + +int large::count = 0; +int large::alloc_copied = 0; +int large::alloc_moved = 0; + +inline bool operator==(large const & lhs, large const & rhs) +{ + return lhs.value == rhs.value; +} + +inline bool operator!=(large const & lhs, large const & rhs) +{ + return lhs.value != rhs.value; +} + +static_assert(std::uses_allocator>::value, "Small uses allocator"); +static_assert(std::uses_allocator>::value, "Large uses allocator"); + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // small const lvalue + { + small const s(1); + any const a(std::allocator_arg, test_allocator(), s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + assert(test_alloc_base::alloc_count == 0); + assert(small::count == 2); + assert(small::copied == 1); + } + assert(small::count == 0); + small::copied = 0; + assert(test_alloc_base::alloc_count == 0); + // small non-const lvalue + { + small s(1); + any const a(std::allocator_arg, test_allocator(), s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + assert(test_alloc_base::alloc_count == 0); + assert(small::count == 2); + assert(small::copied == 1); + assert(small::moved == 0); + } + assert(small::count == 0); + small::copied = 0; + small::moved = 0; + assert(test_alloc_base::alloc_count == 0); + // small non-const rvalue + { + small s(1); + any const a(std::allocator_arg, test_allocator(), std::move(s)); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(s.value == 0); + assert(any_cast(a).value == 1); + assert(small::count == 2); + assert(small::copied == 0); + assert(small::moved == 1); + assert(test_alloc_base::alloc_count == 0); + } + assert(small::count == 0); + small::copied = 0; + small::moved = 0; + assert(test_alloc_base::alloc_count == 0); + // large const lvalue + { + large const s(1); + any const a(std::allocator_arg, test_allocator(), s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == s); + assert(test_alloc_base::alloc_count == 1); + assert(large::count == 2); + assert(large::alloc_copied == 1); + assert(large::alloc_moved == 0); + } + assert(large::count == 0); + large::alloc_copied = 0; + assert(test_alloc_base::alloc_count == 0); + // large non-const lvalue + { + large s(1); + any const a(std::allocator_arg, test_allocator(), s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == s); + assert(test_alloc_base::alloc_count == 1); + assert(large::count == 2); + assert(large::alloc_copied == 1); + assert(large::alloc_moved == 0); + } + assert(large::count == 0); + large::alloc_copied = 0; + assert(test_alloc_base::alloc_count == 0); + // large non-const rvalue + { + large s(1); + any const a(std::allocator_arg, test_allocator(), std::move(s)); + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a).value == 1); + assert(s.value == 0); + assert(large::count == 2); + assert(large::alloc_copied == 0); + assert(large::alloc_moved == 1); + assert(test_alloc_base::alloc_count == 1); + } + assert(large::count == 0); + assert(test_alloc_base::alloc_count == 0); +#endif /* _LIBCPP_STD_VER > 11 */ +} Index: test/experimental/any/any.class/any.cons/uses_allocator_allocator_arg_t.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/uses_allocator_allocator_arg_t.pass.cpp @@ -0,0 +1,253 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::any(allocator_arg_t, Alloc const &, Value &&); + +// Test uses allocator construction on value types that have allocator_arg_t +// signatures. + + +#include +#include +#include +#include +#include +#include "test_allocator.h" + + +struct small +{ + static int count; + static int copied; + static int moved; + + char value; + + typedef test_allocator allocator_type; + + small(char val) + : value(val) + { + ++count; + } + + small(small const & other) throw() + { + value = other.value; + ++count; + ++copied; + } + + small(small && other) throw() + { + value = other.value; + other.value = 0; + ++count; + ++moved; + } + + small(std::allocator_arg_t, test_allocator const &, small const & other) + { + assert(false); + } + + small(std::allocator_arg_t, test_allocator const &, small && other) + { + assert(false); + } + + ~small() + { + value = 0; + --count; + } +}; + +int small::count = 0; +int small::copied = 0; +int small::moved = 0; + +inline bool operator==(small const & lhs, small const & rhs) +{ + return lhs.value == rhs.value; +} + +inline bool operator!=(small const & lhs, small const & rhs) +{ + return lhs.value != rhs.value; +} + +struct large +{ + static int count; + static int alloc_copied; + static int alloc_moved; + + char value; + + typedef test_allocator allocator_type; + + large(char val) : value(val) + { + ++count; + data[0] = 0; + } + + large(large const & other) + { + assert(false); + } + + large(large && other) + { + assert(false); + } + + large(std::allocator_arg_t, test_allocator const &, large const & other) + { + value = other.value; + ++count; + ++alloc_copied; + } + + large(std::allocator_arg_t, test_allocator const &, large && other) + { + value = other.value; + other.value = 0; + ++count; + ++alloc_moved; + } + + ~large() + { + value = 0; + --count; + } +private: + int data[10]; +}; + +int large::count = 0; +int large::alloc_copied = 0; +int large::alloc_moved = 0; + +inline bool operator==(large const & lhs, large const & rhs) +{ + return lhs.value == rhs.value; +} + +inline bool operator!=(large const & lhs, large const & rhs) +{ + return lhs.value != rhs.value; +} + +static_assert(std::uses_allocator>::value, "Small uses allocator"); +static_assert(std::uses_allocator>::value, "Large uses allocator"); + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // small const lvalue + { + small const s(1); + any const a(std::allocator_arg, test_allocator(), s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + assert(test_alloc_base::alloc_count == 0); + assert(small::count == 2); + assert(small::copied == 1); + } + assert(small::count == 0); + small::copied = 0; + assert(test_alloc_base::alloc_count == 0); + // small non-const lvalue + { + small s(1); + any const a(std::allocator_arg, test_allocator(), s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + assert(test_alloc_base::alloc_count == 0); + assert(small::count == 2); + assert(small::copied == 1); + assert(small::moved == 0); + } + assert(small::count == 0); + small::copied = 0; + small::moved = 0; + assert(test_alloc_base::alloc_count == 0); + // small non-const rvalue + { + small s(1); + any const a(std::allocator_arg, test_allocator(), std::move(s)); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(s.value == 0); + assert(any_cast(a).value == 1); + assert(small::count == 2); + assert(small::copied == 0); + assert(small::moved == 1); + assert(test_alloc_base::alloc_count == 0); + } + assert(small::count == 0); + small::copied = 0; + small::moved = 0; + assert(test_alloc_base::alloc_count == 0); + // large const lvalue + { + large const s(1); + any const a(std::allocator_arg, test_allocator(), s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == s); + assert(test_alloc_base::alloc_count == 1); + assert(large::count == 2); + assert(large::alloc_copied == 1); + assert(large::alloc_moved == 0); + } + assert(large::count == 0); + large::alloc_copied = 0; + assert(test_alloc_base::alloc_count == 0); + // large non-const lvalue + { + large s(1); + any const a(std::allocator_arg, test_allocator(), s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == s); + assert(test_alloc_base::alloc_count == 1); + assert(large::count == 2); + assert(large::alloc_copied == 1); + assert(large::alloc_moved == 0); + } + assert(large::count == 0); + large::alloc_copied = 0; + assert(test_alloc_base::alloc_count == 0); + // large non-const rvalue + { + large s(1); + any const a(std::allocator_arg, test_allocator(), std::move(s)); + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a).value == 1); + assert(s.value == 0); + assert(large::count == 2); + assert(large::alloc_copied == 0); + assert(large::alloc_moved == 1); + assert(test_alloc_base::alloc_count == 1); + } + assert(large::count == 0); + assert(test_alloc_base::alloc_count == 0); +#endif /* _LIBCPP_STD_VER > 11 */ +} Index: test/experimental/any/any.class/any.cons/uses_allocator_both_signatures.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/uses_allocator_both_signatures.pass.cpp @@ -0,0 +1,273 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::any(allocator_arg_t, Alloc const &, Value &&); + +// Test uses allocator construction on value types that have both uses allocator +// constructors. The allocator_arg_t constructor should be chosen. + +#include +#include +#include +#include +#include +#include "test_allocator.h" + + +struct small +{ + static int count; + static int copied; + static int moved; + + char value; + + typedef test_allocator allocator_type; + + small(char val) + : value(val) + { + ++count; + } + + small(small const & other) throw() + { + value = other.value; + ++count; + ++copied; + } + + small(small && other) throw() + { + value = other.value; + other.value = 0; + ++count; + ++moved; + } + + small(std::allocator_arg_t, test_allocator const &, small const & other) + { + assert(false); + } + + small(std::allocator_arg_t, test_allocator const &, small && other) + { + assert(false); + } + + small(small const &, test_allocator const &) + { + assert(false); + } + + + small(small &&, test_allocator const &) + { + assert(false); + } + + ~small() + { + value = 0; + --count; + } +}; + +int small::count = 0; +int small::copied = 0; +int small::moved = 0; + +inline bool operator==(small const & lhs, small const & rhs) +{ + return lhs.value == rhs.value; +} + +inline bool operator!=(small const & lhs, small const & rhs) +{ + return lhs.value != rhs.value; +} + +struct large +{ + static int count; + static int alloc_copied; + static int alloc_moved; + + char value; + + typedef test_allocator allocator_type; + + large(char val) : value(val) + { + ++count; + data[0] = 0; + } + + large(large const & other) + { + assert(false); + } + + large(large && other) + { + assert(false); + } + + large(std::allocator_arg_t, test_allocator const &, large const & other) + { + value = other.value; + ++count; + ++alloc_copied; + } + + large(std::allocator_arg_t, test_allocator const &, large && other) + { + value = other.value; + other.value = 0; + ++count; + ++alloc_moved; + } + + large(large const &, test_allocator const &) + { + assert(false); + } + + large(large &&, test_allocator const &) + { + assert(false); + } + + ~large() + { + value = 0; + --count; + } +private: + int data[10]; +}; + +int large::count = 0; +int large::alloc_copied = 0; +int large::alloc_moved = 0; + +inline bool operator==(large const & lhs, large const & rhs) +{ + return lhs.value == rhs.value; +} + +inline bool operator!=(large const & lhs, large const & rhs) +{ + return lhs.value != rhs.value; +} + +static_assert(std::uses_allocator>::value, "Small uses allocator"); +static_assert(std::uses_allocator>::value, "Large uses allocator"); + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // small const lvalue + { + small const s(1); + any const a(std::allocator_arg, test_allocator(), s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + assert(test_alloc_base::alloc_count == 0); + assert(small::count == 2); + assert(small::copied == 1); + } + assert(small::count == 0); + small::copied = 0; + assert(test_alloc_base::alloc_count == 0); + // small non-const lvalue + { + small s(1); + any const a(std::allocator_arg, test_allocator(), s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + assert(test_alloc_base::alloc_count == 0); + assert(small::count == 2); + assert(small::copied == 1); + assert(small::moved == 0); + } + assert(small::count == 0); + small::copied = 0; + small::moved = 0; + assert(test_alloc_base::alloc_count == 0); + // small non-const rvalue + { + small s(1); + any const a(std::allocator_arg, test_allocator(), std::move(s)); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(s.value == 0); + assert(any_cast(a).value == 1); + assert(small::count == 2); + assert(small::copied == 0); + assert(small::moved == 1); + assert(test_alloc_base::alloc_count == 0); + } + assert(small::count == 0); + small::copied = 0; + small::moved = 0; + assert(test_alloc_base::alloc_count == 0); + // large const lvalue + { + large const s(1); + any const a(std::allocator_arg, test_allocator(), s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == s); + assert(test_alloc_base::alloc_count == 1); + assert(large::count == 2); + assert(large::alloc_copied == 1); + assert(large::alloc_moved == 0); + } + assert(large::count == 0); + large::alloc_copied = 0; + assert(test_alloc_base::alloc_count == 0); + // large non-const lvalue + { + large s(1); + any const a(std::allocator_arg, test_allocator(), s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == s); + assert(test_alloc_base::alloc_count == 1); + assert(large::count == 2); + assert(large::alloc_copied == 1); + assert(large::alloc_moved == 0); + } + assert(large::count == 0); + large::alloc_copied = 0; + assert(test_alloc_base::alloc_count == 0); + // large non-const rvalue + { + large s(1); + any const a(std::allocator_arg, test_allocator(), std::move(s)); + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a).value == 1); + assert(s.value == 0); + assert(large::count == 2); + assert(large::alloc_copied == 0); + assert(large::alloc_moved == 1); + assert(test_alloc_base::alloc_count == 1); + } + assert(large::count == 0); + assert(test_alloc_base::alloc_count == 0); +#endif /* _LIBCPP_STD_VER > 11 */ +} Index: test/experimental/any/any.class/any.cons/value.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/value.pass.cpp @@ -0,0 +1,122 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template any(Value &&) + +// Test construction from a value. + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +# if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // small const lvalue + { + small const s(1); + any const a(s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + assert(small::count == 2); + assert(small::copied == 1); + assert(new_called == 0); + } + assert(small::count == 0); + assert(new_called == 0); + small::copied = 0; + small::moved = 0; + // small non-const lvalue + { + small s(1); + any const a(s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(any_cast(a) == s); + assert(small::count == 2); + assert(small::copied == 1); + assert(new_called == 0); + } + assert(small::count == 0); + assert(new_called == 0); + small::copied = 0; + small::moved = 0; + // small non-const rvalue + { + small s(1); + any const a(static_cast(s)); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(s.value == 0); + assert(any_cast(a).value == 1); + assert(small::count == 2); + assert(small::copied == 0); + assert(small::moved == 1); + assert(new_called == 0); + } + assert(small::count == 0); + assert(new_called == 0); + small::copied = 0; + small::moved = 0; + // large const lvalue + { + large const l(1); + any const a(l); + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == l); + assert(new_called == 1); + assert(large::count == 2); + assert(large::copied == 1); + assert(large::moved == 0); + } + assert(large::count == 0); + large::moved = 0; + large::copied = 0; + assert(new_called == 0); + // large non-const lvalue + { + large l(1); + any const a(l); + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(any_cast(a) == l); + assert(new_called == 1); + assert(large::count == 2); + assert(large::copied == 1); + assert(large::moved == 0); + } + assert(large::count == 0); + large::moved = 0; + large::copied = 0; + assert(new_called == 0); + // large non-const rvalue + { + large l(1); + any const a(static_cast(l)); + assert(!a.empty()); + assert(a.type() == typeid(large)); + assert(l.value == 0); + assert(any_cast(a).value == 1); + assert(large::count == 2); + assert(large::moved == 1); + assert(large::copied == 0); + assert(new_called == 1); + } + assert(large::count == 0); + assert(new_called == 0); +#endif /* _LIBCPP_STD_VER > 11 */ +} \ No newline at end of file Index: test/experimental/any/any.class/any.cons/value_copy_throws.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/value_copy_throws.pass.cpp @@ -0,0 +1,116 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template any(Value &&); + +// Test throwing an exception while copying a value. + +#include +#include +#include "../../count_new.hpp" + +struct my_exception {}; + + +struct small_throws_on_copy +{ + static int count; + + small_throws_on_copy() { ++count; } + + small_throws_on_copy(small_throws_on_copy const &) + { + throw my_exception(); + } + + small_throws_on_copy(small_throws_on_copy &&) throw() + { + ++count; + } + + ~small_throws_on_copy() { --count; } +}; + +int small_throws_on_copy::count = 0; + + +struct large_throws_on_copy +{ + static int count; + + large_throws_on_copy() + { + data[0] = 0; + ++count; + } + + large_throws_on_copy(large_throws_on_copy const &) + { + throw my_exception(); + } + + large_throws_on_copy(large_throws_on_copy &&) throw() + { + ++count; + } + + ~large_throws_on_copy() { --count; } + +private: + int data[10]; +}; + +int large_throws_on_copy::count = 0; + +int main() +{ +# if _LIBCPP_STD_VER > 11 + using std::experimental::any; + { + small_throws_on_copy v; + assert(small_throws_on_copy::count == 1); + try { + any const a(v); + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(small_throws_on_copy::count == 1); + assert(new_called == 0); + + // check that we didn't try and allocate. + assert(total_new == 0); + } + assert(small_throws_on_copy::count == 0); + assert(new_called == 0); + { + large_throws_on_copy v; + assert(large_throws_on_copy::count == 1); + try { + any const a(v); + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(large_throws_on_copy::count == 1); + assert(new_called == 0); + // Check that we did try and allocate and we deleted it. + assert(total_new == 1); + assert(delete_called == 1); + } + assert(new_called == 0); + assert(large_throws_on_copy::count == 0); +#endif /* _LIBCPP_STD_VER > 11 */ +} \ No newline at end of file Index: test/experimental/any/any.class/any.cons/value_move_throws.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.cons/value_move_throws.pass.cpp @@ -0,0 +1,70 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template any(Value &&) + +// Test throwing an exception while moving a value. + +#include +#include +#include "../../count_new.hpp" + +struct my_exception {}; + +struct throws_on_move +{ + static int count; + + throws_on_move() { ++count; } + + throws_on_move(throws_on_move const &) + { + ++count; + } + + throws_on_move(throws_on_move &&) + { + throw my_exception(); + } + + ~throws_on_move() { --count; } +}; + +int throws_on_move::count = 0; + + +int main() +{ +# if _LIBCPP_STD_VER > 11 + using std::experimental::any; + { + throws_on_move v; + assert(throws_on_move::count == 1); + try { + any const a(std::move(v)); + assert(false); + } catch (my_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(throws_on_move::count == 1); + assert(new_called == 0); + // check that we tried to allocate since throws_on_move should not be a + // small object. + assert(total_new == 1); + assert(delete_called == 1); + } + assert(throws_on_move::count == 0); + assert(new_called == 0); + +#endif /* _LIBCPP_STD_VER > 11 */ +} \ No newline at end of file Index: test/experimental/any/any.class/any.modifiers/clear.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.modifiers/clear.pass.cpp @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::clear() noexcept + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // empty + { + any a; + + // noexcept check + static_assert( + noexcept(a.clear()) + , "any.clear() must be noexcept" + ); + + a.clear(); + assert(a.empty()); + assert(a.type() == typeid(void)); + assert(new_called == 0); + } + assert(new_called == 0); + // small object + { + small const s(1); + any a(s); + + a.clear(); + + assert(a.empty()); + assert(a.type() == typeid(void)); + assert(any_cast(&a) == nullptr); + assert(small::count == 1); + assert(new_called == 0); + } + assert(new_called == 0); + // large object + { + large const l(1); + any a(l); + + a.clear(); + assert(a.empty()); + assert(a.type() == typeid(void)); + assert(any_cast(&a) == nullptr); + assert(large::count == 1); + assert(new_called == 0); + } + assert(new_called == 0); +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.modifiers/swap_empty_empty.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.modifiers/swap_empty_empty.pass.cpp @@ -0,0 +1,38 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::swap(any &) noexcept + +// Test swap(empty, empty) + +#include +#include +#include "../../count_new.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + { + any a1; + any a2; + + a1.swap(a2); + + assert(a1.empty()); + assert(a1.type() == typeid(void)); + assert(a2.empty()); + assert(a2.type() == typeid(void)); + assert(new_called == 0); + } + assert(new_called == 0); +#endif // _LIBCPP_STD_VER > 11 +} \ No newline at end of file Index: test/experimental/any/any.class/any.modifiers/swap_empty_large.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.modifiers/swap_empty_large.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::swap(any &) noexcept + +// test swap(empty, large) and swap(large, empty) + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // empty.swap(large) + { + any a1; + any a2(large{1}); + + a1.swap(a2); + + assert(!a1.empty()); + assert(a1.type() == typeid(large)); + assert(any_cast(a1).value == 1); + + assert(a2.empty()); + assert(a2.type() == typeid(void)); + assert(large::count == 1); + assert(new_called == 1); + } + assert(new_called == 0); + assert(large::count == 0); + // large.swap(empty) + { + any a1; + any a2(large{1}); + + a2.swap(a1); + + assert(a2.empty()); + assert(a2.type() == typeid(void)); + + assert(!a1.empty()); + assert(a1.type() == typeid(large)); + assert(any_cast(a1).value == 1); + assert(large::count == 1); + assert(new_called == 1); + } + assert(new_called == 0); + assert(large::count == 0); +#endif // _LIBCPP_STD_VER > 11 +} \ No newline at end of file Index: test/experimental/any/any.class/any.modifiers/swap_empty_small.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.modifiers/swap_empty_small.pass.cpp @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::swap(any &) noexcept + +// Test swap(empty, small) and swap(small, empty) + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // empty.swap(small) + { + any a1; + any a2(small{1}); + + a1.swap(a2); + + assert(!a1.empty()); + assert(a1.type() == typeid(small)); + assert(any_cast(a1).value == 1); + assert(a2.empty()); + assert(a2.type() == typeid(void)); + assert(small::count == 1); + assert(new_called == 0); + } + assert(new_called == 0); + assert(small::count == 0); + // small.swap(empty) + { + any a1; + any a2(small{1}); + + a2.swap(a1); + + assert(a2.empty()); + assert(a2.type() == typeid(void)); + assert(!a1.empty()); + assert(a1.type() == typeid(small)); + assert(any_cast(a1).value == 1); + assert(small::count == 1); + assert(new_called == 0); + } + assert(new_called == 0); + assert(small::count == 0); +#endif // _LIBCPP_STD_VER > 11 +} \ No newline at end of file Index: test/experimental/any/any.class/any.modifiers/swap_large_large.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.modifiers/swap_large_large.pass.cpp @@ -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. +// +//===----------------------------------------------------------------------===// + +// + +// any::swap(any &) noexcept + +// Test swap(large, large) + +#include +#include +#include "../../count_new.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // large1.swap(large2) + { + any a1((large1(1))); + any a2((large2(2))); + + a1.swap(a2); + + assert(!a1.empty()); + assert(a1.type() == typeid(large2)); + assert(any_cast(a1).value == 2); + assert(large2::count == 1); + + assert(!a2.empty()); + assert(a2.type() == typeid(large1)); + assert(any_cast(a2).value == 1); + assert(large1::count == 1); + + assert(new_called == 2); + } + assert(new_called == 0); + assert(large1::count == 0); + assert(large2::count == 0); + // large2.swap(large1) + { + any a1((large1(1))); + any a2((large2(2))); + + a2.swap(a1); + + assert(!a1.empty()); + assert(a1.type() == typeid(large2)); + assert(any_cast(a1).value == 2); + assert(large2::count == 1); + + assert(!a2.empty()); + assert(a2.type() == typeid(large1)); + assert(any_cast(a2).value == 1); + assert(large1::count == 1); + + assert(new_called == 2); + } + assert(new_called == 0); + assert(large1::count == 0); + assert(large2::count == 0); +#endif // _LIBCPP_STD_VER > 11 +} \ No newline at end of file Index: test/experimental/any/any.class/any.modifiers/swap_large_small.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.modifiers/swap_large_small.pass.cpp @@ -0,0 +1,72 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::swap(any &) noexcept + +// Test swap(large, small) and swap(small, large) + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // small.swap(large) + { + any a1((small(1))); + any a2(large{2}); + + a1.swap(a2); + + assert(!a1.empty()); + assert(a1.type() == typeid(large)); + assert(any_cast(a1).value == 2); + assert(large::count == 1); + + assert(!a2.empty()); + assert(a2.type() == typeid(small)); + assert(any_cast(a2).value == 1); + assert(small::count == 1); + + assert(new_called == 1); + } + assert(small::count == 0); + assert(large::count == 0); + assert(new_called == 0); + // large.swap(small) + { + any a1((small(1))); + any a2((large(2))); + + a2.swap(a1); + + assert(!a1.empty()); + assert(a1.type() == typeid(large)); + assert(any_cast(a1).value == 2); + assert(large::count == 1); + + assert(!a2.empty()); + assert(a2.type() == typeid(small)); + assert(any_cast(a2).value == 1); + assert(small::count == 1); + + assert(new_called == 1); + } + assert(small::count == 0); + assert(large::count == 0); + assert(new_called == 0); +#endif // _LIBCPP_STD_VER > 11 +} \ No newline at end of file Index: test/experimental/any/any.class/any.modifiers/swap_noexcept.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.modifiers/swap_noexcept.pass.cpp @@ -0,0 +1,28 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::swap(any &) noexcept + +#include + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + + any a1; + any a2; + static_assert( + noexcept(a1.swap(a2)) + , "any::swap(any&) must be noexcept" + ); +#endif // _LIBCPP_STD_VER > 11 +} \ No newline at end of file Index: test/experimental/any/any.class/any.modifiers/swap_small_small.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.modifiers/swap_small_small.pass.cpp @@ -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. +// +//===----------------------------------------------------------------------===// + +// + +// any::swap(any &) noexcept + +// Test swap(small, small) + +#include +#include +#include "../../count_new.hpp" +#include "../../small_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + // small1.swap(small2) + { + any a1((small1(1))); + any a2((small2(2))); + + a1.swap(a2); + + assert(!a1.empty()); + assert(a1.type() == typeid(small2)); + assert(any_cast(a1).value == 2); + assert(small2::count == 1); + + assert(!a2.empty()); + assert(a2.type() == typeid(small1)); + assert(any_cast(a2).value == 1); + assert(small1::count == 1); + + assert(new_called == 0); + } + assert(new_called == 0); + assert(small1::count == 0); + assert(small2::count == 0); + // small2.swap(small1) + { + any a1((small1(1))); + any a2((small2(2))); + + a2.swap(a1); + + assert(!a1.empty()); + assert(a1.type() == typeid(small2)); + assert(any_cast(a1).value == 2); + assert(small2::count == 1); + + assert(!a2.empty()); + assert(a2.type() == typeid(small1)); + assert(any_cast(a2).value == 1); + assert(small1::count == 1); + + assert(new_called == 0); + } + assert(new_called == 0); + assert(small1::count == 0); + assert(small2::count == 0); +#endif // _LIBCPP_STD_VER > 11 +} \ No newline at end of file Index: test/experimental/any/any.class/any.observers/empty.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.observers/empty.pass.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::empty() noexcept + +#include +#include +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + // empty + { + any const a; + assert(a.empty()); + + static_assert( + noexcept(a.empty()) + , "any::empty() must be noexcept" + ); + } + // small object + { + small const s(1); + any const a(s); + assert(!a.empty()); + } + // large object + { + large const l(1); + any const a(l); + assert(!a.empty()); + } +#endif +} \ No newline at end of file Index: test/experimental/any/any.class/any.observers/type.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.class/any.observers/type.pass.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// any::type() noexcept + +#include +#include +#include "../../small_type.hpp" +#include "../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + { + any const a; + assert(a.type() == typeid(void)); + static_assert(noexcept(a.type()), "any::type() must be noexcept"); + } + { + small s(1); + any const a(s); + assert(a.type() == typeid(small)); + + } + { + large l(1); + any const a(l); + assert(a.type() == typeid(large)); + } +#endif +} \ No newline at end of file Index: test/experimental/any/any.nonmembers/any.cast/any.cast.nothrow/bad_type.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.nonmembers/any.cast/any.cast.nothrow/bad_type.pass.cpp @@ -0,0 +1,242 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// ValueType const* any_cast(any const *) noexcept; +// +// template +// ValueType * any_cast(any *) noexcept; + +// Test casting to a bad type. + +#include +#include +#include "../../../small_type.hpp" +#include "../../../large_type.hpp" + +#if _LIBCPP_STD_VER > 11 +using std::experimental::any; +using std::experimental::any_cast; + +void non_const_test() +{ + small const s(42); + { + any a(s); + using T = void; + using Expect = void*; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + Ret ret = any_cast(&a); + assert(ret == nullptr); + + small const* obj = any_cast(&a); + assert(obj); + assert(*obj == s); + } + { + any a(s); + using T = void const; + using Expect = void const*; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + Ret ret = any_cast(&a); + assert(ret == nullptr); + + small const* obj = any_cast(&a); + assert(obj); + assert(*obj == s); + } + { + any a(s); + using T = int; + using Expect = int*; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + Ret ret = any_cast(&a); + assert(ret == nullptr); + + small const* obj = any_cast(&a); + assert(obj); + assert(*obj == s); + } + { + any a(s); + using T = int const; + using Expect = int const*; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + Ret ret = any_cast(&a); + assert(ret == nullptr); + + small const* obj = any_cast(&a); + assert(obj); + assert(*obj == s); + } + { + any a(s); + using T = large; + using Expect = large*; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + Ret ret = any_cast(&a); + assert(ret == nullptr); + + small const* obj = any_cast(&a); + assert(obj); + assert(*obj == s); + } + { + any a(s); + using T = large const; + using Expect = large const*; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + Ret ret = any_cast(&a); + assert(ret == nullptr); + + small const* obj = any_cast(&a); + assert(obj); + assert(*obj == s); + } +} + +void const_test() +{ + small const s(42); + { + any const a(s); + using T = void; + using Expect = void const*; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + Ret ret = any_cast(&a); + assert(ret == nullptr); + + small const* obj = any_cast(&a); + assert(obj); + assert(*obj == s); + } + { + any const a(s); + using T = void const; + using Expect = void const*; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + Ret ret = any_cast(&a); + assert(ret == nullptr); + + small const* obj = any_cast(&a); + assert(obj); + assert(*obj == s); + } + { + any const a(s); + using T = int; + using Expect = int const*; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + Ret ret = any_cast(&a); + assert(ret == nullptr); + + small const* obj = any_cast(&a); + assert(obj); + assert(*obj == s); + } + { + any const a(s); + using T = int const; + using Expect = int const*; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + Ret ret = any_cast(&a); + assert(ret == nullptr); + + small const* obj = any_cast(&a); + assert(obj); + assert(*obj == s); + } + { + any const a(s); + using T = large; + using Expect = large const*; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + Ret ret = any_cast(&a); + assert(ret == nullptr); + + small const* obj = any_cast(&a); + assert(obj); + assert(*obj == s); + } + { + any const a(s); + using T = large const; + using Expect = large const*; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + Ret ret = any_cast(&a); + assert(ret == nullptr); + + small const* obj = any_cast(&a); + assert(obj); + assert(*obj == s); + } +} + +int main() +{ + non_const_test(); + const_test(); +} + +#else /* _LIBCPP_STD_VER <= 11 */ +int main() +{ + +} +#endif /* _LIBCPP_STD_VER > 11 */ \ No newline at end of file Index: test/experimental/any/any.nonmembers/any.cast/any.cast.nothrow/empty.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.nonmembers/any.cast/any.cast.nothrow/empty.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// ValueType const* any_cast(any const *) noexcept; +// +// template +// ValueType * any_cast(any *) noexcept; + +// Test casting an empty object. + +#include +#include + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + { + any a; + assert(nullptr == any_cast(&a)); + assert(nullptr == any_cast(&a)); + } + { + any const a; + assert(nullptr == any_cast(&a)); + } + +#endif +} \ No newline at end of file Index: test/experimental/any/any.nonmembers/any.cast/any.cast.nothrow/large_value.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.nonmembers/any.cast/any.cast.nothrow/large_value.pass.cpp @@ -0,0 +1,164 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// ValueType const* any_cast(any const *) noexcept; +// +// template +// ValueType * any_cast(any *) noexcept; + +// Test casting an any object storing a "large" value. + +#include +#include +#include +#include "../../../large_type.hpp" + + +#if _LIBCPP_STD_VER > 11 + +using std::experimental::any; +using std::experimental::any_cast; + +void non_const_test() +{ + large const s(42); + + // const large + { + any a(s); + using T = large const; + using Expect = large const*; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + + Expect ptr1 = any_cast(&a); + assert(ptr1); + assert(*ptr1 == s); + + Expect ptr2 = any_cast(&a); + assert(ptr1 == ptr2); + } + // non-const large + { + any a(s); + using T = large; + using Expect = large*; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + + Expect ptr1 = any_cast(&a); + assert(ptr1); + assert(*ptr1 == s); + + Expect ptr2 = any_cast(&a); + assert(ptr1 == ptr2); + + ptr1->value = 12; + assert(ptr2->value == 12); + } + { + any a(s); + using T = large const &; + using Expect = large const *; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + + Expect ptr1 = any_cast(&a); + assert(ptr1); + assert(*ptr1 == s); + + Expect ptr2 = any_cast(&a); + assert(ptr1 == ptr2); + } + { + any a(s); + using T = large &; + using Expect = large *; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + + Expect ptr1 = any_cast(&a); + assert(ptr1); + assert(*ptr1 == s); + + Expect ptr2 = any_cast(&a); + assert(ptr1 == ptr2); + + ptr1->value = 12; + assert(ptr2->value == 12); + } +} + +void const_test() +{ + large const s(42); + + // const large + { + any const a(s); + using T = large const; + using Expect = large const*; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + + Expect ptr1 = any_cast(&a); + assert(ptr1); + assert(*ptr1 == s); + + Expect ptr2 = any_cast(&a); + assert(ptr1 == ptr2); + } + // const reference + { + any const a(s); + using T = large const &; + using Expect = large const *; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + + Expect ptr1 = any_cast(&a); + assert(ptr1); + assert(*ptr1 == s); + + Expect ptr2 = any_cast(&a); + assert(ptr1 == ptr2); + } +} + +int main() +{ + non_const_test(); + const_test(); +} +# else /* _LIBCPP_STD_VER <= 11 */ +int main() +{ +} +#endif /* _LIBCPP_STD_VER > 11 */ \ No newline at end of file Index: test/experimental/any/any.nonmembers/any.cast/any.cast.nothrow/noexcept.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.nonmembers/any.cast/any.cast.nothrow/noexcept.pass.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// ValueType const* any_cast(any const *) noexcept; +// +// template +// ValueType * any_cast(any *) noexcept; + +#include + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + { + any a; + static_assert( + noexcept(any_cast(&a)) + , "any_cast(any*) must be noexcept" + ); + } + { + any const a; + static_assert( + noexcept(any_cast(&a)) + , "any_cast(any const *) must be noexcept" + ); + } + +#endif +} \ No newline at end of file Index: test/experimental/any/any.nonmembers/any.cast/any.cast.nothrow/nullptr.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.nonmembers/any.cast/any.cast.nothrow/nullptr.pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// ValueType const* any_cast(any const *) noexcept; +// +// template +// ValueType * any_cast(any *) noexcept; + +#include +#include +#include "../../../small_type.hpp" +#include "../../../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + + assert(nullptr == any_cast(static_cast(nullptr))); + assert(nullptr == any_cast(static_cast(nullptr))); + assert(nullptr == any_cast(static_cast(nullptr))); +#endif +} \ No newline at end of file Index: test/experimental/any/any.nonmembers/any.cast/any.cast.nothrow/small_value.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.nonmembers/any.cast/any.cast.nothrow/small_value.pass.cpp @@ -0,0 +1,163 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// ValueType const* any_cast(any const *) noexcept; +// +// template +// ValueType * any_cast(any *) noexcept; + +// Test casting an any object storing a "small" value. + +#include +#include +#include +#include "../../../small_type.hpp" + + +#if _LIBCPP_STD_VER > 11 + +using std::experimental::any; +using std::experimental::any_cast; +using namespace std; +void non_const_test() +{ + small const s(42); + + // const small + { + any a(s); + using T = small const; + using Expect = small const*; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + + Expect ptr1 = any_cast(&a); + assert(ptr1); + assert(*ptr1 == s); + + Expect ptr2 = any_cast(&a); + assert(ptr1 == ptr2); + } + // non-const small + { + any a(s); + using T = small; + using Expect = small*; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + + Expect ptr1 = any_cast(&a); + assert(ptr1); + assert(*ptr1 == s); + + Expect ptr2 = any_cast(&a); + assert(ptr1 == ptr2); + + ptr1->value = 12; + assert(ptr2->value == 12); + } + { + any a(s); + using T = small const &; + using Expect = small const *; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + + Expect ptr1 = any_cast(&a); + assert(ptr1); + assert(*ptr1 == s); + + Expect ptr2 = any_cast(&a); + assert(ptr1 == ptr2); + } + { + any a(s); + using T = small &; + using Expect = small *; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + + Expect ptr1 = any_cast(&a); + assert(ptr1); + assert(*ptr1 == s); + + Expect ptr2 = any_cast(&a); + assert(ptr1 == ptr2); + + ptr1->value = 12; + assert(ptr2->value == 12); + } +} + +void const_test() +{ + small const s(42); + any const a(s); + // const small + { + using T = small const; + using Expect = small const*; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + + Expect ptr1 = any_cast(&a); + assert(ptr1); + assert(*ptr1 == s); + + Expect ptr2 = any_cast(&a); + assert(ptr1 == ptr2); + } + // const reference + { + any a(s); + using T = small const &; + using Expect = small const *; + using Ret = decltype(any_cast(&a)); + static_assert( + std::is_same::value + , "Expected return type does not match actual return type" + ); + + Expect ptr1 = any_cast(&a); + assert(ptr1); + assert(*ptr1 == s); + + Expect ptr2 = any_cast(&a); + assert(ptr1 == ptr2); + } +} + +int main() +{ + non_const_test(); + const_test(); +} +# else /* _LIBCPP_STD_VER <= 11 */ +int main() +{ +} +#endif /* _LIBCPP_STD_VER > 11 */ \ No newline at end of file Index: test/experimental/any/any.nonmembers/any.cast/any.cast.throws/const_lvalue_cast_const_correctness.fail.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.nonmembers/any.cast/any.cast.throws/const_lvalue_cast_const_correctness.fail.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// ValueType any_cast(any const &); + +// Try and cast away const. + +#include + +struct dummy_t {}; + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + using std::experimental::bad_any_cast; + + any const a(dummy_t{}); + any_cast(a); +#else +# error +#endif +} \ No newline at end of file Index: test/experimental/any/any.nonmembers/any.cast/any.cast.throws/const_lvalue_cast_not_copy_constructible.fail.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.nonmembers/any.cast/any.cast.throws/const_lvalue_cast_not_copy_constructible.fail.cpp @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// ValueType any_cast(any const &); + +// Test instantiating the const lvalue any cast with a non-copyable type. + + +#include + +struct no_copy +{ + no_copy() {} + no_copy(no_copy &&) {} + +private: + no_copy(no_copy const &); +}; + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + using std::experimental::bad_any_cast; + + any const a; + any_cast(a); +#else +# error +#endif +} \ No newline at end of file Index: test/experimental/any/any.nonmembers/any.cast/any.cast.throws/empty.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.nonmembers/any.cast/any.cast.throws/empty.pass.cpp @@ -0,0 +1,79 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// ValueType any_cast(any const &); +// +// template +// ValueType any_cast(any &); +// +// template +// ValueType any_cast(any &&); + +// Test casting an empty object. + +#include +#include +#include "../../../count_new.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + using std::experimental::bad_any_cast; + + // const lvalue + { + any const a; + try { + any_cast(a); + assert(false); + } catch (bad_any_cast const &) { + // do nothing + } catch (...) { + assert(false); + } + + assert(a.empty()); + assert(a.type() == typeid(void)); + } + // non-const lvalue + { + any a; + try { + any_cast(a); + assert(false); + } catch (bad_any_cast const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(a.empty()); + assert(a.type() == typeid(void)); + } + // rvalue + { + any a; + try { + any_cast(static_cast(a)); + assert(false); + } catch (bad_any_cast const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(a.empty()); + assert(a.type() == typeid(void)); + } + assert(total_new == 0); +#endif +} \ No newline at end of file Index: test/experimental/any/any.nonmembers/any.cast/any.cast.throws/large.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.nonmembers/any.cast/any.cast.throws/large.pass.cpp @@ -0,0 +1,332 @@ +////===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// ValueType any_cast(any const &); +// +// template +// ValueType any_cast(any &); +// +// template +// ValueType any_cast(any &&); + +// Test casting an any instance storing a "large" object. + +#include +#include +#include +#include "../../../count_new.hpp" +#include "../../../large_type.hpp" +#include "../../../small_type.hpp" + +#if _LIBCPP_STD_VER > 11 + +void const_lvalue_test() +{ + using std::experimental::any; + using std::experimental::any_cast; + using std::experimental::bad_any_cast; + { + large const s(42); + any const a((s)); + assert(large::count == 2); + assert(new_called == 1); + // no qualifiers + { + using T = large; + using Expect = large; + using Ret = decltype(any_cast(a)); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + large cp = any_cast(a); + assert(new_called == 1); + assert(large::count == 3); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + } + assert(new_called ==1); + assert(large::count == 2); + // const qualifiers + { + using T = large const; + using Expect = large const; + using Ret = decltype(any_cast(a)); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + large cp = any_cast(a); + assert(new_called == 1); + assert(large::count == 3); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + } + assert(new_called == 1); + assert(large::count == 2); + // const reference qualifiers + { + using T = large const &; + using Expect = large const &; + using Ret = decltype(any_cast(a)); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + large const & cp = any_cast(a); + assert(new_called == 1); + assert(large::count == 2); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + + large const & cp2 = any_cast(a); + assert(new_called == 1); + assert(large::count == 2); + assert(cp2 == s); + assert(&cp2 == &cp); + } + assert(new_called == 1); + assert(large::count == 2); + } + assert(new_called == 0); + assert(large::count == 0); +} + +void lvalue_test() +{ + using std::experimental::any; + using std::experimental::any_cast; + using std::experimental::bad_any_cast; + large const s(42); + assert(large::count == 1); + // no qualifiers + { + any a((s)); + assert(new_called == 1); + assert(large::count == 2); + using T = large; + using Expect = large; + using Ret = decltype(any_cast(a)); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + large cp = any_cast(a); + assert(new_called == 1); + assert(large::count == 3); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + } + assert(new_called == 0); + assert(large::count == 1); + // const qualifiers + { + any a((s)); + assert(new_called == 1); + assert(large::count == 2); + using T = large const; + using Expect = large const; + using Ret = decltype(any_cast(a)); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + large cp = any_cast(a); + assert(new_called == 1); + assert(large::count == 3); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + } + assert(new_called == 0); + assert(large::count == 1); + // const reference qualifiers + { + any a((s)); + assert(new_called == 1); + assert(large::count == 2); + using T = large const &; + using Expect = large const &; + using Ret = decltype(any_cast(a)); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + large const & cp = any_cast(a); + assert(new_called == 1); + assert(large::count == 2); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + + large const & cp2 = any_cast(a); + assert(new_called == 1); + assert(large::count == 2); + assert(cp2 == s); + assert(&cp2 == &cp); + } + assert(new_called == 0); + assert(large::count == 1); + // lvalue reference qualifiers + { + any a((s)); + assert(new_called == 1); + assert(large::count == 2); + using T = large &; + using Expect = large &; + using Ret = decltype(any_cast(a)); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + large & cp = any_cast(a); + assert(new_called == 1); + assert(large::count == 2); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + + large & cp2 = any_cast(a); + assert(new_called == 1); + assert(large::count == 2); + assert(cp2 == s); + assert(&cp2 == &cp); + + cp.value = 10; + assert(cp2.value == 10); + } + assert(new_called == 0); + assert(large::count == 1); +} + +void rvalue_test() +{ + using std::experimental::any; + using std::experimental::any_cast; + using std::experimental::bad_any_cast; + large const s(42); + assert(new_called == 0); + assert(large::count == 1); + // no qualifiers + { + any a((s)); + assert(new_called == 1); + assert(large::count == 2); + using T = large; + using Expect = large; + using Ret = decltype(any_cast(std::move(a))); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + large cp = any_cast(std::move(a)); + assert(new_called == 1); + assert(large::count == 3); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + } + assert(new_called == 0); + assert(large::count == 1); + // const qualifiers + { + any a((s)); + assert(new_called == 1); + assert(large::count == 2); + using T = large const; + using Expect = large const; + using Ret = decltype(any_cast(std::move(a))); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + large cp = any_cast(std::move(a)); + assert(new_called == 1); + assert(large::count == 3); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + } + assert(new_called == 0); + assert(large::count == 1); + // const reference qualifiers + { + any a((s)); + assert(new_called == 1); + assert(large::count == 2); + using T = large const &; + using Expect = large const &; + using Ret = decltype(any_cast(std::move(a))); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + large const & cp = any_cast(std::move(a)); + assert(new_called == 1); + assert(large::count == 2); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + + large const & cp2 = any_cast(std::move(a)); + assert(new_called == 1); + assert(large::count == 2); + assert(cp2 == s); + assert(&cp2 == &cp); + } + assert(new_called == 0); + assert(large::count == 1); + // lvalue reference qualifiers + { + any a((s)); + assert(new_called == 1); + assert(large::count == 2); + using T = large &; + using Expect = large &; + using Ret = decltype(any_cast(std::move(a))); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + large & cp = any_cast(std::move(a)); + assert(new_called == 1); + assert(large::count == 2); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(large)); + + large & cp2 = any_cast(std::move(a)); + assert(new_called == 1); + assert(large::count == 2); + assert(cp2 == s); + assert(&cp2 == &cp); + + cp.value = 10; + assert(cp2.value == 10); + } + assert(new_called == 0); + assert(large::count == 1); +} + +int main() +{ + const_lvalue_test(); + lvalue_test(); + rvalue_test(); +} +#else /* _LIBCPP_STD_VER <= 11 */ +int main() {} +#endif /* _LIBCPP_STD_VER > 11 */ Index: test/experimental/any/any.nonmembers/any.cast/any.cast.throws/lvalue_cast_not_copy_constructible.fail.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.nonmembers/any.cast/any.cast.throws/lvalue_cast_not_copy_constructible.fail.cpp @@ -0,0 +1,40 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// ValueType any_cast(any &); + +// Test instantiating the lvalue any_cast with a non-copyable type. + +#include + +struct no_copy +{ + no_copy() {} + no_copy(no_copy &&) {} + +private: + no_copy(no_copy const &); +}; + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + using std::experimental::bad_any_cast; + + any a; + any_cast(a); +#else + int arr[-1]; +#endif +} \ No newline at end of file Index: test/experimental/any/any.nonmembers/any.cast/any.cast.throws/non_copy_ref.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.nonmembers/any.cast/any.cast.throws/non_copy_ref.pass.cpp @@ -0,0 +1,85 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// ValueType any_cast(any const &); +// +// template +// ValueType any_cast(any &); +// +// template +// ValueType any_cast(any &&); + + +#include +#include + +struct no_copy +{ + no_copy() {} + no_copy(no_copy &&) {} + +private: + no_copy(no_copy const &); +}; + +// Even though you can't get a non-copyable class into std::any +// the standard requires that these overloads compile and function. +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + using std::experimental::bad_any_cast; + // const lvalue + { + any const a; + try { + any_cast(a); + assert(false); + } catch (bad_any_cast const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(a.empty()); + assert(a.type() == typeid(void)); + } + // lvalue + { + any a; + try { + any_cast(a); + assert(false); + } catch (bad_any_cast const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(a.empty()); + assert(a.type() == typeid(void)); + } + // rvalue + { + any a; + try { + any_cast(static_cast(a)); + assert(false); + } catch (bad_any_cast const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(a.empty()); + assert(a.type() == typeid(void)); + } +#endif +} \ No newline at end of file Index: test/experimental/any/any.nonmembers/any.cast/any.cast.throws/rvalue_cast_not_copy_constructible.fail.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.nonmembers/any.cast/any.cast.throws/rvalue_cast_not_copy_constructible.fail.cpp @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// ValueType any_cast(any &&); + +// Instantiate the rvalue any cast with a non-copyable type. + + +#include +#include + +struct no_copy +{ + no_copy() {} + no_copy(no_copy &&) {} + +private: + no_copy(no_copy const &); +}; + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + using std::experimental::bad_any_cast; + + any a; + any_cast(std::move(a)); +#else +# error +#endif +} \ No newline at end of file Index: test/experimental/any/any.nonmembers/any.cast/any.cast.throws/small.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.nonmembers/any.cast/any.cast.throws/small.pass.cpp @@ -0,0 +1,294 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// template +// ValueType any_cast(any const &); +// +// template +// ValueType any_cast(any &); +// +// template +// ValueType any_cast(any &&); + +// Test casting an any instance storing a "small" object. + + +#include +#include +#include +#include "../../../count_new.hpp" +#include "../../../small_type.hpp" +#include "../../../large_type.hpp" + +#if _LIBCPP_STD_VER > 11 + +void const_lvalue_test() +{ + using std::experimental::any; + using std::experimental::any_cast; + using std::experimental::bad_any_cast; + small const s(42); + any const a((s)); + assert(small::count == 2); + // no qualifiers + { + using T = small; + using Expect = small; + using Ret = decltype(any_cast(a)); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + small cp = any_cast(a); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(small::count == 3); + } + assert(small::count == 2); + // const qualifiers + { + using T = small const; + using Expect = small const; + using Ret = decltype(any_cast(a)); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + small cp = any_cast(a); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(small::count == 3); + } + assert(small::count == 2); + // const reference qualifiers + { + using T = small const &; + using Expect = small const &; + using Ret = decltype(any_cast(a)); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + small const & cp = any_cast(a); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(small::count == 2); + + small const & cp2 = any_cast(a); + assert(cp2 == s); + assert(&cp2 == &cp); + assert(small::count == 2); + } + assert(small::count == 2); + assert(total_new == 0); +} + +void lvalue_test() +{ + using std::experimental::any; + using std::experimental::any_cast; + using std::experimental::bad_any_cast; + small const s(42); + // no qualifiers + { + any a((s)); + assert(small::count == 2); + using T = small; + using Expect = small; + using Ret = decltype(any_cast(a)); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + small cp = any_cast(a); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(small::count == 3); + } + assert(small::count == 1); + // const qualifiers + { + any a((s)); + assert(small::count == 2); + using T = small const; + using Expect = small const; + using Ret = decltype(any_cast(a)); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + small cp = any_cast(a); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(small::count == 3); + } + assert(small::count == 1); + // const reference qualifiers + { + any a((s)); + assert(small::count == 2); + using T = small const &; + using Expect = small const &; + using Ret = decltype(any_cast(a)); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + small const & cp = any_cast(a); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(small::count == 2); + + small const & cp2 = any_cast(a); + assert(cp2 == s); + assert(&cp2 == &cp); + assert(small::count == 2); + } + assert(small::count == 1); + // lvalue reference qualifiers + { + any a((s)); + assert(small::count == 2); + using T = small &; + using Expect = small &; + using Ret = decltype(any_cast(a)); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + small & cp = any_cast(a); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(small::count == 2); + + small & cp2 = any_cast(a); + assert(cp2 == s); + assert(&cp2 == &cp); + assert(small::count == 2); + + cp.value = 10; + assert(cp2.value == 10); + } + assert(small::count == 1); + assert(total_new == 0); +} + +void rvalue_test() +{ + using std::experimental::any; + using std::experimental::any_cast; + using std::experimental::bad_any_cast; + small const s(42); + assert(small::count == 1); + // no qualifiers + { + any a((s)); + assert(small::count == 2); + using T = small; + using Expect = small; + using Ret = decltype(any_cast(std::move(a))); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + small cp = any_cast(std::move(a)); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(small::count == 3); + } + assert(small::count == 1); + // const qualifiers + { + any a((s)); + assert(small::count == 2); + using T = small const; + using Expect = small const; + using Ret = decltype(any_cast(std::move(a))); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + small cp = any_cast(std::move(a)); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(small::count == 3); + } + assert(small::count == 1); + // const reference qualifiers + { + any a((s)); + assert(small::count == 2); + using T = small const &; + using Expect = small const &; + using Ret = decltype(any_cast(std::move(a))); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + small const & cp = any_cast(std::move(a)); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(small::count == 2); + + small const & cp2 = any_cast(std::move(a)); + assert(cp2 == s); + assert(&cp2 == &cp); + assert(small::count == 2); + } + assert(small::count == 1); + // lvalue reference qualifiers + { + any a((s)); + assert(small::count == 2); + using T = small &; + using Expect = small &; + using Ret = decltype(any_cast(std::move(a))); + static_assert( + std::is_same::value + , "Return type unexpected" + ); + small & cp = any_cast(std::move(a)); + assert(cp == s); + assert(!a.empty()); + assert(a.type() == typeid(small)); + assert(small::count == 2); + + small & cp2 = any_cast(std::move(a)); + assert(cp2 == s); + assert(&cp2 == &cp); + assert(small::count == 2); + + cp.value = 10; + assert(cp2.value == 10); + } + assert(small::count == 1); + assert(total_new == 0); +} + +int main() +{ + const_lvalue_test(); + lvalue_test(); + rvalue_test(); +} +# else /* _LIBCPP_STD_VER <= 11 */ +int main() {} +#endif /* _LIBCPP_STD_VER > 11 */ Index: test/experimental/any/any.nonmembers/any.cast/nothing_to_do.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.nonmembers/any.cast/nothing_to_do.pass.cpp @@ -0,0 +1,12 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +int main() +{ +} Index: test/experimental/any/any.nonmembers/swap.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/any.nonmembers/swap.pass.cpp @@ -0,0 +1,66 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +// void swap(any &, any &) noexcept + +// swap(...) just wraps any::swap(...). That function is tested elsewhere. + +#include +#include +#include "../count_new.hpp" +#include "../small_type.hpp" +#include "../large_type.hpp" + +int main() +{ +#if _LIBCPP_STD_VER > 11 + using std::experimental::any; + using std::experimental::any_cast; + { + small const s(1); + any a1(s); + assert(!a1.empty()); + assert(a1.type() == typeid(small)); + assert(any_cast(a1) == s); + assert(small::count == 2); + assert(new_called == 0); + + large const l(2); + any a2(l); + assert(!a2.empty()); + assert(a2.type() == typeid(large)); + assert(large::count == 2); + assert(new_called == 1); + + static_assert( + noexcept(swap(a1, a2)) + , "swap(any&, any&) must be noexcept" + ); + + swap(a1, a2); + + assert(!a1.empty()); + assert(a1.type() == typeid(large)); + assert(any_cast(a1) == l); + assert(large::count == 2); + + assert(!a2.empty()); + assert(a2.type() == typeid(small)); + assert(any_cast(a2) == s); + assert(small::count == 2); + + assert(new_called == 1); + } + assert(small::count == 0); + assert(large::count == 0); + assert(new_called == 0); +#endif // _LIBCPP_STD_VER > 11 +} \ No newline at end of file Index: test/experimental/any/count_new.hpp =================================================================== --- /dev/null +++ test/experimental/any/count_new.hpp @@ -0,0 +1,25 @@ +#ifndef COUNT_NEW_HPP +#define COUNT_NEW_HPP + +# include +# include + +int new_called = 0; +int total_new = 0; +int delete_called = 0; + +void* operator new(std::size_t s) throw(std::bad_alloc) +{ + ++new_called; + ++total_new; + return std::malloc(s); +} + +void operator delete(void* p) throw() +{ + ++delete_called; + --new_called; + std::free(p); +} + +#endif /* COUNT_NEW_HPP */ Index: test/experimental/any/large_type.hpp =================================================================== --- /dev/null +++ test/experimental/any/large_type.hpp @@ -0,0 +1,74 @@ +#ifndef LARGE_TYPE_HPP +#define LARGE_TYPE_HPP + +template +struct large_type +{ + static int count; + static int copied; + static int moved; + + static void reset() { + large_type::copied = 0; + large_type::moved = 0; + } + + char value; + + large_type(char val) : value(val) + { + ++count; + data[0] = 0; + } + + large_type(large_type const & other) + { + value = other.value; + ++count; + ++copied; + } + + large_type(large_type && other) + { + value = other.value; + other.value = 0; + ++count; + ++moved; + } + + ~large_type() + { + value = 0; + --count; + } +private: + int data[10]; +}; + +template +int large_type::count = 0; + +template +int large_type::copied = 0; + +template +int large_type::moved = 0; + + +template +inline bool operator==(large_type const & lhs, large_type const & rhs) +{ + return lhs.value == rhs.value; +} + +template +inline bool operator!=(large_type const & lhs, large_type const & rhs) +{ + return lhs.value != rhs.value; +} + +typedef large_type<> large; +typedef large_type<1> large1; +typedef large_type<2> large2; + +#endif /* LARGE_TYPE_HPP */ Index: test/experimental/any/small_type.hpp =================================================================== --- /dev/null +++ test/experimental/any/small_type.hpp @@ -0,0 +1,71 @@ +#ifndef SMALL_TYPE_HPP +#define SMALL_TYPE_HPP + +template +struct small_type +{ + static int count; + static int copied; + static int moved; + + static void reset() { + small_type::copied = 0; + small_type::moved = 0; + } + + char value; + + small_type(char val) + : value(val) + { + ++count; + } + + small_type(small_type const & other) throw() + { + value = other.value; + ++count; + ++copied; + } + + small_type(small_type && other) throw() + { + value = other.value; + other.value = 0; + ++count; + ++moved; + } + + ~small_type() + { + value = 0; + --count; + } +}; + +template +int small_type::count = 0; + +template +int small_type::copied = 0; + +template +int small_type::moved = 0; + +template +inline bool operator==(small_type const & lhs, small_type const & rhs) +{ + return lhs.value == rhs.value; +} + +template +inline bool operator!=(small_type const & lhs, small_type const & rhs) +{ + return lhs.value != rhs.value; +} + +typedef small_type<> small; +typedef small_type<1> small1; +typedef small_type<2> small2; + +#endif /* SMALL_TYPE_HPP */ Index: test/experimental/any/version.pass.cpp =================================================================== --- /dev/null +++ test/experimental/any/version.pass.cpp @@ -0,0 +1,26 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// + +#include + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +#if _LIBCPP_STD_VER > 11 +# ifndef __cpp_lib_experimental_any +# error "__cpp_lib_experimental_any should be defined in C++1y" +# endif +#endif + +int main() +{ +} Index: www/ts1z_status.html =================================================================== --- www/ts1z_status.html +++ www/ts1z_status.html @@ -68,7 +68,7 @@ SearchersNot started Optional ObjectsInitial implementation complete - class anyNot started + class anyImplementation in progress string_viewImplementation in progress memoryNot started Algorithms libraryNot started