aboutsummaryrefslogtreecommitdiff
path: root/test/std/utilities/optional/optional.object
diff options
context:
space:
mode:
Diffstat (limited to 'test/std/utilities/optional/optional.object')
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp273
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp254
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp102
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp237
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp113
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp174
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp67
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp268
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp143
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp128
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp134
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp155
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp81
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp121
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp84
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp148
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp116
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp201
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp73
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp93
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp153
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp68
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp61
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp37
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp73
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp69
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp69
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp73
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp37
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp72
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp76
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.observe/value.pass.cpp73
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.observe/value_const.fail.cpp33
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp64
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp64
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp68
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.observe/value_or_const.pass.cpp77
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.observe/value_rvalue.pass.cpp72
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp306
-rw-r--r--test/std/utilities/optional/optional.object/optional_requires_destructible_object.fail.cpp50
-rw-r--r--test/std/utilities/optional/optional.object/special_member_gen.pass.cpp74
-rw-r--r--test/std/utilities/optional/optional.object/types.pass.cpp38
42 files changed, 4672 insertions, 0 deletions
diff --git a/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp
new file mode 100644
index 000000000000..1207e24150ff
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp
@@ -0,0 +1,273 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class U> optional<T>& operator=(U&& v);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+#include <memory>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+using std::optional;
+
+struct ThrowAssign {
+ static int dtor_called;
+ ThrowAssign() = default;
+ ThrowAssign(int) { TEST_THROW(42); }
+ ThrowAssign& operator=(int) {
+ TEST_THROW(42);
+ }
+ ~ThrowAssign() { ++dtor_called; }
+};
+int ThrowAssign::dtor_called = 0;
+
+template <class T, class Arg = T, bool Expect = true>
+void assert_assignable() {
+ static_assert(std::is_assignable<optional<T>&, Arg>::value == Expect, "");
+ static_assert(!std::is_assignable<const optional<T>&, Arg>::value, "");
+}
+
+struct MismatchType {
+ explicit MismatchType(int) {}
+ explicit MismatchType(char*) {}
+ explicit MismatchType(int*) = delete;
+ MismatchType& operator=(int) { return *this; }
+ MismatchType& operator=(int*) { return *this; }
+ MismatchType& operator=(char*) = delete;
+};
+
+struct FromOptionalType {
+ using Opt = std::optional<FromOptionalType>;
+ FromOptionalType() = default;
+ FromOptionalType(FromOptionalType const&) = delete;
+ template <class Dummy = void>
+ constexpr FromOptionalType(Opt&) { Dummy::BARK; }
+ template <class Dummy = void>
+ constexpr FromOptionalType& operator=(Opt&) { Dummy::BARK; return *this; }
+};
+
+void test_sfinae() {
+ using I = TestTypes::TestType;
+ using E = ExplicitTestTypes::TestType;
+ assert_assignable<int>();
+ assert_assignable<int, int&>();
+ assert_assignable<int, int const&>();
+ // Implicit test type
+ assert_assignable<I, I const&>();
+ assert_assignable<I, I&&>();
+ assert_assignable<I, int>();
+ assert_assignable<I, void*, false>();
+ // Explicit test type
+ assert_assignable<E, E const&>();
+ assert_assignable<E, E &&>();
+ assert_assignable<E, int>();
+ assert_assignable<E, void*, false>();
+ // Mismatch type
+ assert_assignable<MismatchType, int>();
+ assert_assignable<MismatchType, int*, false>();
+ assert_assignable<MismatchType, char*, false>();
+ // Type constructible from optional
+ assert_assignable<FromOptionalType, std::optional<FromOptionalType>&, false>();
+}
+
+void test_with_test_type()
+{
+ using T = TestTypes::TestType;
+ T::reset();
+ { // to empty
+ optional<T> opt;
+ opt = 3;
+ assert(T::alive == 1);
+ assert(T::constructed == 1);
+ assert(T::value_constructed == 1);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 0);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(3));
+ }
+ { // to existing
+ optional<T> opt(42);
+ T::reset_constructors();
+ opt = 3;
+ assert(T::alive == 1);
+ assert(T::constructed == 0);
+ assert(T::assigned == 1);
+ assert(T::value_assigned == 1);
+ assert(T::destroyed == 0);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(3));
+ }
+ { // test default argument
+ optional<T> opt;
+ T::reset_constructors();
+ opt = {1, 2};
+ assert(T::alive == 1);
+ assert(T::constructed == 2);
+ assert(T::value_constructed == 1);
+ assert(T::move_constructed == 1);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(1, 2));
+ }
+ { // test default argument
+ optional<T> opt(42);
+ T::reset_constructors();
+ opt = {1, 2};
+ assert(T::alive == 1);
+ assert(T::constructed == 1);
+ assert(T::value_constructed == 1);
+ assert(T::assigned == 1);
+ assert(T::move_assigned == 1);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(1, 2));
+ }
+ { // test default argument
+ optional<T> opt;
+ T::reset_constructors();
+ opt = {1};
+ assert(T::alive == 1);
+ assert(T::constructed == 2);
+ assert(T::value_constructed == 1);
+ assert(T::move_constructed == 1);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(1));
+ }
+ { // test default argument
+ optional<T> opt(42);
+ T::reset_constructors();
+ opt = {};
+ assert(static_cast<bool>(opt) == false);
+ assert(T::alive == 0);
+ assert(T::constructed == 0);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 1);
+ }
+}
+
+template <class T, class Value = int>
+void test_with_type() {
+ { // to empty
+ optional<T> opt;
+ opt = Value(3);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(3));
+ }
+ { // to existing
+ optional<T> opt(Value(42));
+ opt = Value(3);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(3));
+ }
+ { // test const
+ optional<T> opt(Value(42));
+ const T t(Value(3));
+ opt = t;
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(3));
+ }
+ { // test default argument
+ optional<T> opt;
+ opt = {Value(1)};
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(1));
+ }
+ { // test default argument
+ optional<T> opt(Value(42));
+ opt = {};
+ assert(static_cast<bool>(opt) == false);
+ }
+}
+
+template <class T>
+void test_with_type_multi() {
+ test_with_type<T>();
+ { // test default argument
+ optional<T> opt;
+ opt = {1, 2};
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(1, 2));
+ }
+ { // test default argument
+ optional<T> opt(42);
+ opt = {1, 2};
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(1, 2));
+ }
+}
+
+void test_throws()
+{
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ using T = ThrowAssign;
+ {
+ using T = ThrowAssign;
+ optional<T> opt;
+ try {
+ opt = 42;
+ assert(false);
+ } catch (int) {}
+ assert(static_cast<bool>(opt) == false);
+ }
+ assert(T::dtor_called == 0);
+ {
+ T::dtor_called = 0;
+ optional<T> opt(std::in_place);
+ try {
+ opt = 42;
+ assert(false);
+ } catch (int) {}
+ assert(static_cast<bool>(opt) == true);
+ assert(T::dtor_called == 0);
+ }
+ assert(T::dtor_called == 1);
+#endif
+}
+
+enum MyEnum { Zero, One, Two, Three, FortyTwo = 42 };
+
+using Fn = void(*)();
+
+int main()
+{
+ test_sfinae();
+ // Test with instrumented type
+ test_with_test_type();
+ // Test with various scalar types
+ test_with_type<int>();
+ test_with_type<MyEnum, MyEnum>();
+ test_with_type<int, MyEnum>();
+ test_with_type<Fn, Fn>();
+ // Test types with multi argument constructors
+ test_with_type_multi<ConstexprTestTypes::TestType>();
+ test_with_type_multi<TrivialTestTypes::TestType>();
+ // Test move only types
+ {
+ optional<std::unique_ptr<int>> opt;
+ opt = std::unique_ptr<int>(new int(3));
+ assert(static_cast<bool>(opt) == true);
+ assert(**opt == 3);
+ }
+ {
+ optional<std::unique_ptr<int>> opt(std::unique_ptr<int>(new int(2)));
+ opt = std::unique_ptr<int>(new int(3));
+ assert(static_cast<bool>(opt) == true);
+ assert(**opt == 3);
+ }
+ test_throws();
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp
new file mode 100644
index 000000000000..d471c053c907
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp
@@ -0,0 +1,254 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// <optional>
+
+// From LWG2451:
+// template<class U>
+// optional<T>& operator=(const optional<U>& rhs);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+using std::optional;
+
+struct X
+{
+ static bool throw_now;
+
+ X() = default;
+ X(int)
+ {
+ if (throw_now)
+ TEST_THROW(6);
+ }
+};
+
+bool X::throw_now = false;
+
+struct Y1
+{
+ Y1() = default;
+ Y1(const int&) {}
+ Y1& operator=(const Y1&) = delete;
+};
+
+struct Y2
+{
+ Y2() = default;
+ Y2(const int&) = delete;
+ Y2& operator=(const int&) { return *this; }
+};
+
+template <class T>
+struct AssignableFrom {
+ static int type_constructed;
+ static int type_assigned;
+static int int_constructed;
+ static int int_assigned;
+
+ static void reset() {
+ type_constructed = int_constructed = 0;
+ type_assigned = int_assigned = 0;
+ }
+
+ AssignableFrom() = default;
+
+ explicit AssignableFrom(T) { ++type_constructed; }
+ AssignableFrom& operator=(T) { ++type_assigned; return *this; }
+
+ AssignableFrom(int) { ++int_constructed; }
+ AssignableFrom& operator=(int) { ++int_assigned; return *this; }
+private:
+ AssignableFrom(AssignableFrom const&) = delete;
+ AssignableFrom& operator=(AssignableFrom const&) = delete;
+};
+
+template <class T> int AssignableFrom<T>::type_constructed = 0;
+template <class T> int AssignableFrom<T>::type_assigned = 0;
+template <class T> int AssignableFrom<T>::int_constructed = 0;
+template <class T> int AssignableFrom<T>::int_assigned = 0;
+
+
+void test_with_test_type() {
+ using T = TestTypes::TestType;
+ T::reset();
+ { // non-empty to empty
+ T::reset_constructors();
+ optional<T> opt;
+ const optional<int> other(42);
+ opt = other;
+ assert(T::alive == 1);
+ assert(T::constructed == 1);
+ assert(T::value_constructed == 1);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 0);
+ assert(static_cast<bool>(other) == true);
+ assert(*other == 42);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(42));
+ }
+ assert(T::alive == 0);
+ { // non-empty to non-empty
+ optional<T> opt(101);
+ const optional<int> other(42);
+ T::reset_constructors();
+ opt = other;
+ assert(T::alive == 1);
+ assert(T::constructed == 0);
+ assert(T::assigned == 1);
+ assert(T::value_assigned == 1);
+ assert(T::destroyed == 0);
+ assert(static_cast<bool>(other) == true);
+ assert(*other == 42);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(42));
+ }
+ assert(T::alive == 0);
+ { // empty to non-empty
+ optional<T> opt(101);
+ const optional<int> other;
+ T::reset_constructors();
+ opt = other;
+ assert(T::alive == 0);
+ assert(T::constructed == 0);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(other) == false);
+ assert(static_cast<bool>(opt) == false);
+ }
+ assert(T::alive == 0);
+ { // empty to empty
+ optional<T> opt;
+ const optional<int> other;
+ T::reset_constructors();
+ opt = other;
+ assert(T::alive == 0);
+ assert(T::constructed == 0);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 0);
+ assert(static_cast<bool>(other) == false);
+ assert(static_cast<bool>(opt) == false);
+ }
+ assert(T::alive == 0);
+}
+
+void test_ambigious_assign() {
+ using OptInt = std::optional<int>;
+ {
+ using T = AssignableFrom<OptInt const&>;
+ const OptInt a(42);
+ T::reset();
+ {
+ std::optional<T> t;
+ t = a;
+ assert(T::type_constructed == 1);
+ assert(T::type_assigned == 0);
+ assert(T::int_constructed == 0);
+ assert(T::int_assigned == 0);
+ }
+ T::reset();
+ {
+ std::optional<T> t(42);
+ t = a;
+ assert(T::type_constructed == 0);
+ assert(T::type_assigned == 1);
+ assert(T::int_constructed == 1);
+ assert(T::int_assigned == 0);
+ }
+ T::reset();
+ {
+ std::optional<T> t(42);
+ t = std::move(a);
+ assert(T::type_constructed == 0);
+ assert(T::type_assigned == 1);
+ assert(T::int_constructed == 1);
+ assert(T::int_assigned == 0);
+ }
+ }
+ {
+ using T = AssignableFrom<OptInt&>;
+ OptInt a(42);
+ T::reset();
+ {
+ std::optional<T> t;
+ t = a;
+ assert(T::type_constructed == 1);
+ assert(T::type_assigned == 0);
+ assert(T::int_constructed == 0);
+ assert(T::int_assigned == 0);
+ }
+ {
+ using Opt = std::optional<T>;
+ static_assert(!std::is_assignable_v<Opt&, OptInt const&>, "");
+ }
+ }
+}
+
+
+int main()
+{
+ test_with_test_type();
+ test_ambigious_assign();
+ {
+ optional<int> opt;
+ constexpr optional<short> opt2;
+ opt = opt2;
+ static_assert(static_cast<bool>(opt2) == false, "");
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ }
+ {
+ optional<int> opt;
+ constexpr optional<short> opt2(short{2});
+ opt = opt2;
+ static_assert(static_cast<bool>(opt2) == true, "");
+ static_assert(*opt2 == 2, "");
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ assert(*opt == *opt2);
+ }
+ {
+ optional<int> opt(3);
+ constexpr optional<short> opt2;
+ opt = opt2;
+ static_assert(static_cast<bool>(opt2) == false, "");
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ }
+ {
+ optional<int> opt(3);
+ constexpr optional<short> opt2(short{2});
+ opt = opt2;
+ static_assert(static_cast<bool>(opt2) == true, "");
+ static_assert(*opt2 == 2, "");
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ assert(*opt == *opt2);
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ optional<X> opt;
+ optional<int> opt2(42);
+ assert(static_cast<bool>(opt2) == true);
+ try
+ {
+ X::throw_now = true;
+ opt = opt2;
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ assert(static_cast<bool>(opt) == false);
+ }
+ }
+#endif
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp
new file mode 100644
index 000000000000..98c90aa1d4fb
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.assign/copy.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, c++14
+// <optional>
+
+// optional<T>& operator=(const optional<T>& rhs);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+using std::optional;
+
+struct X
+{
+ static bool throw_now;
+
+ X() = default;
+ X(const X&)
+ {
+ if (throw_now)
+ TEST_THROW(6);
+ }
+};
+
+bool X::throw_now = false;
+
+template <class Tp>
+constexpr bool assign_empty(optional<Tp>&& lhs) {
+ const optional<Tp> rhs;
+ lhs = rhs;
+ return !lhs.has_value() && !rhs.has_value();
+}
+
+template <class Tp>
+constexpr bool assign_value(optional<Tp>&& lhs) {
+ const optional<Tp> rhs(101);
+ lhs = rhs;
+ return lhs.has_value() && rhs.has_value() && *lhs == *rhs;
+}
+
+int main()
+{
+ {
+ using O = optional<int>;
+ LIBCPP_STATIC_ASSERT(assign_empty(O{42}), "");
+ LIBCPP_STATIC_ASSERT(assign_value(O{42}), "");
+ assert(assign_empty(O{42}));
+ assert(assign_value(O{42}));
+ }
+ {
+ using O = optional<TrivialTestTypes::TestType>;
+ LIBCPP_STATIC_ASSERT(assign_empty(O{42}), "");
+ LIBCPP_STATIC_ASSERT(assign_value(O{42}), "");
+ assert(assign_empty(O{42}));
+ assert(assign_value(O{42}));
+ }
+ {
+ using O = optional<TestTypes::TestType>;
+ assert(assign_empty(O{42}));
+ assert(assign_value(O{42}));
+ }
+ {
+ using T = TestTypes::TestType;
+ T::reset();
+ optional<T> opt(3);
+ const optional<T> opt2;
+ assert(T::alive == 1);
+ opt = opt2;
+ assert(T::alive == 0);
+ assert(!opt2.has_value());
+ assert(!opt.has_value());
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ optional<X> opt;
+ optional<X> opt2(X{});
+ assert(static_cast<bool>(opt2) == true);
+ try
+ {
+ X::throw_now = true;
+ opt = opt2;
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ assert(static_cast<bool>(opt) == false);
+ }
+ }
+#endif
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp
new file mode 100644
index 000000000000..b5362589963c
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp
@@ -0,0 +1,237 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// <optional>
+
+// template <class... Args> void optional<T>::emplace(Args&&... args);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+#include <memory>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+using std::optional;
+
+class X
+{
+ int i_;
+ int j_ = 0;
+public:
+ X() : i_(0) {}
+ X(int i) : i_(i) {}
+ X(int i, int j) : i_(i), j_(j) {}
+
+ friend bool operator==(const X& x, const X& y)
+ {return x.i_ == y.i_ && x.j_ == y.j_;}
+};
+
+class Y
+{
+public:
+ static bool dtor_called;
+ Y() = default;
+ Y(int) { TEST_THROW(6);}
+ ~Y() {dtor_called = true;}
+};
+
+bool Y::dtor_called = false;
+
+template <class T>
+void test_one_arg() {
+ using Opt = std::optional<T>;
+ {
+ Opt opt;
+ opt.emplace();
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(0));
+ }
+ {
+ Opt opt;
+ opt.emplace(1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(1));
+ }
+ {
+ Opt opt(2);
+ opt.emplace();
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(0));
+ }
+ {
+ Opt opt(2);
+ opt.emplace(1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(1));
+ }
+}
+
+
+template <class T>
+void test_multi_arg()
+{
+ test_one_arg<T>();
+ using Opt = std::optional<T>;
+ {
+ Opt opt;
+ opt.emplace(101, 41);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(101, 41));
+ }
+ {
+ Opt opt;
+ opt.emplace({1, 2, 3, 4});
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(4)); // T sets its value to the size of the init list
+ }
+ {
+ Opt opt;
+ opt.emplace({1, 2, 3, 4, 5}, 6);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(5)); // T sets its value to the size of the init list
+ }
+}
+
+template <class T>
+void test_on_test_type() {
+
+ T::reset();
+ optional<T> opt;
+ assert(T::alive == 0);
+ {
+ T::reset_constructors();
+ opt.emplace();
+ assert(T::alive == 1);
+ assert(T::constructed == 1);
+ assert(T::default_constructed == 1);
+ assert(T::destroyed == 0);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T());
+ }
+ {
+ T::reset_constructors();
+ opt.emplace();
+ assert(T::alive == 1);
+ assert(T::constructed == 1);
+ assert(T::default_constructed == 1);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T());
+ }
+ {
+ T::reset_constructors();
+ opt.emplace(101);
+ assert(T::alive == 1);
+ assert(T::constructed == 1);
+ assert(T::value_constructed == 1);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(101));
+ }
+ {
+ T::reset_constructors();
+ opt.emplace(-10, 99);
+ assert(T::alive == 1);
+ assert(T::constructed == 1);
+ assert(T::value_constructed == 1);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(-10, 99));
+ }
+ {
+ T::reset_constructors();
+ opt.emplace(-10, 99);
+ assert(T::alive == 1);
+ assert(T::constructed == 1);
+ assert(T::value_constructed == 1);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(-10, 99));
+ }
+ {
+ T::reset_constructors();
+ opt.emplace({-10, 99, 42, 1});
+ assert(T::alive == 1);
+ assert(T::constructed == 1);
+ assert(T::value_constructed == 1);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(4)); // size of the initializer list
+ }
+ {
+ T::reset_constructors();
+ opt.emplace({-10, 99, 42, 1}, 42);
+ assert(T::alive == 1);
+ assert(T::constructed == 1);
+ assert(T::value_constructed == 1);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(4)); // size of the initializer list
+ }
+}
+
+
+
+int main()
+{
+ {
+ test_on_test_type<TestTypes::TestType>();
+ test_on_test_type<ExplicitTestTypes::TestType>();
+ }
+ {
+ using T = int;
+ test_one_arg<T>();
+ test_one_arg<const T>();
+ }
+ {
+ using T = ConstexprTestTypes::TestType;
+ test_multi_arg<T>();
+ }
+ {
+ using T = ExplicitConstexprTestTypes::TestType;
+ test_multi_arg<T>();
+ }
+ {
+ using T = TrivialTestTypes::TestType;
+ test_multi_arg<T>();
+ }
+ {
+ using T = ExplicitTrivialTestTypes::TestType;
+ test_multi_arg<T>();
+ }
+ {
+ optional<const int> opt;
+ opt.emplace(42);
+ assert(*opt == 42);
+ opt.emplace();
+ assert(*opt == 0);
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ Y::dtor_called = false;
+ {
+ Y y;
+ optional<Y> opt(y);
+ try
+ {
+ assert(static_cast<bool>(opt) == true);
+ assert(Y::dtor_called == false);
+ opt.emplace(1);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ assert(static_cast<bool>(opt) == false);
+ assert(Y::dtor_called == true);
+ }
+ }
+#endif
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp
new file mode 100644
index 000000000000..1c3c69a70303
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp
@@ -0,0 +1,113 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// <optional>
+
+// template <class U, class... Args>
+// void optional<T>::emplace(initializer_list<U> il, Args&&... args);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+#include <vector>
+
+#include "test_macros.h"
+
+using std::optional;
+
+class X
+{
+ int i_;
+ int j_ = 0;
+public:
+ static bool dtor_called;
+ constexpr X() : i_(0) {}
+ constexpr X(int i) : i_(i) {}
+ constexpr X(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) {}
+ ~X() {dtor_called = true;}
+
+ friend constexpr bool operator==(const X& x, const X& y)
+ {return x.i_ == y.i_ && x.j_ == y.j_;}
+};
+
+bool X::dtor_called = false;
+
+class Y
+{
+ int i_;
+ int j_ = 0;
+public:
+ constexpr Y() : i_(0) {}
+ constexpr Y(int i) : i_(i) {}
+ constexpr Y(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) {}
+
+ friend constexpr bool operator==(const Y& x, const Y& y)
+ {return x.i_ == y.i_ && x.j_ == y.j_;}
+};
+
+class Z
+{
+ int i_;
+ int j_ = 0;
+public:
+ static bool dtor_called;
+ Z() : i_(0) {}
+ Z(int i) : i_(i) {}
+ Z(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1])
+ { TEST_THROW(6);}
+ ~Z() {dtor_called = true;}
+
+ friend bool operator==(const Z& x, const Z& y)
+ {return x.i_ == y.i_ && x.j_ == y.j_;}
+};
+
+bool Z::dtor_called = false;
+
+int main()
+{
+ {
+ X x;
+ optional<X> opt(x);
+ assert(X::dtor_called == false);
+ opt.emplace({1, 2});
+ assert(X::dtor_called == true);
+ assert(*opt == X({1, 2}));
+ }
+ {
+ optional<std::vector<int>> opt;
+ opt.emplace({1, 2, 3}, std::allocator<int>());
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == std::vector<int>({1, 2, 3}));
+ }
+ {
+ optional<Y> opt;
+ opt.emplace({1, 2});
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == Y({1, 2}));
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ Z z;
+ optional<Z> opt(z);
+ try
+ {
+ assert(static_cast<bool>(opt) == true);
+ assert(Z::dtor_called == false);
+ opt.emplace({1, 2});
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ assert(static_cast<bool>(opt) == false);
+ assert(Z::dtor_called == true);
+ }
+ }
+#endif
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp
new file mode 100644
index 000000000000..3ba261b52464
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp
@@ -0,0 +1,174 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// <optional>
+
+// optional<T>& operator=(optional<T>&& rhs)
+// noexcept(is_nothrow_move_assignable<T>::value &&
+// is_nothrow_move_constructible<T>::value);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+using std::optional;
+
+struct X
+{
+ static bool throw_now;
+ static int alive;
+
+ X() { ++alive; }
+ X(X&&)
+ {
+ if (throw_now)
+ TEST_THROW(6);
+ ++alive;
+ }
+
+ X& operator=(X&&)
+ {
+ if (throw_now)
+ TEST_THROW(42);
+ return *this;
+ }
+
+ ~X() { assert(alive > 0); --alive; }
+};
+
+struct Y {};
+
+bool X::throw_now = false;
+int X::alive = 0;
+
+int main()
+{
+ {
+ static_assert(std::is_nothrow_move_assignable<optional<int>>::value, "");
+ optional<int> opt;
+ constexpr optional<int> opt2;
+ opt = std::move(opt2);
+ static_assert(static_cast<bool>(opt2) == false, "");
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ }
+ {
+ optional<int> opt;
+ constexpr optional<int> opt2(2);
+ opt = std::move(opt2);
+ static_assert(static_cast<bool>(opt2) == true, "");
+ static_assert(*opt2 == 2, "");
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ assert(*opt == *opt2);
+ }
+ {
+ optional<int> opt(3);
+ constexpr optional<int> opt2;
+ opt = std::move(opt2);
+ static_assert(static_cast<bool>(opt2) == false, "");
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ }
+ {
+ using T = TestTypes::TestType;
+ T::reset();
+ optional<T> opt(3);
+ optional<T> opt2;
+ assert(T::alive == 1);
+ opt = std::move(opt2);
+ assert(T::alive == 0);
+ assert(static_cast<bool>(opt2) == false);
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ }
+ {
+ optional<int> opt(3);
+ constexpr optional<int> opt2(2);
+ opt = std::move(opt2);
+ static_assert(static_cast<bool>(opt2) == true, "");
+ static_assert(*opt2 == 2, "");
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ assert(*opt == *opt2);
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");
+ X::alive = 0;
+ X::throw_now = false;
+ optional<X> opt;
+ optional<X> opt2(X{});
+ assert(X::alive == 1);
+ assert(static_cast<bool>(opt2) == true);
+ try
+ {
+ X::throw_now = true;
+ opt = std::move(opt2);
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ assert(static_cast<bool>(opt) == false);
+ }
+ assert(X::alive == 1);
+ }
+ assert(X::alive == 0);
+ {
+ static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");
+ X::throw_now = false;
+ optional<X> opt(X{});
+ optional<X> opt2(X{});
+ assert(X::alive == 2);
+ assert(static_cast<bool>(opt2) == true);
+ try
+ {
+ X::throw_now = true;
+ opt = std::move(opt2);
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 42);
+ assert(static_cast<bool>(opt) == true);
+ }
+ assert(X::alive == 2);
+ }
+ assert(X::alive == 0);
+#endif // TEST_HAS_NO_EXCEPTIONS
+ {
+ static_assert(std::is_nothrow_move_assignable<optional<Y>>::value, "");
+ }
+ {
+ struct ThrowsMove {
+ ThrowsMove() noexcept {}
+ ThrowsMove(ThrowsMove const&) noexcept {}
+ ThrowsMove(ThrowsMove &&) noexcept(false) {}
+ ThrowsMove& operator=(ThrowsMove const&) noexcept { return *this; }
+ ThrowsMove& operator=(ThrowsMove &&) noexcept { return *this; }
+ };
+ static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMove>>::value, "");
+ struct ThrowsMoveAssign {
+ ThrowsMoveAssign() noexcept {}
+ ThrowsMoveAssign(ThrowsMoveAssign const&) noexcept {}
+ ThrowsMoveAssign(ThrowsMoveAssign &&) noexcept {}
+ ThrowsMoveAssign& operator=(ThrowsMoveAssign const&) noexcept { return *this; }
+ ThrowsMoveAssign& operator=(ThrowsMoveAssign &&) noexcept(false) { return *this; }
+ };
+ static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMoveAssign>>::value, "");
+ struct NoThrowMove {
+ NoThrowMove() noexcept(false) {}
+ NoThrowMove(NoThrowMove const&) noexcept(false) {}
+ NoThrowMove(NoThrowMove &&) noexcept {}
+ NoThrowMove& operator=(NoThrowMove const&) noexcept { return *this; }
+ NoThrowMove& operator=(NoThrowMove&&) noexcept { return *this; }
+ };
+ static_assert(std::is_nothrow_move_assignable<optional<NoThrowMove>>::value, "");
+ }
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp
new file mode 100644
index 000000000000..991f4334304c
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp
@@ -0,0 +1,67 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// <optional>
+
+// optional<T>& operator=(nullopt_t) noexcept;
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+using std::optional;
+using std::nullopt_t;
+using std::nullopt;
+
+int main()
+{
+ {
+ optional<int> opt;
+ static_assert(noexcept(opt = nullopt) == true, "");
+ opt = nullopt;
+ assert(static_cast<bool>(opt) == false);
+ }
+ {
+ optional<int> opt(3);
+ opt = nullopt;
+ assert(static_cast<bool>(opt) == false);
+ }
+ using TT = TestTypes::TestType;
+ TT::reset();
+ {
+ optional<TT> opt;
+ static_assert(noexcept(opt = nullopt) == true, "");
+ assert(TT::destroyed == 0);
+ opt = nullopt;
+ assert(TT::constructed == 0);
+ assert(TT::alive == 0);
+ assert(TT::destroyed == 0);
+ assert(static_cast<bool>(opt) == false);
+ }
+ assert(TT::alive == 0);
+ assert(TT::destroyed == 0);
+ TT::reset();
+ {
+ optional<TT> opt(42);
+ assert(TT::destroyed == 0);
+ TT::reset_constructors();
+ opt = nullopt;
+ assert(TT::constructed == 0);
+ assert(TT::alive == 0);
+ assert(TT::destroyed == 1);
+ assert(static_cast<bool>(opt) == false);
+ }
+ assert(TT::alive == 0);
+ assert(TT::destroyed == 1);
+ TT::reset();
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp
new file mode 100644
index 000000000000..db7fc19bfb10
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp
@@ -0,0 +1,268 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// <optional>
+
+// From LWG2451:
+// template <class U>
+// optional<T>& operator=(optional<U>&& rhs);
+
+#include <optional>
+#include <type_traits>
+#include <memory>
+#include <cassert>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+using std::optional;
+
+struct X
+{
+ static bool throw_now;
+
+ X() = default;
+ X(int &&)
+ {
+ if (throw_now)
+ TEST_THROW(6);
+ }
+};
+
+bool X::throw_now = false;
+
+struct Y1
+{
+ Y1() = default;
+ Y1(const int&) {}
+ Y1& operator=(const Y1&) = delete;
+};
+
+struct Y2
+{
+ Y2() = default;
+ Y2(const int&) = delete;
+ Y2& operator=(const int&) { return *this; }
+};
+
+class B {};
+class D : public B {};
+
+
+template <class T>
+struct AssignableFrom {
+ static int type_constructed;
+ static int type_assigned;
+static int int_constructed;
+ static int int_assigned;
+
+ static void reset() {
+ type_constructed = int_constructed = 0;
+ type_assigned = int_assigned = 0;
+ }
+
+ AssignableFrom() = default;
+
+ explicit AssignableFrom(T) { ++type_constructed; }
+ AssignableFrom& operator=(T) { ++type_assigned; return *this; }
+
+ AssignableFrom(int) { ++int_constructed; }
+ AssignableFrom& operator=(int) { ++int_assigned; return *this; }
+private:
+ AssignableFrom(AssignableFrom const&) = delete;
+ AssignableFrom& operator=(AssignableFrom const&) = delete;
+};
+
+template <class T> int AssignableFrom<T>::type_constructed = 0;
+template <class T> int AssignableFrom<T>::type_assigned = 0;
+template <class T> int AssignableFrom<T>::int_constructed = 0;
+template <class T> int AssignableFrom<T>::int_assigned = 0;
+
+void test_with_test_type() {
+ using T = TestTypes::TestType;
+ T::reset();
+ { // non-empty to empty
+ T::reset_constructors();
+ optional<T> opt;
+ optional<int> other(42);
+ opt = std::move(other);
+ assert(T::alive == 1);
+ assert(T::constructed == 1);
+ assert(T::value_constructed == 1);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 0);
+ assert(static_cast<bool>(other) == true);
+ assert(*other == 42);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(42));
+ }
+ assert(T::alive == 0);
+ { // non-empty to non-empty
+ optional<T> opt(101);
+ optional<int> other(42);
+ T::reset_constructors();
+ opt = std::move(other);
+ assert(T::alive == 1);
+ assert(T::constructed == 0);
+ assert(T::assigned == 1);
+ assert(T::value_assigned == 1);
+ assert(T::destroyed == 0);
+ assert(static_cast<bool>(other) == true);
+ assert(*other == 42);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(42));
+ }
+ assert(T::alive == 0);
+ { // empty to non-empty
+ optional<T> opt(101);
+ optional<int> other;
+ T::reset_constructors();
+ opt = std::move(other);
+ assert(T::alive == 0);
+ assert(T::constructed == 0);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(other) == false);
+ assert(static_cast<bool>(opt) == false);
+ }
+ assert(T::alive == 0);
+ { // empty to empty
+ optional<T> opt;
+ optional<int> other;
+ T::reset_constructors();
+ opt = std::move(other);
+ assert(T::alive == 0);
+ assert(T::constructed == 0);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 0);
+ assert(static_cast<bool>(other) == false);
+ assert(static_cast<bool>(opt) == false);
+ }
+ assert(T::alive == 0);
+}
+
+
+void test_ambigious_assign() {
+ using OptInt = std::optional<int>;
+ {
+ using T = AssignableFrom<OptInt&&>;
+ T::reset();
+ {
+ OptInt a(42);
+ std::optional<T> t;
+ t = std::move(a);
+ assert(T::type_constructed == 1);
+ assert(T::type_assigned == 0);
+ assert(T::int_constructed == 0);
+ assert(T::int_assigned == 0);
+ }
+ {
+ using Opt = std::optional<T>;
+ static_assert(!std::is_assignable<Opt&, const OptInt&&>::value, "");
+ static_assert(!std::is_assignable<Opt&, const OptInt&>::value, "");
+ static_assert(!std::is_assignable<Opt&, OptInt&>::value, "");
+ }
+ }
+ {
+ using T = AssignableFrom<OptInt const&&>;
+ T::reset();
+ {
+ const OptInt a(42);
+ std::optional<T> t;
+ t = std::move(a);
+ assert(T::type_constructed == 1);
+ assert(T::type_assigned == 0);
+ assert(T::int_constructed == 0);
+ assert(T::int_assigned == 0);
+ }
+ T::reset();
+ {
+ OptInt a(42);
+ std::optional<T> t;
+ t = std::move(a);
+ assert(T::type_constructed == 1);
+ assert(T::type_assigned == 0);
+ assert(T::int_constructed == 0);
+ assert(T::int_assigned == 0);
+ }
+ {
+ using Opt = std::optional<T>;
+ static_assert(std::is_assignable<Opt&, OptInt&&>::value, "");
+ static_assert(!std::is_assignable<Opt&, const OptInt&>::value, "");
+ static_assert(!std::is_assignable<Opt&, OptInt&>::value, "");
+ }
+ }
+}
+
+
+int main()
+{
+ test_with_test_type();
+ test_ambigious_assign();
+ {
+ optional<int> opt;
+ optional<short> opt2;
+ opt = std::move(opt2);
+ assert(static_cast<bool>(opt2) == false);
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ }
+ {
+ optional<int> opt;
+ optional<short> opt2(short{2});
+ opt = std::move(opt2);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 2);
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ assert(*opt == *opt2);
+ }
+ {
+ optional<int> opt(3);
+ optional<short> opt2;
+ opt = std::move(opt2);
+ assert(static_cast<bool>(opt2) == false);
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ }
+ {
+ optional<int> opt(3);
+ optional<short> opt2(short{2});
+ opt = std::move(opt2);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 2);
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ assert(*opt == *opt2);
+ }
+ {
+ optional<std::unique_ptr<B>> opt;
+ optional<std::unique_ptr<D>> other(new D());
+ opt = std::move(other);
+ assert(static_cast<bool>(opt) == true);
+ assert(static_cast<bool>(other) == true);
+ assert(opt->get() != nullptr);
+ assert(other->get() == nullptr);
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ optional<X> opt;
+ optional<int> opt2(42);
+ assert(static_cast<bool>(opt2) == true);
+ try
+ {
+ X::throw_now = true;
+ opt = std::move(opt2);
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ assert(static_cast<bool>(opt) == false);
+ }
+ }
+#endif
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
new file mode 100644
index 000000000000..c4d4763a6f0a
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
@@ -0,0 +1,143 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <optional>
+
+// template <class U>
+// constexpr EXPLICIT optional(U&& u);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+#include "test_convertible.hpp"
+
+
+using std::optional;
+
+struct ImplicitThrow
+{
+ constexpr ImplicitThrow(int x) { if (x != -1) TEST_THROW(6);}
+};
+
+struct ExplicitThrow
+{
+ constexpr explicit ExplicitThrow(int x) { if (x != -1) TEST_THROW(6);}
+};
+
+
+template <class To, class From>
+constexpr bool implicit_conversion(optional<To>&& opt, const From& v)
+{
+ using O = optional<To>;
+ static_assert(test_convertible<O, From>(), "");
+ static_assert(!test_convertible<O, void*>(), "");
+ static_assert(!test_convertible<O, From, int>(), "");
+ return opt && *opt == static_cast<To>(v);
+}
+
+template <class To, class Input, class Expect>
+constexpr bool explicit_conversion(Input&& in, const Expect& v)
+{
+ using O = optional<To>;
+ static_assert(std::is_constructible<O, Input>::value, "");
+ static_assert(!std::is_convertible<Input, O>::value, "");
+ static_assert(!std::is_constructible<O, void*>::value, "");
+ static_assert(!std::is_constructible<O, Input, int>::value, "");
+ optional<To> opt(std::forward<Input>(in));
+ return opt && *opt == static_cast<To>(v);
+}
+
+void test_implicit()
+{
+ {
+ using T = long long;
+ static_assert(implicit_conversion<long long>(42, 42), "");
+ }
+ {
+ using T = long double;
+ static_assert(implicit_conversion<long double>(3.14, 3.14), "");
+ }
+ {
+ int x = 42;
+ optional<void* const> o(&x);
+ assert(*o == &x);
+ }
+ {
+ using T = TrivialTestTypes::TestType;
+ static_assert(implicit_conversion<T>(42, 42), "");
+ }
+ {
+ using T = TestTypes::TestType;
+ assert(implicit_conversion<T>(3, T(3)));
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ try {
+ using T = ImplicitThrow;
+ optional<T> t = 42;
+ assert(false);
+ ((void)t);
+ } catch (int) {
+ }
+ }
+#endif
+}
+
+void test_explicit() {
+ {
+ using T = ExplicitTrivialTestTypes::TestType;
+ using O = optional<T>;
+ static_assert(explicit_conversion<T>(42, 42), "");
+ }
+ {
+ using T = ExplicitConstexprTestTypes::TestType;
+ using O = optional<T>;
+ static_assert(explicit_conversion<T>(42, 42), "");
+ static_assert(!std::is_convertible<int, T>::value, "");
+ }
+ {
+ using T = ExplicitTestTypes::TestType;
+ using O = optional<T>;
+ T::reset();
+ {
+ assert(explicit_conversion<T>(42, 42));
+ assert(T::alive == 0);
+ }
+ T::reset();
+ {
+ optional<T> t(42);
+ assert(T::alive == 1);
+ assert(T::value_constructed == 1);
+ assert(T::move_constructed == 0);
+ assert(T::copy_constructed == 0);
+ assert(t.value().value == 42);
+ }
+ assert(T::alive == 0);
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ try {
+ using T = ExplicitThrow;
+ optional<T> t(42);
+ assert(false);
+ } catch (int) {
+ }
+ }
+#endif
+}
+
+int main() {
+ test_implicit();
+ test_explicit();
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp
new file mode 100644
index 000000000000..34a12b8ad1c3
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp
@@ -0,0 +1,128 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <optional>
+
+// constexpr optional(const T& v);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+using std::optional;
+
+int main()
+{
+ {
+ typedef int T;
+ constexpr T t(5);
+ constexpr optional<T> opt(t);
+ static_assert(static_cast<bool>(opt) == true, "");
+ static_assert(*opt == 5, "");
+
+ struct test_constexpr_ctor
+ : public optional<T>
+ {
+ constexpr test_constexpr_ctor(const T&) {}
+ };
+
+ }
+ {
+ typedef double T;
+ constexpr T t(3);
+ constexpr optional<T> opt(t);
+ static_assert(static_cast<bool>(opt) == true, "");
+ static_assert(*opt == 3, "");
+
+ struct test_constexpr_ctor
+ : public optional<T>
+ {
+ constexpr test_constexpr_ctor(const T&) {}
+ };
+
+ }
+ {
+ const int x = 42;
+ optional<const int> o(x);
+ assert(*o == x);
+ }
+ {
+ typedef TestTypes::TestType T;
+ T::reset();
+ const T t(3);
+ optional<T> opt = t;
+ assert(T::alive == 2);
+ assert(T::copy_constructed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(opt.value().value == 3);
+ }
+ {
+ typedef ExplicitTestTypes::TestType T;
+ static_assert(!std::is_convertible<T const&, optional<T>>::value, "");
+ T::reset();
+ const T t(3);
+ optional<T> opt(t);
+ assert(T::alive == 2);
+ assert(T::copy_constructed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(opt.value().value == 3);
+ }
+ {
+ typedef ConstexprTestTypes::TestType T;
+ constexpr T t(3);
+ constexpr optional<T> opt = {t};
+ static_assert(static_cast<bool>(opt) == true, "");
+ static_assert(opt.value().value == 3, "");
+
+ struct test_constexpr_ctor
+ : public optional<T>
+ {
+ constexpr test_constexpr_ctor(const T&) {}
+ };
+ }
+ {
+ typedef ExplicitConstexprTestTypes::TestType T;
+ static_assert(!std::is_convertible<const T&, optional<T>>::value, "");
+ constexpr T t(3);
+ constexpr optional<T> opt(t);
+ static_assert(static_cast<bool>(opt) == true, "");
+ static_assert(opt.value().value == 3, "");
+
+ struct test_constexpr_ctor
+ : public optional<T>
+ {
+ constexpr test_constexpr_ctor(const T&) {}
+ };
+
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ struct Z {
+ Z(int) {}
+ Z(const Z&) {throw 6;}
+ };
+ typedef Z T;
+ try
+ {
+ const T t(3);
+ optional<T> opt(t);
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ }
+ }
+#endif
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
new file mode 100644
index 000000000000..e12f6cb28f5a
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
@@ -0,0 +1,134 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// <optional>
+
+// template <class U>
+// optional(const optional<U>& rhs);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+using std::optional;
+
+template <class T, class U>
+void
+test(const optional<U>& rhs, bool is_going_to_throw = false)
+{
+ bool rhs_engaged = static_cast<bool>(rhs);
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try
+ {
+ optional<T> lhs = rhs;
+ assert(is_going_to_throw == false);
+ assert(static_cast<bool>(lhs) == rhs_engaged);
+ if (rhs_engaged)
+ assert(*lhs == *rhs);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ }
+#else
+ if (is_going_to_throw) return;
+ optional<T> lhs = rhs;
+ assert(static_cast<bool>(lhs) == rhs_engaged);
+ if (rhs_engaged)
+ assert(*lhs == *rhs);
+#endif
+}
+
+class X
+{
+ int i_;
+public:
+ X(int i) : i_(i) {}
+ X(const X& x) : i_(x.i_) {}
+ ~X() {i_ = 0;}
+ friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
+};
+
+class Y
+{
+ int i_;
+public:
+ Y(int i) : i_(i) {}
+
+ friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;}
+};
+
+int count = 0;
+
+class Z
+{
+ int i_;
+public:
+ Z(int i) : i_(i) {TEST_THROW(6);}
+
+ friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
+};
+
+
+int main()
+{
+ {
+ typedef short U;
+ typedef int T;
+ optional<U> rhs;
+ test<T>(rhs);
+ }
+ {
+ typedef short U;
+ typedef int T;
+ optional<U> rhs(U{3});
+ test<T>(rhs);
+ }
+ {
+ typedef X T;
+ typedef int U;
+ optional<U> rhs;
+ test<T>(rhs);
+ }
+ {
+ typedef X T;
+ typedef int U;
+ optional<U> rhs(U{3});
+ test<T>(rhs);
+ }
+ {
+ typedef Y T;
+ typedef int U;
+ optional<U> rhs;
+ test<T>(rhs);
+ }
+ {
+ typedef Y T;
+ typedef int U;
+ optional<U> rhs(U{3});
+ test<T>(rhs);
+ }
+ {
+ typedef Z T;
+ typedef int U;
+ optional<U> rhs;
+ test<T>(rhs);
+ }
+ {
+ typedef Z T;
+ typedef int U;
+ optional<U> rhs(U{3});
+ test<T>(rhs, true);
+ }
+
+ static_assert(!(std::is_constructible<optional<X>, const optional<Y>&>::value), "");
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
new file mode 100644
index 000000000000..5906d4edd119
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
@@ -0,0 +1,155 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// <optional>
+
+// optional(const optional<T>& rhs);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+using std::optional;
+
+template <class T, class ...InitArgs>
+void test(InitArgs&&... args)
+{
+ const optional<T> rhs(std::forward<InitArgs>(args)...);
+ bool rhs_engaged = static_cast<bool>(rhs);
+ optional<T> lhs = rhs;
+ assert(static_cast<bool>(lhs) == rhs_engaged);
+ if (rhs_engaged)
+ assert(*lhs == *rhs);
+}
+
+void test_throwing_ctor() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ struct Z {
+ Z() : count(0) {}
+ Z(Z const& o) : count(o.count + 1)
+ { if (count == 2) throw 6; }
+ int count;
+ };
+ const Z z;
+ const optional<Z> rhs(z);
+ try
+ {
+ optional<Z> lhs(rhs);
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ }
+#endif
+}
+
+template <class T, class ...InitArgs>
+void test_ref(InitArgs&&... args)
+{
+ const optional<T> rhs(std::forward<InitArgs>(args)...);
+ bool rhs_engaged = static_cast<bool>(rhs);
+ optional<T> lhs = rhs;
+ assert(static_cast<bool>(lhs) == rhs_engaged);
+ if (rhs_engaged)
+ assert(&(*lhs) == &(*rhs));
+}
+
+
+void test_reference_extension()
+{
+#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled.
+ using T = TestTypes::TestType;
+ T::reset();
+ {
+ T t;
+ T::reset_constructors();
+ test_ref<T&>();
+ test_ref<T&>(t);
+ assert(T::alive == 1);
+ assert(T::constructed == 0);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 0);
+ }
+ assert(T::destroyed == 1);
+ assert(T::alive == 0);
+ {
+ T t;
+ const T& ct = t;
+ T::reset_constructors();
+ test_ref<T const&>();
+ test_ref<T const&>(t);
+ test_ref<T const&>(ct);
+ assert(T::alive == 1);
+ assert(T::constructed == 0);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 0);
+ }
+ assert(T::alive == 0);
+ assert(T::destroyed == 1);
+ {
+ static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, "");
+ static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, "");
+ }
+#endif
+}
+
+int main()
+{
+ test<int>();
+ test<int>(3);
+ {
+ const optional<const int> o(42);
+ optional<const int> o2(o);
+ assert(*o2 == 42);
+ }
+ {
+ using T = TestTypes::TestType;
+ T::reset();
+ const optional<T> rhs;
+ assert(T::alive == 0);
+ const optional<T> lhs(rhs);
+ assert(lhs.has_value() == false);
+ assert(T::alive == 0);
+ }
+ TestTypes::TestType::reset();
+ {
+ using T = TestTypes::TestType;
+ T::reset();
+ const optional<T> rhs(42);
+ assert(T::alive == 1);
+ assert(T::value_constructed == 1);
+ assert(T::copy_constructed == 0);
+ const optional<T> lhs(rhs);
+ assert(lhs.has_value());
+ assert(T::copy_constructed == 1);
+ assert(T::alive == 2);
+ }
+ TestTypes::TestType::reset();
+ {
+ using namespace ConstexprTestTypes;
+ test<TestType>();
+ test<TestType>(42);
+ }
+ {
+ using namespace TrivialTestTypes;
+ test<TestType>();
+ test<TestType>(42);
+ }
+ {
+ test_throwing_ctor();
+ }
+ {
+ test_reference_extension();
+ }
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp
new file mode 100644
index 000000000000..62795b91f9fd
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp
@@ -0,0 +1,81 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// <optional>
+
+// constexpr optional() noexcept;
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+using std::optional;
+
+template <class Opt>
+void
+test_constexpr()
+{
+ static_assert(std::is_nothrow_default_constructible<Opt>::value, "");
+ static_assert(std::is_trivially_destructible<Opt>::value, "");
+ static_assert(std::is_trivially_destructible<typename Opt::value_type>::value, "");
+
+ constexpr Opt opt;
+ static_assert(static_cast<bool>(opt) == false, "");
+
+ struct test_constexpr_ctor
+ : public Opt
+ {
+ constexpr test_constexpr_ctor() {}
+ };
+}
+
+template <class Opt>
+void
+test()
+{
+ static_assert(std::is_nothrow_default_constructible<Opt>::value, "");
+ static_assert(!std::is_trivially_destructible<Opt>::value, "");
+ static_assert(!std::is_trivially_destructible<typename Opt::value_type>::value, "");
+ {
+ Opt opt;
+ assert(static_cast<bool>(opt) == false);
+ }
+ {
+ const Opt opt;
+ assert(static_cast<bool>(opt) == false);
+ }
+
+ struct test_constexpr_ctor
+ : public Opt
+ {
+ constexpr test_constexpr_ctor() {}
+ };
+}
+
+int main()
+{
+ test_constexpr<optional<int>>();
+ test_constexpr<optional<int*>>();
+ test_constexpr<optional<ImplicitTypes::NoCtors>>();
+ test_constexpr<optional<NonTrivialTypes::NoCtors>>();
+ test_constexpr<optional<NonConstexprTypes::NoCtors>>();
+ test<optional<NonLiteralTypes::NoCtors>>();
+ // EXTENSIONS
+#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled.
+ test_constexpr<optional<int&>>();
+ test_constexpr<optional<const int&>>();
+ test_constexpr<optional<int&>>();
+ test_constexpr<optional<NonLiteralTypes::NoCtors&>>();
+ test_constexpr<optional<NonLiteralTypes::NoCtors&&>>();
+#endif
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp
new file mode 100644
index 000000000000..64ac05316c2a
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp
@@ -0,0 +1,121 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// <optional>
+
+// template <class U>
+// explicit optional(const optional<U>& rhs);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+using std::optional;
+
+template <class T, class U>
+void
+test(const optional<U>& rhs, bool is_going_to_throw = false)
+{
+ static_assert(!(std::is_convertible<const optional<U>&, optional<T>>::value), "");
+ bool rhs_engaged = static_cast<bool>(rhs);
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try
+ {
+ optional<T> lhs(rhs);
+ assert(is_going_to_throw == false);
+ assert(static_cast<bool>(lhs) == rhs_engaged);
+ if (rhs_engaged)
+ assert(*lhs == T(*rhs));
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ }
+#else
+ if (is_going_to_throw) return;
+ optional<T> lhs(rhs);
+ assert(static_cast<bool>(lhs) == rhs_engaged);
+ if (rhs_engaged)
+ assert(*lhs == T(*rhs));
+#endif
+}
+
+class X
+{
+ int i_;
+public:
+ explicit X(int i) : i_(i) {}
+ X(const X& x) : i_(x.i_) {}
+ ~X() {i_ = 0;}
+ friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
+};
+
+class Y
+{
+ int i_;
+public:
+ explicit Y(int i) : i_(i) {}
+
+ friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;}
+};
+
+int count = 0;
+
+class Z
+{
+ int i_;
+public:
+ explicit Z(int i) : i_(i) { TEST_THROW(6);}
+
+ friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
+};
+
+
+int main()
+{
+ {
+ typedef X T;
+ typedef int U;
+ optional<U> rhs;
+ test<T>(rhs);
+ }
+ {
+ typedef X T;
+ typedef int U;
+ optional<U> rhs(3);
+ test<T>(rhs);
+ }
+ {
+ typedef Y T;
+ typedef int U;
+ optional<U> rhs;
+ test<T>(rhs);
+ }
+ {
+ typedef Y T;
+ typedef int U;
+ optional<U> rhs(3);
+ test<T>(rhs);
+ }
+ {
+ typedef Z T;
+ typedef int U;
+ optional<U> rhs;
+ test<T>(rhs);
+ }
+ {
+ typedef Z T;
+ typedef int U;
+ optional<U> rhs(3);
+ test<T>(rhs, true);
+ }
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp
new file mode 100644
index 000000000000..2c6757a95825
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp
@@ -0,0 +1,84 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class U>
+// explicit optional(optional<U>&& rhs);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+using std::optional;
+
+template <class T, class U>
+void
+test(optional<U>&& rhs, bool is_going_to_throw = false)
+{
+ static_assert(!(std::is_convertible<optional<U>&&, optional<T>>::value), "");
+ bool rhs_engaged = static_cast<bool>(rhs);
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try
+ {
+ optional<T> lhs(std::move(rhs));
+ assert(is_going_to_throw == false);
+ assert(static_cast<bool>(lhs) == rhs_engaged);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ }
+#else
+ if (is_going_to_throw) return;
+ optional<T> lhs(std::move(rhs));
+ assert(static_cast<bool>(lhs) == rhs_engaged);
+#endif
+}
+
+class X
+{
+ int i_;
+public:
+ explicit X(int i) : i_(i) {}
+ X(X&& x) : i_(std::exchange(x.i_, 0)) {}
+ ~X() {i_ = 0;}
+ friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
+};
+
+int count = 0;
+
+class Z
+{
+public:
+ explicit Z(int) { TEST_THROW(6); }
+};
+
+int main()
+{
+ {
+ optional<int> rhs;
+ test<X>(std::move(rhs));
+ }
+ {
+ optional<int> rhs(3);
+ test<X>(std::move(rhs));
+ }
+ {
+ optional<int> rhs;
+ test<Z>(std::move(rhs));
+ }
+ {
+ optional<int> rhs(3);
+ test<Z>(std::move(rhs), true);
+ }
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp
new file mode 100644
index 000000000000..d0823d2c8c82
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp
@@ -0,0 +1,148 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <optional>
+
+// template <class... Args>
+// constexpr explicit optional(in_place_t, Args&&... args);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+using std::optional;
+using std::in_place_t;
+using std::in_place;
+
+class X
+{
+ int i_;
+ int j_ = 0;
+public:
+ X() : i_(0) {}
+ X(int i) : i_(i) {}
+ X(int i, int j) : i_(i), j_(j) {}
+
+ ~X() {}
+
+ friend bool operator==(const X& x, const X& y)
+ {return x.i_ == y.i_ && x.j_ == y.j_;}
+};
+
+class Y
+{
+ int i_;
+ int j_ = 0;
+public:
+ constexpr Y() : i_(0) {}
+ constexpr Y(int i) : i_(i) {}
+ constexpr Y(int i, int j) : i_(i), j_(j) {}
+
+ friend constexpr bool operator==(const Y& x, const Y& y)
+ {return x.i_ == y.i_ && x.j_ == y.j_;}
+};
+
+class Z
+{
+public:
+ Z(int) {TEST_THROW(6);}
+};
+
+
+int main()
+{
+ {
+ constexpr optional<int> opt(in_place, 5);
+ static_assert(static_cast<bool>(opt) == true, "");
+ static_assert(*opt == 5, "");
+
+ struct test_constexpr_ctor
+ : public optional<int>
+ {
+ constexpr test_constexpr_ctor(in_place_t, int i)
+ : optional<int>(in_place, i) {}
+ };
+
+ }
+ {
+ optional<const int> opt(in_place, 5);
+ assert(*opt == 5);
+ }
+ {
+ const optional<X> opt(in_place);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == X());
+ }
+ {
+ const optional<X> opt(in_place, 5);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == X(5));
+ }
+ {
+ const optional<X> opt(in_place, 5, 4);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == X(5, 4));
+ }
+ {
+ constexpr optional<Y> opt(in_place);
+ static_assert(static_cast<bool>(opt) == true, "");
+ static_assert(*opt == Y(), "");
+
+ struct test_constexpr_ctor
+ : public optional<Y>
+ {
+ constexpr test_constexpr_ctor(in_place_t)
+ : optional<Y>(in_place) {}
+ };
+
+ }
+ {
+ constexpr optional<Y> opt(in_place, 5);
+ static_assert(static_cast<bool>(opt) == true, "");
+ static_assert(*opt == Y(5), "");
+
+ struct test_constexpr_ctor
+ : public optional<Y>
+ {
+ constexpr test_constexpr_ctor(in_place_t, int i)
+ : optional<Y>(in_place, i) {}
+ };
+
+ }
+ {
+ constexpr optional<Y> opt(in_place, 5, 4);
+ static_assert(static_cast<bool>(opt) == true, "");
+ static_assert(*opt == Y(5, 4), "");
+
+ struct test_constexpr_ctor
+ : public optional<Y>
+ {
+ constexpr test_constexpr_ctor(in_place_t, int i, int j)
+ : optional<Y>(in_place, i, j) {}
+ };
+
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ try
+ {
+ const optional<Z> opt(in_place, 1);
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ }
+ }
+#endif
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp
new file mode 100644
index 000000000000..6d9f45a97d45
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.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, c++14
+// <optional>
+
+// template <class U, class... Args>
+// constexpr
+// explicit optional(in_place_t, initializer_list<U> il, Args&&... args);
+
+#include <optional>
+#include <type_traits>
+#include <vector>
+#include <cassert>
+
+#include "test_macros.h"
+
+using std::optional;
+using std::in_place_t;
+using std::in_place;
+
+class X
+{
+ int i_;
+ int j_ = 0;
+public:
+ X() : i_(0) {}
+ X(int i) : i_(i) {}
+ X(int i, int j) : i_(i), j_(j) {}
+
+ ~X() {}
+
+ friend bool operator==(const X& x, const X& y)
+ {return x.i_ == y.i_ && x.j_ == y.j_;}
+};
+
+class Y
+{
+ int i_;
+ int j_ = 0;
+public:
+ constexpr Y() : i_(0) {}
+ constexpr Y(int i) : i_(i) {}
+ constexpr Y(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) {}
+
+ friend constexpr bool operator==(const Y& x, const Y& y)
+ {return x.i_ == y.i_ && x.j_ == y.j_;}
+};
+
+class Z
+{
+ int i_;
+ int j_ = 0;
+public:
+ Z() : i_(0) {}
+ Z(int i) : i_(i) {}
+ Z(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1])
+ {TEST_THROW(6);}
+
+ friend bool operator==(const Z& x, const Z& y)
+ {return x.i_ == y.i_ && x.j_ == y.j_;}
+};
+
+int main()
+{
+ {
+ static_assert(!std::is_constructible<X, std::initializer_list<int>&>::value, "");
+ static_assert(!std::is_constructible<optional<X>, std::initializer_list<int>&>::value, "");
+ }
+ {
+ optional<std::vector<int>> opt(in_place, {3, 1});
+ assert(static_cast<bool>(opt) == true);
+ assert((*opt == std::vector<int>{3, 1}));
+ assert(opt->size() == 2);
+ }
+ {
+ optional<std::vector<int>> opt(in_place, {3, 1}, std::allocator<int>());
+ assert(static_cast<bool>(opt) == true);
+ assert((*opt == std::vector<int>{3, 1}));
+ assert(opt->size() == 2);
+ }
+ {
+ static_assert(std::is_constructible<optional<Y>, std::initializer_list<int>&>::value, "");
+ constexpr optional<Y> opt(in_place, {3, 1});
+ static_assert(static_cast<bool>(opt) == true, "");
+ static_assert(*opt == Y{3, 1}, "");
+
+ struct test_constexpr_ctor
+ : public optional<Y>
+ {
+ constexpr test_constexpr_ctor(in_place_t, std::initializer_list<int> i)
+ : optional<Y>(in_place, i) {}
+ };
+
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ static_assert(std::is_constructible<optional<Z>, std::initializer_list<int>&>::value, "");
+ try
+ {
+ optional<Z> opt(in_place, {3, 1});
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ }
+ }
+#endif
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
new file mode 100644
index 000000000000..bff6f5bf8f6f
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
@@ -0,0 +1,201 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// <optional>
+
+// optional(optional<T>&& rhs);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+using std::optional;
+
+template <class T, class ...InitArgs>
+void test(InitArgs&&... args)
+{
+ const optional<T> orig(std::forward<InitArgs>(args)...);
+ optional<T> rhs(orig);
+ bool rhs_engaged = static_cast<bool>(rhs);
+ optional<T> lhs = std::move(rhs);
+ assert(static_cast<bool>(lhs) == rhs_engaged);
+ if (rhs_engaged)
+ assert(*lhs == *orig);
+}
+
+void test_throwing_ctor() {
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ struct Z {
+ Z() : count(0) {}
+ Z(Z&& o) : count(o.count + 1)
+ { if (count == 2) throw 6; }
+ int count;
+ };
+ Z z;
+ optional<Z> rhs(std::move(z));
+ try
+ {
+ optional<Z> lhs(std::move(rhs));
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ }
+#endif
+}
+
+
+template <class T, class ...InitArgs>
+void test_ref(InitArgs&&... args)
+{
+ optional<T> rhs(std::forward<InitArgs>(args)...);
+ bool rhs_engaged = static_cast<bool>(rhs);
+ optional<T> lhs = std::move(rhs);
+ assert(static_cast<bool>(lhs) == rhs_engaged);
+ if (rhs_engaged)
+ assert(&(*lhs) == &(*rhs));
+}
+
+void test_reference_extension()
+{
+#if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled.
+ using T = TestTypes::TestType;
+ T::reset();
+ {
+ T t;
+ T::reset_constructors();
+ test_ref<T&>();
+ test_ref<T&>(t);
+ assert(T::alive == 1);
+ assert(T::constructed == 0);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 0);
+ }
+ assert(T::destroyed == 1);
+ assert(T::alive == 0);
+ {
+ T t;
+ const T& ct = t;
+ T::reset_constructors();
+ test_ref<T const&>();
+ test_ref<T const&>(t);
+ test_ref<T const&>(ct);
+ assert(T::alive == 1);
+ assert(T::constructed == 0);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 0);
+ }
+ assert(T::alive == 0);
+ assert(T::destroyed == 1);
+ {
+ T t;
+ T::reset_constructors();
+ test_ref<T&&>();
+ test_ref<T&&>(std::move(t));
+ assert(T::alive == 1);
+ assert(T::constructed == 0);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 0);
+ }
+ assert(T::alive == 0);
+ assert(T::destroyed == 1);
+ {
+ T t;
+ const T& ct = t;
+ T::reset_constructors();
+ test_ref<T const&&>();
+ test_ref<T const&&>(std::move(t));
+ test_ref<T const&&>(std::move(ct));
+ assert(T::alive == 1);
+ assert(T::constructed == 0);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 0);
+ }
+ assert(T::alive == 0);
+ assert(T::destroyed == 1);
+ {
+ static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, "");
+ static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, "");
+ }
+#endif
+}
+
+
+int main()
+{
+ test<int>();
+ test<int>(3);
+ {
+ optional<const int> o(42);
+ optional<const int> o2(std::move(o));
+ assert(*o2 == 42);
+ }
+ {
+ using T = TestTypes::TestType;
+ T::reset();
+ optional<T> rhs;
+ assert(T::alive == 0);
+ const optional<T> lhs(std::move(rhs));
+ assert(lhs.has_value() == false);
+ assert(rhs.has_value() == false);
+ assert(T::alive == 0);
+ }
+ TestTypes::TestType::reset();
+ {
+ using T = TestTypes::TestType;
+ T::reset();
+ optional<T> rhs(42);
+ assert(T::alive == 1);
+ assert(T::value_constructed == 1);
+ assert(T::move_constructed == 0);
+ const optional<T> lhs(std::move(rhs));
+ assert(lhs.has_value());
+ assert(rhs.has_value());
+ assert(lhs.value().value == 42);
+ assert(rhs.value().value == -1);
+ assert(T::move_constructed == 1);
+ assert(T::alive == 2);
+ }
+ TestTypes::TestType::reset();
+ {
+ using namespace ConstexprTestTypes;
+ test<TestType>();
+ test<TestType>(42);
+ }
+ {
+ using namespace TrivialTestTypes;
+ test<TestType>();
+ test<TestType>(42);
+ }
+ {
+ test_throwing_ctor();
+ }
+ {
+ struct ThrowsMove {
+ ThrowsMove() noexcept(false) {}
+ ThrowsMove(ThrowsMove const&) noexcept(false) {}
+ ThrowsMove(ThrowsMove &&) noexcept(false) {}
+ };
+ static_assert(!std::is_nothrow_move_constructible<optional<ThrowsMove>>::value, "");
+ struct NoThrowMove {
+ NoThrowMove() noexcept(false) {}
+ NoThrowMove(NoThrowMove const&) noexcept(false) {}
+ NoThrowMove(NoThrowMove &&) noexcept(true) {}
+ };
+ static_assert(std::is_nothrow_move_constructible<optional<NoThrowMove>>::value, "");
+ }
+ {
+ test_reference_extension();
+ }
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp
new file mode 100644
index 000000000000..468a00346fc7
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// constexpr optional(nullopt_t) noexcept;
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "archetypes.hpp"
+
+using std::optional;
+using std::nullopt_t;
+using std::nullopt;
+
+template <class Opt>
+void
+test_constexpr()
+{
+ static_assert(std::is_nothrow_constructible<Opt, nullopt_t&>::value, "");
+ static_assert(std::is_trivially_destructible<Opt>::value, "");
+ static_assert(std::is_trivially_destructible<typename Opt::value_type>::value, "");
+
+ constexpr Opt opt(nullopt);
+ static_assert(static_cast<bool>(opt) == false, "");
+
+ struct test_constexpr_ctor
+ : public Opt
+ {
+ constexpr test_constexpr_ctor() {}
+ };
+}
+
+template <class Opt>
+void
+test()
+{
+ static_assert(std::is_nothrow_constructible<Opt, nullopt_t&>::value, "");
+ static_assert(!std::is_trivially_destructible<Opt>::value, "");
+ static_assert(!std::is_trivially_destructible<typename Opt::value_type>::value, "");
+ {
+ Opt opt(nullopt);
+ assert(static_cast<bool>(opt) == false);
+ }
+ {
+ const Opt opt(nullopt);
+ assert(static_cast<bool>(opt) == false);
+ }
+ struct test_constexpr_ctor
+ : public Opt
+ {
+ constexpr test_constexpr_ctor() {}
+ };
+}
+
+int main()
+{
+ test_constexpr<optional<int>>();
+ test_constexpr<optional<int*>>();
+ test_constexpr<optional<ImplicitTypes::NoCtors>>();
+ test_constexpr<optional<NonTrivialTypes::NoCtors>>();
+ test_constexpr<optional<NonConstexprTypes::NoCtors>>();
+ test<optional<NonLiteralTypes::NoCtors>>();
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
new file mode 100644
index 000000000000..0e180c14ec67
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
@@ -0,0 +1,93 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class U>
+// optional(optional<U>&& rhs);
+
+#include <optional>
+#include <type_traits>
+#include <memory>
+#include <cassert>
+
+#include "test_macros.h"
+
+using std::optional;
+
+template <class T, class U>
+void
+test(optional<U>&& rhs, bool is_going_to_throw = false)
+{
+ bool rhs_engaged = static_cast<bool>(rhs);
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ try
+ {
+ optional<T> lhs = std::move(rhs);
+ assert(is_going_to_throw == false);
+ assert(static_cast<bool>(lhs) == rhs_engaged);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ }
+#else
+ if (is_going_to_throw) return;
+ optional<T> lhs = std::move(rhs);
+ assert(static_cast<bool>(lhs) == rhs_engaged);
+#endif
+}
+
+class X
+{
+ int i_;
+public:
+ X(int i) : i_(i) {}
+ X(X&& x) : i_(std::exchange(x.i_, 0)) {}
+ ~X() {i_ = 0;}
+ friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
+};
+
+int count = 0;
+
+struct Z
+{
+ Z(int) { TEST_THROW(6); }
+};
+
+int main()
+{
+ {
+ optional<short> rhs;
+ test<int>(std::move(rhs));
+ }
+ {
+ optional<short> rhs(short{3});
+ test<int>(std::move(rhs));
+ }
+ {
+ optional<int> rhs;
+ test<X>(std::move(rhs));
+ }
+ {
+ optional<int> rhs(3);
+ test<X>(std::move(rhs));
+ }
+ {
+ optional<int> rhs;
+ test<Z>(std::move(rhs));
+ }
+ {
+ optional<int> rhs(3);
+ test<Z>(std::move(rhs), true);
+ }
+
+ static_assert(!(std::is_constructible<optional<X>, optional<Z>>::value), "");
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp
new file mode 100644
index 000000000000..eee749d01707
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp
@@ -0,0 +1,153 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <optional>
+
+// constexpr optional(T&& v);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+
+using std::optional;
+
+
+class Z
+{
+public:
+ Z(int) {}
+ Z(Z&&) {TEST_THROW(6);}
+};
+
+
+int main()
+{
+ {
+ typedef int T;
+ constexpr optional<T> opt(T(5));
+ static_assert(static_cast<bool>(opt) == true, "");
+ static_assert(*opt == 5, "");
+
+ struct test_constexpr_ctor
+ : public optional<T>
+ {
+ constexpr test_constexpr_ctor(T&&) {}
+ };
+ }
+ {
+ typedef double T;
+ constexpr optional<T> opt(T(3));
+ static_assert(static_cast<bool>(opt) == true, "");
+ static_assert(*opt == 3, "");
+
+ struct test_constexpr_ctor
+ : public optional<T>
+ {
+ constexpr test_constexpr_ctor(T&&) {}
+ };
+ }
+ {
+ const int x = 42;
+ optional<const int> o(std::move(x));
+ assert(*o == 42);
+ }
+ {
+ typedef TestTypes::TestType T;
+ T::reset();
+ optional<T> opt = T{3};
+ assert(T::alive == 1);
+ assert(T::move_constructed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(opt.value().value == 3);
+ }
+ {
+ typedef ExplicitTestTypes::TestType T;
+ static_assert(!std::is_convertible<T&&, optional<T>>::value, "");
+ T::reset();
+ optional<T> opt(T{3});
+ assert(T::alive == 1);
+ assert(T::move_constructed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(opt.value().value == 3);
+ }
+ {
+ typedef TestTypes::TestType T;
+ T::reset();
+ optional<T> opt = {3};
+ assert(T::alive == 1);
+ assert(T::value_constructed == 1);
+ assert(T::copy_constructed == 0);
+ assert(T::move_constructed == 0);
+ assert(static_cast<bool>(opt) == true);
+ assert(opt.value().value == 3);
+ }
+ {
+ typedef ConstexprTestTypes::TestType T;
+ constexpr optional<T> opt = {T(3)};
+ static_assert(static_cast<bool>(opt) == true, "");
+ static_assert(opt.value().value == 3, "");
+
+ struct test_constexpr_ctor
+ : public optional<T>
+ {
+ constexpr test_constexpr_ctor(const T&) {}
+ };
+ }
+ {
+ typedef ConstexprTestTypes::TestType T;
+ constexpr optional<T> opt = {3};
+ static_assert(static_cast<bool>(opt) == true, "");
+ static_assert(opt.value().value == 3, "");
+
+ struct test_constexpr_ctor
+ : public optional<T>
+ {
+ constexpr test_constexpr_ctor(const T&) {}
+ };
+ }
+ {
+ typedef ExplicitConstexprTestTypes::TestType T;
+ static_assert(!std::is_convertible<T&&, optional<T>>::value, "");
+ constexpr optional<T> opt(T{3});
+ static_assert(static_cast<bool>(opt) == true, "");
+ static_assert(opt.value().value == 3, "");
+
+ struct test_constexpr_ctor
+ : public optional<T>
+ {
+ constexpr test_constexpr_ctor(T&&) {}
+ };
+
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ struct Z {
+ Z(int) {}
+ Z(Z&&) {throw 6;}
+ };
+ typedef Z T;
+ try
+ {
+ T t(3);
+ optional<T> opt(std::move(t));
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ }
+ }
+#endif
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp
new file mode 100644
index 000000000000..5132c9a73d0f
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp
@@ -0,0 +1,68 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// <optional>
+
+// ~optional();
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+using std::optional;
+
+struct PODType {
+ int value;
+ int value2;
+};
+
+class X
+{
+public:
+ static bool dtor_called;
+ X() = default;
+ ~X() {dtor_called = true;}
+};
+
+bool X::dtor_called = false;
+
+int main()
+{
+ {
+ typedef int T;
+ static_assert(std::is_trivially_destructible<T>::value, "");
+ static_assert(std::is_trivially_destructible<optional<T>>::value, "");
+ static_assert(std::is_literal_type<optional<T>>::value, "");
+ }
+ {
+ typedef double T;
+ static_assert(std::is_trivially_destructible<T>::value, "");
+ static_assert(std::is_trivially_destructible<optional<T>>::value, "");
+ static_assert(std::is_literal_type<optional<T>>::value, "");
+ }
+ {
+ typedef PODType T;
+ static_assert(std::is_trivially_destructible<T>::value, "");
+ static_assert(std::is_trivially_destructible<optional<T>>::value, "");
+ static_assert(std::is_literal_type<optional<T>>::value, "");
+ }
+ {
+ typedef X T;
+ static_assert(!std::is_trivially_destructible<T>::value, "");
+ static_assert(!std::is_trivially_destructible<optional<T>>::value, "");
+ static_assert(!std::is_literal_type<optional<T>>::value, "");
+ {
+ X x;
+ optional<X> opt{x};
+ assert(X::dtor_called == false);
+ }
+ assert(X::dtor_called == true);
+ }
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp
new file mode 100644
index 000000000000..cee73da849b6
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp
@@ -0,0 +1,61 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <optional>
+
+// void reset() noexcept;
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+using std::optional;
+
+struct X
+{
+ static bool dtor_called;
+ ~X() {dtor_called = true;}
+};
+
+bool X::dtor_called = false;
+
+int main()
+{
+ {
+ optional<int> opt;
+ static_assert(noexcept(opt.reset()) == true, "");
+ opt.reset();
+ assert(static_cast<bool>(opt) == false);
+ }
+ {
+ optional<int> opt(3);
+ opt.reset();
+ assert(static_cast<bool>(opt) == false);
+ }
+ {
+ optional<X> opt;
+ static_assert(noexcept(opt.reset()) == true, "");
+ assert(X::dtor_called == false);
+ opt.reset();
+ assert(X::dtor_called == false);
+ assert(static_cast<bool>(opt) == false);
+ }
+ assert(X::dtor_called == false); // TRANSITION, Clang/C2 VSO#239997
+ {
+ optional<X> opt(X{});
+ X::dtor_called = false;
+ opt.reset();
+ assert(X::dtor_called == true);
+ assert(static_cast<bool>(opt) == false);
+ X::dtor_called = false;
+ }
+ assert(X::dtor_called == false); // TRANSITION, Clang/C2 VSO#239997
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp
new file mode 100644
index 000000000000..9820d50f632e
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.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, c++14
+// <optional>
+
+// constexpr explicit optional<T>::operator bool() const noexcept;
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+int main()
+{
+ using std::optional;
+ {
+ const optional<int> opt; ((void)opt);
+ ASSERT_NOEXCEPT(bool(opt));
+ static_assert(!std::is_convertible<optional<int>, bool>::value, "");
+ }
+ {
+ constexpr optional<int> opt;
+ static_assert(!opt, "");
+ }
+ {
+ constexpr optional<int> opt(0);
+ static_assert(opt, "");
+ }
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp
new file mode 100644
index 000000000000..4087cfdf104e
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// constexpr T& optional<T>::operator*() &;
+
+#ifdef _LIBCPP_DEBUG
+#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
+#endif
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+using std::optional;
+
+struct X
+{
+ constexpr int test() const& {return 3;}
+ int test() & {return 4;}
+ constexpr int test() const&& {return 5;}
+ int test() && {return 6;}
+};
+
+struct Y
+{
+ constexpr int test() {return 7;}
+};
+
+constexpr int
+test()
+{
+ optional<Y> opt{Y{}};
+ return (*opt).test();
+}
+
+int main()
+{
+ {
+ optional<X> opt; ((void)opt);
+ ASSERT_SAME_TYPE(decltype(*opt), X&);
+ // ASSERT_NOT_NOEXCEPT(*opt);
+ // FIXME: This assertion fails with GCC because it can see that
+ // (A) operator*() is constexpr, and
+ // (B) there is no path through the function that throws.
+ // It's arguable if this is the correct behavior for the noexcept
+ // operator.
+ // Regardless this function should still be noexcept(false) because
+ // it has a narrow contract.
+ }
+ {
+ optional<X> opt(X{});
+ assert((*opt).test() == 4);
+ }
+ static_assert(test() == 7, "");
+#ifdef _LIBCPP_DEBUG
+ {
+ optional<X> opt;
+ assert((*opt).test() == 3);
+ assert(false);
+ }
+#endif // _LIBCPP_DEBUG
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
new file mode 100644
index 000000000000..0779c9047c9e
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
@@ -0,0 +1,69 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// constexpr const T& optional<T>::operator*() const &;
+
+#ifdef _LIBCPP_DEBUG
+#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
+#endif
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+using std::optional;
+
+struct X
+{
+ constexpr int test() const& {return 3;}
+ int test() & {return 4;}
+ constexpr int test() const&& {return 5;}
+ int test() && {return 6;}
+};
+
+struct Y
+{
+ int test() const {return 2;}
+};
+
+int main()
+{
+ {
+ const optional<X> opt; ((void)opt);
+ ASSERT_SAME_TYPE(decltype(*opt), X const&);
+ // ASSERT_NOT_NOEXCEPT(*opt);
+ // FIXME: This assertion fails with GCC because it can see that
+ // (A) operator*() is constexpr, and
+ // (B) there is no path through the function that throws.
+ // It's arguable if this is the correct behavior for the noexcept
+ // operator.
+ // Regardless this function should still be noexcept(false) because
+ // it has a narrow contract.
+ }
+ {
+ constexpr optional<X> opt(X{});
+ static_assert((*opt).test() == 3, "");
+ }
+ {
+ constexpr optional<Y> opt(Y{});
+ assert((*opt).test() == 2);
+ }
+#ifdef _LIBCPP_DEBUG
+ {
+ const optional<X> opt;
+ assert((*opt).test() == 3);
+ assert(false);
+ }
+#endif // _LIBCPP_DEBUG
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp
new file mode 100644
index 000000000000..78fd992952c9
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp
@@ -0,0 +1,69 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// constexpr T&& optional<T>::operator*() const &&;
+
+#ifdef _LIBCPP_DEBUG
+#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
+#endif
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+using std::optional;
+
+struct X
+{
+ constexpr int test() const& {return 3;}
+ int test() & {return 4;}
+ constexpr int test() const&& {return 5;}
+ int test() && {return 6;}
+};
+
+struct Y
+{
+ int test() const && {return 2;}
+};
+
+int main()
+{
+ {
+ const optional<X> opt; ((void)opt);
+ ASSERT_SAME_TYPE(decltype(*std::move(opt)), X const &&);
+ // ASSERT_NOT_NOEXCEPT(*std::move(opt));
+ // FIXME: This assertion fails with GCC because it can see that
+ // (A) operator*() is constexpr, and
+ // (B) there is no path through the function that throws.
+ // It's arguable if this is the correct behavior for the noexcept
+ // operator.
+ // Regardless this function should still be noexcept(false) because
+ // it has a narrow contract.
+ }
+ {
+ constexpr optional<X> opt(X{});
+ static_assert((*std::move(opt)).test() == 5, "");
+ }
+ {
+ constexpr optional<Y> opt(Y{});
+ assert((*std::move(opt)).test() == 2);
+ }
+#ifdef _LIBCPP_DEBUG
+ {
+ optional<X> opt;
+ assert((*std::move(opt)).test() == 5);
+ assert(false);
+ }
+#endif // _LIBCPP_DEBUG
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp
new file mode 100644
index 000000000000..2924123234a8
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// constexpr T&& optional<T>::operator*() &&;
+
+#ifdef _LIBCPP_DEBUG
+#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
+#endif
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+using std::optional;
+
+struct X
+{
+ constexpr int test() const& {return 3;}
+ int test() & {return 4;}
+ constexpr int test() const&& {return 5;}
+ int test() && {return 6;}
+};
+
+struct Y
+{
+ constexpr int test() && {return 7;}
+};
+
+constexpr int
+test()
+{
+ optional<Y> opt{Y{}};
+ return (*std::move(opt)).test();
+}
+
+int main()
+{
+ {
+ optional<X> opt; ((void)opt);
+ ASSERT_SAME_TYPE(decltype(*std::move(opt)), X&&);
+ // ASSERT_NOT_NOEXCEPT(*std::move(opt));
+ // FIXME: This assertion fails with GCC because it can see that
+ // (A) operator*() is constexpr, and
+ // (B) there is no path through the function that throws.
+ // It's arguable if this is the correct behavior for the noexcept
+ // operator.
+ // Regardless this function should still be noexcept(false) because
+ // it has a narrow contract.
+ }
+ {
+ optional<X> opt(X{});
+ assert((*std::move(opt)).test() == 6);
+ }
+ static_assert(test() == 7, "");
+#ifdef _LIBCPP_DEBUG
+ {
+ optional<X> opt;
+ assert((*std::move(opt)).test() == 3);
+ assert(false);
+ }
+#endif // _LIBCPP_DEBUG
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp
new file mode 100644
index 000000000000..5df295d01e22
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.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, c++14
+// <optional>
+
+// constexpr bool optional<T>::has_value() const noexcept;
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+int main()
+{
+ using std::optional;
+ {
+ const optional<int> opt; ((void)opt);
+ ASSERT_NOEXCEPT(opt.has_value());
+ ASSERT_SAME_TYPE(decltype(opt.has_value()), bool);
+ }
+ {
+ constexpr optional<int> opt;
+ static_assert(!opt.has_value(), "");
+ }
+ {
+ constexpr optional<int> opt(0);
+ static_assert(opt.has_value(), "");
+ }
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp
new file mode 100644
index 000000000000..2f1648c48c89
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp
@@ -0,0 +1,72 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// constexpr T* optional<T>::operator->();
+
+#ifdef _LIBCPP_DEBUG
+#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
+#endif
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+using std::optional;
+
+struct X
+{
+ int test() noexcept {return 3;}
+};
+
+struct Y
+{
+ constexpr int test() {return 3;}
+};
+
+constexpr int
+test()
+{
+ optional<Y> opt{Y{}};
+ return opt->test();
+}
+
+int main()
+{
+ {
+ std::optional<X> opt; ((void)opt);
+ ASSERT_SAME_TYPE(decltype(opt.operator->()), X*);
+ // ASSERT_NOT_NOEXCEPT(opt.operator->());
+ // FIXME: This assertion fails with GCC because it can see that
+ // (A) operator->() is constexpr, and
+ // (B) there is no path through the function that throws.
+ // It's arguable if this is the correct behavior for the noexcept
+ // operator.
+ // Regardless this function should still be noexcept(false) because
+ // it has a narrow contract.
+ }
+ {
+ optional<X> opt(X{});
+ assert(opt->test() == 3);
+ }
+ {
+ static_assert(test() == 3, "");
+ }
+#ifdef _LIBCPP_DEBUG
+ {
+ optional<X> opt;
+ assert(opt->test() == 3);
+ assert(false);
+ }
+#endif // _LIBCPP_DEBUG
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp
new file mode 100644
index 000000000000..887edc7114eb
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp
@@ -0,0 +1,76 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// <optional>
+
+// constexpr const T* optional<T>::operator->() const;
+
+#ifdef _LIBCPP_DEBUG
+#define _LIBCPP_ASSERT(x, m) ((x) ? (void)0 : std::exit(0))
+#endif
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+using std::optional;
+
+struct X
+{
+ constexpr int test() const {return 3;}
+};
+
+struct Y
+{
+ int test() const noexcept {return 2;}
+};
+
+struct Z
+{
+ const Z* operator&() const;
+ constexpr int test() const {return 1;}
+};
+
+int main()
+{
+ {
+ const std::optional<X> opt; ((void)opt);
+ ASSERT_SAME_TYPE(decltype(opt.operator->()), X const*);
+ // ASSERT_NOT_NOEXCEPT(opt.operator->());
+ // FIXME: This assertion fails with GCC because it can see that
+ // (A) operator->() is constexpr, and
+ // (B) there is no path through the function that throws.
+ // It's arguable if this is the correct behavior for the noexcept
+ // operator.
+ // Regardless this function should still be noexcept(false) because
+ // it has a narrow contract.
+ }
+ {
+ constexpr optional<X> opt(X{});
+ static_assert(opt->test() == 3, "");
+ }
+ {
+ constexpr optional<Y> opt(Y{});
+ assert(opt->test() == 2);
+ }
+ {
+ constexpr optional<Z> opt(Z{});
+ static_assert(opt->test() == 1, "");
+ }
+#ifdef _LIBCPP_DEBUG
+ {
+ const optional<X> opt;
+ assert(opt->test() == 3);
+ assert(false);
+ }
+#endif // _LIBCPP_DEBUG
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/value.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/value.pass.cpp
new file mode 100644
index 000000000000..516a79db5f64
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.observe/value.pass.cpp
@@ -0,0 +1,73 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// constexpr T& optional<T>::value() &;
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+using std::optional;
+using std::bad_optional_access;
+
+struct X
+{
+ X() = default;
+ X(const X&) = delete;
+ constexpr int test() const & {return 3;}
+ int test() & {return 4;}
+ constexpr int test() const && {return 5;}
+ int test() && {return 6;}
+};
+
+struct Y
+{
+ constexpr int test() & {return 7;}
+};
+
+constexpr int
+test()
+{
+ optional<Y> opt{Y{}};
+ return opt.value().test();
+}
+
+
+int main()
+{
+ {
+ optional<X> opt; ((void)opt);
+ ASSERT_NOT_NOEXCEPT(opt.value());
+ ASSERT_SAME_TYPE(decltype(opt.value()), X&);
+ }
+ {
+ optional<X> opt;
+ opt.emplace();
+ assert(opt.value().test() == 4);
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ optional<X> opt;
+ try
+ {
+ opt.value();
+ assert(false);
+ }
+ catch (const bad_optional_access&)
+ {
+ }
+ }
+#endif
+ static_assert(test() == 7, "");
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/value_const.fail.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/value_const.fail.cpp
new file mode 100644
index 000000000000..6076c509fa41
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.observe/value_const.fail.cpp
@@ -0,0 +1,33 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// constexpr const T& optional<T>::value() const &;
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+using std::optional;
+
+struct X
+{
+ constexpr int test() const {return 3;}
+ int test() {return 4;}
+};
+
+int main()
+{
+ {
+ constexpr optional<X> opt;
+ static_assert(opt.value().test() == 3, "");
+ }
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp
new file mode 100644
index 000000000000..d4038e4efa6b
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.observe/value_const.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, c++14
+// <optional>
+
+// constexpr const T& optional<T>::value() const &;
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+using std::optional;
+using std::in_place_t;
+using std::in_place;
+using std::bad_optional_access;
+
+struct X
+{
+ X() = default;
+ X(const X&) = delete;
+ constexpr int test() const & {return 3;}
+ int test() & {return 4;}
+ constexpr int test() const && {return 5;}
+ int test() && {return 6;}
+};
+
+int main()
+{
+ {
+ const optional<X> opt; ((void)opt);
+ ASSERT_NOT_NOEXCEPT(opt.value());
+ ASSERT_SAME_TYPE(decltype(opt.value()), X const&);
+ }
+ {
+ constexpr optional<X> opt(in_place);
+ static_assert(opt.value().test() == 3, "");
+ }
+ {
+ const optional<X> opt(in_place);
+ assert(opt.value().test() == 3);
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ const optional<X> opt;
+ try
+ {
+ opt.value();
+ assert(false);
+ }
+ catch (const bad_optional_access&)
+ {
+ }
+ }
+#endif
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp
new file mode 100644
index 000000000000..e189d3af6886
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.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, c++14
+// <optional>
+
+// constexpr const T& optional<T>::value() const &&;
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+using std::optional;
+using std::in_place_t;
+using std::in_place;
+using std::bad_optional_access;
+
+struct X
+{
+ X() = default;
+ X(const X&) = delete;
+ constexpr int test() const & {return 3;}
+ int test() & {return 4;}
+ constexpr int test() const && {return 5;}
+ int test() && {return 6;}
+};
+
+int main()
+{
+ {
+ const optional<X> opt; ((void)opt);
+ ASSERT_NOT_NOEXCEPT(std::move(opt).value());
+ ASSERT_SAME_TYPE(decltype(std::move(opt).value()), X const&&);
+ }
+ {
+ constexpr optional<X> opt(in_place);
+ static_assert(std::move(opt).value().test() == 5, "");
+ }
+ {
+ const optional<X> opt(in_place);
+ assert(std::move(opt).value().test() == 5);
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ const optional<X> opt;
+ try
+ {
+ std::move(opt).value();
+ assert(false);
+ }
+ catch (const bad_optional_access&)
+ {
+ }
+ }
+#endif
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp
new file mode 100644
index 000000000000..c219e9704716
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp
@@ -0,0 +1,68 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// <optional>
+
+// template <class U> T optional<T>::value_or(U&& v) &&;
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+using std::optional;
+using std::in_place_t;
+using std::in_place;
+
+struct Y
+{
+ int i_;
+
+ Y(int i) : i_(i) {}
+};
+
+struct X
+{
+ int i_;
+
+ X(int i) : i_(i) {}
+ X(X&& x) : i_(x.i_) {x.i_ = 0;}
+ X(const Y& y) : i_(y.i_) {}
+ X(Y&& y) : i_(y.i_+1) {}
+ friend constexpr bool operator==(const X& x, const X& y)
+ {return x.i_ == y.i_;}
+};
+
+int main()
+{
+ {
+ optional<X> opt(in_place, 2);
+ Y y(3);
+ assert(std::move(opt).value_or(y) == 2);
+ assert(*opt == 0);
+ }
+ {
+ optional<X> opt(in_place, 2);
+ assert(std::move(opt).value_or(Y(3)) == 2);
+ assert(*opt == 0);
+ }
+ {
+ optional<X> opt;
+ Y y(3);
+ assert(std::move(opt).value_or(y) == 3);
+ assert(!opt);
+ }
+ {
+ optional<X> opt;
+ assert(std::move(opt).value_or(Y(3)) == 4);
+ assert(!opt);
+ }
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/value_or_const.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/value_or_const.pass.cpp
new file mode 100644
index 000000000000..36a85811ba49
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.observe/value_or_const.pass.cpp
@@ -0,0 +1,77 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class U> constexpr T optional<T>::value_or(U&& v) const&;
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+using std::optional;
+
+struct Y
+{
+ int i_;
+
+ constexpr Y(int i) : i_(i) {}
+};
+
+struct X
+{
+ int i_;
+
+ constexpr X(int i) : i_(i) {}
+ constexpr X(const Y& y) : i_(y.i_) {}
+ constexpr X(Y&& y) : i_(y.i_+1) {}
+ friend constexpr bool operator==(const X& x, const X& y)
+ {return x.i_ == y.i_;}
+};
+
+int main()
+{
+ {
+ constexpr optional<X> opt(2);
+ constexpr Y y(3);
+ static_assert(opt.value_or(y) == 2, "");
+ }
+ {
+ constexpr optional<X> opt(2);
+ static_assert(opt.value_or(Y(3)) == 2, "");
+ }
+ {
+ constexpr optional<X> opt;
+ constexpr Y y(3);
+ static_assert(opt.value_or(y) == 3, "");
+ }
+ {
+ constexpr optional<X> opt;
+ static_assert(opt.value_or(Y(3)) == 4, "");
+ }
+ {
+ const optional<X> opt(2);
+ const Y y(3);
+ assert(opt.value_or(y) == 2);
+ }
+ {
+ const optional<X> opt(2);
+ assert(opt.value_or(Y(3)) == 2);
+ }
+ {
+ const optional<X> opt;
+ const Y y(3);
+ assert(opt.value_or(y) == 3);
+ }
+ {
+ const optional<X> opt;
+ assert(opt.value_or(Y(3)) == 4);
+ }
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.observe/value_rvalue.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.observe/value_rvalue.pass.cpp
new file mode 100644
index 000000000000..2ef485b7fe50
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.observe/value_rvalue.pass.cpp
@@ -0,0 +1,72 @@
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// constexpr T& optional<T>::value() &&;
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+using std::optional;
+using std::bad_optional_access;
+
+struct X
+{
+ X() = default;
+ X(const X&) = delete;
+ constexpr int test() const & {return 3;}
+ int test() & {return 4;}
+ constexpr int test() const && {return 5;}
+ int test() && {return 6;}
+};
+
+struct Y
+{
+ constexpr int test() && {return 7;}
+};
+
+constexpr int
+test()
+{
+ optional<Y> opt{Y{}};
+ return std::move(opt).value().test();
+}
+
+int main()
+{
+ {
+ optional<X> opt; ((void)opt);
+ ASSERT_NOT_NOEXCEPT(std::move(opt).value());
+ ASSERT_SAME_TYPE(decltype(std::move(opt).value()), X&&);
+ }
+ {
+ optional<X> opt;
+ opt.emplace();
+ assert(std::move(opt).value().test() == 6);
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ optional<X> opt;
+ try
+ {
+ std::move(opt).value();
+ assert(false);
+ }
+ catch (const bad_optional_access&)
+ {
+ }
+ }
+#endif
+ static_assert(test() == 7, "");
+}
diff --git a/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp
new file mode 100644
index 000000000000..26041259fa93
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp
@@ -0,0 +1,306 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// <optional>
+
+// void swap(optional&)
+// noexcept(is_nothrow_move_constructible<T>::value &&
+// is_nothrow_swappable<T>::value)
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+using std::optional;
+
+class X
+{
+ int i_;
+public:
+ static unsigned dtor_called;
+ X(int i) : i_(i) {}
+ X(X&& x) = default;
+ X& operator=(X&&) = default;
+ ~X() {++dtor_called;}
+
+ friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;}
+};
+
+unsigned X::dtor_called = 0;
+
+class Y
+{
+ int i_;
+public:
+ static unsigned dtor_called;
+ Y(int i) : i_(i) {}
+ Y(Y&&) = default;
+ ~Y() {++dtor_called;}
+
+ friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;}
+ friend void swap(Y& x, Y& y) {std::swap(x.i_, y.i_);}
+};
+
+unsigned Y::dtor_called = 0;
+
+class Z
+{
+ int i_;
+public:
+ Z(int i) : i_(i) {}
+ Z(Z&&) {TEST_THROW(7);}
+
+ friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;}
+ friend void swap(Z&, Z&) {TEST_THROW(6);}
+};
+
+
+int main()
+{
+ {
+ optional<int> opt1;
+ optional<int> opt2;
+ static_assert(noexcept(opt1.swap(opt2)) == true, "");
+ assert(static_cast<bool>(opt1) == false);
+ assert(static_cast<bool>(opt2) == false);
+ opt1.swap(opt2);
+ assert(static_cast<bool>(opt1) == false);
+ assert(static_cast<bool>(opt2) == false);
+ }
+ {
+ optional<int> opt1(1);
+ optional<int> opt2;
+ static_assert(noexcept(opt1.swap(opt2)) == true, "");
+ assert(static_cast<bool>(opt1) == true);
+ assert(*opt1 == 1);
+ assert(static_cast<bool>(opt2) == false);
+ opt1.swap(opt2);
+ assert(static_cast<bool>(opt1) == false);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 1);
+ }
+ {
+ optional<int> opt1;
+ optional<int> opt2(2);
+ static_assert(noexcept(opt1.swap(opt2)) == true, "");
+ assert(static_cast<bool>(opt1) == false);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 2);
+ opt1.swap(opt2);
+ assert(static_cast<bool>(opt1) == true);
+ assert(*opt1 == 2);
+ assert(static_cast<bool>(opt2) == false);
+ }
+ {
+ optional<int> opt1(1);
+ optional<int> opt2(2);
+ static_assert(noexcept(opt1.swap(opt2)) == true, "");
+ assert(static_cast<bool>(opt1) == true);
+ assert(*opt1 == 1);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 2);
+ opt1.swap(opt2);
+ assert(static_cast<bool>(opt1) == true);
+ assert(*opt1 == 2);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 1);
+ }
+ {
+ optional<X> opt1;
+ optional<X> opt2;
+ static_assert(noexcept(opt1.swap(opt2)) == true, "");
+ assert(static_cast<bool>(opt1) == false);
+ assert(static_cast<bool>(opt2) == false);
+ opt1.swap(opt2);
+ assert(static_cast<bool>(opt1) == false);
+ assert(static_cast<bool>(opt2) == false);
+ assert(X::dtor_called == 0);
+ }
+ {
+ optional<X> opt1(1);
+ optional<X> opt2;
+ static_assert(noexcept(opt1.swap(opt2)) == true, "");
+ assert(static_cast<bool>(opt1) == true);
+ assert(*opt1 == 1);
+ assert(static_cast<bool>(opt2) == false);
+ X::dtor_called = 0;
+ opt1.swap(opt2);
+ assert(X::dtor_called == 1);
+ assert(static_cast<bool>(opt1) == false);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 1);
+ }
+ {
+ optional<X> opt1;
+ optional<X> opt2(2);
+ static_assert(noexcept(opt1.swap(opt2)) == true, "");
+ assert(static_cast<bool>(opt1) == false);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 2);
+ X::dtor_called = 0;
+ opt1.swap(opt2);
+ assert(X::dtor_called == 1);
+ assert(static_cast<bool>(opt1) == true);
+ assert(*opt1 == 2);
+ assert(static_cast<bool>(opt2) == false);
+ }
+ {
+ optional<X> opt1(1);
+ optional<X> opt2(2);
+ static_assert(noexcept(opt1.swap(opt2)) == true, "");
+ assert(static_cast<bool>(opt1) == true);
+ assert(*opt1 == 1);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 2);
+ X::dtor_called = 0;
+ opt1.swap(opt2);
+ assert(X::dtor_called == 1); // from inside std::swap
+ assert(static_cast<bool>(opt1) == true);
+ assert(*opt1 == 2);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 1);
+ }
+ {
+ optional<Y> opt1;
+ optional<Y> opt2;
+ static_assert(noexcept(opt1.swap(opt2)) == false, "");
+ assert(static_cast<bool>(opt1) == false);
+ assert(static_cast<bool>(opt2) == false);
+ opt1.swap(opt2);
+ assert(static_cast<bool>(opt1) == false);
+ assert(static_cast<bool>(opt2) == false);
+ assert(Y::dtor_called == 0);
+ }
+ {
+ optional<Y> opt1(1);
+ optional<Y> opt2;
+ static_assert(noexcept(opt1.swap(opt2)) == false, "");
+ assert(static_cast<bool>(opt1) == true);
+ assert(*opt1 == 1);
+ assert(static_cast<bool>(opt2) == false);
+ Y::dtor_called = 0;
+ opt1.swap(opt2);
+ assert(Y::dtor_called == 1);
+ assert(static_cast<bool>(opt1) == false);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 1);
+ }
+ {
+ optional<Y> opt1;
+ optional<Y> opt2(2);
+ static_assert(noexcept(opt1.swap(opt2)) == false, "");
+ assert(static_cast<bool>(opt1) == false);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 2);
+ Y::dtor_called = 0;
+ opt1.swap(opt2);
+ assert(Y::dtor_called == 1);
+ assert(static_cast<bool>(opt1) == true);
+ assert(*opt1 == 2);
+ assert(static_cast<bool>(opt2) == false);
+ }
+ {
+ optional<Y> opt1(1);
+ optional<Y> opt2(2);
+ static_assert(noexcept(opt1.swap(opt2)) == false, "");
+ assert(static_cast<bool>(opt1) == true);
+ assert(*opt1 == 1);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 2);
+ Y::dtor_called = 0;
+ opt1.swap(opt2);
+ assert(Y::dtor_called == 0);
+ assert(static_cast<bool>(opt1) == true);
+ assert(*opt1 == 2);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 1);
+ }
+ {
+ optional<Z> opt1;
+ optional<Z> opt2;
+ static_assert(noexcept(opt1.swap(opt2)) == false, "");
+ assert(static_cast<bool>(opt1) == false);
+ assert(static_cast<bool>(opt2) == false);
+ opt1.swap(opt2);
+ assert(static_cast<bool>(opt1) == false);
+ assert(static_cast<bool>(opt2) == false);
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ optional<Z> opt1;
+ opt1.emplace(1);
+ optional<Z> opt2;
+ static_assert(noexcept(opt1.swap(opt2)) == false, "");
+ assert(static_cast<bool>(opt1) == true);
+ assert(*opt1 == 1);
+ assert(static_cast<bool>(opt2) == false);
+ try
+ {
+ opt1.swap(opt2);
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 7);
+ }
+ assert(static_cast<bool>(opt1) == true);
+ assert(*opt1 == 1);
+ assert(static_cast<bool>(opt2) == false);
+ }
+ {
+ optional<Z> opt1;
+ optional<Z> opt2;
+ opt2.emplace(2);
+ static_assert(noexcept(opt1.swap(opt2)) == false, "");
+ assert(static_cast<bool>(opt1) == false);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 2);
+ try
+ {
+ opt1.swap(opt2);
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 7);
+ }
+ assert(static_cast<bool>(opt1) == false);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 2);
+ }
+ {
+ optional<Z> opt1;
+ opt1.emplace(1);
+ optional<Z> opt2;
+ opt2.emplace(2);
+ static_assert(noexcept(opt1.swap(opt2)) == false, "");
+ assert(static_cast<bool>(opt1) == true);
+ assert(*opt1 == 1);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 2);
+ try
+ {
+ opt1.swap(opt2);
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ }
+ assert(static_cast<bool>(opt1) == true);
+ assert(*opt1 == 1);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 2);
+ }
+#endif
+}
diff --git a/test/std/utilities/optional/optional.object/optional_requires_destructible_object.fail.cpp b/test/std/utilities/optional/optional.object/optional_requires_destructible_object.fail.cpp
new file mode 100644
index 000000000000..8a2c77af0ec1
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/optional_requires_destructible_object.fail.cpp
@@ -0,0 +1,50 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// <optional>
+
+// T shall be an object type and shall satisfy the requirements of Destructible
+
+#include <optional>
+
+using std::optional;
+
+struct X
+{
+private:
+ ~X() {}
+};
+
+int main()
+{
+ using std::optional;
+ {
+ // expected-error@optional:* 2 {{static_assert failed "instantiation of optional with a reference type is ill-formed}}
+ optional<int&> opt1;
+ optional<int&&> opt2;
+ }
+ {
+ // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-destructible type is ill-formed"}}
+ optional<X> opt3;
+ }
+ {
+ // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-object type is undefined behavior"}}
+ // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-destructible type is ill-formed}}
+ optional<void()> opt4;
+ }
+ {
+ // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-object type is undefined behavior"}}
+ // expected-error@optional:* {{static_assert failed "instantiation of optional with a non-destructible type is ill-formed}}
+ // expected-error@optional:* 1+ {{cannot form a reference to 'void'}}
+ optional<const void> opt4;
+ }
+ // FIXME these are garbage diagnostics that Clang should not produce
+ // expected-error@optional:* 0+ {{is not a base class}}
+}
diff --git a/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp b/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp
new file mode 100644
index 000000000000..fdd0f154f0e5
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp
@@ -0,0 +1,74 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+// <optional>
+
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "archetypes.hpp"
+
+template <class T>
+struct SpecialMemberTest {
+ using O = std::optional<T>;
+
+ static_assert(std::is_default_constructible_v<O>,
+ "optional is always default constructible.");
+ static_assert(std::is_copy_constructible_v<O> == std::is_copy_constructible_v<T>,
+ "optional<T> is copy constructible if and only if T is copy constructible.");
+ static_assert(std::is_move_constructible_v<O> ==
+ (std::is_copy_constructible_v<T> || std::is_move_constructible_v<T>),
+ "optional<T> is move constructible if and only if T is copy or move constructible.");
+ static_assert(std::is_copy_assignable_v<O> ==
+ (std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>),
+ "optional<T> is copy assignable if and only if T is both copy "
+ "constructible and copy assignable.");
+ static_assert(std::is_move_assignable_v<O> ==
+ ((std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>) ||
+ (std::is_move_constructible_v<T> && std::is_move_assignable_v<T>)),
+ "optional<T> is move assignable if and only if T is both move assignable and "
+ "move constructible, or both copy constructible and copy assignable.");
+};
+
+template <class ...Args> static void sink(Args&&...) {}
+
+template <class ...TestTypes>
+struct DoTestsMetafunction {
+ DoTestsMetafunction() { sink(SpecialMemberTest<TestTypes>{}...); }
+};
+
+struct TrivialMoveNonTrivialCopy {
+ TrivialMoveNonTrivialCopy() = default;
+ TrivialMoveNonTrivialCopy(const TrivialMoveNonTrivialCopy&) {}
+ TrivialMoveNonTrivialCopy(TrivialMoveNonTrivialCopy&&) = default;
+ TrivialMoveNonTrivialCopy& operator=(const TrivialMoveNonTrivialCopy&) { return *this; }
+ TrivialMoveNonTrivialCopy& operator=(TrivialMoveNonTrivialCopy&&) = default;
+};
+
+struct TrivialCopyNonTrivialMove {
+ TrivialCopyNonTrivialMove() = default;
+ TrivialCopyNonTrivialMove(const TrivialCopyNonTrivialMove&) = default;
+ TrivialCopyNonTrivialMove(TrivialCopyNonTrivialMove&&) {}
+ TrivialCopyNonTrivialMove& operator=(const TrivialCopyNonTrivialMove&) = default;
+ TrivialCopyNonTrivialMove& operator=(TrivialCopyNonTrivialMove&&) { return *this; }
+};
+
+int main()
+{
+ sink(
+ ImplicitTypes::ApplyTypes<DoTestsMetafunction>{},
+ ExplicitTypes::ApplyTypes<DoTestsMetafunction>{},
+ NonLiteralTypes::ApplyTypes<DoTestsMetafunction>{},
+ NonTrivialTypes::ApplyTypes<DoTestsMetafunction>{},
+ DoTestsMetafunction<TrivialMoveNonTrivialCopy, TrivialCopyNonTrivialMove>{}
+ );
+}
diff --git a/test/std/utilities/optional/optional.object/types.pass.cpp b/test/std/utilities/optional/optional.object/types.pass.cpp
new file mode 100644
index 000000000000..0230a13dded1
--- /dev/null
+++ b/test/std/utilities/optional/optional.object/types.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, c++14
+// <optional>
+
+// template <class T>
+// class optional
+// {
+// public:
+// typedef T value_type;
+// ...
+
+#include <optional>
+#include <type_traits>
+
+using std::optional;
+
+template <class Opt, class T>
+void
+test()
+{
+ static_assert(std::is_same<typename Opt::value_type, T>::value, "");
+}
+
+int main()
+{
+ test<optional<int>, int>();
+ test<optional<const int>, const int>();
+ test<optional<double>, double>();
+ test<optional<const double>, const double>();
+}