diff options
Diffstat (limited to 'libcxx/test')
26 files changed, 2260 insertions, 0 deletions
diff --git a/libcxx/test/libcxx/experimental/any/size_and_alignment.pass.cpp b/libcxx/test/libcxx/experimental/any/size_and_alignment.pass.cpp new file mode 100644 index 00000000000..b7db5402047 --- /dev/null +++ b/libcxx/test/libcxx/experimental/any/size_and_alignment.pass.cpp @@ -0,0 +1,23 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// Check that the size and alignment of any are what we expect. + +#include <experimental/any> + +int main() +{ + using std::experimental::any; + static_assert(sizeof(any) == sizeof(void*)*4, ""); + static_assert(alignof(any) == alignof(void*), ""); +} diff --git a/libcxx/test/libcxx/experimental/any/small_type.pass.cpp b/libcxx/test/libcxx/experimental/any/small_type.pass.cpp new file mode 100644 index 00000000000..bcd15f181fd --- /dev/null +++ b/libcxx/test/libcxx/experimental/any/small_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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// Check that the size and alignment of any are what we expect. + +#include <experimental/any> +#include "any_helpers.h" + +class SmallThrowsDtor +{ +public: + SmallThrowsDtor() {} + SmallThrowsDtor(SmallThrowsDtor const &) noexcept {} + SmallThrowsDtor(SmallThrowsDtor &&) noexcept {} + ~SmallThrowsDtor() noexcept(false) {} +}; + +int main() +{ + using std::experimental::any; + using std::experimental::__any_imp::_IsSmallObject; + static_assert(_IsSmallObject<small>::value, ""); + static_assert(_IsSmallObject<void*>::value, ""); + static_assert(!_IsSmallObject<SmallThrowsDtor>::value, ""); + static_assert(!_IsSmallObject<large>::value, ""); + // long double is over aligned. + static_assert(sizeof(long double) <= sizeof(void*) * 3, ""); + static_assert(alignof(long double) > alignof(void*), ""); + static_assert(!_IsSmallObject<long double>::value, ""); +} diff --git a/libcxx/test/libcxx/experimental/any/version.pass.cpp b/libcxx/test/libcxx/experimental/any/version.pass.cpp new file mode 100644 index 00000000000..611d65027b1 --- /dev/null +++ b/libcxx/test/libcxx/experimental/any/version.pass.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <experimental/any> + +#include <experimental/any> + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ +} diff --git a/libcxx/test/std/experimental/any/any.class/any.assign/copy.pass.cpp b/libcxx/test/std/experimental/any/any.class/any.assign/copy.pass.cpp new file mode 100644 index 00000000000..8ee575c408f --- /dev/null +++ b/libcxx/test/std/experimental/any/any.class/any.assign/copy.pass.cpp @@ -0,0 +1,197 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// any& operator=(any const &); + +// Test copy assignment + +#include <experimental/any> +#include <cassert> + +#include "any_helpers.h" +#include "count_new.hpp" +#include "test_macros.h" + +using std::experimental::any; +using std::experimental::any_cast; + +template <class LHS, class RHS> +void test_copy_assign() { + assert(LHS::count == 0); + assert(RHS::count == 0); + LHS::reset(); + RHS::reset(); + { + any lhs(LHS(1)); + any const rhs(RHS(2)); + + assert(LHS::count == 1); + assert(RHS::count == 1); + assert(RHS::copied == 0); + + lhs = rhs; + + assert(RHS::copied == 1); + assert(LHS::count == 0); + assert(RHS::count == 2); + + assertContains<RHS>(lhs, 2); + assertContains<RHS>(rhs, 2); + } + assert(LHS::count == 0); + assert(RHS::count == 0); +} + +template <class LHS> +void test_copy_assign_empty() { + assert(LHS::count == 0); + LHS::reset(); + { + any lhs; + any const rhs(LHS(42)); + + assert(LHS::count == 1); + assert(LHS::copied == 0); + + lhs = rhs; + + assert(LHS::copied == 1); + assert(LHS::count == 2); + + assertContains<LHS>(lhs, 42); + assertContains<LHS>(rhs, 42); + } + assert(LHS::count == 0); + LHS::reset(); + { + any lhs(LHS(1)); + any const rhs; + + assert(LHS::count == 1); + assert(LHS::copied == 0); + + lhs = rhs; + + assert(LHS::copied == 0); + assert(LHS::count == 0); + + assertEmpty<LHS>(lhs); + assertEmpty(rhs); + } + assert(LHS::count == 0); +} + +void test_copy_assign_self() { + // empty + { + any a; + a = a; + assertEmpty(a); + assert(globalMemCounter.checkOutstandingNewEq(0)); + } + assert(globalMemCounter.checkOutstandingNewEq(0)); + // small + { + any a((small(1))); + assert(small::count == 1); + + a = a; + + assert(small::count == 1); + assertContains<small>(a, 1); + assert(globalMemCounter.checkOutstandingNewEq(0)); + } + assert(small::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); + // large + { + any a(large(1)); + assert(large::count == 1); + + a = a; + + assert(large::count == 1); + assertContains<large>(a, 1); + assert(globalMemCounter.checkOutstandingNewEq(1)); + } + assert(large::count == 0); + assert(globalMemCounter.checkOutstandingNewEq(0)); +} + +template <class Tp> +void test_copy_assign_throws() +{ +#if !defined(TEST_HAS_NO_EXCEPTIONS) + auto try_throw = + [](any& lhs, any const& rhs) { + try { + lhs = rhs; + assert(false); + } catch (my_any_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + }; + // const lvalue to empty + { + any lhs; + any const rhs((Tp(1))); + assert(Tp::count == 1); + + try_throw(lhs, rhs); + + assert(Tp::count == 1); + assertEmpty<Tp>(lhs); + assertContains<Tp>(rhs); + } + { + any lhs((small(2))); + any const rhs((Tp(1))); + assert(small::count == 1); + assert(Tp::count == 1); + + try_throw(lhs, rhs); + + assert(small::count == 1); + assert(Tp::count == 1); + assertContains<small>(lhs, 2); + assertContains<Tp>(rhs); + } + { + any lhs((large(2))); + any const rhs((Tp(1))); + assert(large::count == 1); + assert(Tp::count == 1); + + try_throw(lhs, rhs); + + assert(large::count == 1); + assert(Tp::count == 1); + assertContains<large>(lhs, 2); + assertContains<Tp>(rhs); + } +#endif +} + +int main() { + test_copy_assign<small1, small2>(); + test_copy_assign<large1, large2>(); + test_copy_assign<small, large>(); + test_copy_assign<large, small>(); + test_copy_assign_empty<small>(); + test_copy_assign_empty<large>(); + test_copy_assign_self(); + test_copy_assign_throws<small_throws_on_copy>(); + test_copy_assign_throws<large_throws_on_copy>(); +} diff --git a/libcxx/test/std/experimental/any/any.class/any.assign/move.pass.cpp b/libcxx/test/std/experimental/any/any.class/any.assign/move.pass.cpp new file mode 100644 index 00000000000..0a2d71967cd --- /dev/null +++ b/libcxx/test/std/experimental/any/any.class/any.assign/move.pass.cpp @@ -0,0 +1,102 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// any& operator=(any &&); + +// Test move assignment. + +#include <experimental/any> +#include <cassert> + +#include "any_helpers.h" +#include "test_macros.h" + +using std::experimental::any; +using std::experimental::any_cast; + +template <class LHS, class RHS> +void test_move_assign() { + assert(LHS::count == 0); + assert(RHS::count == 0); + { + LHS const s1(1); + any a(s1); + RHS const s2(2); + any a2(s2); + + assert(LHS::count == 2); + assert(RHS::count == 2); + + a = std::move(a2); + + assert(LHS::count == 1); + assert(RHS::count == 2); + + assertContains<RHS>(a, 2); + assertEmpty<RHS>(a2); + } + assert(LHS::count == 0); + assert(RHS::count == 0); +} + +template <class LHS> +void test_move_assign_empty() { + assert(LHS::count == 0); + { + any a; + any a2((LHS(1))); + + assert(LHS::count == 1); + + a = std::move(a2); + + assert(LHS::count == 1); + + assertContains<LHS>(a, 1); + assertEmpty<LHS>(a2); + } + assert(LHS::count == 0); + { + any a((LHS(1))); + any a2; + + assert(LHS::count == 1); + + a = std::move(a2); + + assert(LHS::count == 0); + + assertEmpty<LHS>(a); + assertEmpty(a2); + } + assert(LHS::count == 0); +} + +void test_move_assign_noexcept() { + any a1; + any a2; + static_assert( + noexcept(a1 = std::move(a2)) + , "any & operator=(any &&) must be noexcept" + ); +} + +int main() { + test_move_assign_noexcept(); + test_move_assign<small1, small2>(); + test_move_assign<large1, large2>(); + test_move_assign<small, large>(); + test_move_assign<large, small>(); + test_move_assign_empty<small>(); + test_move_assign_empty<large>(); +} diff --git a/libcxx/test/std/experimental/any/any.class/any.assign/value.pass.cpp b/libcxx/test/std/experimental/any/any.class/any.assign/value.pass.cpp new file mode 100644 index 00000000000..8262990523c --- /dev/null +++ b/libcxx/test/std/experimental/any/any.class/any.assign/value.pass.cpp @@ -0,0 +1,177 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// any& operator=(any const &); + +// Test value copy and move assignment. + +#include <experimental/any> +#include <cassert> + +#include "any_helpers.h" +#include "count_new.hpp" +#include "test_macros.h" + +using std::experimental::any; +using std::experimental::any_cast; + +template <class LHS, class RHS> +void test_assign_value() { + assert(LHS::count == 0); + assert(RHS::count == 0); + LHS::reset(); + RHS::reset(); + { + any lhs(LHS(1)); + any const rhs(RHS(2)); + + assert(LHS::count == 1); + assert(RHS::count == 1); + assert(RHS::copied == 0); + + lhs = rhs; + + assert(RHS::copied == 1); + assert(LHS::count == 0); + assert(RHS::count == 2); + + assertContains<RHS>(lhs, 2); + assertContains<RHS>(rhs, 2); + } + assert(LHS::count == 0); + assert(RHS::count == 0); + LHS::reset(); + RHS::reset(); + { + any lhs(LHS(1)); + any rhs(RHS(2)); + + assert(LHS::count == 1); + assert(RHS::count == 1); + assert(RHS::moved == 1); + + lhs = std::move(rhs); + + assert(RHS::moved >= 1); + assert(RHS::copied == 0); + assert(LHS::count == 0); + assert(RHS::count == 1); + + assertContains<RHS>(lhs, 2); + assertEmpty<RHS>(rhs); + } + assert(LHS::count == 0); + assert(RHS::count == 0); +} + +template <class RHS> +void test_assign_value_empty() { + assert(RHS::count == 0); + RHS::reset(); + { + any lhs; + RHS rhs(42); + assert(RHS::count == 1); + assert(RHS::copied == 0); + + lhs = rhs; + + assert(RHS::count == 2); + assert(RHS::copied == 1); + assert(RHS::moved >= 0); + assertContains<RHS>(lhs, 42); + } + assert(RHS::count == 0); + RHS::reset(); + { + any lhs; + RHS rhs(42); + assert(RHS::count == 1); + assert(RHS::moved == 0); + + lhs = std::move(rhs); + + assert(RHS::count == 2); + assert(RHS::copied == 0); + assert(RHS::moved >= 1); + assertContains<RHS>(lhs, 42); + } + assert(RHS::count == 0); + RHS::reset(); +} + + +template <class Tp, bool Move = false> +void test_assign_throws() { +#if !defined(TEST_HAS_NO_EXCEPTIONS) + auto try_throw= + [](any& lhs, auto&& rhs) { + try { + Move ? lhs = std::move(rhs) + : lhs = rhs; + assert(false); + } catch (my_any_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + }; + // const lvalue to empty + { + any lhs; + Tp rhs(1); + assert(Tp::count == 1); + + try_throw(lhs, rhs); + + assert(Tp::count == 1); + assertEmpty<Tp>(lhs); + } + { + any lhs((small(2))); + Tp rhs(1); + assert(small::count == 1); + assert(Tp::count == 1); + + try_throw(lhs, rhs); + + assert(small::count == 1); + assert(Tp::count == 1); + assertContains<small>(lhs, 2); + } + { + any lhs((large(2))); + Tp rhs(1); + assert(large::count == 1); + assert(Tp::count == 1); + + try_throw(lhs, rhs); + + assert(large::count == 1); + assert(Tp::count == 1); + assertContains<large>(lhs, 2); + } +#endif +} + +int main() { + test_assign_value<small1, small2>(); + test_assign_value<large1, large2>(); + test_assign_value<small, large>(); + test_assign_value<large, small>(); + test_assign_value_empty<small>(); + test_assign_value_empty<large>(); + test_assign_throws<small_throws_on_copy>(); + test_assign_throws<large_throws_on_copy>(); + test_assign_throws<throws_on_move, /* Move = */ true>(); +}
\ No newline at end of file diff --git a/libcxx/test/std/experimental/any/any.class/any.assign/value_non_copyable_assign.fail.cpp b/libcxx/test/std/experimental/any/any.class/any.assign/value_non_copyable_assign.fail.cpp new file mode 100644 index 00000000000..ce0d44f32d9 --- /dev/null +++ b/libcxx/test/std/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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// template <class Value> +// any& operator=(Value &&); + +// Instantiate the value assignment operator with a non-copyable type. + +#include <experimental/any> + +class non_copyable +{ + non_copyable(non_copyable const &); + +public: + non_copyable() {} + non_copyable(non_copyable &&) {} +}; + +int main() +{ + using namespace std::experimental; + non_copyable nc; + any a; + a = static_cast<non_copyable &&>(nc); // expected-error@experimental/any:* 2 {{static_assert failed "_ValueType must be CopyConstructible."}} + // expected-error@experimental/any:* {{calling a private constructor of class 'non_copyable'}} + +} diff --git a/libcxx/test/std/experimental/any/any.class/any.cons/copy.pass.cpp b/libcxx/test/std/experimental/any/any.class/any.cons/copy.pass.cpp new file mode 100644 index 00000000000..3d0b34b2740 --- /dev/null +++ b/libcxx/test/std/experimental/any/any.class/any.cons/copy.pass.cpp @@ -0,0 +1,100 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// any(any const &); + +#include <experimental/any> +#include <cassert> + +#include "any_helpers.h" +#include "count_new.hpp" +#include "test_macros.h" + +using std::experimental::any; +using std::experimental::any_cast; + +template <class Type> +void test_copy_throws() { +#if !defined(TEST_HAS_NO_EXCEPTIONS) + assert(Type::count == 0); + { + any const a((Type(42))); + assert(Type::count == 1); + try { + any const a2(a); + assert(false); + } catch (my_any_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(Type::count == 1); + assertContains<Type>(a, 42); + } + assert(Type::count == 0); +#endif +} + +void test_copy_empty() { + DisableAllocationGuard g; ((void)g); // No allocations should occur. + any a1; + any a2(a1); + + assertEmpty(a1); + assertEmpty(a2); +} + +template <class Type> +void test_copy() +{ + // Copying small types should not perform any allocations. + DisableAllocationGuard g(isSmallType<Type>()); ((void)g); + assert(Type::count == 0); + Type::reset(); + { + any a((Type(42))); + assert(Type::count == 1); + assert(Type::copied == 0); + + any a2(a); + + assert(Type::copied == 1); + assert(Type::count == 2); + assertContains<Type>(a, 42); + assertContains<Type>(a, 42); + + // Modify a and check that a2 is unchanged + modifyValue<Type>(a, -1); + assertContains<Type>(a, -1); + assertContains<Type>(a2, 42); + + // modify a2 and check that a is unchanged + modifyValue<Type>(a2, 999); + assertContains<Type>(a, -1); + assertContains<Type>(a2, 999); + + // clear a and check that a2 is unchanged + a.clear(); + assertEmpty(a); + assertContains<Type>(a2, 999); + } + assert(Type::count == 0); +} + +int main() { + test_copy<small>(); + test_copy<large>(); + test_copy_empty(); + test_copy_throws<small_throws_on_copy>(); + test_copy_throws<large_throws_on_copy>(); +} diff --git a/libcxx/test/std/experimental/any/any.class/any.cons/default.pass.cpp b/libcxx/test/std/experimental/any/any.class/any.cons/default.pass.cpp new file mode 100644 index 00000000000..b52c83fc388 --- /dev/null +++ b/libcxx/test/std/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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// any() noexcept; + +#include <experimental/any> +#include <type_traits> +#include <cassert> + +#include "any_helpers.h" +#include "count_new.hpp" + + +int main() +{ + using std::experimental::any; + { + static_assert( + std::is_nothrow_default_constructible<any>::value + , "Must be default constructible" + ); + } + { + DisableAllocationGuard g; ((void)g); + any const a; + assertEmpty(a); + } +} diff --git a/libcxx/test/std/experimental/any/any.class/any.cons/move.pass.cpp b/libcxx/test/std/experimental/any/any.class/any.cons/move.pass.cpp new file mode 100644 index 00000000000..40534cb5506 --- /dev/null +++ b/libcxx/test/std/experimental/any/any.class/any.cons/move.pass.cpp @@ -0,0 +1,102 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// any(any &&) noexcept; + +#include <experimental/any> +#include <utility> +#include <type_traits> +#include <cassert> + +#include "any_helpers.h" +#include "count_new.hpp" +#include "test_macros.h" + +using std::experimental::any; +using std::experimental::any_cast; + +// Moves are always noexcept. The throws_on_move object +// must be stored dynamically so the pointer is moved and +// not the stored object. +void test_move_does_not_throw() +{ +#if !defined(TEST_HAS_NO_EXCEPTIONS) + assert(throws_on_move::count == 0); + { + throws_on_move v(42); + any a(v); + assert(throws_on_move::count == 2); + // No allocations should be performed after this point. + DisableAllocationGuard g; ((void)g); + try { + any const a2(std::move(a)); + assertEmpty(a); + assertContains<throws_on_move>(a2, 42); + } catch (...) { + assert(false); + } + assert(throws_on_move::count == 1); + assertEmpty(a); + } + assert(throws_on_move::count == 0); +#endif +} + +void test_move_empty() { + DisableAllocationGuard g; ((void)g); // no allocations should be performed. + + any a1; + any a2(std::move(a1)); + + assertEmpty(a1); + assertEmpty(a2); +} + +template <class Type> +void test_move() { + assert(Type::count == 0); + Type::reset(); + { + any a((Type(42))); + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 1); + + // Moving should not perform allocations since it must be noexcept. + DisableAllocationGuard g; ((void)g); + + any a2(std::move(a)); + + assert(Type::moved >= 1); // zero or more move operations can be performed. + assert(Type::copied == 0); // no copies can be performed. + assert(Type::count == 1); + assertEmpty(a); // Moves are always destructive. + assertContains<Type>(a2, 42); + } + assert(Type::count == 0); +} + +int main() +{ + // noexcept test + { + static_assert( + std::is_nothrow_move_constructible<any>::value + , "any must be nothrow move constructible" + ); + } + test_move<small>(); + test_move<large>(); + test_move_empty(); + test_move_does_not_throw(); +} diff --git a/libcxx/test/std/experimental/any/any.class/any.cons/non_copyable_value.fail.cpp b/libcxx/test/std/experimental/any/any.class/any.cons/non_copyable_value.fail.cpp new file mode 100644 index 00000000000..643b9621ca2 --- /dev/null +++ b/libcxx/test/std/experimental/any/any.class/any.cons/non_copyable_value.fail.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// any::any<Value>(Value &&) + +// Attempt to construct any with a non-copyable type. + +#include <experimental/any> + +class non_copyable +{ + non_copyable(non_copyable const &); + +public: + non_copyable() {} + non_copyable(non_copyable &&) {} +}; + +int main() +{ + using namespace std::experimental; + non_copyable nc; + any a(static_cast<non_copyable &&>(nc)); + // expected-error@experimental/any:* 1 {{static_assert failed "_ValueType must be CopyConstructible."}} + // expected-error@experimental/any:* 1 {{calling a private constructor of class 'non_copyable'}} +} diff --git a/libcxx/test/std/experimental/any/any.class/any.cons/value.pass.cpp b/libcxx/test/std/experimental/any/any.class/any.cons/value.pass.cpp new file mode 100644 index 00000000000..7bb134efd28 --- /dev/null +++ b/libcxx/test/std/experimental/any/any.class/any.cons/value.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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// template <class Value> any(Value &&) + +// Test construction from a value. +// Concerns: +// --------- +// 1. The value is properly move/copied depending on the value category. +// 2. Both small and large values are properly handled. + + +#include <experimental/any> +#include <cassert> + +#include "any_helpers.h" +#include "count_new.hpp" +#include "test_macros.h" + +using std::experimental::any; +using std::experimental::any_cast; + +template <class Type> +void test_copy_value_throws() +{ +#if !defined(TEST_HAS_NO_EXCEPTIONS) + assert(Type::count == 0); + { + Type const t(42); + assert(Type::count == 1); + try { + any const a2(t); + assert(false); + } catch (my_any_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(Type::count == 1); + assert(t.value == 42); + } + assert(Type::count == 0); +#endif +} + +void test_move_value_throws() +{ +#if !defined(TEST_HAS_NO_EXCEPTIONS) + assert(throws_on_move::count == 0); + { + throws_on_move v; + assert(throws_on_move::count == 1); + try { + any const a(std::move(v)); + assert(false); + } catch (my_any_exception const &) { + // do nothing + } catch (...) { + assert(false); + } + assert(throws_on_move::count == 1); + } + assert(throws_on_move::count == 0); +#endif +} + +template <class Type> +void test_copy_move_value() { + // constructing from a small type should perform no allocations. + DisableAllocationGuard g(isSmallType<Type>()); ((void)g); + assert(Type::count == 0); + Type::reset(); + { + Type t(42); + assert(Type::count == 1); + + any a(t); + + assert(Type::count == 2); + assert(Type::copied == 1); + assert(Type::moved == 0); + assertContains<Type>(a, 42); + } + assert(Type::count == 0); + Type::reset(); + { + Type t(42); + assert(Type::count == 1); + + any a(std::move(t)); + + assert(Type::count == 2); + assert(Type::copied == 0); + assert(Type::moved == 1); + assertContains<Type>(a, 42); + } +} + + +int main() { + test_copy_move_value<small>(); + test_copy_move_value<large>(); + test_copy_value_throws<small_throws_on_copy>(); + test_copy_value_throws<large_throws_on_copy>(); + test_move_value_throws(); +}
\ No newline at end of file diff --git a/libcxx/test/std/experimental/any/any.class/any.modifiers/clear.pass.cpp b/libcxx/test/std/experimental/any/any.class/any.modifiers/clear.pass.cpp new file mode 100644 index 00000000000..603490cef43 --- /dev/null +++ b/libcxx/test/std/experimental/any/any.class/any.modifiers/clear.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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// any::clear() noexcept + +#include <experimental/any> +#include <cassert> + +#include "any_helpers.h" + +int main() +{ + using std::experimental::any; + using std::experimental::any_cast; + // empty + { + any a; + + // noexcept check + static_assert( + noexcept(a.clear()) + , "any.clear() must be noexcept" + ); + + assertEmpty(a); + + a.clear(); + + assertEmpty(a); + } + // small object + { + any a((small(1))); + assert(small::count == 1); + assertContains<small>(a, 1); + + a.clear(); + + assertEmpty<small>(a); + assert(small::count == 0); + } + // large object + { + any a(large(1)); + assert(large::count == 1); + assertContains<large>(a); + + a.clear(); + + assertEmpty<large>(a); + assert(large::count == 0); + } +} diff --git a/libcxx/test/std/experimental/any/any.class/any.modifiers/swap.pass.cpp b/libcxx/test/std/experimental/any/any.class/any.modifiers/swap.pass.cpp new file mode 100644 index 00000000000..064935167eb --- /dev/null +++ b/libcxx/test/std/experimental/any/any.class/any.modifiers/swap.pass.cpp @@ -0,0 +1,101 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// any::swap(any &) noexcept + +// Test swap(large, small) and swap(small, large) + +#include <experimental/any> +#include <cassert> + +#include "any_helpers.h" + +using std::experimental::any; +using std::experimental::any_cast; + +template <class LHS, class RHS> +void test_swap() { + assert(LHS::count == 0); + assert(RHS::count == 0); + { + any a1((LHS(1))); + any a2(RHS{2}); + assert(LHS::count == 1); + assert(RHS::count == 1); + + a1.swap(a2); + + assert(LHS::count == 1); + assert(RHS::count == 1); + + assertContains<RHS>(a1, 2); + assertContains<LHS>(a2, 1); + } + assert(LHS::count == 0); + assert(RHS::count == 0); + assert(LHS::copied == 0); + assert(RHS::copied == 0); +} + +template <class Tp> +void test_swap_empty() { + assert(Tp::count == 0); + { + any a1((Tp(1))); + any a2; + assert(Tp::count == 1); + + a1.swap(a2); + + assert(Tp::count == 1); + + assertContains<Tp>(a2, 1); + assertEmpty(a1); + } + assert(Tp::count == 0); + { + any a1((Tp(1))); + any a2; + assert(Tp::count == 1); + + a2.swap(a1); + + assert(Tp::count == 1); + + assertContains<Tp>(a2, 1); + assertEmpty(a1); + } + assert(Tp::count == 0); + assert(Tp::copied == 0); +} + +void test_noexcept() +{ + any a1; + any a2; + static_assert( + noexcept(a1.swap(a2)) + , "any::swap(any&) must be noexcept" + ); +} + +int main() +{ + test_noexcept(); + test_swap_empty<small>(); + test_swap_empty<large>(); + test_swap<small1, small2>(); + test_swap<large1, large2>(); + test_swap<small, large>(); + test_swap<large, small>(); +} diff --git a/libcxx/test/std/experimental/any/any.class/any.observers/empty.pass.cpp b/libcxx/test/std/experimental/any/any.class/any.observers/empty.pass.cpp new file mode 100644 index 00000000000..8c681f37017 --- /dev/null +++ b/libcxx/test/std/experimental/any/any.class/any.observers/empty.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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// any::empty() noexcept + +#include <experimental/any> +#include <cassert> + +#include "any_helpers.h" + +int main() +{ + using std::experimental::any; + // noexcept test + { + any a; + static_assert(noexcept(a.empty()), "any::empty() must be noexcept"); + } + // empty + { + any a; + assert(a.empty()); + + a.clear(); + assert(a.empty()); + + a = 42; + assert(!a.empty()); + } + // small object + { + small const s(1); + any a(s); + assert(!a.empty()); + + a.clear(); + assert(a.empty()); + + a = s; + assert(!a.empty()); + } + // large object + { + large const l(1); + any a(l); + assert(!a.empty()); + + a.clear(); + assert(a.empty()); + + a = l; + assert(!a.empty()); + } +} diff --git a/libcxx/test/std/experimental/any/any.class/any.observers/type.pass.cpp b/libcxx/test/std/experimental/any/any.class/any.observers/type.pass.cpp new file mode 100644 index 00000000000..682b73bc98c --- /dev/null +++ b/libcxx/test/std/experimental/any/any.class/any.observers/type.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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// XFAIL: libcpp-no-rtti + +// <experimental/any> + +// any::type() noexcept + +#include <experimental/any> +#include <cassert> +#include "any_helpers.h" + +int main() +{ + using std::experimental::any; + { + any const a; + assert(a.type() == typeid(void)); + static_assert(noexcept(a.type()), "any::type() must be noexcept"); + } + { + small const s(1); + any const a(s); + assert(a.type() == typeid(small)); + + } + { + large const l(1); + any const a(l); + assert(a.type() == typeid(large)); + } +} diff --git a/libcxx/test/std/experimental/any/any.class/nothing_to_do.pass.cpp b/libcxx/test/std/experimental/any/any.class/nothing_to_do.pass.cpp new file mode 100644 index 00000000000..c21f8a70168 --- /dev/null +++ b/libcxx/test/std/experimental/any/any.class/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. +// +//===----------------------------------------------------------------------===// + +#include <experimental/string_view> + +int main () {} diff --git a/libcxx/test/std/experimental/any/any.nonmembers/any.cast/any_cast_pointer.pass.cpp b/libcxx/test/std/experimental/any/any.nonmembers/any.cast/any_cast_pointer.pass.cpp new file mode 100644 index 00000000000..9d9a5cdb472 --- /dev/null +++ b/libcxx/test/std/experimental/any/any.nonmembers/any.cast/any_cast_pointer.pass.cpp @@ -0,0 +1,146 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// template <class ValueType> +// ValueType const* any_cast(any const *) noexcept; +// +// template <class ValueType> +// ValueType * any_cast(any *) noexcept; + +#include <experimental/any> +#include <type_traits> +#include <cassert> + +#include "any_helpers.h" + +using std::experimental::any; +using std::experimental::any_cast; + +// Test that the operators are properly noexcept. +void test_cast_is_noexcept() { + any a; + static_assert(noexcept(any_cast<int>(&a)), ""); + + any const& ca = a; + static_assert(noexcept(any_cast<int>(&ca)), ""); +} + +// Test that the return type of any_cast is correct. +void test_cast_return_type() { + any a; + static_assert(std::is_same<decltype(any_cast<int>(&a)), int*>::value, ""); + static_assert(std::is_same<decltype(any_cast<int const>(&a)), int const*>::value, ""); + + any const& ca = a; + static_assert(std::is_same<decltype(any_cast<int>(&ca)), int const*>::value, ""); + static_assert(std::is_same<decltype(any_cast<int const>(&ca)), int const*>::value, ""); +} + +// Test that any_cast handles null pointers. +void test_cast_nullptr() { + any* a = nullptr; + assert(nullptr == any_cast<int>(a)); + assert(nullptr == any_cast<int const>(a)); + + any const* ca = nullptr; + assert(nullptr == any_cast<int>(ca)); + assert(nullptr == any_cast<int const>(ca)); +} + +// Test casting an empty object. +void test_cast_empty() { + { + any a; + assert(nullptr == any_cast<int>(&a)); + assert(nullptr == any_cast<int const>(&a)); + + any const& ca = a; + assert(nullptr == any_cast<int>(&ca)); + assert(nullptr == any_cast<int const>(&ca)); + } + // Create as non-empty, then make empty and run test. + { + any a(42); + a.clear(); + assert(nullptr == any_cast<int>(&a)); + assert(nullptr == any_cast<int const>(&a)); + + any const& ca = a; + assert(nullptr == any_cast<int>(&ca)); + assert(nullptr == any_cast<int const>(&ca)); + } +} + +template <class Type> +void test_cast() { + assert(Type::count == 0); + Type::reset(); + { + any a((Type(42))); + any const& ca = a; + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 1); + + // Try a cast to a bad type. + // NOTE: Type cannot be an int. + assert(any_cast<int>(&a) == nullptr); + assert(any_cast<int const>(&a) == nullptr); + assert(any_cast<int const volatile>(&a) == nullptr); + + // Try a cast to the right type, but as a pointer. + assert(any_cast<Type*>(&a) == nullptr); + assert(any_cast<Type const*>(&a) == nullptr); + + // Check getting a unqualified type from a non-const any. + Type* v = any_cast<Type>(&a); + assert(v != nullptr); + assert(v->value == 42); + + // change the stored value and later check for the new value. + v->value = 999; + + // Check getting a const qualified type from a non-const any. + Type const* cv = any_cast<Type const>(&a); + assert(cv != nullptr); + assert(cv == v); + assert(cv->value == 999); + + // Check getting a unqualified type from a const any. + cv = any_cast<Type>(&ca); + assert(cv != nullptr); + assert(cv == v); + assert(cv->value == 999); + + // Check getting a const-qualified type from a const any. + cv = any_cast<Type const>(&ca); + assert(cv != nullptr); + assert(cv == v); + assert(cv->value == 999); + + // Check that no more objects were created, copied or moved. + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 1); + } + assert(Type::count == 0); +} + +int main() { + test_cast_is_noexcept(); + test_cast_return_type(); + test_cast_nullptr(); + test_cast_empty(); + test_cast<small>(); + test_cast<large>(); +} diff --git a/libcxx/test/std/experimental/any/any.nonmembers/any.cast/any_cast_reference.pass.cpp b/libcxx/test/std/experimental/any/any.nonmembers/any.cast/any_cast_reference.pass.cpp new file mode 100644 index 00000000000..e97560937fb --- /dev/null +++ b/libcxx/test/std/experimental/any/any.nonmembers/any.cast/any_cast_reference.pass.cpp @@ -0,0 +1,309 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// template <class ValueType> +// ValueType const any_cast(any const&); +// +// template <class ValueType> +// ValueType any_cast(any &); +// +// template <class ValueType> +// ValueType any_cast(any &&); + +#include <experimental/any> +#include <type_traits> +#include <cassert> + +#include "any_helpers.h" +#include "count_new.hpp" +#include "test_macros.h" + +using std::experimental::any; +using std::experimental::any_cast; +using std::experimental::bad_any_cast; + + +// Test that the operators are NOT marked noexcept. +void test_cast_is_not_noexcept() { + any a; + static_assert(!noexcept(any_cast<int>(static_cast<any&>(a))), ""); + static_assert(!noexcept(any_cast<int>(static_cast<any const&>(a))), ""); + static_assert(!noexcept(any_cast<int>(static_cast<any &&>(a))), ""); +} + +// Test that the return type of any_cast is correct. +void test_cast_return_type() { + any a; + static_assert(std::is_same<decltype(any_cast<int>(a)), int>::value, ""); + static_assert(std::is_same<decltype(any_cast<int const>(a)), int>::value, ""); + static_assert(std::is_same<decltype(any_cast<int&>(a)), int&>::value, ""); + static_assert(std::is_same<decltype(any_cast<int const&>(a)), int const&>::value, ""); + + //static_assert(std::is_same<decltype(any_cast<int&&>(a)), int&&>::value, ""); + //static_assert(std::is_same<decltype(any_cast<int const&&>(a)), int const&&>::value, ""); + + static_assert(std::is_same<decltype(any_cast<int>(std::move(a))), int>::value, ""); + static_assert(std::is_same<decltype(any_cast<int const>(std::move(a))), int>::value, ""); + static_assert(std::is_same<decltype(any_cast<int&>(std::move(a))), int&>::value, ""); + static_assert(std::is_same<decltype(any_cast<int const&>(std::move(a))), int const&>::value, ""); + + //static_assert(std::is_same<decltype(any_cast<int&&>(std::move(a))), int&&>::value, ""); + //static_assert(std::is_same<decltype(any_cast<int const&&>(std::move(a))), int const&&>::value, ""); + + any const& ca = a; + static_assert(std::is_same<decltype(any_cast<int>(ca)), int>::value, ""); + static_assert(std::is_same<decltype(any_cast<int const>(ca)), int>::value, ""); + static_assert(std::is_same<decltype(any_cast<int const&>(ca)), int const&>::value, ""); + + //static_assert(std::is_same<decltype(any_cast<int const&&>(ca)), int const&&>::value, ""); +} + +template <class Type, class ConstT = Type> +void checkThrows(any& a) +{ +#if !defined(TEST_HAS_NO_EXCEPTIONS) + try { + any_cast<Type>(a); + assert(false); + } catch (bad_any_cast const &) { + // do nothing + } catch (...) { + assert(false); + } + + try { + any_cast<ConstT>(static_cast<any const&>(a)); + assert(false); + } catch (bad_any_cast const &) { + // do nothing + } catch (...) { + assert(false); + } + + try { + any_cast<Type>(static_cast<any&&>(a)); + assert(false); + } catch (bad_any_cast const &) { + // do nothing + } catch (...) { + assert(false); + } +#endif +} + +void test_cast_empty() { + // None of these operations should allocate. + DisableAllocationGuard g; ((void)g); + any a; + checkThrows<int>(a); +} + +template <class Type> +void test_cast_to_reference() { + assert(Type::count == 0); + Type::reset(); + { + any a((Type(42))); + any const& ca = a; + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 1); + + // Try a cast to a bad type. + // NOTE: Type cannot be an int. + checkThrows<int>(a); + checkThrows<int&, int const&>(a); + checkThrows<Type*, Type const*>(a); + checkThrows<Type const*>(a); + + // Check getting a type by reference from a non-const lvalue any. + { + Type& v = any_cast<Type&>(a); + assert(v.value == 42); + + Type const &cv = any_cast<Type const&>(a); + assert(&cv == &v); + } + // Check getting a type by reference from a const lvalue any. + { + Type const& v = any_cast<Type const&>(ca); + assert(v.value == 42); + + Type const &cv = any_cast<Type const&>(ca); + assert(&cv == &v); + } + // Check getting a type by reference from a non-const rvalue + { + Type& v = any_cast<Type&>(std::move(a)); + assert(v.value == 42); + + Type const &cv = any_cast<Type const&>(std::move(a)); + assert(&cv == &v); + } + // Check getting a type by reference from a const rvalue any. + { + Type const& v = any_cast<Type const&>(std::move(ca)); + assert(v.value == 42); + + Type const &cv = any_cast<Type const&>(std::move(ca)); + assert(&cv == &v); + } + + // Check that the original object hasn't been changed. + assertContains<Type>(a, 42); + + // Check that no objects have been created/copied/moved. + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 1); + } + assert(Type::count == 0); +} + +template <class Type> +void test_cast_to_value() { + assert(Type::count == 0); + Type::reset(); + { + any a((Type(42))); + any const& ca = a; + assert(Type::count == 1); + assert(Type::copied == 0); + assert(Type::moved == 1); + + // Try a cast to a bad type. + // NOTE: Type cannot be an int. + checkThrows<int>(a); + checkThrows<int&, int const&>(a); + checkThrows<Type*, Type const*>(a); + checkThrows<Type const*>(a); + + Type::reset(); // NOTE: reset does not modify Type::count + // Check getting Type by value from a non-const lvalue any. + // This should cause the non-const copy constructor to be called. + { + Type t = any_cast<Type>(a); + + assert(Type::count == 2); + assert(Type::copied == 1); + assert(Type::const_copied == 0); + assert(Type::non_const_copied == 1); + assert(Type::moved == 0); + assert(t.value == 42); + } + assert(Type::count == 1); + Type::reset(); + // Check getting const Type by value from a non-const lvalue any. + // This should cause the const copy constructor to be called. + { + Type t = any_cast<Type const>(a); + + assert(Type::count == 2); + assert(Type::copied == 1); + assert(Type::const_copied == 1); + assert(Type::non_const_copied == 0); + assert(Type::moved == 0); + assert(t.value == 42); + } + assert(Type::count == 1); + Type::reset(); + // Check getting Type by value from a non-const lvalue any. + // This should cause the const copy constructor to be called. + { + Type t = any_cast<Type>(static_cast<any const&>(a)); + + assert(Type::count == 2); + assert(Type::copied == 1); + assert(Type::const_copied == 1); + assert(Type::non_const_copied == 0); + assert(Type::moved == 0); + assert(t.value == 42); + } + assert(Type::count == 1); + Type::reset(); + // Check getting Type by value from a non-const rvalue any. + // This should cause the non-const copy constructor to be called. + { + Type t = any_cast<Type>(static_cast<any &&>(a)); + + assert(Type::count == 2); + assert(Type::copied == 1); + assert(Type::const_copied == 0); + assert(Type::non_const_copied == 1); + assert(Type::moved == 0); + assert(t.value == 42); + } + assert(Type::count == 1); + Type::reset(); + // Check getting const Type by value from a non-const rvalue any. + // This should cause the const copy constructor to be called. + { + Type t = any_cast<Type const>(static_cast<any &&>(a)); + + assert(Type::count == 2); + assert(Type::copied == 1); + assert(Type::const_copied == 1); + assert(Type::non_const_copied == 0); + assert(Type::moved == 0); + assert(t.value == 42); + } + assert(Type::count == 1); + Type::reset(); + // Check getting Type by value from a const rvalue any. + // This should cause the const copy constructor to be called. + { + Type t = any_cast<Type>(static_cast<any const&&>(a)); + + assert(Type::count == 2); + assert(Type::copied == 1); + assert(Type::const_copied == 1); + assert(Type::non_const_copied == 0); + assert(Type::moved == 0); + assert(t.value == 42); + } + // Ensure we still only have 1 Type object alive. + assert(Type::count == 1); + + // Check that the original object hasn't been changed. + assertContains<Type>(a, 42); + } + assert(Type::count == 0); +} + +// Even though you can't get a non-copyable class into std::any +// the standard requires that these overloads compile and function. +void test_non_copyable_ref() { + struct no_copy + { + no_copy() {} + no_copy(no_copy &&) {} + private: + no_copy(no_copy const &); + }; + + any a; + checkThrows<no_copy &, no_copy const&>(a); + checkThrows<no_copy const&>(a); + assertEmpty(a); +} + +int main() { + test_cast_is_not_noexcept(); + test_cast_return_type(); + test_cast_empty(); + test_cast_to_reference<small>(); + test_cast_to_reference<large>(); + test_cast_to_value<small>(); + test_cast_to_value<large>(); + test_non_copyable_ref(); +} diff --git a/libcxx/test/std/experimental/any/any.nonmembers/any.cast/const_correctness.fail.cpp b/libcxx/test/std/experimental/any/any.nonmembers/any.cast/const_correctness.fail.cpp new file mode 100644 index 00000000000..db5149265cc --- /dev/null +++ b/libcxx/test/std/experimental/any/any.nonmembers/any.cast/const_correctness.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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// template <class ValueType> +// ValueType any_cast(any const &); + +// Try and cast away const. + +#include <experimental/any> + +struct TestType {}; +struct TestType2 {}; + +int main() +{ + using std::experimental::any; + using std::experimental::any_cast; + + any a; + + // expected-error@experimental/any:* 2 {{binding value of type '_Tp' (aka 'const TestType') to reference to type 'TestType' drops 'const' qualifier}} + any_cast<TestType &>(static_cast<any const&>(a)); // expected-note {{requested here}} + any_cast<TestType &&>(static_cast<any const&>(a)); // expected-note {{requested here}} + + // expected-error@experimental/any:* 2 {{binding value of type '_Tp' (aka 'const TestType2') to reference to type 'TestType2' drops 'const' qualifier}} + any_cast<TestType2 &>(static_cast<any const&&>(a)); // expected-note {{requested here}} + any_cast<TestType2 &&>(static_cast<any const&&>(a)); // expected-note {{requested here}} +} diff --git a/libcxx/test/std/experimental/any/any.nonmembers/any.cast/not_copy_constructible.fail.cpp b/libcxx/test/std/experimental/any/any.nonmembers/any.cast/not_copy_constructible.fail.cpp new file mode 100644 index 00000000000..c6cc68d7270 --- /dev/null +++ b/libcxx/test/std/experimental/any/any.nonmembers/any.cast/not_copy_constructible.fail.cpp @@ -0,0 +1,45 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// template <class ValueType> +// ValueType const any_cast(any const&); +// +// template <class ValueType> +// ValueType any_cast(any &); +// +// template <class ValueType> +// ValueType any_cast(any &&); + +// Test instantiating the any_cast with a non-copyable type. + +#include <experimental/any> + +using std::experimental::any; +using std::experimental::any_cast; + +struct no_copy +{ + no_copy() {} + no_copy(no_copy &&) {} +private: + no_copy(no_copy const &); +}; + +int main() { + any a; + any_cast<no_copy>(static_cast<any&>(a)); + any_cast<no_copy>(static_cast<any const&>(a)); + any_cast<no_copy>(static_cast<any &&>(a)); + // expected-error@experimental/any:* 3 {{static_assert failed "_ValueType is required to be a reference or a CopyConstructible type."}} + // expected-error@experimental/any:* 3 {{calling a private constructor of class 'no_copy'}} +}
\ No newline at end of file diff --git a/libcxx/test/std/experimental/any/any.nonmembers/any.cast/reference_types.fail.cpp b/libcxx/test/std/experimental/any/any.nonmembers/any.cast/reference_types.fail.cpp new file mode 100644 index 00000000000..6c6ccc68787 --- /dev/null +++ b/libcxx/test/std/experimental/any/any.nonmembers/any.cast/reference_types.fail.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// template <class ValueType> +// ValueType const* any_cast(any const *) noexcept; +// +// template <class ValueType> +// ValueType * any_cast(any *) noexcept; + +#include <experimental/any> + +using std::experimental::any; +using std::experimental::any_cast; + +int main() +{ + any a(1); + any_cast<int &>(&a); // expected-error@experimental/any:* 1 {{static_assert failed "_ValueType may not be a reference."}} + any_cast<int &&>(&a); // expected-error@experimental/any:* 1 {{static_assert failed "_ValueType may not be a reference."}} + any_cast<int const &>(&a); // expected-error@experimental/any:* 1 {{static_assert failed "_ValueType may not be a reference."}} + any_cast<int const&&>(&a); // expected-error@experimental/any:* 1 {{static_assert failed "_ValueType may not be a reference."}} + any const& a2 = a; + any_cast<int &>(&a2); // expected-error@experimental/any:* 1 {{static_assert failed "_ValueType may not be a reference."}} + any_cast<int &&>(&a2); // expected-error@experimental/any:* 1 {{static_assert failed "_ValueType may not be a reference."}} + any_cast<int const &>(&a2); // expected-error@experimental/any:* 1 {{static_assert failed "_ValueType may not be a reference."}} + any_cast<int const &&>(&a2); // expected-error@experimental/any:* 1 {{static_assert failed "_ValueType may not be a reference."}} +} diff --git a/libcxx/test/std/experimental/any/any.nonmembers/swap.pass.cpp b/libcxx/test/std/experimental/any/any.nonmembers/swap.pass.cpp new file mode 100644 index 00000000000..a3fbd43d924 --- /dev/null +++ b/libcxx/test/std/experimental/any/any.nonmembers/swap.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. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 + +// <experimental/any> + +// void swap(any &, any &) noexcept + +// swap(...) just wraps any::swap(...). That function is tested elsewhere. + +#include <experimental/any> +#include <cassert> + +using std::experimental::any; +using std::experimental::any_cast; + +int main() +{ + + { // test noexcept + any a; + static_assert(noexcept(swap(a, a)), "swap(any&, any&) must be noexcept"); + } + { + any a1(1); + any a2(2); + + swap(a1, a2); + + assert(any_cast<int>(a1) == 2); + assert(any_cast<int>(a2) == 1); + } +} diff --git a/libcxx/test/support/any_helpers.h b/libcxx/test/support/any_helpers.h new file mode 100644 index 00000000000..76b1922fb1f --- /dev/null +++ b/libcxx/test/support/any_helpers.h @@ -0,0 +1,318 @@ +#ifndef ANY_HELPERS_H +#define ANY_HELPERS_H + +#include <experimental/any> +#include <typeinfo> +#include <type_traits> +#include <cassert> + +#include "test_macros.h" + +#if !defined(TEST_HAS_NO_RTTI) +#define RTTI_ASSERT(X) assert(X) +#else +#define RTTI_ASSERT(X) +#endif + +template <class _Tp> + struct IsSmallObject + : public std::integral_constant<bool + , sizeof(_Tp) <= (sizeof(void*)*3) + && std::alignment_of<void*>::value + % std::alignment_of<_Tp>::value == 0 + && std::is_nothrow_move_constructible<_Tp>::value + > + {}; + + +// Return 'true' if 'Type' will be considered a small type by 'any' +template <class Type> +bool isSmallType() { +#if defined(_LIBCPP_VERSION) + return std::experimental::__any_imp::_IsSmallObject<Type>::value; +#else + return IsSmallObject<Type>::value; +#endif + +} + +// Assert that an object is empty. If the object used to contain an object +// of type 'LastType' check that it can no longer be accessed. +template <class LastType = int> +void assertEmpty(std::experimental::any const& a) { + assert(a.empty()); + RTTI_ASSERT(a.type() == typeid(void)); + assert(std::experimental::any_cast<LastType const>(&a) == nullptr); +} + +// Assert that an 'any' object stores the specified 'Type' and 'value'. +template <class Type> +void assertContains(std::experimental::any const& a, int value = 1) { + assert(!a.empty()); + RTTI_ASSERT(a.type() == typeid(Type)); + assert(std::experimental::any_cast<Type const &>(a).value == value); +} + +// Modify the value of a "test type" stored within an any to the specified +// 'value'. +template <class Type> +void modifyValue(std::experimental::any& a, int value) { + assert(!a.empty()); + RTTI_ASSERT(a.type() == typeid(Type)); + std::experimental::any_cast<Type&>(a).value = value; +} + +// A test type that will trigger the small object optimization within 'any'. +template <int Dummy = 0> +struct small_type +{ + static int count; + static int copied; + static int moved; + static int const_copied; + static int non_const_copied; + + static void reset() { + small_type::copied = 0; + small_type::moved = 0; + small_type::const_copied = 0; + small_type::non_const_copied = 0; + } + + int value; + + explicit small_type(int val) : value(val) { + ++count; + } + + small_type(small_type const & other) throw() { + value = other.value; + ++count; + ++copied; + ++const_copied; + } + + small_type(small_type& other) throw() { + value = other.value; + ++count; + ++copied; + ++non_const_copied; + } + + small_type(small_type && other) throw() { + value = other.value; + other.value = 0; + ++count; + ++moved; + } + + ~small_type() { + value = -1; + --count; + } + +private: + small_type& operator=(small_type const&) = delete; + small_type& operator=(small_type&&) = delete; +}; + +template <int Dummy> +int small_type<Dummy>::count = 0; + +template <int Dummy> +int small_type<Dummy>::copied = 0; + +template <int Dummy> +int small_type<Dummy>::moved = 0; + +template <int Dummy> +int small_type<Dummy>::const_copied = 0; + +template <int Dummy> +int small_type<Dummy>::non_const_copied = 0; + +typedef small_type<> small; +typedef small_type<1> small1; +typedef small_type<2> small2; + + +// A test type that will NOT trigger the small object optimization in any. +template <int Dummy = 0> +struct large_type +{ + static int count; + static int copied; + static int moved; + static int const_copied; + static int non_const_copied; + + static void reset() { + large_type::copied = 0; + large_type::moved = 0; + large_type::const_copied = 0; + large_type::non_const_copied = 0; + } + + int value; + + large_type(int val) : value(val) { + ++count; + data[0] = 0; + } + + large_type(large_type const & other) { + value = other.value; + ++count; + ++copied; + ++const_copied; + } + + large_type(large_type & other) { + value = other.value; + ++count; + ++copied; + ++non_const_copied; + } + + large_type(large_type && other) { + value = other.value; + other.value = 0; + ++count; + ++moved; + } + + ~large_type() { + value = 0; + --count; + } + +private: + large_type& operator=(large_type const&) = delete; + large_type& operator=(large_type &&) = delete; + int data[10]; +}; + +template <int Dummy> +int large_type<Dummy>::count = 0; + +template <int Dummy> +int large_type<Dummy>::copied = 0; + +template <int Dummy> +int large_type<Dummy>::moved = 0; + +template <int Dummy> +int large_type<Dummy>::const_copied = 0; + +template <int Dummy> +int large_type<Dummy>::non_const_copied = 0; + +typedef large_type<> large; +typedef large_type<1> large1; +typedef large_type<2> large2; + +// The exception type thrown by 'small_throws_on_copy', 'large_throws_on_copy' +// and 'throws_on_move'. +struct my_any_exception {}; + +void throwMyAnyExpression() { +#if !defined(TEST_HAS_NO_EXCEPTIONS) + throw my_any_exception(); +#else + assert(false && "Exceptions are disabled"); +#endif +} + +// A test type that will trigger the small object optimization within 'any'. +// this type throws if it is copied. +struct small_throws_on_copy +{ + static int count; + int value; + + explicit small_throws_on_copy(int val = 0) : value(val) { + ++count; + } + + small_throws_on_copy(small_throws_on_copy const &) { + throwMyAnyExpression(); + } + + small_throws_on_copy(small_throws_on_copy && other) throw() { + value = other.value; + ++count; + } + + ~small_throws_on_copy() { + --count; + } +private: + small_throws_on_copy& operator=(small_throws_on_copy const&) = delete; + small_throws_on_copy& operator=(small_throws_on_copy &&) = delete; +}; + +int small_throws_on_copy::count = 0; + +// A test type that will NOT trigger the small object optimization within 'any'. +// this type throws if it is copied. +struct large_throws_on_copy +{ + static int count; + int value = 0; + + explicit large_throws_on_copy(int val = 0) : value(val) { + data[0] = 0; + ++count; + } + + large_throws_on_copy(large_throws_on_copy const &) { + throwMyAnyExpression(); + } + + large_throws_on_copy(large_throws_on_copy && other) throw() { + value = other.value; + ++count; + } + + ~large_throws_on_copy() { + --count; + } + +private: + large_throws_on_copy& operator=(large_throws_on_copy const&) = delete; + large_throws_on_copy& operator=(large_throws_on_copy &&) = delete; + int data[10]; +}; + +int large_throws_on_copy::count = 0; + +// A test type that throws when it is moved. This object will NOT trigger +// the small object optimization in 'any'. +struct throws_on_move +{ + static int count; + int value; + + explicit throws_on_move(int val = 0) : value(val) { ++count; } + + throws_on_move(throws_on_move const & other) { + value = other.value; + ++count; + } + + throws_on_move(throws_on_move &&) { + throwMyAnyExpression(); + } + + ~throws_on_move() { + --count; + } +private: + throws_on_move& operator=(throws_on_move const&) = delete; + throws_on_move& operator=(throws_on_move &&) = delete; +}; + +int throws_on_move::count = 0; + + +#endif diff --git a/libcxx/test/support/count_new.hpp b/libcxx/test/support/count_new.hpp index ddaf036f7d1..57aca7def33 100644 --- a/libcxx/test/support/count_new.hpp +++ b/libcxx/test/support/count_new.hpp @@ -30,6 +30,10 @@ public: // All checks return true when disable_checking is enabled. static const bool disable_checking; + // Disallow any allocations from occurring. Useful for testing that + // code doesn't perform any allocations. + bool disable_allocations; + int outstanding_new; int new_called; int delete_called; @@ -43,6 +47,7 @@ public: public: void newCalled(std::size_t s) { + assert(disable_allocations == false); assert(s); ++new_called; ++outstanding_new; @@ -58,6 +63,7 @@ public: void newArrayCalled(std::size_t s) { + assert(disable_allocations == false); assert(s); ++outstanding_array_new; ++new_array_called; @@ -71,8 +77,20 @@ public: ++delete_array_called; } + void disableAllocations() + { + disable_allocations = true; + } + + void enableAllocations() + { + disable_allocations = false; + } + void reset() { + disable_allocations = false; + outstanding_new = 0; new_called = 0; delete_called = 0; @@ -203,4 +221,29 @@ void operator delete[](void* p) throw() #endif // DISABLE_NEW_COUNT + +struct DisableAllocationGuard { + explicit DisableAllocationGuard(bool disable = true) : m_disabled(disable) + { + // Don't re-disable if already disabled. + if (globalMemCounter.disable_allocations == true) m_disabled = false; + if (m_disabled) globalMemCounter.disableAllocations(); + } + + void release() { + if (m_disabled) globalMemCounter.enableAllocations(); + m_disabled = false; + } + + ~DisableAllocationGuard() { + release(); + } + +private: + bool m_disabled; + + DisableAllocationGuard(DisableAllocationGuard const&); + DisableAllocationGuard& operator=(DisableAllocationGuard const&); +}; + #endif /* COUNT_NEW_HPP */ diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h index a08ca87be93..08ec28f7c7b 100644 --- a/libcxx/test/support/test_macros.h +++ b/libcxx/test/support/test_macros.h @@ -14,6 +14,12 @@ #define TEST_CONCAT1(X, Y) X##Y #define TEST_CONCAT(X, Y) TEST_CONCAT1(X, Y) +#ifdef __has_feature +#define TEST_HAS_FEATURE(X) __has_feature(X) +#else +#define TEST_HAS_FEATURE(X) 0 +#endif + #ifdef __has_extension #define TEST_HAS_EXTENSION(X) __has_extension(X) #else @@ -80,4 +86,12 @@ template <unsigned> struct static_assert_check {}; } // end namespace test_detail +#if !TEST_HAS_FEATURE(cxx_rtti) && !defined(__cxx_rtti) +#define TEST_HAS_NO_RTTI +#endif + +#if !TEST_HAS_FEATURE(cxx_exceptions) && !defined(__cxx_exceptions) +#define TEST_HAS_NO_EXCEPTIONS +#endif + #endif // SUPPORT_TEST_MACROS_HPP |

