197 changes: 197 additions & 0 deletions libcxx/test/std/utilities/any/any.class/any.assign/copy.pass.cpp
Original file line number Diff line number Diff line change
@@ -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, c++14

// <any>

// any& operator=(any const &);

// Test copy assignment

#include <any>
#include <cassert>

#include "any_helpers.h"
#include "count_new.hpp"
#include "test_macros.h"

using std::any;
using std::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>();
}
102 changes: 102 additions & 0 deletions libcxx/test/std/utilities/any/any.class/any.assign/move.pass.cpp
Original file line number Diff line number Diff line change
@@ -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, c++14

// <any>

// any& operator=(any &&);

// Test move assignment.

#include <any>
#include <cassert>

#include "any_helpers.h"
#include "test_macros.h"

using std::any;
using std::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>();
}
205 changes: 205 additions & 0 deletions libcxx/test/std/utilities/any/any.class/any.assign/value.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
//===----------------------------------------------------------------------===//
//
// 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, c++14

// <any>

// any& operator=(any const &);

// Test value copy and move assignment.

#include <any>
#include <cassert>

#include "any_helpers.h"
#include "count_new.hpp"
#include "test_macros.h"

using std::any;
using std::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
}


// Test that any& operator=(ValueType&&) is *never* selected for:
// * std::in_place type.
// * Non-copyable types
void test_sfinae_constraints() {
{
using Tag = std::in_place_type_t<int>;
using RawTag = std::remove_reference_t<Tag>;
static_assert(!std::is_assignable<std::any, RawTag&&>::value, "");
}
{
struct Dummy { Dummy() = delete; };
using T = std::in_place_type_t<Dummy>;
static_assert(!std::is_assignable<std::any, T>::value, "");
}
{
// Test that the ValueType&& constructor SFINAE's away when the
// argument is non-copyable
struct NoCopy {
NoCopy() = default;
NoCopy(NoCopy const&) = delete;
NoCopy(NoCopy&&) = default;
};
static_assert(!std::is_assignable<std::any, NoCopy>::value, "");
}
}

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>();
test_sfinae_constraints();
}
100 changes: 100 additions & 0 deletions libcxx/test/std/utilities/any/any.class/any.cons/copy.pass.cpp
Original file line number Diff line number Diff line change
@@ -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, c++14

// <any>

// any(any const &);

#include <any>
#include <cassert>

#include "any_helpers.h"
#include "count_new.hpp"
#include "test_macros.h"

using std::any;
using std::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.reset();
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>();
}
47 changes: 47 additions & 0 deletions libcxx/test/std/utilities/any/any.class/any.cons/default.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
//===----------------------------------------------------------------------===//
//
// 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, c++14

// <any>

// any() noexcept;

#include <any>
#include <type_traits>
#include <cassert>

#include "test_macros.h"
#include "any_helpers.h"
#include "count_new.hpp"

#if TEST_HAS_BUILTIN_IDENTIFIER(__has_constant_initializer)
// std::any must have a constexpr default constructor, but it's a non-literal
// type so we can't create a constexpr variable. This tests that we actually
// get 'constant initialization'.
std::any a;
static_assert(__has_constant_initializer(a),
"any must be constant initializable");
#endif

int main()
{
using std::any;
{
static_assert(
std::is_nothrow_default_constructible<any>::value
, "Must be default constructible"
);
}
{
DisableAllocationGuard g; ((void)g);
any const a;
assertEmpty(a);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
//===----------------------------------------------------------------------===//
//
// 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, c++14

// <any>

// template <class T, class ...Args> any(in_place_type_t<T>, Args&&...);
// template <class T, class U, class ...Args>
// any(in_place_type_t<T>, initializer_list<U>, Args&&...);

// 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 <any>
#include <cassert>

#include "any_helpers.h"
#include "count_new.hpp"
#include "test_macros.h"
#include "test_convertible.hpp"

using std::any;
using std::any_cast;

template <class Type>
void test_in_place_type() {
// constructing from a small type should perform no allocations.
DisableAllocationGuard g(isSmallType<Type>()); ((void)g);
assert(Type::count == 0);
Type::reset();
{
any a(std::in_place<Type>);

assert(Type::count == 1);
assert(Type::copied == 0);
assert(Type::moved == 0);
assertContains<Type>(a, 0);
}
assert(Type::count == 0);
Type::reset();
{
any a(std::in_place<Type>, 101);

assert(Type::count == 1);
assert(Type::copied == 0);
assert(Type::moved == 0);
assertContains<Type>(a, 101);
}
assert(Type::count == 0);
Type::reset();
{
any a(std::in_place<Type>, -1, 42, -1);

assert(Type::count == 1);
assert(Type::copied == 0);
assert(Type::moved == 0);
assertContains<Type>(a, 42);
}
assert(Type::count == 0);
Type::reset();
}

template <class Type>
void test_in_place_type_tracked() {
// constructing from a small type should perform no allocations.
DisableAllocationGuard g(isSmallType<Type>()); ((void)g);
{
any a(std::in_place<Type>);
assertArgsMatch<Type>(a);
}
{
any a(std::in_place<Type>, -1, 42, -1);
assertArgsMatch<Type, int, int, int>(a);
}
// initializer_list constructor tests
{
any a(std::in_place<Type>, {-1, 42, -1});
assertArgsMatch<Type, std::initializer_list<int>>(a);
}
{
int x = 42;
any a(std::in_place<Type>, {-1, 42, -1}, x);
assertArgsMatch<Type, std::initializer_list<int>, int&>(a);
}
}

void test_ctor_sfinae() {
{
// Test that the init-list ctor SFINAE's away properly when
// construction would be ill-formed.
using IL = std::initializer_list<int>;
static_assert(!std::is_constructible<std::any,
std::in_place_type_t<int>, IL>::value, "");
static_assert(std::is_constructible<std::any,
std::in_place_type_t<small_tracked_t>, IL>::value, "");
}
{
// Test that the tagged dispatch constructor SFINAE's away when the
// argument is non-copyable
struct NoCopy {
NoCopy() = default;
NoCopy(NoCopy const&) = delete;
NoCopy(int) {}
NoCopy(std::initializer_list<int>, int) {}
};
using Tag = std::in_place_type_t<NoCopy>;
using IL = std::initializer_list<int>;
static_assert(!std::is_constructible<std::any, Tag>::value, "");
static_assert(!std::is_constructible<std::any, Tag, int>::value, "");
static_assert(!std::is_constructible<std::any, Tag, IL, int>::value, "");
}
}

struct Implicit {
Implicit(int) {}
Implicit(int, int, int) {}
Implicit(std::initializer_list<int>, int) {}
};

void test_constructor_explicit() {
using I = Implicit;
using IT = std::in_place_type_t<I>;
static_assert(!test_convertible<std::any, IT, int>(), "");
static_assert(std::is_constructible<std::any, IT, int>::value, "");
static_assert(!test_convertible<std::any, IT, int, int, int>(), "");
static_assert(std::is_constructible<std::any, IT, int, int, int>::value, "");
static_assert(!test_convertible<std::any, IT, std::initializer_list<int>&, int>(), "");
static_assert(std::is_constructible<std::any, IT, std::initializer_list<int>&, int>::value, "");
}

int main() {
test_in_place_type<small>();
test_in_place_type<large>();
test_in_place_type<small_throws_on_copy>();
test_in_place_type<large_throws_on_copy>();
test_in_place_type<throws_on_move>();
test_in_place_type_tracked<small_tracked_t>();
test_in_place_type_tracked<large_tracked_t>();
test_ctor_sfinae();
test_constructor_explicit();
}
102 changes: 102 additions & 0 deletions libcxx/test/std/utilities/any/any.class/any.cons/move.pass.cpp
Original file line number Diff line number Diff line change
@@ -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, c++14

// <any>

// any(any &&) noexcept;

#include <any>
#include <utility>
#include <type_traits>
#include <cassert>

#include "any_helpers.h"
#include "count_new.hpp"
#include "test_macros.h"

using std::any;
using std::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();
}
184 changes: 184 additions & 0 deletions libcxx/test/std/utilities/any/any.class/any.cons/value.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
//===----------------------------------------------------------------------===//
//
// 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, c++14

// <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 <any>
#include <cassert>

#include "any_helpers.h"
#include "count_new.hpp"
#include "test_macros.h"

using std::any;
using std::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);
}
}

void test_non_moveable_type()
{
using Type = deleted_move;
{
deleted_move mv(42);
std::any a(mv);
assert(Type::count == 2);
assert(Type::copied == 1);
assert(Type::moved == 0);
assertContains<Type>(a, 42);
}
assert(Type::count == 0);
Type::reset();
{
deleted_move mv(42);
std::any a(std::move(mv));
assert(Type::count == 2);
assert(Type::copied == 1);
assert(Type::moved == 0);
assertContains<Type>(a, 42);
}
assert(Type::count == 0);
Type::reset();
}



// Test that any(ValueType&&) is *never* selected for a std::in_place type.
void test_sfinae_constraints() {
using Tag = std::in_place_type_t<int>;
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wignored-qualifiers"
#endif
static_assert(std::is_same<Tag, const Tag>::value, "");
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
// Test that the tag type is properly handled in SFINAE
Tag t = std::in_place;
{
std::any a(t);
assertContains<int>(a, 0);
}
{
std::any a(std::move(t));
assertContains<int>(a, 0);
}
{
struct Dummy { Dummy() = delete; };
using T = std::in_place_type_t<Dummy>;
static_assert(!std::is_constructible<std::any, T>::value, "");
}
{
// Test that the ValueType&& constructor SFINAE's away when the
// argument is non-copyable
struct NoCopy {
NoCopy() = default;
NoCopy(NoCopy const&) = delete;
NoCopy(int) {}
};
static_assert(!std::is_constructible<std::any, NoCopy>::value, "");
static_assert(!std::is_convertible<NoCopy, std::any>::value, "");
}
}

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();
test_non_moveable_type();
test_sfinae_constraints();
}
255 changes: 255 additions & 0 deletions libcxx/test/std/utilities/any/any.class/any.modifiers/emplace.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
//===----------------------------------------------------------------------===//
//
// 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, c++14

// <any>

// template <class T, class ...Args> emplace(Args&&...);
// template <class T, class U, class ...Args>
// void emplace(initializer_list<U>, Args&&...);

#include <any>
#include <cassert>

#include "any_helpers.h"
#include "count_new.hpp"
#include "test_macros.h"

using std::any;
using std::any_cast;

struct Tracked {
static int count;
Tracked() {++count;}
~Tracked() { --count; }
};
int Tracked::count = 0;

template <class Type>
void test_emplace_type() {
// constructing from a small type should perform no allocations.
DisableAllocationGuard g(isSmallType<Type>()); ((void)g);
assert(Type::count == 0);
Type::reset();
{
any a(std::in_place<Tracked>);
assert(Tracked::count == 1);

a.emplace<Type>();

assert(Tracked::count == 0);
assert(Type::count == 1);
assert(Type::copied == 0);
assert(Type::moved == 0);
assertContains<Type>(a, 0);
}
assert(Type::count == 0);
Type::reset();
{
any a(std::in_place<Tracked>);
assert(Tracked::count == 1);

a.emplace<Type>(101);

assert(Tracked::count == 0);
assert(Type::count == 1);
assert(Type::copied == 0);
assert(Type::moved == 0);
assertContains<Type>(a, 101);
}
assert(Type::count == 0);
Type::reset();
{
any a(std::in_place<Tracked>);
assert(Tracked::count == 1);

a.emplace<Type>(-1, 42, -1);

assert(Tracked::count == 0);
assert(Type::count == 1);
assert(Type::copied == 0);
assert(Type::moved == 0);
assertContains<Type>(a, 42);
}
assert(Type::count == 0);
Type::reset();
}

template <class Type>
void test_emplace_type_tracked() {
// constructing from a small type should perform no allocations.
DisableAllocationGuard g(isSmallType<Type>()); ((void)g);
{
any a(std::in_place<Tracked>);
assert(Tracked::count == 1);
a.emplace<Type>();
assert(Tracked::count == 0);
assertArgsMatch<Type>(a);
}
{
any a(std::in_place<Tracked>);
assert(Tracked::count == 1);
a.emplace<Type>(-1, 42, -1);
assert(Tracked::count == 0);
assertArgsMatch<Type, int, int, int>(a);
}
// initializer_list constructor tests
{
any a(std::in_place<Tracked>);
assert(Tracked::count == 1);
a.emplace<Type>({-1, 42, -1});
assert(Tracked::count == 0);
assertArgsMatch<Type, std::initializer_list<int>>(a);
}
{
int x = 42;
any a(std::in_place<Tracked>);
assert(Tracked::count == 1);
a.emplace<Type>({-1, 42, -1}, x);
assert(Tracked::count == 0);
assertArgsMatch<Type, std::initializer_list<int>, int&>(a);
}
}

#ifndef TEST_HAS_NO_EXCEPTIONS

struct SmallThrows {
SmallThrows(int) { throw 42; }
SmallThrows(std::initializer_list<int>, int) { throw 42; }
};
static_assert(IsSmallObject<SmallThrows>::value, "");

struct LargeThrows {
LargeThrows(int) { throw 42; }
LargeThrows(std::initializer_list<int>, int) { throw 42; }
int data[10];
};
static_assert(!IsSmallObject<LargeThrows>::value, "");

template <class Type>
void test_emplace_throws()
{
// any stores small type
{
std::any a(small{42});
assert(small::count == 1);
try {
a.emplace<Type>(101);
assert(false);
} catch (int const&) {
}
assert(small::count == 0);
}
{
std::any a(small{42});
assert(small::count == 1);
try {
a.emplace<Type>({1, 2, 3}, 101);
assert(false);
} catch (int const&) {
}
assert(small::count == 0);
}
// any stores large type
{
std::any a(large{42});
assert(large::count == 1);
try {
a.emplace<Type>(101);
assert(false);
} catch (int const&) {
}
assert(large::count == 0);
}
{
std::any a(large{42});
assert(large::count == 1);
try {
a.emplace<Type>({1, 2, 3}, 101);
assert(false);
} catch (int const&) {
}
assert(large::count == 0);
}
}

#endif

template <class T, class ...Args>
constexpr auto has_emplace(int)
-> decltype(std::any{}.emplace<T>(std::declval<Args>()...), true) { return true; }

template <class ...Args>
constexpr bool has_emplace(long) { return false; }

template <class ...Args>
constexpr bool has_emplace() { return has_emplace<Args...>(0); }


template <class T, class IT, class ...Args>
constexpr auto has_emplace_init_list(int)
-> decltype(std::any{}.emplace<T>(
{std::declval<IT>(), std::declval<IT>(), std::declval<IT>()},
std::declval<Args>()...), true) { return true; }

template <class ...Args>
constexpr bool has_emplace_init_list(long) { return false; }

template <class ...Args>
constexpr bool has_emplace_init_list() { return has_emplace_init_list<Args...>(0); }


void test_emplace_sfinae_constraints() {
{
static_assert(has_emplace<int>(), "");
static_assert(has_emplace<int, int>(), "");
static_assert(!has_emplace<int, int, int>(), "not constructible");
static_assert(!has_emplace_init_list<int, int>(), "not constructible from il");
}
{
static_assert(has_emplace<small>(), "");
static_assert(has_emplace<large>(), "");
static_assert(!has_emplace<small, void*>(), "");
static_assert(!has_emplace<large, void*>(), "");

static_assert(has_emplace_init_list<small, int>(), "");
static_assert(has_emplace_init_list<large, int>(), "");
static_assert(!has_emplace_init_list<small, void*>(), "");
static_assert(!has_emplace_init_list<large, void*>(), "");
}
{
// Test that the emplace SFINAE's away when the
// argument is non-copyable
struct NoCopy {
NoCopy() = default;
NoCopy(NoCopy const&) = delete;
NoCopy(int) {}
NoCopy(std::initializer_list<int>, int, int) {}
};
static_assert(!has_emplace<NoCopy>(), "");
static_assert(!has_emplace<NoCopy, int>(), "");
static_assert(!has_emplace_init_list<NoCopy, int, int, int>(), "");
}
}

int main() {
test_emplace_type<small>();
test_emplace_type<large>();
test_emplace_type<small_throws_on_copy>();
test_emplace_type<large_throws_on_copy>();
test_emplace_type<throws_on_move>();
test_emplace_type_tracked<small_tracked_t>();
test_emplace_type_tracked<large_tracked_t>();
test_emplace_sfinae_constraints();
#ifndef TEST_HAS_NO_EXCEPTIONS
test_emplace_throws<SmallThrows>();
test_emplace_throws<LargeThrows>();
#endif
}
Original file line number Diff line number Diff line change
@@ -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, c++14

// <any>

// any::reset() noexcept

#include <any>
#include <cassert>

#include "any_helpers.h"

int main()
{
using std::any;
using std::any_cast;
// empty
{
any a;

// noexcept check
static_assert(
noexcept(a.reset())
, "any.reset() must be noexcept"
);

assertEmpty(a);

a.reset();

assertEmpty(a);
}
// small object
{
any a((small(1)));
assert(small::count == 1);
assertContains<small>(a, 1);

a.reset();

assertEmpty<small>(a);
assert(small::count == 0);
}
// large object
{
any a(large(1));
assert(large::count == 1);
assertContains<large>(a);

a.reset();

assertEmpty<large>(a);
assert(large::count == 0);
}
}
101 changes: 101 additions & 0 deletions libcxx/test/std/utilities/any/any.class/any.modifiers/swap.pass.cpp
Original file line number Diff line number Diff line change
@@ -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, c++14

// <any>

// any::swap(any &) noexcept

// Test swap(large, small) and swap(small, large)

#include <any>
#include <cassert>

#include "any_helpers.h"

using std::any;
using std::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>();
}
Original file line number Diff line number Diff line change
@@ -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, c++14

// <any>

// any::has_value() noexcept

#include <any>
#include <cassert>

#include "any_helpers.h"

int main()
{
using std::any;
// noexcept test
{
any a;
static_assert(noexcept(a.has_value()), "any::has_value() must be noexcept");
}
// empty
{
any a;
assert(!a.has_value());

a.reset();
assert(!a.has_value());

a = 42;
assert(a.has_value());
}
// small object
{
small const s(1);
any a(s);
assert(a.has_value());

a.reset();
assert(!a.has_value());

a = s;
assert(a.has_value());
}
// large object
{
large const l(1);
any a(l);
assert(a.has_value());

a.reset();
assert(!a.has_value());

a = l;
assert(a.has_value());
}
}
Original file line number Diff line number Diff line change
@@ -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, c++14

// XFAIL: libcpp-no-rtti

// <any>

// any::type() noexcept

#include <any>
#include <cassert>
#include "any_helpers.h"

int main()
{
using std::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));
}
}
21 changes: 21 additions & 0 deletions libcxx/test/std/utilities/any/any.class/not_literal_type.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//===----------------------------------------------------------------------===//
//
// 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, c++14

// <any>

// [Note any is a not a literal type --end note]

#include <any>
#include <type_traits>

int main () {
static_assert(!std::is_literal_type<std::any>::value, "");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
//===----------------------------------------------------------------------===//
//
// 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, c++14

// <any>

// template <class ValueType>
// ValueType const* any_cast(any const *) noexcept;
//
// template <class ValueType>
// ValueType * any_cast(any *) noexcept;

#include <any>
#include <type_traits>
#include <cassert>

#include "any_helpers.h"

using std::any;
using std::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.reset();
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);
}

void test_cast_non_copyable_type()
{
// Even though 'any' never stores non-copyable types
// we still need to support any_cast<NoCopy>(ptr)
struct NoCopy { NoCopy(NoCopy const&) = delete; };
std::any a(42);
std::any const& ca = a;
assert(std::any_cast<NoCopy>(&a) == nullptr);
assert(std::any_cast<NoCopy>(&ca) == nullptr);
}

int main() {
test_cast_is_noexcept();
test_cast_return_type();
test_cast_nullptr();
test_cast_empty();
test_cast<small>();
test_cast<large>();
test_cast_non_copyable_type();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,396 @@
//===----------------------------------------------------------------------===//
//
// 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, c++14

// <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 <any>
#include <type_traits>
#include <cassert>

#include "any_helpers.h"
#include "count_new.hpp"
#include "test_macros.h"

using std::any;
using std::any_cast;
using std::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 getting a type by reference from a const rvalue any.
{
Type&& v = any_cast<Type&&>(std::move(a));
assert(v.value == 42);
assert(any_cast<Type&>(a).value == 42);

Type&& cv = any_cast<Type&&>(std::move(a));
assert(&cv == &v);
assert(any_cast<Type&>(a).value == 42);
}
// Check getting a type by reference from a const rvalue any.
{
Type const&& v = any_cast<Type const&&>(std::move(a));
assert(v.value == 42);
assert(any_cast<Type&>(a).value == 42);

Type const&& cv = any_cast<Type const&&>(std::move(a));
assert(&cv == &v);
assert(any_cast<Type&>(a).value == 42);
}
// 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::moved == 1);
assert(Type::copied == 0);
assert(Type::const_copied == 0);
assert(Type::non_const_copied == 0);
assert(t.value == 42);
assert(any_cast<Type&>(a).value == 0);
any_cast<Type&>(a).value = 42; // reset the value
}
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(any_cast<Type&>(a).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);
assert(any_cast<Type&>(a).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);
}

void test_cast_to_value_deleted_move()
{
using Type = deleted_move;
{
std::any a(deleted_move(42));
assert(Type::count == 1);
assert(Type::copied == 1);
assert(Type::moved == 0);

Type const& t = any_cast<Type>(a);
assert(Type::count == 2);
assert(Type::copied == 2);
assert(Type::moved == 0);
assertContains<Type>(a, 42);
}
assert(Type::count == 0);
Type::reset();
{
std::any a(deleted_move(42));
std::any const& ca = a;
assert(Type::count == 1);
assert(Type::copied == 1);
assert(Type::moved == 0);

Type const& t = any_cast<Type>(ca);
assert(Type::count == 2);
assert(Type::copied == 2);
assert(Type::moved == 0);
assertContains<Type>(a, 42);
}
assert(Type::count == 0);
Type::reset();
{
std::any a(deleted_move(42));
assert(Type::count == 1);
assert(Type::copied == 1);
assert(Type::moved == 0);

Type&& t = any_cast<Type>(std::move(a));
assert(Type::count == 2);
assert(Type::copied == 2);
assert(Type::moved == 0);
assertContains<Type>(a, 42);
}
assert(Type::count == 0);
Type::reset();
{
std::any a(deleted_move(42));
std::any const& ca = a;
assert(Type::count == 1);
assert(Type::copied == 1);
assert(Type::moved == 0);

Type&& t = any_cast<Type>(std::move(ca));
assert(Type::count == 2);
assert(Type::copied == 2);
assert(Type::moved == 0);
assertContains<Type>(a, 42);
}
assert(Type::count == 0);
Type::reset();
}

// 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_cast_to_value_deleted_move();
test_non_copyable_ref();
}
Original file line number Diff line number Diff line change
@@ -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, c++14

// <any>

// template <class ValueType>
// ValueType any_cast(any const &);

// Try and cast away const.

#include <any>

struct TestType {};
struct TestType2 {};

int main()
{
using std::any;
using std::any_cast;

any a;

// expected-error@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@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}}
}
Original file line number Diff line number Diff line change
@@ -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, c++14

// <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 <any>

using std::any;
using std::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)); // expected-note {{requested here}}
any_cast<no_copy>(static_cast<any const&>(a)); // expected-note {{requested here}}
any_cast<no_copy>(static_cast<any &&>(a)); // expected-note {{requested here}}
// expected-error@any:* 3 {{static_assert failed "_ValueType is required to be a reference or a CopyConstructible type."}}
// expected-error@any:* 2 {{calling a private constructor of class 'no_copy'}}
}
Original file line number Diff line number Diff line change
@@ -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, c++14

// <any>

// template <class ValueType>
// ValueType const* any_cast(any const *) noexcept;
//
// template <class ValueType>
// ValueType * any_cast(any *) noexcept;

#include <any>

using std::any;
using std::any_cast;

int main()
{
any a(1);
any_cast<int &>(&a); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}}
any_cast<int &&>(&a); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}}
any_cast<int const &>(&a); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}}
any_cast<int const&&>(&a); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}}
any const& a2 = a;
any_cast<int &>(&a2); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}}
any_cast<int &&>(&a2); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}}
any_cast<int const &>(&a2); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}}
any_cast<int const &&>(&a2); // expected-error@any:* 1 {{static_assert failed "_ValueType may not be a reference."}}
}
140 changes: 140 additions & 0 deletions libcxx/test/std/utilities/any/any.nonmembers/make_any.pass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
//===----------------------------------------------------------------------===//
//
// 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, c++14

// <any>

// template <class T, class ...Args> any make_any(Args&&...);
// template <class T, class U, class ...Args>
// any make_any(initializer_list<U>, Args&&...);

#include <any>
#include <cassert>

#include "any_helpers.h"
#include "count_new.hpp"
#include "test_macros.h"

using std::any;
using std::any_cast;


template <class Type>
void test_make_any_type() {
// constructing from a small type should perform no allocations.
DisableAllocationGuard g(isSmallType<Type>()); ((void)g);
assert(Type::count == 0);
Type::reset();
{
any a = std::make_any<Type>();

assert(Type::count == 1);
assert(Type::copied == 0);
assert(Type::moved == 0);
assertContains<Type>(a, 0);
}
assert(Type::count == 0);
Type::reset();
{
any a = std::make_any<Type>(101);

assert(Type::count == 1);
assert(Type::copied == 0);
assert(Type::moved == 0);
assertContains<Type>(a, 101);
}
assert(Type::count == 0);
Type::reset();
{
any a = std::make_any<Type>(-1, 42, -1);

assert(Type::count == 1);
assert(Type::copied == 0);
assert(Type::moved == 0);
assertContains<Type>(a, 42);
}
assert(Type::count == 0);
Type::reset();
}

template <class Type>
void test_make_any_type_tracked() {
// constructing from a small type should perform no allocations.
DisableAllocationGuard g(isSmallType<Type>()); ((void)g);
{
any a = std::make_any<Type>();
assertArgsMatch<Type>(a);
}
{
any a = std::make_any<Type>(-1, 42, -1);
assertArgsMatch<Type, int, int, int>(a);
}
// initializer_list constructor tests
{
any a = std::make_any<Type>({-1, 42, -1});
assertArgsMatch<Type, std::initializer_list<int>>(a);
}
{
int x = 42;
any a = std::make_any<Type>({-1, 42, -1}, x);
assertArgsMatch<Type, std::initializer_list<int>, int&>(a);
}
}

#ifndef TEST_HAS_NO_EXCEPTIONS

struct SmallThrows {
SmallThrows(int) { throw 42; }
SmallThrows(std::initializer_list<int>, int) { throw 42; }
};
static_assert(IsSmallObject<SmallThrows>::value, "");

struct LargeThrows {
LargeThrows(int) { throw 42; }
LargeThrows(std::initializer_list<int>, int) { throw 42; }
int data[10];
};
static_assert(!IsSmallObject<LargeThrows>::value, "");

template <class Type>
void test_make_any_throws()
{
{
try {
std::make_any<Type>(101);
assert(false);
} catch (int const&) {
}
}
{
try {
std::make_any<Type>({1, 2, 3}, 101);
assert(false);
} catch (int const&) {
}
}
}

#endif

int main() {
test_make_any_type<small>();
test_make_any_type<large>();
test_make_any_type<small_throws_on_copy>();
test_make_any_type<large_throws_on_copy>();
test_make_any_type<throws_on_move>();
test_make_any_type_tracked<small_tracked_t>();
test_make_any_type_tracked<large_tracked_t>();
#ifndef TEST_HAS_NO_EXCEPTIONS
test_make_any_throws<SmallThrows>();
test_make_any_throws<LargeThrows>();

#endif
}
40 changes: 40 additions & 0 deletions libcxx/test/std/utilities/any/any.nonmembers/swap.pass.cpp
Original file line number Diff line number Diff line change
@@ -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, c++14

// <any>

// void swap(any &, any &) noexcept

// swap(...) just wraps any::swap(...). That function is tested elsewhere.

#include <any>
#include <cassert>

using std::any;
using std::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);
}
}
215 changes: 186 additions & 29 deletions libcxx/test/support/any_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
#ifndef ANY_HELPERS_H
#define ANY_HELPERS_H

#include <experimental/any>
#include <typeinfo>
#include <type_traits>
#include <cassert>

namespace std { namespace experimental {} }

#include "test_macros.h"
#include "type_id.h"

#if !defined(TEST_HAS_NO_RTTI)
#define RTTI_ASSERT(X) assert(X)
Expand All @@ -32,42 +34,55 @@ template <class _Tp>
>
{};

template <class T>
bool containsType(std::any const& a) {
#if !defined(TEST_HAS_NO_RTTI)
return a.type() == typeid(T);
#else
return a.has_value() && std::any_cast<T>(&a) != nullptr;
#endif
}

// 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());
void assertEmpty(std::any const& a) {
using namespace std;
assert(!a.has_value());
RTTI_ASSERT(a.type() == typeid(void));
assert(std::experimental::any_cast<LastType const>(&a) == nullptr);
assert(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);
void assertContains(std::any const& a, int value = 1) {
assert(a.has_value());
assert(containsType<Type>(a));
assert(std::any_cast<Type const &>(a).value == value);
}

template <>
void assertContains<int>(std::any const& a, int value) {
assert(a.has_value());
assert(containsType<int>(a));
assert(std::any_cast<int const &>(a) == 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;
void modifyValue(std::any& a, int value) {
using namespace std;
using namespace std::experimental;
assert(a.has_value());
assert(containsType<Type>(a));
any_cast<Type&>(a).value = value;
}

// A test type that will trigger the small object optimization within 'any'.
Expand All @@ -89,25 +104,31 @@ struct small_type

int value;

explicit small_type(int val) : value(val) {
explicit small_type(int val = 0) : value(val) {
++count;
}
explicit small_type(int, int val, int) : value(val) {
++count;
}
small_type(std::initializer_list<int> il) : value(*il.begin()) {
++count;
}

small_type(small_type const & other) throw() {
small_type(small_type const & other) noexcept {
value = other.value;
++count;
++copied;
++const_copied;
}

small_type(small_type& other) throw() {
small_type(small_type& other) noexcept {
value = other.value;
++count;
++copied;
++non_const_copied;
}

small_type(small_type && other) throw() {
small_type(small_type && other) noexcept {
value = other.value;
other.value = 0;
++count;
Expand Down Expand Up @@ -163,11 +184,17 @@ struct large_type

int value;

large_type(int val) : value(val) {
large_type(int val = 0) : value(val) {
++count;
data[0] = 0;
}

large_type(int, int val, int) : value(val) {
++count;
data[0] = 0;
}
large_type(std::initializer_list<int> il) : value(*il.begin()) {
++count;
}
large_type(large_type const & other) {
value = other.value;
++count;
Expand Down Expand Up @@ -219,6 +246,67 @@ typedef large_type<> large;
typedef large_type<1> large1;
typedef large_type<2> large2;


struct deleted_move
{
static int count;
static int copied;
static int moved;
static int const_copied;
static int non_const_copied;

static void reset() {
deleted_move::copied = 0;
deleted_move::moved = 0;
deleted_move::const_copied = 0;
deleted_move::non_const_copied = 0;
}

int value;

explicit deleted_move(int val = 0) : value(val) {
++count;
}
explicit deleted_move(int, int val, int) : value(val) {
++count;
}
deleted_move(std::initializer_list<int> il) : value(*il.begin()) {
++count;
}

deleted_move(deleted_move const & other) noexcept {
value = other.value;
++count;
++copied;
++const_copied;
}

deleted_move(deleted_move& other) noexcept {
value = other.value;
++count;
++copied;
++non_const_copied;
}

deleted_move(deleted_move && other) = delete;

~deleted_move() {
value = -1;
--count;
}

private:
deleted_move& operator=(deleted_move const&) = delete;
deleted_move& operator=(deleted_move&&) = delete;
};

int deleted_move::count = 0;
int deleted_move::copied = 0;
int deleted_move::moved = 0;
int deleted_move::const_copied = 0;
int deleted_move::non_const_copied = 0;


// The exception type thrown by 'small_throws_on_copy', 'large_throws_on_copy'
// and 'throws_on_move'.
struct my_any_exception {};
Expand All @@ -236,19 +324,24 @@ void throwMyAnyExpression() {
struct small_throws_on_copy
{
static int count;
static int copied;
static int moved;
static void reset() { count = copied = moved = 0; }
int value;

explicit small_throws_on_copy(int val = 0) : value(val) {
++count;
}

explicit small_throws_on_copy(int, int val, int) : 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;
++count; ++moved;
}

~small_throws_on_copy() {
Expand All @@ -260,26 +353,35 @@ struct small_throws_on_copy
};

int small_throws_on_copy::count = 0;
int small_throws_on_copy::copied = 0;
int small_throws_on_copy::moved = 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;
static int copied;
static int moved;
static void reset() { count = copied = moved = 0; }
int value = 0;

explicit large_throws_on_copy(int val = 0) : value(val) {
data[0] = 0;
++count;
}

explicit large_throws_on_copy(int, int val, int) : 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;
++count; ++moved;
}

~large_throws_on_copy() {
Expand All @@ -293,19 +395,24 @@ struct large_throws_on_copy
};

int large_throws_on_copy::count = 0;
int large_throws_on_copy::copied = 0;
int large_throws_on_copy::moved = 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;
static int copied;
static int moved;
static void reset() { count = copied = moved = 0; }
int value;

explicit throws_on_move(int val = 0) : value(val) { ++count; }

explicit throws_on_move(int, int val, int) : value(val) { ++count; }
throws_on_move(throws_on_move const & other) {
value = other.value;
++count;
++count; ++copied;
}

throws_on_move(throws_on_move &&) {
Expand All @@ -321,6 +428,56 @@ struct throws_on_move
};

int throws_on_move::count = 0;
int throws_on_move::copied = 0;
int throws_on_move::moved = 0;

struct small_tracked_t {
small_tracked_t()
: arg_types(&makeArgumentID<>()) {}
small_tracked_t(small_tracked_t const&) noexcept
: arg_types(&makeArgumentID<small_tracked_t const&>()) {}
small_tracked_t(small_tracked_t &&) noexcept
: arg_types(&makeArgumentID<small_tracked_t &&>()) {}
template <class ...Args>
explicit small_tracked_t(Args&&...)
: arg_types(&makeArgumentID<Args...>()) {}
template <class ...Args>
explicit small_tracked_t(std::initializer_list<int>, Args&&...)
: arg_types(&makeArgumentID<std::initializer_list<int>, Args...>()) {}

TypeID const* arg_types;
};
static_assert(IsSmallObject<small_tracked_t>::value, "must be small");

struct large_tracked_t {
large_tracked_t()
: arg_types(&makeArgumentID<>()) { dummy[0] = 42; }
large_tracked_t(large_tracked_t const&) noexcept
: arg_types(&makeArgumentID<large_tracked_t const&>()) {}
large_tracked_t(large_tracked_t &&) noexcept
: arg_types(&makeArgumentID<large_tracked_t &&>()) {}
template <class ...Args>
explicit large_tracked_t(Args&&...)
: arg_types(&makeArgumentID<Args...>()) {}
template <class ...Args>
explicit large_tracked_t(std::initializer_list<int>, Args&&...)
: arg_types(&makeArgumentID<std::initializer_list<int>, Args...>()) {}

TypeID const* arg_types;
int dummy[10];
};

static_assert(!IsSmallObject<large_tracked_t>::value, "must be small");


template <class Type, class ...Args>
void assertArgsMatch(std::any const& a) {
using namespace std;
using namespace std::experimental;
assert(a.has_value());
assert(containsType<Type>(a));
assert(any_cast<Type const &>(a).arg_types == &makeArgumentID<Args...>());
};


#endif
Loading