Add <optional> header.
authorEric Fiselier <eric@efcs.ca>
Wed, 12 Oct 2016 06:45:11 +0000 (06:45 +0000)
committerEric Fiselier <eric@efcs.ca>
Wed, 12 Oct 2016 06:45:11 +0000 (06:45 +0000)
This patch is largely thanks to Casey Carter @ Microsoft. He did the initial
work of porting our experimental implementation and tests over to namespace
std.

llvm-svn: 283977

86 files changed:
libcxx/.gitignore
libcxx/include/__config
libcxx/include/optional [new file with mode: 0644]
libcxx/include/type_traits
libcxx/src/optional.cpp
libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp [new file with mode: 0644]
libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/move.pass.cpp [new file with mode: 0644]
libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp [new file with mode: 0644]
libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp [new file with mode: 0644]
libcxx/test/libcxx/utilities/optional/optional.object/special_member_gen.pass.cpp [new file with mode: 0644]
libcxx/test/libcxx/utilities/optional/version.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/meta/meta.unary/meta.unary.prop/is_nothrow_swappable_with.pass.cpp
libcxx/test/std/utilities/optional/optional.bad_optional_access/default.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.bad_optional_access/derive.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.comp_with_t/equal.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.comp_with_t/greater.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.comp_with_t/greater_equal.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.comp_with_t/less_equal.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.comp_with_t/less_than.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.comp_with_t/not_equal.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.hash/hash.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.nullops/equal.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.nullops/greater.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.nullops/greater_equal.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.nullops/less_equal.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.nullops/less_than.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.nullops/not_equal.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.nullopt/not_brace_initializable.fail.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.fail.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or_const.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_rvalue.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/optional_requires_destructible_object.fail.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.object/types.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.relops/equal.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.relops/greater_equal.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.relops/greater_than.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.relops/less_equal.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.relops/less_than.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.relops/not_equal.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.specalg/make_optional.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit_initializer_list.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.specalg/swap.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.syn/optional_in_place_t.fail.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.syn/optional_includes_initializer_list.pass.cpp [new file with mode: 0644]
libcxx/test/std/utilities/optional/optional.syn/optional_nullopt_t.fail.cpp [new file with mode: 0644]
libcxx/test/support/archetypes.hpp
libcxx/test/support/archetypes.ipp

index db7f90d..49657ed 100644 (file)
@@ -56,3 +56,6 @@ target/
 # MSVC libraries test harness
 env.lst
 keep.lst
+
+# Editor by-products
+.vscode/
index db55b2c..b18bd46 100644 (file)
@@ -914,6 +914,10 @@ extern "C" void __sanitizer_annotate_contiguous_container(
 #define _LIBCPP_SAFE_STATIC
 #endif
 
+#if !__has_builtin(__builtin_addressof) && _GNUC_VER < 700
+#define _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
+#endif
+
 #endif // __cplusplus
 
 #endif // _LIBCPP_CONFIG
diff --git a/libcxx/include/optional b/libcxx/include/optional
new file mode 100644 (file)
index 0000000..2a767f2
--- /dev/null
@@ -0,0 +1,1318 @@
+// -*- C++ -*-
+//===-------------------------- optional ----------------------------------===//
+//
+//                     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.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_OPTIONAL
+#define _LIBCPP_OPTIONAL
+
+/*
+    optional synopsis
+
+// C++1z
+
+namespace std {
+  // 20.6.3, optional for object types
+  template <class T> class optional;
+
+  // 20.6.4, no-value state indicator
+  struct nullopt_t{see below };
+  constexpr nullopt_t nullopt(unspecified );
+
+  // 20.6.5, class bad_optional_access
+  class bad_optional_access;
+
+  // 20.6.6, relational operators
+  template <class T>
+  constexpr bool operator==(const optional<T>&, const optional<T>&);
+  template <class T>
+  constexpr bool operator!=(const optional<T>&, const optional<T>&);
+  template <class T>
+  constexpr bool operator<(const optional<T>&, const optional<T>&);
+  template <class T>
+  constexpr bool operator>(const optional<T>&, const optional<T>&);
+  template <class T>
+  constexpr bool operator<=(const optional<T>&, const optional<T>&);
+  template <class T>
+  constexpr bool operator>=(const optional<T>&, const optional<T>&);
+  template <class T> constexpr bool operator==(const optional<T>&, nullopt_t) noexcept;
+  template <class T> constexpr bool operator==(nullopt_t, const optional<T>&) noexcept;
+  template <class T> constexpr bool operator!=(const optional<T>&, nullopt_t) noexcept;
+  template <class T> constexpr bool operator!=(nullopt_t, const optional<T>&) noexcept;
+  template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept;
+  template <class T> constexpr bool operator<(nullopt_t, const optional<T>&) noexcept;
+  template <class T> constexpr bool operator<=(const optional<T>&, nullopt_t) noexcept;
+  template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept;
+  template <class T> constexpr bool operator>(const optional<T>&, nullopt_t) noexcept;
+  template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept;
+  template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept;
+  template <class T> constexpr bool operator>=(nullopt_t, const optional<T>&) noexcept;
+
+  // 20.6.8, comparison with T
+  template <class T> constexpr bool operator==(const optional<T>&, const T&);
+  template <class T> constexpr bool operator==(const T&, const optional<T>&);
+  template <class T> constexpr bool operator!=(const optional<T>&, const T&);
+  template <class T> constexpr bool operator!=(const T&, const optional<T>&);
+  template <class T> constexpr bool operator<(const optional<T>&, const T&);
+  template <class T> constexpr bool operator<(const T&, const optional<T>&);
+  template <class T> constexpr bool operator<=(const optional<T>&, const T&);
+  template <class T> constexpr bool operator<=(const T&, const optional<T>&);
+  template <class T> constexpr bool operator>(const optional<T>&, const T&);
+  template <class T> constexpr bool operator>(const T&, const optional<T>&);
+  template <class T> constexpr bool operator>=(const optional<T>&, const T&);
+  template <class T> constexpr bool operator>=(const T&, const optional<T>&);
+
+  // 20.6.9, specialized algorithms
+  template <class T> void swap(optional<T>&, optional<T>&) noexcept(see below );
+  template <class T> constexpr optional<see below > make_optional(T&&);
+  template <class T, class... Args>
+    constexpr optional<T> make_optional(Args&&... args);
+  template <class T, class U, class... Args>
+    constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
+
+  // 20.6.10, hash support
+  template <class T> struct hash;
+  template <class T> struct hash<optional<T>>;
+
+  template <class T> class optional {
+  public:
+    using value_type = T;
+
+    // 20.6.3.1, constructors
+    constexpr optional() noexcept;
+    constexpr optional(nullopt_t) noexcept;
+    optional(const optional &);
+    optional(optional &&) noexcept(see below );
+    template <class... Args> constexpr explicit optional(in_place_t, Args &&...);
+    template <class U, class... Args>
+      constexpr explicit optional(in_place_t, initializer_list<U>, Args &&...);
+    template <class U = T>
+      constexpr EXPLICIT optional(U &&);
+    template <class U>
+      constexpr EXPLICIT optional(const optional<U> &);
+    template <class U>
+      constexpr EXPLICIT optional(optional<U> &&);
+
+    // 20.6.3.2, destructor
+    ~optional();
+
+    // 20.6.3.3, assignment
+    optional &operator=(nullopt_t) noexcept;
+    optional &operator=(const optional &);
+    optional &operator=(optional &&) noexcept(see below );
+    template <class U = T> optional &operator=(U &&);
+    template <class U> optional &operator=(const optional<U> &);
+    template <class U> optional &operator=(optional<U> &&);
+    template <class... Args> void emplace(Args &&...);
+    template <class U, class... Args>
+      void emplace(initializer_list<U>, Args &&...);
+
+    // 20.6.3.4, swap
+    void swap(optional &) noexcept(see below );
+
+    // 20.6.3.5, observers
+    constexpr T const *operator->() const;
+    constexpr T *operator->();
+    constexpr T const &operator*() const &;
+    constexpr T &operator*() &;
+    constexpr T &&operator*() &&;
+    constexpr const T &&operator*() const &&;
+    constexpr explicit operator bool() const noexcept;
+    constexpr bool has_value() const noexcept;
+    constexpr T const &value() const &;
+    constexpr T &value() &;
+    constexpr T &&value() &&;
+    constexpr const T &&value() const &&;
+    template <class U> constexpr T value_or(U &&) const &;
+    template <class U> constexpr T value_or(U &&) &&;
+
+    // 20.6.3.6, modifiers
+    void reset() noexcept;
+
+  private:
+    T *val; // exposition only
+  };
+} // namespace std
+
+*/
+
+#include <__config>
+#include <__debug>
+#include <__functional_base>
+#include <__undef_min_max>
+#include <functional>
+#include <initializer_list>
+#include <new>
+#include <stdexcept>
+#include <type_traits>
+#include <utility>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+namespace std  // purposefully not using versioning namespace
+{
+
+class _LIBCPP_EXCEPTION_ABI bad_optional_access
+    : public logic_error
+{
+public:
+    _LIBCPP_INLINE_VISIBILITY
+    bad_optional_access() : logic_error("bad optional access") {}
+
+    // Get the key function ~bad_optional_access() into the dylib
+    _LIBCPP_FUNC_VIS
+    virtual ~bad_optional_access() _NOEXCEPT;
+};
+
+}  // std
+
+#if _LIBCPP_STD_VER > 14
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+_LIBCPP_NORETURN
+inline _LIBCPP_INLINE_VISIBILITY
+void __throw_bad_optional_access() {
+#ifndef _LIBCPP_NO_EXCEPTIONS
+        throw bad_optional_access();
+#else
+        _VSTD::abort();
+#endif
+}
+
+struct nullopt_t
+{
+    struct __secret_tag { _LIBCPP_INLINE_VISIBILITY explicit __secret_tag() = default; };
+    _LIBCPP_INLINE_VISIBILITY constexpr explicit nullopt_t(__secret_tag, __secret_tag) noexcept {}
+};
+
+/* inline */ constexpr nullopt_t nullopt{nullopt_t::__secret_tag{}, nullopt_t::__secret_tag{}};
+
+template <class _Tp, bool = is_trivially_destructible<_Tp>::value>
+struct __optional_destruct_base;
+
+template <class _Tp>
+struct __optional_destruct_base<_Tp, false>
+{
+    typedef _Tp value_type;
+    static_assert(is_object_v<value_type>,
+        "instantiation of optional with a non-object type is undefined behavior");
+    union
+    {
+        char __null_state_;
+        value_type __val_;
+    };
+    bool __engaged_;
+
+    _LIBCPP_INLINE_VISIBILITY
+    ~__optional_destruct_base()
+    {
+        if (__engaged_)
+            __val_.~value_type();
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr __optional_destruct_base() noexcept
+        :  __null_state_(),
+           __engaged_(false) {}
+
+    template <class... _Args>
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
+        :  __val_(_VSTD::forward<_Args>(__args)...),
+           __engaged_(true) {}
+
+    _LIBCPP_INLINE_VISIBILITY
+    void reset() noexcept
+    {
+        if (__engaged_)
+        {
+            __val_.~value_type();
+            __engaged_ = false;
+        }
+    }
+};
+
+template <class _Tp>
+struct __optional_destruct_base<_Tp, true>
+{
+    typedef _Tp value_type;
+    static_assert(is_object_v<value_type>,
+        "instantiation of optional with a non-object type is undefined behavior");
+    union
+    {
+        char __null_state_;
+        value_type __val_;
+    };
+    bool __engaged_;
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr __optional_destruct_base() noexcept
+        :  __null_state_(),
+           __engaged_(false) {}
+
+    template <class... _Args>
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr explicit __optional_destruct_base(in_place_t, _Args&&... __args)
+        :  __val_(_VSTD::forward<_Args>(__args)...),
+           __engaged_(true) {}
+
+    _LIBCPP_INLINE_VISIBILITY
+    void reset() noexcept
+    {
+        if (__engaged_)
+        {
+            __engaged_ = false;
+        }
+    }
+};
+
+template <class _Tp, bool = is_reference<_Tp>::value>
+struct __optional_storage_base : __optional_destruct_base<_Tp>
+{
+    using __base = __optional_destruct_base<_Tp>;
+    using value_type = _Tp;
+    using __base::__base;
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr bool has_value() const noexcept
+    {
+        return this->__engaged_;
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr value_type& __get() & noexcept
+    {
+        return this->__val_;
+    }
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr const value_type& __get() const& noexcept
+    {
+        return this->__val_;
+    }
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr value_type&& __get() && noexcept
+    {
+        return _VSTD::move(this->__val_);
+    }
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr const value_type&& __get() const&& noexcept
+    {
+        return _VSTD::move(this->__val_);
+    }
+
+    template <class... _Args>
+    _LIBCPP_INLINE_VISIBILITY
+    void __construct(_Args&&... __args)
+    {
+        _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
+        ::new((void*)_VSTD::addressof(this->__val_)) value_type(_VSTD::forward<_Args>(__args)...);
+        this->__engaged_ = true;
+    }
+
+    template <class _That>
+    _LIBCPP_INLINE_VISIBILITY
+    void __construct_from(_That&& __opt)
+    {
+        if (__opt.has_value())
+            __construct(_VSTD::forward<_That>(__opt).__get());
+    }
+
+    template <class _That>
+    _LIBCPP_INLINE_VISIBILITY
+    void __assign_from(_That&& __opt)
+    {
+        if (this->__engaged_ == __opt.has_value())
+        {
+            if (this->__engaged_)
+                this->__val_ = _VSTD::forward<_That>(__opt).__get();
+        }
+        else
+        {
+            if (this->__engaged_)
+                this->reset();
+            else
+                __construct(_VSTD::forward<_That>(__opt).__get());
+        }
+    }
+};
+
+// optional<T&> is currently required ill-formed, however it may to be in the
+// future. For this reason it has already been implemented to ensure we can
+// make the change in an ABI compatible manner.
+template <class _Tp>
+struct __optional_storage_base<_Tp, true>
+{
+    using value_type = _Tp;
+    using __raw_type = remove_reference_t<_Tp>;
+    __raw_type* __value_;
+
+    template <class _Up>
+    static constexpr bool __can_bind_reference() {
+        using _RawUp = typename remove_reference<_Up>::type;
+        using _UpPtr = _RawUp*;
+        using _RawTp = typename remove_reference<_Tp>::type;
+        using _TpPtr = _RawTp*;
+        using _CheckLValueArg = integral_constant<bool,
+            (is_lvalue_reference<_Up>::value && is_convertible<_UpPtr, _TpPtr>::value)
+        ||  is_same<_RawUp, reference_wrapper<_RawTp>>::value
+        ||  is_same<_RawUp, reference_wrapper<typename remove_const<_RawTp>::type>>::value
+        >;
+        return (is_lvalue_reference<_Tp>::value && _CheckLValueArg::value)
+            || (is_rvalue_reference<_Tp>::value && !is_lvalue_reference<_Up>::value &&
+                is_convertible<_UpPtr, _TpPtr>::value);
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr __optional_storage_base() noexcept
+        :  __value_(nullptr) {}
+
+    template <class _UArg>
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr explicit __optional_storage_base(in_place_t, _UArg&& __uarg)
+        :  __value_(_VSTD::addressof(__uarg))
+    {
+      static_assert(__can_bind_reference<_UArg>(),
+        "Attempted to construct a reference element in tuple from a "
+        "possible temporary");
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    void reset() noexcept { __value_ = nullptr; }
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr bool has_value() const noexcept
+      { return __value_ != nullptr; }
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr value_type& __get() const& noexcept
+      { return *__value_; }
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr value_type&& __get() const&& noexcept
+      { return _VSTD::forward<value_type>(*__value_); }
+
+    template <class _UArg>
+    _LIBCPP_INLINE_VISIBILITY
+    void __construct(_UArg&& __val)
+    {
+        _LIBCPP_ASSERT(!has_value(), "__construct called for engaged __optional_storage");
+        static_assert(__can_bind_reference<_UArg>(),
+            "Attempted to construct a reference element in tuple from a "
+            "possible temporary");
+        __value_ = _VSTD::addressof(__val);
+    }
+
+    template <class _That>
+    _LIBCPP_INLINE_VISIBILITY
+    void __construct_from(_That&& __opt)
+    {
+        if (__opt.has_value())
+            __construct(_VSTD::forward<_That>(__opt).__get());
+    }
+
+    template <class _That>
+    _LIBCPP_INLINE_VISIBILITY
+    void __assign_from(_That&& __opt)
+    {
+        if (has_value() == __opt.has_value())
+        {
+            if (has_value())
+                *__value_ = _VSTD::forward<_That>(__opt).__get();
+        }
+        else
+        {
+            if (has_value())
+                reset();
+            else
+                __construct(_VSTD::forward<_That>(__opt).__get());
+        }
+    }
+};
+
+template <class _Tp, bool = is_trivially_copyable<_Tp>::value>
+struct __optional_storage;
+
+template <class _Tp>
+struct __optional_storage<_Tp, true> : __optional_storage_base<_Tp>
+{
+    using __optional_storage_base<_Tp>::__optional_storage_base;
+};
+
+template <class _Tp>
+struct __optional_storage<_Tp, false> : __optional_storage_base<_Tp>
+{
+    using value_type = _Tp;
+    using __optional_storage_base<_Tp>::__optional_storage_base;
+
+    _LIBCPP_INLINE_VISIBILITY
+    __optional_storage() = default;
+
+    _LIBCPP_INLINE_VISIBILITY
+    __optional_storage(const __optional_storage& __opt)
+    {
+        this->__construct_from(__opt);
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    __optional_storage(__optional_storage&& __opt)
+        noexcept(is_nothrow_move_constructible_v<value_type>)
+    {
+        this->__construct_from(_VSTD::move(__opt));
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    __optional_storage& operator=(const __optional_storage& __opt)
+    {
+        this->__assign_from(__opt);
+        return *this;
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    __optional_storage& operator=(__optional_storage&& __opt)
+        noexcept(is_nothrow_move_assignable_v<value_type> &&
+                 is_nothrow_move_constructible_v<value_type>)
+    {
+        this->__assign_from(_VSTD::move(__opt));
+        return *this;
+    }
+};
+
+template <class _Tp>
+using __optional_sfinae_ctor_base_t = __sfinae_ctor_base<
+    is_copy_constructible<_Tp>::value,
+    is_move_constructible<_Tp>::value
+>;
+
+template <class _Tp>
+using __optional_sfinae_assign_base_t = __sfinae_assign_base<
+    (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value),
+    (is_move_constructible<_Tp>::value && is_move_assignable<_Tp>::value) ||
+        (is_copy_constructible<_Tp>::value && is_copy_assignable<_Tp>::value)
+>;
+
+template <class _Tp>
+class optional
+    : private __optional_storage<_Tp>
+    , private __optional_sfinae_ctor_base_t<_Tp>
+    , private __optional_sfinae_assign_base_t<_Tp>
+{
+    using __base = __optional_storage<_Tp>;
+public:
+    using value_type = _Tp;
+
+private:
+     // Disable the reference extension using this static assert.
+    static_assert(!is_same_v<value_type, in_place_t>,
+        "instantiation of optional with in_place_t is ill-formed");
+    static_assert(!is_same_v<__uncvref_t<value_type>, nullopt_t>,
+        "instantiation of optional with nullopt_t is ill-formed");
+    static_assert(!is_reference_v<value_type>,
+        "instantiation of optional with a reference type is ill-formed");
+    static_assert(is_destructible_v<value_type>,
+        "instantiation of optional with a non-destructible type is ill-formed");
+
+    // LWG2756: conditionally explicit conversion from _Up
+    struct _CheckOptionalArgsConstructor {
+      template <class _Up>
+      static constexpr bool __enable_implicit() {
+          return is_constructible_v<_Tp, _Up&&> &&
+                 is_convertible_v<_Up&&, _Tp>;
+      }
+
+      template <class _Up>
+      static constexpr bool __enable_explicit() {
+          return is_constructible_v<_Tp, _Up&&> &&
+                 !is_convertible_v<_Up&&, _Tp>;
+      }
+    };
+    template <class _Up>
+    using _CheckOptionalArgsCtor = conditional_t<
+        !is_same_v<in_place_t, _Up> &&
+        !is_same_v<decay_t<_Up>, optional>,
+        _CheckOptionalArgsConstructor,
+        __check_tuple_constructor_fail
+    >;
+    template <class _QualUp>
+    struct _CheckOptionalLikeConstructor {
+      template <class _Up, class _Opt = optional<_Up>>
+      using __check_constructible_from_opt = __lazy_or<
+          is_constructible<_Tp, _Opt&>,
+          is_constructible<_Tp, _Opt const&>,
+          is_constructible<_Tp, _Opt&&>,
+          is_constructible<_Tp, _Opt const&&>,
+          is_convertible<_Opt&, _Tp>,
+          is_convertible<_Opt const&, _Tp>,
+          is_convertible<_Opt&&, _Tp>,
+          is_convertible<_Opt const&&, _Tp>
+      >;
+      template <class _Up, class _Opt = optional<_Up>>
+      using __check_assignable_from_opt = __lazy_or<
+          is_assignable<_Tp&, _Opt&>,
+          is_assignable<_Tp&, _Opt const&>,
+          is_assignable<_Tp&, _Opt&&>,
+          is_assignable<_Tp&, _Opt const&&>
+      >;
+      template <class _Up, class _QUp = _QualUp>
+      static constexpr bool __enable_implicit() {
+          return is_convertible<_QUp, _Tp>::value &&
+              !__check_constructible_from_opt<_Up>::value;
+      }
+      template <class _Up, class _QUp = _QualUp>
+      static constexpr bool __enable_explicit() {
+          return !is_convertible<_QUp, _Tp>::value &&
+              !__check_constructible_from_opt<_Up>::value;
+      }
+      template <class _Up, class _QUp = _QualUp>
+      static constexpr bool __enable_assign() {
+          // Construction and assignability of _Qup to _Tp has already been
+          // checked.
+          return !__check_constructible_from_opt<_Up>::value &&
+              !__check_assignable_from_opt<_Up>::value;
+      }
+    };
+
+    template <class _Up, class _QualUp>
+    using _CheckOptionalLikeCtor = conditional_t<
+      __lazy_and<
+          __lazy_not<is_same<_Up, _Tp>>,
+          is_constructible<_Tp, _QualUp>
+      >::value,
+      _CheckOptionalLikeConstructor<_QualUp>,
+      __check_tuple_constructor_fail
+    >;
+    template <class _Up, class _QualUp>
+    using _CheckOptionalLikeAssign = conditional_t<
+      __lazy_and<
+          __lazy_not<is_same<_Up, _Tp>>,
+          is_constructible<_Tp, _QualUp>,
+          is_assignable<_Tp&, _QualUp>
+      >::value,
+      _CheckOptionalLikeConstructor<_QualUp>,
+      __check_tuple_constructor_fail
+    >;
+public:
+
+    _LIBCPP_INLINE_VISIBILITY constexpr optional() noexcept {}
+    _LIBCPP_INLINE_VISIBILITY optional(const optional&) = default;
+    _LIBCPP_INLINE_VISIBILITY optional(optional&&) = default;
+    _LIBCPP_INLINE_VISIBILITY constexpr optional(nullopt_t) noexcept {}
+
+    template <class... _Args, class = enable_if_t<
+        is_constructible_v<value_type, _Args...>>
+    >
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr explicit optional(in_place_t, _Args&&... __args)
+        : __base(in_place, _VSTD::forward<_Args>(__args)...) {}
+
+    template <class _Up, class... _Args, class = enable_if_t<
+        is_constructible_v<value_type, initializer_list<_Up>&, _Args...>>
+    >
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr explicit optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args)
+        : __base(in_place, __il, _VSTD::forward<_Args>(__args)...) {}
+
+    template <class _Up = value_type, enable_if_t<
+        _CheckOptionalArgsCtor<_Up>::template __enable_implicit<_Up>()
+    , int> = 0>
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr optional(_Up&& __v)
+        : __base(in_place, _VSTD::forward<_Up>(__v)) {}
+
+    template <class _Up, enable_if_t<
+        _CheckOptionalArgsCtor<_Up>::template __enable_explicit<_Up>()
+    , int> = 0>
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr explicit optional(_Up&& __v)
+        : __base(in_place, _VSTD::forward<_Up>(__v)) {}
+
+    // LWG2756: conditionally explicit conversion from const optional<_Up>&
+    template <class _Up, enable_if_t<
+        _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_implicit<_Up>()
+    , int> = 0>
+    _LIBCPP_INLINE_VISIBILITY
+    optional(const optional<_Up>& __v)
+    {
+        this->__construct_from(__v);
+    }
+    template <class _Up, enable_if_t<
+        _CheckOptionalLikeCtor<_Up, _Up const&>::template __enable_explicit<_Up>()
+    , int> = 0>
+    _LIBCPP_INLINE_VISIBILITY
+    explicit optional(const optional<_Up>& __v)
+    {
+        this->__construct_from(__v);
+    }
+
+    // LWG2756: conditionally explicit conversion from optional<_Up>&&
+    template <class _Up, enable_if_t<
+        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_implicit<_Up>()
+    , int> = 0>
+    _LIBCPP_INLINE_VISIBILITY
+    optional(optional<_Up>&& __v)
+    {
+        this->__construct_from(_VSTD::move(__v));
+    }
+    template <class _Up, enable_if_t<
+        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_explicit<_Up>()
+    , int> = 0>
+    _LIBCPP_INLINE_VISIBILITY
+    explicit optional(optional<_Up>&& __v)
+    {
+        this->__construct_from(_VSTD::move(__v));
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    optional& operator=(nullopt_t) noexcept
+    {
+        reset();
+        return *this;
+    }
+
+    _LIBCPP_INLINE_VISIBILITY optional& operator=(const optional&) = default;
+    _LIBCPP_INLINE_VISIBILITY optional& operator=(optional&&) = default;
+
+    // LWG2756
+    template <class _Up = value_type,
+              class = enable_if_t
+                      <
+                          !is_same_v<_Up, optional> &&
+                          !(is_same_v<_Up, value_type> && is_scalar_v<value_type>) &&
+                          is_constructible_v<value_type, _Up> &&
+                          is_assignable_v<value_type&, _Up>
+                      >
+             >
+    _LIBCPP_INLINE_VISIBILITY
+    optional&
+    operator=(_Up&& __v)
+    {
+        if (this->has_value())
+            this->__get() = _VSTD::forward<_Up>(__v);
+        else
+            this->__construct(_VSTD::forward<_Up>(__v));
+        return *this;
+    }
+
+    // LWG2756
+    template <class _Up, enable_if_t<
+        _CheckOptionalLikeAssign<_Up, _Up const&>::template __enable_assign<_Up>()
+    , int> = 0>
+    _LIBCPP_INLINE_VISIBILITY
+    optional&
+    operator=(const optional<_Up>& __v)
+    {
+        this->__assign_from(__v);
+        return *this;
+    }
+
+    // LWG2756
+    template <class _Up, enable_if_t<
+        _CheckOptionalLikeCtor<_Up, _Up &&>::template __enable_assign<_Up>()
+    , int> = 0>
+    _LIBCPP_INLINE_VISIBILITY
+    optional&
+    operator=(optional<_Up>&& __v)
+    {
+        this->__assign_from(_VSTD::move(__v));
+        return *this;
+    }
+
+    template <class... _Args,
+              class = enable_if_t
+                      <
+                          is_constructible_v<value_type, _Args...>
+                      >
+             >
+    _LIBCPP_INLINE_VISIBILITY
+    void
+    emplace(_Args&&... __args)
+    {
+        reset();
+        this->__construct(_VSTD::forward<_Args>(__args)...);
+    }
+
+    template <class _Up, class... _Args,
+              class = enable_if_t
+                      <
+                          is_constructible_v<value_type, initializer_list<_Up>&, _Args...>
+                      >
+             >
+    _LIBCPP_INLINE_VISIBILITY
+    void
+    emplace(initializer_list<_Up> __il, _Args&&... __args)
+    {
+        reset();
+        this->__construct(__il, _VSTD::forward<_Args>(__args)...);
+    }
+
+    template <bool _Dummy = false, class = enable_if_t<
+        __dependent_type<is_move_constructible<_Tp>, _Dummy>::value &&
+        __dependent_type<is_swappable<_Tp>, _Dummy>::value
+    >>
+    _LIBCPP_INLINE_VISIBILITY
+    void swap(optional& __opt)
+        noexcept(is_nothrow_move_constructible_v<value_type> &&
+                 is_nothrow_swappable_v<value_type>)
+    {
+        if (this->has_value() == __opt.has_value())
+        {
+            using _VSTD::swap;
+            if (this->has_value())
+                swap(this->__get(), __opt.__get());
+        }
+        else
+        {
+            if (this->has_value())
+            {
+                __opt.__construct(_VSTD::move(this->__get()));
+                reset();
+            }
+            else
+            {
+                this->__construct(_VSTD::move(__opt.__get()));
+                __opt.reset();
+            }
+        }
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr
+    add_pointer_t<value_type const>
+    operator->() const
+    {
+        _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
+#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
+        return _VSTD::addressof(this->__get());
+#else
+        return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
+#endif
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr
+    add_pointer_t<value_type>
+    operator->()
+    {
+        _LIBCPP_ASSERT(this->has_value(), "optional operator-> called for disengaged value");
+#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
+        return _VSTD::addressof(this->__get());
+#else
+        return __operator_arrow(__has_operator_addressof<value_type>{}, this->__get());
+#endif
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr
+    const value_type&
+    operator*() const&
+    {
+        _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
+        return this->__get();
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr
+    value_type&
+    operator*() &
+    {
+        _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
+        return this->__get();
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr
+    value_type&&
+    operator*() &&
+    {
+        _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
+        return _VSTD::move(this->__get());
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr
+    const value_type&&
+    operator*() const&&
+    {
+        _LIBCPP_ASSERT(this->has_value(), "optional operator* called for disengaged value");
+        return _VSTD::move(this->__get());
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr explicit operator bool() const noexcept { return has_value(); }
+
+    using __base::has_value;
+    using __base::__get;
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr value_type const& value() const&
+    {
+        if (!this->has_value())
+            __throw_bad_optional_access();
+        return this->__get();
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr value_type& value() &
+    {
+        if (!this->has_value())
+            __throw_bad_optional_access();
+        return this->__get();
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr value_type&& value() &&
+    {
+        if (!this->has_value())
+            __throw_bad_optional_access();
+        return _VSTD::move(this->__get());
+    }
+
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr value_type const&& value() const&&
+    {
+        if (!this->has_value())
+            __throw_bad_optional_access();
+        return _VSTD::move(this->__get());
+    }
+
+    template <class _Up>
+    _LIBCPP_INLINE_VISIBILITY
+    constexpr value_type value_or(_Up&& __v) const&
+    {
+        static_assert(is_copy_constructible_v<value_type>,
+                      "optional<T>::value_or: T must be copy constructible");
+        static_assert(is_convertible_v<_Up, value_type>,
+                      "optional<T>::value_or: U must be convertible to T");
+        return this->has_value() ? this->__get() :
+                                  static_cast<value_type>(_VSTD::forward<_Up>(__v));
+    }
+
+    template <class _Up>
+    _LIBCPP_INLINE_VISIBILITY
+    value_type value_or(_Up&& __v) &&
+    {
+        static_assert(is_move_constructible_v<value_type>,
+                      "optional<T>::value_or: T must be move constructible");
+        static_assert(is_convertible_v<_Up, value_type>,
+                      "optional<T>::value_or: U must be convertible to T");
+        return this->has_value() ? _VSTD::move(this->__get()) :
+                                  static_cast<value_type>(_VSTD::forward<_Up>(__v));
+    }
+
+    using __base::reset;
+
+private:
+    template <class _Up>
+    _LIBCPP_INLINE_VISIBILITY
+    static _Up*
+    __operator_arrow(true_type, _Up& __x)
+    {
+        return _VSTD::addressof(__x);
+    }
+
+    template <class _Up>
+    _LIBCPP_INLINE_VISIBILITY
+    static constexpr _Up*
+    __operator_arrow(false_type, _Up& __x)
+    {
+        return &__x;
+    }
+};
+
+// Comparisons between optionals
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+enable_if_t<
+    is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
+        _VSTD::declval<const _Tp&>()), bool>,
+    bool
+>
+operator==(const optional<_Tp>& __x, const optional<_Tp>& __y)
+{
+    if (static_cast<bool>(__x) != static_cast<bool>(__y))
+        return false;
+    if (!static_cast<bool>(__x))
+        return true;
+    return *__x == *__y;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+enable_if_t<
+    is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
+        _VSTD::declval<const _Tp&>()), bool>,
+    bool
+>
+operator!=(const optional<_Tp>& __x, const optional<_Tp>& __y)
+{
+    if (static_cast<bool>(__x) != static_cast<bool>(__y))
+        return true;
+    if (!static_cast<bool>(__x))
+        return false;
+    return *__x != *__y;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+enable_if_t<
+    is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
+        _VSTD::declval<const _Tp&>()), bool>,
+    bool
+>
+operator<(const optional<_Tp>& __x, const optional<_Tp>& __y)
+{
+    if (!static_cast<bool>(__y))
+        return false;
+    if (!static_cast<bool>(__x))
+        return true;
+    return *__x < *__y;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+enable_if_t<
+    is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
+        _VSTD::declval<const _Tp&>()), bool>,
+    bool
+>
+operator>(const optional<_Tp>& __x, const optional<_Tp>& __y)
+{
+    if (!static_cast<bool>(__x))
+        return false;
+    if (!static_cast<bool>(__y))
+        return true;
+    return *__x > *__y;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+enable_if_t<
+    is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
+        _VSTD::declval<const _Tp&>()), bool>,
+    bool
+>
+operator<=(const optional<_Tp>& __x, const optional<_Tp>& __y)
+{
+    if (!static_cast<bool>(__x))
+        return true;
+    if (!static_cast<bool>(__y))
+        return false;
+    return *__x <= *__y;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+enable_if_t<
+    is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
+        _VSTD::declval<const _Tp&>()), bool>,
+    bool
+>
+operator>=(const optional<_Tp>& __x, const optional<_Tp>& __y)
+{
+    if (!static_cast<bool>(__y))
+        return true;
+    if (!static_cast<bool>(__x))
+        return false;
+    return *__x >= *__y;
+}
+
+// Comparisons with nullopt
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+bool
+operator==(const optional<_Tp>& __x, nullopt_t) noexcept
+{
+    return !static_cast<bool>(__x);
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+bool
+operator==(nullopt_t, const optional<_Tp>& __x) noexcept
+{
+    return !static_cast<bool>(__x);
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+bool
+operator!=(const optional<_Tp>& __x, nullopt_t) noexcept
+{
+    return static_cast<bool>(__x);
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+bool
+operator!=(nullopt_t, const optional<_Tp>& __x) noexcept
+{
+    return static_cast<bool>(__x);
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+bool
+operator<(const optional<_Tp>&, nullopt_t) noexcept
+{
+    return false;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+bool
+operator<(nullopt_t, const optional<_Tp>& __x) noexcept
+{
+    return static_cast<bool>(__x);
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+bool
+operator<=(const optional<_Tp>& __x, nullopt_t) noexcept
+{
+    return !static_cast<bool>(__x);
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+bool
+operator<=(nullopt_t, const optional<_Tp>& __x) noexcept
+{
+    return true;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+bool
+operator>(const optional<_Tp>& __x, nullopt_t) noexcept
+{
+    return static_cast<bool>(__x);
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+bool
+operator>(nullopt_t, const optional<_Tp>& __x) noexcept
+{
+    return false;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+bool
+operator>=(const optional<_Tp>&, nullopt_t) noexcept
+{
+    return true;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+bool
+operator>=(nullopt_t, const optional<_Tp>& __x) noexcept
+{
+    return !static_cast<bool>(__x);
+}
+
+// Comparisons with T
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+enable_if_t<
+    is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
+        _VSTD::declval<const _Tp&>()), bool>,
+    bool
+>
+operator==(const optional<_Tp>& __x, const _Tp& __v)
+{
+    return static_cast<bool>(__x) ? *__x == __v : false;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+enable_if_t<
+    is_convertible_v<decltype(_VSTD::declval<const _Tp&>() ==
+        _VSTD::declval<const _Tp&>()), bool>,
+    bool
+>
+operator==(const _Tp& __v, const optional<_Tp>& __x)
+{
+    return static_cast<bool>(__x) ? __v == *__x : false;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+enable_if_t<
+    is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
+        _VSTD::declval<const _Tp&>()), bool>,
+    bool
+>
+operator!=(const optional<_Tp>& __x, const _Tp& __v)
+{
+    return static_cast<bool>(__x) ? *__x != __v : true;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+enable_if_t<
+    is_convertible_v<decltype(_VSTD::declval<const _Tp&>() !=
+        _VSTD::declval<const _Tp&>()), bool>,
+    bool
+>
+operator!=(const _Tp& __v, const optional<_Tp>& __x)
+{
+    return static_cast<bool>(__x) ? __v != *__x : true;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+enable_if_t<
+    is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
+        _VSTD::declval<const _Tp&>()), bool>,
+    bool
+>
+operator<(const optional<_Tp>& __x, const _Tp& __v)
+{
+    return static_cast<bool>(__x) ? *__x < __v : true;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+enable_if_t<
+    is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <
+        _VSTD::declval<const _Tp&>()), bool>,
+    bool
+>
+operator<(const _Tp& __v, const optional<_Tp>& __x)
+{
+    return static_cast<bool>(__x) ? __v < *__x : false;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+enable_if_t<
+    is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
+        _VSTD::declval<const _Tp&>()), bool>,
+    bool
+>
+operator<=(const optional<_Tp>& __x, const _Tp& __v)
+{
+    return static_cast<bool>(__x) ? *__x <= __v : true;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+enable_if_t<
+    is_convertible_v<decltype(_VSTD::declval<const _Tp&>() <=
+        _VSTD::declval<const _Tp&>()), bool>,
+    bool
+>
+operator<=(const _Tp& __v, const optional<_Tp>& __x)
+{
+    return static_cast<bool>(__x) ? __v <= *__x : false;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+enable_if_t<
+    is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
+        _VSTD::declval<const _Tp&>()), bool>,
+    bool
+>
+operator>(const optional<_Tp>& __x, const _Tp& __v)
+{
+    return static_cast<bool>(__x) ? *__x > __v : false;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+enable_if_t<
+    is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >
+        _VSTD::declval<const _Tp&>()), bool>,
+    bool
+>
+operator>(const _Tp& __v, const optional<_Tp>& __x)
+{
+    return static_cast<bool>(__x) ? __v > *__x : true;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+enable_if_t<
+    is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
+        _VSTD::declval<const _Tp&>()), bool>,
+    bool
+>
+operator>=(const optional<_Tp>& __x, const _Tp& __v)
+{
+    return static_cast<bool>(__x) ? *__x >= __v : false;
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+enable_if_t<
+    is_convertible_v<decltype(_VSTD::declval<const _Tp&>() >=
+        _VSTD::declval<const _Tp&>()), bool>,
+    bool
+>
+operator>=(const _Tp& __v, const optional<_Tp>& __x)
+{
+    return static_cast<bool>(__x) ? __v >= *__x : true;
+}
+
+
+template <class _Tp>
+inline _LIBCPP_INLINE_VISIBILITY
+enable_if_t<
+    is_move_constructible_v<_Tp> && is_swappable_v<_Tp>,
+    void
+>
+swap(optional<_Tp>& __x, optional<_Tp>& __y) noexcept(noexcept(__x.swap(__y)))
+{
+    __x.swap(__y);
+}
+
+template <class _Tp>
+_LIBCPP_INLINE_VISIBILITY constexpr
+optional<decay_t<_Tp>> make_optional(_Tp&& __v)
+{
+    return optional<decay_t<_Tp>>(_VSTD::forward<_Tp>(__v));
+}
+
+template <class _Tp, class... _Args>
+_LIBCPP_INLINE_VISIBILITY constexpr
+optional<_Tp> make_optional(_Args&&... __args)
+{
+    return optional<_Tp>(in_place, _VSTD::forward<_Args>(__args)...);
+}
+
+template <class _Tp, class _Up, class... _Args>
+_LIBCPP_INLINE_VISIBILITY constexpr
+optional<_Tp> make_optional(initializer_list<_Up> __il,  _Args&&... __args)
+{
+    return optional<_Tp>(in_place, __il, _VSTD::forward<_Args>(__args)...);
+}
+
+template <class _Tp>
+struct _LIBCPP_TYPE_VIS_ONLY hash<optional<_Tp> >
+{
+    typedef optional<_Tp> argument_type;
+    typedef size_t        result_type;
+
+    _LIBCPP_INLINE_VISIBILITY
+    result_type operator()(const argument_type& __opt) const _NOEXCEPT
+    {
+        return static_cast<bool>(__opt) ? hash<_Tp>()(*__opt) : 0;
+    }
+};
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif  // _LIBCPP_STD_VER > 14
+
+#endif  // _LIBCPP_OPTIONAL
index 06ee3e7..43687a7 100644 (file)
@@ -425,7 +425,7 @@ template <bool _Bp, class _Tp = void> using enable_if_t = typename enable_if<_Bp
 #endif
 
 // addressof
-#if __has_builtin(__builtin_addressof) || _GNUC_VER >= 700
+#ifndef _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
 
 template <class _Tp>
 inline _LIBCPP_CONSTEXPR_AFTER_CXX14
@@ -446,7 +446,7 @@ addressof(_Tp& __x) _NOEXCEPT
     return (_Tp*)&reinterpret_cast<const volatile char&>(__x);
 }
 
-#endif // __has_builtin(__builtin_addressof)
+#endif // _LIBCPP_HAS_NO_BUILTIN_ADDRESSOF
 
 #if defined(_LIBCPP_HAS_OBJC_ARC) && !defined(_LIBCPP_PREDEFINED_OBJC_ARC_ADDRESSOF)
 // Objective-C++ Automatic Reference Counting uses qualified pointers
index 8c5dd76..f2fbfdf 100644 (file)
@@ -7,18 +7,18 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "optional"
 #include "experimental/optional"
 
-_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
+namespace std
+{
 
-#ifdef _LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS
+bad_optional_access::~bad_optional_access() _NOEXCEPT = default;
 
-bad_optional_access::~bad_optional_access() _NOEXCEPT {}
+} // std
 
-#else
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL
 
 bad_optional_access::~bad_optional_access() _NOEXCEPT = default;
 
-#endif
-
 _LIBCPP_END_NAMESPACE_EXPERIMENTAL
diff --git a/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp
new file mode 100644 (file)
index 0000000..e4de92f
--- /dev/null
@@ -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
+// XFAIL: libcpp-no-exceptions
+// <optional>
+
+// optional<T>& operator=(const optional<T>& rhs);
+
+#include <optional>
+#include <string>
+#include <type_traits>
+
+using std::optional;
+
+struct X {};
+
+struct Y
+{
+    Y() = default;
+    Y& operator=(const Y&) { return *this; }
+};
+
+struct Z1
+{
+    Z1() = default;
+    Z1(Z1&&) = default;
+    Z1(const Z1&) = default;
+    Z1& operator=(Z1&&) = default;
+    Z1& operator=(const Z1&) = delete;
+};
+
+struct Z2
+{
+    Z2() = default;
+    Z2(Z2&&) = default;
+    Z2(const Z2&) = delete;
+    Z2& operator=(Z2&&) = default;
+    Z2& operator=(const Z2&) = default;
+};
+
+#if __cplusplus >= 201402
+template <class T>
+constexpr bool
+test()
+{
+    optional<T> opt;
+    optional<T> opt2;
+    opt = opt2;
+    return true;
+}
+#endif
+
+int main()
+{
+    {
+        using T = int;
+        static_assert((std::is_trivially_copy_assignable<optional<T>>::value), "");
+#if __cplusplus >= 201402
+        static_assert(test<T>(), "");
+#endif
+    }
+    {
+        using T = X;
+        static_assert((std::is_trivially_copy_assignable<optional<T>>::value), "");
+#if __cplusplus >= 201402
+        static_assert(test<T>(), "");
+#endif
+    }
+    static_assert(!(std::is_trivially_copy_assignable<optional<Y>>::value), "");
+    static_assert(!(std::is_trivially_copy_assignable<optional<std::string>>::value), "");
+
+    static_assert(!(std::is_copy_assignable<optional<Z1>>::value), "");
+    static_assert(!(std::is_copy_assignable<optional<Z2>>::value), "");
+}
diff --git a/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/move.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.assign/move.pass.cpp
new file mode 100644 (file)
index 0000000..e2eaa8c
--- /dev/null
@@ -0,0 +1,78 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// XFAIL: libcpp-no-exceptions
+// <optional>
+
+// optional<T>& operator=(optional<T>&& rhs);
+
+#include <optional>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+using std::optional;
+
+struct X {};
+
+struct Y
+{
+    Y() = default;
+    Y& operator=(Y&&) { return *this; }
+};
+
+struct Z1
+{
+    Z1() = default;
+    Z1(Z1&&) = default;
+    Z1& operator=(Z1&&) = delete;
+};
+
+struct Z2
+{
+    Z2() = default;
+    Z2(Z2&&) = delete;
+    Z2& operator=(Z2&&) = default;
+};
+
+#if __cplusplus >= 201402
+template <class T>
+constexpr bool
+test()
+{
+    optional<T> opt;
+    optional<T> opt2;
+    opt = std::move(opt2);
+    return true;
+}
+#endif
+
+int main()
+{
+    {
+        using T = int;
+        static_assert((std::is_trivially_copy_constructible<optional<T>>::value), "");
+#if __cplusplus >= 201402
+        static_assert(test<T>(), "");
+#endif
+    }
+    {
+        using T = X;
+        static_assert((std::is_trivially_copy_constructible<optional<T>>::value), "");
+#if __cplusplus >= 201402
+        static_assert(test<T>(), "");
+#endif
+    }
+    static_assert(!(std::is_trivially_move_assignable<optional<Y>>::value), "");
+    static_assert(!(std::is_trivially_move_assignable<optional<std::string>>::value), "");
+
+    static_assert(!(std::is_move_assignable<optional<Z1>>::value), "");
+    static_assert(!(std::is_move_assignable<optional<Z2>>::value), "");
+}
diff --git a/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
new file mode 100644 (file)
index 0000000..75e7635
--- /dev/null
@@ -0,0 +1,59 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// XFAIL: libcpp-no-exceptions
+// <optional>
+
+// optional(const optional<T>& rhs);
+
+#include <optional>
+#include <string>
+#include <type_traits>
+
+using std::optional;
+
+struct X {};
+
+struct Y
+{
+    Y() = default;
+    Y(const Y&) {}
+};
+
+struct Z
+{
+    Z() = default;
+    Z(Z&&) = delete;
+    Z(const Z&) = delete;
+    Z& operator=(Z&&) = delete;
+    Z& operator=(const Z&) = delete;
+};
+
+int main()
+{
+    {
+        using T = int;
+        static_assert((std::is_trivially_copy_constructible<optional<T>>::value), "");
+        constexpr optional<T> opt;
+        constexpr optional<T> opt2 = opt;
+        (void)opt2;
+    }
+    {
+        using T = X;
+        static_assert((std::is_trivially_copy_constructible<optional<T>>::value), "");
+        constexpr optional<T> opt;
+        constexpr optional<T> opt2 = opt;
+        (void)opt2;
+    }
+    static_assert(!(std::is_trivially_copy_constructible<optional<Y>>::value), "");
+    static_assert(!(std::is_trivially_copy_constructible<optional<std::string>>::value), "");
+
+    static_assert(!(std::is_copy_constructible<optional<Z>>::value), "");
+}
diff --git a/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
new file mode 100644 (file)
index 0000000..e6d9bb8
--- /dev/null
@@ -0,0 +1,60 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// XFAIL: libcpp-no-exceptions
+// <optional>
+
+// optional(optional<T>&& rhs);
+
+#include <optional>
+#include <string>
+#include <type_traits>
+#include <utility>
+
+using std::optional;
+
+struct X {};
+
+struct Y
+{
+    Y() = default;
+    Y(Y&&) {}
+};
+
+struct Z
+{
+    Z() = default;
+    Z(Z&&) = delete;
+    Z(const Z&) = delete;
+    Z& operator=(Z&&) = delete;
+    Z& operator=(const Z&) = delete;
+};
+
+int main()
+{
+    {
+        using T = int;
+        static_assert((std::is_trivially_copy_constructible<optional<T>>::value), "");
+        constexpr optional<T> opt;
+        constexpr optional<T> opt2 = std::move(opt);
+        (void)opt2;
+    }
+    {
+        using T = X;
+        static_assert((std::is_trivially_copy_constructible<optional<T>>::value), "");
+        constexpr optional<T> opt;
+        constexpr optional<T> opt2 = std::move(opt);
+        (void)opt2;
+    }
+    static_assert(!(std::is_trivially_move_constructible<optional<Y>>::value), "");
+    static_assert(!(std::is_trivially_move_constructible<optional<std::string>>::value), "");
+
+    static_assert(!(std::is_move_constructible<optional<Z>>::value), "");
+}
diff --git a/libcxx/test/libcxx/utilities/optional/optional.object/special_member_gen.pass.cpp b/libcxx/test/libcxx/utilities/optional/optional.object/special_member_gen.pass.cpp
new file mode 100644 (file)
index 0000000..9493d6b
--- /dev/null
@@ -0,0 +1,66 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// 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>;
+
+    template <template <class> class TestMF>
+    static constexpr bool check_same() {
+        return TestMF<O>::value == TestMF<T>::value;
+    }
+
+    // Test that optional inherits the correct trivial/non-trivial members
+    static_assert(check_same<std::is_trivially_destructible>(), "");
+    static_assert(check_same<std::is_trivially_copyable>(), "");
+};
+
+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/libcxx/test/libcxx/utilities/optional/version.pass.cpp b/libcxx/test/libcxx/utilities/optional/version.pass.cpp
new file mode 100644 (file)
index 0000000..e7581b5
--- /dev/null
@@ -0,0 +1,20 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <optional>
+
+#include <optional>
+
+#ifndef _LIBCPP_VERSION
+#error _LIBCPP_VERSION not defined
+#endif
+
+int main()
+{
+}
index 408231f..b23a5e4 100644 (file)
@@ -59,7 +59,7 @@ int main()
                       !std::is_nothrow_swappable_with<A&, A&>::value, "");
     }
     {
-        // test that hetrogenius swap is allowed only if both 'swap(A, B)' and
+        // test that heterogeneous swap is allowed only if both 'swap(A, B)' and
         // 'swap(B, A)' are valid.
         static_assert(std::is_nothrow_swappable_with<A&, B&>::value, "");
         static_assert(!std::is_nothrow_swappable_with<A&, C&>::value &&
diff --git a/libcxx/test/std/utilities/optional/optional.bad_optional_access/default.pass.cpp b/libcxx/test/std/utilities/optional/optional.bad_optional_access/default.pass.cpp
new file mode 100644 (file)
index 0000000..e3c7bb5
--- /dev/null
@@ -0,0 +1,23 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <optional>
+
+// class bad_optional_access is default constructible
+
+#include <optional>
+#include <type_traits>
+
+int main()
+{
+    using std::bad_optional_access;
+    bad_optional_access ex;
+}
diff --git a/libcxx/test/std/utilities/optional/optional.bad_optional_access/derive.pass.cpp b/libcxx/test/std/utilities/optional/optional.bad_optional_access/derive.pass.cpp
new file mode 100644 (file)
index 0000000..85e36d2
--- /dev/null
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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>
+
+// class bad_optional_access : public logic_error
+
+#include <optional>
+#include <type_traits>
+
+int main()
+{
+    using std::bad_optional_access;
+
+    static_assert(std::is_base_of<std::logic_error, bad_optional_access>::value, "");
+    static_assert(std::is_convertible<bad_optional_access*, std::logic_error*>::value, "");
+}
diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/equal.pass.cpp
new file mode 100644 (file)
index 0000000..b54a08f
--- /dev/null
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class T> constexpr bool operator==(const optional<T>& x, const T& v);
+// template <class T> constexpr bool operator==(const T& v, const optional<T>& x);
+
+#include <optional>
+
+using std::optional;
+
+struct X
+{
+    int i_;
+
+    constexpr X(int i) : i_(i) {}
+};
+
+constexpr bool operator == ( const X &lhs, const X &rhs )
+    { return lhs.i_ == rhs.i_ ; }
+
+int main()
+{
+    {
+    typedef X T;
+    typedef optional<T> O;
+
+    constexpr T val(2);
+    constexpr O o1;       // disengaged
+    constexpr O o2{1};    // engaged
+    constexpr O o3{val};  // engaged
+
+    static_assert ( !(o1 == T(1)), "" );
+    static_assert (  (o2 == T(1)), "" );
+    static_assert ( !(o3 == T(1)), "" );
+    static_assert (  (o3 == T(2)), "" );
+    static_assert (  (o3 == val),  "" );
+
+    static_assert ( !(T(1) == o1), "" );
+    static_assert (  (T(1) == o2), "" );
+    static_assert ( !(T(1) == o3), "" );
+    static_assert (  (T(2) == o3), "" );
+    static_assert (  (val  == o3), "" );
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/greater.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/greater.pass.cpp
new file mode 100644 (file)
index 0000000..064114f
--- /dev/null
@@ -0,0 +1,55 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class T> constexpr bool operator>(const optional<T>& x, const T& v);
+// template <class T> constexpr bool operator>(const T& v, const optional<T>& x);
+
+#include <optional>
+
+using std::optional;
+
+struct X
+{
+    int i_;
+
+    constexpr X(int i) : i_(i) {}
+};
+
+constexpr bool operator > ( const X &lhs, const X &rhs )
+    { return lhs.i_ > rhs.i_ ; }
+
+int main()
+{
+    {
+    typedef X T;
+    typedef optional<T> O;
+
+    constexpr T val(2);
+    constexpr O o1;       // disengaged
+    constexpr O o2{1};    // engaged
+    constexpr O o3{val};  // engaged
+
+    static_assert ( !(o1 > T(1)), "" );
+    static_assert ( !(o2 > T(1)), "" );  // equal
+    static_assert (  (o3 > T(1)), "" );
+    static_assert ( !(o2 >  val), "" );
+    static_assert ( !(o3 >  val), "" );  // equal
+    static_assert ( !(o3 > T(3)), "" );
+
+    static_assert (   (T(1) > o1), "" );
+    static_assert (  !(T(1) > o2), "" ); // equal
+    static_assert (  !(T(1) > o3), "" );
+    static_assert (   (val  > o2), "" );
+    static_assert (  !(val  > o3), "" ); // equal
+    static_assert (   (T(3) > o3), "" );
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/greater_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/greater_equal.pass.cpp
new file mode 100644 (file)
index 0000000..663686c
--- /dev/null
@@ -0,0 +1,55 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class T> constexpr bool operator>=(const optional<T>& x, const T& v);
+// template <class T> constexpr bool operator>=(const T& v, const optional<T>& x);
+
+#include <optional>
+
+using std::optional;
+
+struct X
+{
+    int i_;
+
+    constexpr X(int i) : i_(i) {}
+};
+
+constexpr bool operator >= ( const X &lhs, const X &rhs )
+    { return lhs.i_ >= rhs.i_ ; }
+
+int main()
+{
+    {
+    typedef X T;
+    typedef optional<T> O;
+
+    constexpr T val(2);
+    constexpr O o1;       // disengaged
+    constexpr O o2{1};    // engaged
+    constexpr O o3{val};  // engaged
+
+    static_assert ( !(o1 >= T(1)), "" );
+    static_assert (  (o2 >= T(1)), "" );  // equal
+    static_assert (  (o3 >= T(1)), "" );
+    static_assert ( !(o2 >=  val), "" );
+    static_assert (  (o3 >=  val), "" );  // equal
+    static_assert ( !(o3 >= T(3)), "" );
+
+    static_assert (   (T(1) >= o1), "" );
+    static_assert (   (T(1) >= o2), "" ); // equal
+    static_assert (  !(T(1) >= o3), "" );
+    static_assert (   (val  >= o2), "" );
+    static_assert (   (val  >= o3), "" ); // equal
+    static_assert (   (T(3) >= o3), "" );
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/less_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/less_equal.pass.cpp
new file mode 100644 (file)
index 0000000..05ac5eb
--- /dev/null
@@ -0,0 +1,55 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class T> constexpr bool operator<=(const optional<T>& x, const T& v);
+// template <class T> constexpr bool operator<=(const T& v, const optional<T>& x);
+
+#include <optional>
+
+using std::optional;
+
+struct X
+{
+    int i_;
+
+    constexpr X(int i) : i_(i) {}
+};
+
+constexpr bool operator <= ( const X &lhs, const X &rhs )
+    { return lhs.i_ <= rhs.i_ ; }
+
+int main()
+{
+    {
+    typedef X T;
+    typedef optional<T> O;
+
+    constexpr T val(2);
+    constexpr O o1;       // disengaged
+    constexpr O o2{1};    // engaged
+    constexpr O o3{val};  // engaged
+
+    static_assert (  (o1 <= T(1)), "" );
+    static_assert (  (o2 <= T(1)), "" );  // equal
+    static_assert ( !(o3 <= T(1)), "" );
+    static_assert (  (o2 <=  val), "" );
+    static_assert (  (o3 <=  val), "" );  // equal
+    static_assert (  (o3 <= T(3)), "" );
+
+    static_assert (  !(T(1) <= o1), "" );
+    static_assert (   (T(1) <= o2), "" ); // equal
+    static_assert (   (T(1) <= o3), "" );
+    static_assert (  !(val  <= o2), "" );
+    static_assert (   (val  <= o3), "" ); // equal
+    static_assert (  !(T(3) <= o3), "" );
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/less_than.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/less_than.pass.cpp
new file mode 100644 (file)
index 0000000..d1891a2
--- /dev/null
@@ -0,0 +1,55 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class T> constexpr bool operator<(const optional<T>& x, const T& v);
+// template <class T> constexpr bool operator<(const T& v, const optional<T>& x);
+
+#include <optional>
+
+using std::optional;
+
+struct X
+{
+    int i_;
+
+    constexpr X(int i) : i_(i) {}
+};
+
+constexpr bool operator < ( const X &lhs, const X &rhs )
+    { return lhs.i_ < rhs.i_ ; }
+
+int main()
+{
+    {
+    typedef X T;
+    typedef optional<T> O;
+
+    constexpr T val(2);
+    constexpr O o1;       // disengaged
+    constexpr O o2{1};    // engaged
+    constexpr O o3{val};  // engaged
+
+    static_assert (  (o1 < T(1)), "" );
+    static_assert ( !(o2 < T(1)), "" );  // equal
+    static_assert ( !(o3 < T(1)), "" );
+    static_assert (  (o2 <  val), "" );
+    static_assert ( !(o3 <  val), "" );  // equal
+    static_assert (  (o3 < T(3)), "" );
+
+    static_assert (  !(T(1) < o1), "" );
+    static_assert (  !(T(1) < o2), "" ); // equal
+    static_assert (   (T(1) < o3), "" );
+    static_assert (  !(val  < o2), "" );
+    static_assert (  !(val  < o3), "" ); // equal
+    static_assert (  !(T(3) < o3), "" );
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.comp_with_t/not_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.comp_with_t/not_equal.pass.cpp
new file mode 100644 (file)
index 0000000..ae2ff80
--- /dev/null
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class T> constexpr bool operator!=(const optional<T>& x, const T& v);
+// template <class T> constexpr bool operator!=(const T& v, const optional<T>& x);
+
+#include <optional>
+
+using std::optional;
+
+struct X
+{
+    int i_;
+
+    constexpr X(int i) : i_(i) {}
+};
+
+constexpr bool operator != ( const X &lhs, const X &rhs )
+    { return lhs.i_ != rhs.i_ ; }
+
+int main()
+{
+    {
+    typedef X T;
+    typedef optional<T> O;
+
+    constexpr T val(2);
+    constexpr O o1;       // disengaged
+    constexpr O o2{1};    // engaged
+    constexpr O o3{val};  // engaged
+
+    static_assert (  (o1 != T(1)), "" );
+    static_assert ( !(o2 != T(1)), "" );
+    static_assert (  (o3 != T(1)), "" );
+    static_assert ( !(o3 != T(2)), "" );
+    static_assert ( !(o3 != val),  "" );
+
+    static_assert (  (T(1) != o1), "" );
+    static_assert ( !(T(1) != o2), "" );
+    static_assert (  (T(1) != o3), "" );
+    static_assert ( !(T(2) != o3), "" );
+    static_assert ( !(val  != o3), "" );
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.hash/hash.pass.cpp b/libcxx/test/std/utilities/optional/optional.hash/hash.pass.cpp
new file mode 100644 (file)
index 0000000..dfdd07d
--- /dev/null
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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> struct hash<optional<T>>;
+
+#include <optional>
+#include <string>
+#include <memory>
+#include <cassert>
+
+
+int main()
+{
+    using std::optional;
+    const std::size_t nullopt_hash =
+        std::hash<optional<double>>{}(optional<double>{});
+
+    {
+        typedef int T;
+        optional<T> opt;
+        assert(std::hash<optional<T>>{}(opt) == nullopt_hash);
+        opt = 2;
+        assert(std::hash<optional<T>>{}(opt) == std::hash<T>{}(*opt));
+    }
+    {
+        typedef std::string T;
+        optional<T> opt;
+        assert(std::hash<optional<T>>{}(opt) == nullopt_hash);
+        opt = std::string("123");
+        assert(std::hash<optional<T>>{}(opt) == std::hash<T>{}(*opt));
+    }
+    {
+        typedef std::unique_ptr<int> T;
+        optional<T> opt;
+        assert(std::hash<optional<T>>{}(opt) == nullopt_hash);
+        opt = std::unique_ptr<int>(new int(3));
+        assert(std::hash<optional<T>>{}(opt) == std::hash<T>{}(*opt));
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.nullops/equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullops/equal.pass.cpp
new file mode 100644 (file)
index 0000000..a87a87f
--- /dev/null
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept;
+// template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept;
+
+#include <optional>
+
+int main()
+{
+    using std::optional;
+    using std::nullopt_t;
+    using std::nullopt;
+
+    {
+    typedef int T;
+    typedef optional<T> O;
+
+    constexpr O o1;     // disengaged
+    constexpr O o2{1};  // engaged
+
+    static_assert (  (nullopt == o1), "" );
+    static_assert ( !(nullopt == o2), "" );
+    static_assert (  (o1 == nullopt), "" );
+    static_assert ( !(o2 == nullopt), "" );
+
+    static_assert (noexcept(nullopt == o1), "");
+    static_assert (noexcept(o1 == nullopt), "");
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.nullops/greater.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullops/greater.pass.cpp
new file mode 100644 (file)
index 0000000..3986a0a
--- /dev/null
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept;
+// template <class T> constexpr bool operator>(nullopt_t, const optional<T>& x) noexcept;
+
+#include <optional>
+
+int main()
+{
+    using std::optional;
+    using std::nullopt_t;
+    using std::nullopt;
+
+    {
+    typedef int T;
+    typedef optional<T> O;
+
+    constexpr O o1;     // disengaged
+    constexpr O o2{1};  // engaged
+
+    static_assert ( !(nullopt > o1), "" );
+    static_assert ( !(nullopt > o2), "" );
+    static_assert ( !(o1 > nullopt), "" );
+    static_assert (  (o2 > nullopt), "" );
+
+    static_assert (noexcept(nullopt > o1), "");
+    static_assert (noexcept(o1 > nullopt), "");
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.nullops/greater_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullops/greater_equal.pass.cpp
new file mode 100644 (file)
index 0000000..9f24272
--- /dev/null
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class T> constexpr bool operator>=(const optional<T>& x, nullopt_t) noexcept;
+// template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept;
+
+#include <optional>
+
+int main()
+{
+    using std::optional;
+    using std::nullopt_t;
+    using std::nullopt;
+
+    {
+    typedef int T;
+    typedef optional<T> O;
+
+    constexpr O o1;     // disengaged
+    constexpr O o2{1};  // engaged
+
+    static_assert (  (nullopt >= o1), "" );
+    static_assert ( !(nullopt >= o2), "" );
+    static_assert (  (o1 >= nullopt), "" );
+    static_assert (  (o2 >= nullopt), "" );
+
+    static_assert (noexcept(nullopt >= o1), "");
+    static_assert (noexcept(o1 >= nullopt), "");
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.nullops/less_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullops/less_equal.pass.cpp
new file mode 100644 (file)
index 0000000..8e73247
--- /dev/null
@@ -0,0 +1,40 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+
+// <optional>
+
+// template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept;
+// template <class T> constexpr bool operator<=(nullopt_t, const optional<T>& x) noexcept;
+
+#include <optional>
+
+int main()
+{
+    using std::optional;
+    using std::nullopt_t;
+    using std::nullopt;
+
+    {
+    typedef int T;
+    typedef optional<T> O;
+
+    constexpr O o1;     // disengaged
+    constexpr O o2{1};  // engaged
+
+    static_assert (  (nullopt <= o1), "" );
+    static_assert (  (nullopt <= o2), "" );
+    static_assert (  (o1 <= nullopt), "" );
+    static_assert ( !(o2 <= nullopt), "" );
+
+    static_assert (noexcept(nullopt <= o1), "");
+    static_assert (noexcept(o1 <= nullopt), "");
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.nullops/less_than.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullops/less_than.pass.cpp
new file mode 100644 (file)
index 0000000..39a8e4a
--- /dev/null
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class T> constexpr bool operator<(const optional<T>& x, nullopt_t) noexcept;
+// template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept;
+
+#include <optional>
+
+int main()
+{
+    using std::optional;
+    using std::nullopt_t;
+    using std::nullopt;
+
+    {
+    typedef int T;
+    typedef optional<T> O;
+
+    constexpr O o1;     // disengaged
+    constexpr O o2{1};  // engaged
+
+    static_assert ( !(nullopt < o1), "" );
+    static_assert (  (nullopt < o2), "" );
+    static_assert ( !(o1 < nullopt), "" );
+    static_assert ( !(o2 < nullopt), "" );
+
+    static_assert (noexcept(nullopt < o1), "");
+    static_assert (noexcept(o1 < nullopt), "");
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.nullops/not_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullops/not_equal.pass.cpp
new file mode 100644 (file)
index 0000000..1c96dd4
--- /dev/null
@@ -0,0 +1,39 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept;
+// template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept;
+
+#include <optional>
+
+int main()
+{
+    using std::optional;
+    using std::nullopt_t;
+    using std::nullopt;
+
+    {
+    typedef int T;
+    typedef optional<T> O;
+
+    constexpr O o1;     // disengaged
+    constexpr O o2{1};  // engaged
+
+    static_assert ( !(nullopt != o1), "" );
+    static_assert (  (nullopt != o2), "" );
+    static_assert ( !(o1 != nullopt), "" );
+    static_assert (  (o2 != nullopt), "" );
+
+    static_assert (noexcept(nullopt != o1), "");
+    static_assert (noexcept(o1 != nullopt), "");
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.nullopt/not_brace_initializable.fail.cpp b/libcxx/test/std/utilities/optional/optional.nullopt/not_brace_initializable.fail.cpp
new file mode 100644 (file)
index 0000000..86da505
--- /dev/null
@@ -0,0 +1,25 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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>
+
+// struct nullopt_t{see below};
+
+#include <optional>
+
+using std::optional;
+using std::nullopt_t;
+
+int main()
+{
+    // I roughly interpret LWG2736 as "it shall not be possible to copy-list-initialize nullopt_t with an
+    // empty braced-init-list."
+    nullopt_t foo = {};
+}
diff --git a/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.nullopt/nullopt_t.pass.cpp
new file mode 100644 (file)
index 0000000..84bb29f
--- /dev/null
@@ -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>
+
+// struct nullopt_t{see below};
+// constexpr nullopt_t nullopt(unspecified);
+
+#include <optional>
+#include <type_traits>
+
+using std::optional;
+using std::nullopt_t;
+using std::nullopt;
+
+constexpr
+int
+test(const nullopt_t&)
+{
+    return 3;
+}
+
+int main()
+{
+    static_assert((std::is_class<nullopt_t>::value), "");
+    static_assert((std::is_empty<nullopt_t>::value), "");
+    static_assert((std::is_literal_type<nullopt_t>::value), "");
+    static_assert((!std::is_default_constructible<nullopt_t>::value), "");
+
+    static_assert(test(nullopt) == 3, "");
+}
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp
new file mode 100644 (file)
index 0000000..6abdd0d
--- /dev/null
@@ -0,0 +1,261 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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;
+};
+
+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>();
+}
+
+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/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp
new file mode 100644 (file)
index 0000000..d471c05
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp
new file mode 100644 (file)
index 0000000..98c90aa
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp
new file mode 100644 (file)
index 0000000..be17aa6
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp
new file mode 100644 (file)
index 0000000..1c3c69a
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp
new file mode 100644 (file)
index 0000000..3ba261b
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp
new file mode 100644 (file)
index 0000000..991f433
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp
new file mode 100644 (file)
index 0000000..db7fc19
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/U.pass.cpp
new file mode 100644 (file)
index 0000000..4830fe9
--- /dev/null
@@ -0,0 +1,137 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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), "");
+    }
+    {
+        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);
+        } 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();
+}
\ No newline at end of file
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_T.pass.cpp
new file mode 100644 (file)
index 0000000..3f98d90
--- /dev/null
@@ -0,0 +1,123 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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&) {}
+        };
+
+    }
+    {
+        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/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/const_optional_U.pass.cpp
new file mode 100644 (file)
index 0000000..e12f6cb
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
new file mode 100644 (file)
index 0000000..d2b704c
--- /dev/null
@@ -0,0 +1,150 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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);
+    {
+        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/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/default.pass.cpp
new file mode 100644 (file)
index 0000000..62795b9
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_const_optional_U.pass.cpp
new file mode 100644 (file)
index 0000000..64ac053
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/explicit_optional_U.pass.cpp
new file mode 100644 (file)
index 0000000..2c6757a
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/in_place_t.pass.cpp
new file mode 100644 (file)
index 0000000..9b59b02
--- /dev/null
@@ -0,0 +1,144 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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 i) {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) {}
+        };
+
+    }
+    {
+        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/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/initializer_list.pass.cpp
new file mode 100644 (file)
index 0000000..6d9f45a
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
new file mode 100644 (file)
index 0000000..5a4929c
--- /dev/null
@@ -0,0 +1,196 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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);
+    {
+        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/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/nullopt_t.pass.cpp
new file mode 100644 (file)
index 0000000..468a003
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/optional_U.pass.cpp
new file mode 100644 (file)
index 0000000..0e180c1
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.ctor/rvalue_T.pass.cpp
new file mode 100644 (file)
index 0000000..496661d
--- /dev/null
@@ -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>
+
+// 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&&) {}
+        };
+    }
+    {
+        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/libcxx/test/std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.dtor/dtor.pass.cpp
new file mode 100644 (file)
index 0000000..5132c9a
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.mod/reset.pass.cpp
new file mode 100644 (file)
index 0000000..cee73da
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/bool.pass.cpp
new file mode 100644 (file)
index 0000000..9820d50
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference.pass.cpp
new file mode 100644 (file)
index 0000000..4087cfd
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const.pass.cpp
new file mode 100644 (file)
index 0000000..0779c90
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_const_rvalue.pass.cpp
new file mode 100644 (file)
index 0000000..78fd992
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/dereference_rvalue.pass.cpp
new file mode 100644 (file)
index 0000000..2924123
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/has_value.pass.cpp
new file mode 100644 (file)
index 0000000..5df295d
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow.pass.cpp
new file mode 100644 (file)
index 0000000..2f1648c
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/op_arrow_const.pass.cpp
new file mode 100644 (file)
index 0000000..887edc7
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value.pass.cpp
new file mode 100644 (file)
index 0000000..516a79d
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.fail.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.fail.cpp
new file mode 100644 (file)
index 0000000..6076c50
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const.pass.cpp
new file mode 100644 (file)
index 0000000..d4038e4
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_const_rvalue.pass.cpp
new file mode 100644 (file)
index 0000000..e189d3a
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or.pass.cpp
new file mode 100644 (file)
index 0000000..c219e97
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or_const.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_or_const.pass.cpp
new file mode 100644 (file)
index 0000000..36a8581
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_rvalue.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.observe/value_rvalue.pass.cpp
new file mode 100644 (file)
index 0000000..2ef485b
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.swap/swap.pass.cpp
new file mode 100644 (file)
index 0000000..6bbb880
--- /dev/null
@@ -0,0 +1,345 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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& x, Z& y) {TEST_THROW(6);}
+};
+
+template <class T, class = decltype(std::declval<T&>().swap(std::declval<T&>()))>
+constexpr bool has_swap(int) { return true; }
+template <class T>
+constexpr bool has_swap(long) { return false; }
+template <class T>
+constexpr bool has_swap() {return has_swap<T>(0); }
+
+struct NonSwappable {
+};
+void swap(NonSwappable&, NonSwappable&) = delete;
+
+void test_swap_sfinae() {
+    using std::optional;
+    {
+        using T = TestTypes::TestType;
+        static_assert(has_swap<optional<T>>(), "");
+    }
+    {
+        using T = TestTypes::MoveOnly;
+        static_assert(has_swap<optional<T>>(), "");
+    }
+    {
+        using T = TestTypes::Copyable;
+        static_assert(has_swap<optional<T>>(), "");
+    }
+    {
+        using T = TestTypes::NoCtors;
+        static_assert(!has_swap<optional<T>>(), "");
+    }
+    {
+        using T = TestTypes::CopyOnly;
+        static_assert(!has_swap<optional<T>>(), "");
+    }
+    {
+        using T = NonSwappable;
+        static_assert(!has_swap<optional<T>>(), "");
+    }
+}
+
+int main()
+{
+    test_swap_sfinae();
+    {
+        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/libcxx/test/std/utilities/optional/optional.object/optional_requires_destructible_object.fail.cpp b/libcxx/test/std/utilities/optional/optional.object/optional_requires_destructible_object.fail.cpp
new file mode 100644 (file)
index 0000000..8a2c77a
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/special_member_gen.pass.cpp
new file mode 100644 (file)
index 0000000..fdd0f15
--- /dev/null
@@ -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/libcxx/test/std/utilities/optional/optional.object/types.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/types.pass.cpp
new file mode 100644 (file)
index 0000000..0230a13
--- /dev/null
@@ -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>();
+}
diff --git a/libcxx/test/std/utilities/optional/optional.relops/equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/equal.pass.cpp
new file mode 100644 (file)
index 0000000..6650b67
--- /dev/null
@@ -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>
+
+// template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+using std::optional;
+
+struct X
+{
+    int i_;
+
+    constexpr X(int i) : i_(i) {}
+};
+
+constexpr bool operator == ( const X &lhs, const X &rhs )
+    { return lhs.i_ == rhs.i_ ; }
+
+int main()
+{
+    {
+    typedef X T;
+    typedef optional<T> O;
+
+    constexpr O o1;     // disengaged
+    constexpr O o2;     // disengaged
+    constexpr O o3{1};  // engaged
+    constexpr O o4{2};  // engaged
+    constexpr O o5{1};  // engaged
+
+    static_assert (   o1 == o1 , "" );
+    static_assert (   o1 == o2 , "" );
+    static_assert ( !(o1 == o3), "" );
+    static_assert ( !(o1 == o4), "" );
+    static_assert ( !(o1 == o5), "" );
+
+    static_assert (   o2 == o1 , "" );
+    static_assert (   o2 == o2 , "" );
+    static_assert ( !(o2 == o3), "" );
+    static_assert ( !(o2 == o4), "" );
+    static_assert ( !(o2 == o5), "" );
+
+    static_assert ( !(o3 == o1), "" );
+    static_assert ( !(o3 == o2), "" );
+    static_assert (   o3 == o3 , "" );
+    static_assert ( !(o3 == o4), "" );
+    static_assert (   o3 == o5 , "" );
+
+    static_assert ( !(o4 == o1), "" );
+    static_assert ( !(o4 == o2), "" );
+    static_assert ( !(o4 == o3), "" );
+    static_assert (   o4 == o4 , "" );
+    static_assert ( !(o4 == o5), "" );
+
+    static_assert ( !(o5 == o1), "" );
+    static_assert ( !(o5 == o2), "" );
+    static_assert (   o5 == o3 , "" );
+    static_assert ( !(o5 == o4), "" );
+    static_assert (   o5 == o5 , "" );
+
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.relops/greater_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/greater_equal.pass.cpp
new file mode 100644 (file)
index 0000000..f9b3044
--- /dev/null
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class T> constexpr bool operator>= (const optional<T>& x, const optional<T>& y);
+
+#include <optional>
+
+using std::optional;
+
+struct X
+{
+    int i_;
+
+    constexpr X(int i) : i_(i) {}
+};
+
+constexpr bool operator >= ( const X &lhs, const X &rhs )
+    { return lhs.i_ >= rhs.i_ ; }
+
+int main()
+{
+    {
+    typedef optional<X> O;
+
+    constexpr O o1;     // disengaged
+    constexpr O o2;     // disengaged
+    constexpr O o3{1};  // engaged
+    constexpr O o4{2};  // engaged
+    constexpr O o5{1};  // engaged
+
+    static_assert (  (o1 >= o1), "" );
+    static_assert (  (o1 >= o2), "" );
+    static_assert ( !(o1 >= o3), "" );
+    static_assert ( !(o1 >= o4), "" );
+    static_assert ( !(o1 >= o5), "" );
+
+    static_assert (  (o2 >= o1), "" );
+    static_assert (  (o2 >= o2), "" );
+    static_assert ( !(o2 >= o3), "" );
+    static_assert ( !(o2 >= o4), "" );
+    static_assert ( !(o2 >= o5), "" );
+
+    static_assert (  (o3 >= o1), "" );
+    static_assert (  (o3 >= o2), "" );
+    static_assert (  (o3 >= o3), "" );
+    static_assert ( !(o3 >= o4), "" );
+    static_assert (  (o3 >= o5), "" );
+
+    static_assert (  (o4 >= o1), "" );
+    static_assert (  (o4 >= o2), "" );
+    static_assert (  (o4 >= o3), "" );
+    static_assert (  (o4 >= o4), "" );
+    static_assert (  (o4 >= o5), "" );
+
+    static_assert (  (o5 >= o1), "" );
+    static_assert (  (o5 >= o2), "" );
+    static_assert (  (o5 >= o3), "" );
+    static_assert ( !(o5 >= o4), "" );
+    static_assert (  (o5 >= o5), "" );
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.relops/greater_than.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/greater_than.pass.cpp
new file mode 100644 (file)
index 0000000..8a27eb4
--- /dev/null
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class T> constexpr bool operator> (const optional<T>& x, const optional<T>& y);
+
+#include <optional>
+
+using std::optional;
+
+struct X
+{
+    int i_;
+
+    constexpr X(int i) : i_(i) {}
+};
+
+constexpr bool operator > ( const X &lhs, const X &rhs )
+    { return lhs.i_ > rhs.i_ ; }
+
+int main()
+{
+    {
+    typedef optional<X> O;
+
+    constexpr O o1;     // disengaged
+    constexpr O o2;     // disengaged
+    constexpr O o3{1};  // engaged
+    constexpr O o4{2};  // engaged
+    constexpr O o5{1};  // engaged
+
+    static_assert ( !(o1 > o1), "" );
+    static_assert ( !(o1 > o2), "" );
+    static_assert ( !(o1 > o3), "" );
+    static_assert ( !(o1 > o4), "" );
+    static_assert ( !(o1 > o5), "" );
+
+    static_assert ( !(o2 > o1), "" );
+    static_assert ( !(o2 > o2), "" );
+    static_assert ( !(o2 > o3), "" );
+    static_assert ( !(o2 > o4), "" );
+    static_assert ( !(o2 > o5), "" );
+
+    static_assert (  (o3 > o1), "" );
+    static_assert (  (o3 > o2), "" );
+    static_assert ( !(o3 > o3), "" );
+    static_assert ( !(o3 > o4), "" );
+    static_assert ( !(o3 > o5), "" );
+
+    static_assert (  (o4 > o1), "" );
+    static_assert (  (o4 > o2), "" );
+    static_assert (  (o4 > o3), "" );
+    static_assert ( !(o4 > o4), "" );
+    static_assert (  (o4 > o5), "" );
+
+    static_assert (  (o5 > o1), "" );
+    static_assert (  (o5 > o2), "" );
+    static_assert ( !(o5 > o3), "" );
+    static_assert ( !(o5 > o4), "" );
+    static_assert ( !(o5 > o5), "" );
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.relops/less_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/less_equal.pass.cpp
new file mode 100644 (file)
index 0000000..a7d594d
--- /dev/null
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class T> constexpr bool operator<= (const optional<T>& x, const optional<T>& y);
+
+#include <optional>
+
+using std::optional;
+
+struct X
+{
+    int i_;
+
+    constexpr X(int i) : i_(i) {}
+};
+
+constexpr bool operator <= ( const X &lhs, const X &rhs )
+    { return lhs.i_ <= rhs.i_ ; }
+
+int main()
+{
+    {
+    typedef optional<X> O;
+
+    constexpr O o1;     // disengaged
+    constexpr O o2;     // disengaged
+    constexpr O o3{1};  // engaged
+    constexpr O o4{2};  // engaged
+    constexpr O o5{1};  // engaged
+
+    static_assert (  (o1 <= o1), "" );
+    static_assert (  (o1 <= o2), "" );
+    static_assert (  (o1 <= o3), "" );
+    static_assert (  (o1 <= o4), "" );
+    static_assert (  (o1 <= o5), "" );
+
+    static_assert (  (o2 <= o1), "" );
+    static_assert (  (o2 <= o2), "" );
+    static_assert (  (o2 <= o3), "" );
+    static_assert (  (o2 <= o4), "" );
+    static_assert (  (o2 <= o5), "" );
+
+    static_assert ( !(o3 <= o1), "" );
+    static_assert ( !(o3 <= o2), "" );
+    static_assert (  (o3 <= o3), "" );
+    static_assert (  (o3 <= o4), "" );
+    static_assert (  (o3 <= o5), "" );
+
+    static_assert ( !(o4 <= o1), "" );
+    static_assert ( !(o4 <= o2), "" );
+    static_assert ( !(o4 <= o3), "" );
+    static_assert (  (o4 <= o4), "" );
+    static_assert ( !(o4 <= o5), "" );
+
+    static_assert ( !(o5 <= o1), "" );
+    static_assert ( !(o5 <= o2), "" );
+    static_assert (  (o5 <= o3), "" );
+    static_assert (  (o5 <= o4), "" );
+    static_assert (  (o5 <= o5), "" );
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.relops/less_than.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/less_than.pass.cpp
new file mode 100644 (file)
index 0000000..deffa5e
--- /dev/null
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class T> constexpr bool operator< (const optional<T>& x, const optional<T>& y);
+
+#include <optional>
+
+using std::optional;
+
+struct X
+{
+    int i_;
+
+    constexpr X(int i) : i_(i) {}
+};
+
+constexpr bool operator < ( const X &lhs, const X &rhs )
+    { return lhs.i_ < rhs.i_ ; }
+
+int main()
+{
+    {
+    typedef optional<X> O;
+
+    constexpr O o1;     // disengaged
+    constexpr O o2;     // disengaged
+    constexpr O o3{1};  // engaged
+    constexpr O o4{2};  // engaged
+    constexpr O o5{1};  // engaged
+
+    static_assert ( !(o1 < o1), "" );
+    static_assert ( !(o1 < o2), "" );
+    static_assert (  (o1 < o3), "" );
+    static_assert (  (o1 < o4), "" );
+    static_assert (  (o1 < o5), "" );
+
+    static_assert ( !(o2 < o1), "" );
+    static_assert ( !(o2 < o2), "" );
+    static_assert (  (o2 < o3), "" );
+    static_assert (  (o2 < o4), "" );
+    static_assert (  (o2 < o5), "" );
+
+    static_assert ( !(o3 < o1), "" );
+    static_assert ( !(o3 < o2), "" );
+    static_assert ( !(o3 < o3), "" );
+    static_assert (  (o3 < o4), "" );
+    static_assert ( !(o3 < o5), "" );
+
+    static_assert ( !(o4 < o1), "" );
+    static_assert ( !(o4 < o2), "" );
+    static_assert ( !(o4 < o3), "" );
+    static_assert ( !(o4 < o4), "" );
+    static_assert ( !(o4 < o5), "" );
+
+    static_assert ( !(o5 < o1), "" );
+    static_assert ( !(o5 < o2), "" );
+    static_assert ( !(o5 < o3), "" );
+    static_assert (  (o5 < o4), "" );
+    static_assert ( !(o5 < o5), "" );
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.relops/not_equal.pass.cpp b/libcxx/test/std/utilities/optional/optional.relops/not_equal.pass.cpp
new file mode 100644 (file)
index 0000000..fd11b2a
--- /dev/null
@@ -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>
+
+// template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+using std::optional;
+
+struct X
+{
+    int i_;
+
+    constexpr X(int i) : i_(i) {}
+};
+
+constexpr bool operator != ( const X &lhs, const X &rhs )
+    { return lhs.i_ != rhs.i_ ; }
+
+int main()
+{
+    {
+    typedef X T;
+    typedef optional<T> O;
+
+    constexpr O o1;     // disengaged
+    constexpr O o2;     // disengaged
+    constexpr O o3{1};  // engaged
+    constexpr O o4{2};  // engaged
+    constexpr O o5{1};  // engaged
+
+    static_assert ( !(o1 != o1), "" );
+    static_assert ( !(o1 != o2), "" );
+    static_assert (  (o1 != o3), "" );
+    static_assert (  (o1 != o4), "" );
+    static_assert (  (o1 != o5), "" );
+
+    static_assert ( !(o2 != o1), "" );
+    static_assert ( !(o2 != o2), "" );
+    static_assert (  (o2 != o3), "" );
+    static_assert (  (o2 != o4), "" );
+    static_assert (  (o2 != o5), "" );
+
+    static_assert (  (o3 != o1), "" );
+    static_assert (  (o3 != o2), "" );
+    static_assert ( !(o3 != o3), "" );
+    static_assert (  (o3 != o4), "" );
+    static_assert ( !(o3 != o5), "" );
+
+    static_assert (  (o4 != o1), "" );
+    static_assert (  (o4 != o2), "" );
+    static_assert (  (o4 != o3), "" );
+    static_assert ( !(o4 != o4), "" );
+    static_assert (  (o4 != o5), "" );
+
+    static_assert (  (o5 != o1), "" );
+    static_assert (  (o5 != o2), "" );
+    static_assert ( !(o5 != o3), "" );
+    static_assert (  (o5 != o4), "" );
+    static_assert ( !(o5 != o5), "" );
+
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.specalg/make_optional.pass.cpp b/libcxx/test/std/utilities/optional/optional.specalg/make_optional.pass.cpp
new file mode 100644 (file)
index 0000000..3fbf19f
--- /dev/null
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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>
+//   constexpr optional<decay_t<T>> make_optional(T&& v);
+
+#include <optional>
+#include <string>
+#include <memory>
+#include <cassert>
+
+#include "test_macros.h"
+
+int main()
+{
+    using std::optional;
+    using std::make_optional;
+    {
+        int arr[10]; ((void)arr);
+        ASSERT_SAME_TYPE(decltype(make_optional(arr)), optional<int*>);
+    }
+    {
+        constexpr auto opt = make_optional(2);
+        ASSERT_SAME_TYPE(decltype(opt), const optional<int>);
+        static_assert(opt.value() == 2);
+    }
+    {
+        optional<int> opt = make_optional(2);
+        assert(*opt == 2);
+    }
+    {
+        std::string s("123");
+        optional<std::string> opt = make_optional(s);
+        assert(*opt == s);
+    }
+    {
+        std::unique_ptr<int> s(new int(3));
+        optional<std::unique_ptr<int>> opt = make_optional(std::move(s));
+        assert(**opt == 3);
+        assert(s == nullptr);
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit.pass.cpp b/libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit.pass.cpp
new file mode 100644 (file)
index 0000000..bdfeefb
--- /dev/null
@@ -0,0 +1,45 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class T, class... Args>
+//   constexpr optional<T> make_optional(Args&&... args);
+
+#include <optional>
+#include <string>
+#include <memory>
+#include <cassert>
+
+int main()
+{
+    using std::optional;
+    using std::make_optional;
+
+    {
+        constexpr auto opt = make_optional<int>('a');
+        static_assert(*opt == int('a'), "");
+    }
+    {
+        std::string s("123");
+        auto opt = make_optional<std::string>(s);
+        assert(*opt == s);
+    }
+    {
+        std::unique_ptr<int> s(new int(3));
+        auto opt = make_optional<std::unique_ptr<int>>(std::move(s));
+        assert(**opt == 3);
+        assert(s == nullptr);
+    }
+    {
+        auto opt = make_optional<std::string>(4, 'X');
+        assert(*opt == "XXXX");
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit_initializer_list.pass.cpp b/libcxx/test/std/utilities/optional/optional.specalg/make_optional_explicit_initializer_list.pass.cpp
new file mode 100644 (file)
index 0000000..f17f582
--- /dev/null
@@ -0,0 +1,53 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// template <class T, class U, class... Args>
+//   constexpr optional<T> make_optional(initializer_list<U> il, Args&&... args);
+
+#include <optional>
+#include <string>
+#include <memory>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct TestT {
+  int x;
+  int size;
+  constexpr TestT(std::initializer_list<int> il) : x(*il.begin()), size(il.size()) {}
+  constexpr TestT(std::initializer_list<int> il, const int*)
+      : x(*il.begin()), size(il.size()) {}
+};
+
+int main()
+{
+    using std::make_optional;
+    {
+        constexpr auto opt = make_optional<TestT>({42, 2, 3});
+        ASSERT_SAME_TYPE(decltype(opt), const std::optional<TestT>);
+        static_assert(opt->x == 42, "");
+        static_assert(opt->size == 3, "");
+    }
+    {
+        constexpr auto opt = make_optional<TestT>({42, 2, 3}, nullptr);
+        static_assert(opt->x == 42, "");
+        static_assert(opt->size == 3, "");
+    }
+    {
+        auto opt = make_optional<std::string>({'1', '2', '3'});
+        assert(*opt == "123");
+    }
+    {
+        auto opt = make_optional<std::string>({'a', 'b', 'c'}, std::allocator<char>{});
+        assert(*opt == "abc");
+    }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.specalg/swap.pass.cpp b/libcxx/test/std/utilities/optional/optional.specalg/swap.pass.cpp
new file mode 100644 (file)
index 0000000..f364d7d
--- /dev/null
@@ -0,0 +1,303 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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> void swap(optional<T>& x, optional<T>& y)
+//     noexcept(noexcept(x.swap(y)));
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+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& x, Z& y) { TEST_THROW(6);}
+};
+
+int main()
+{
+    {
+        optional<int> opt1;
+        optional<int> opt2;
+        static_assert(noexcept(swap(opt1, opt2)) == true, "");
+        assert(static_cast<bool>(opt1) == false);
+        assert(static_cast<bool>(opt2) == false);
+        swap(opt1, opt2);
+        assert(static_cast<bool>(opt1) == false);
+        assert(static_cast<bool>(opt2) == false);
+    }
+    {
+        optional<int> opt1(1);
+        optional<int> opt2;
+        static_assert(noexcept(swap(opt1, opt2)) == true, "");
+        assert(static_cast<bool>(opt1) == true);
+        assert(*opt1 == 1);
+        assert(static_cast<bool>(opt2) == false);
+        swap(opt1, 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(swap(opt1, opt2)) == true, "");
+        assert(static_cast<bool>(opt1) == false);
+        assert(static_cast<bool>(opt2) == true);
+        assert(*opt2 == 2);
+        swap(opt1, 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(swap(opt1, opt2)) == true, "");
+        assert(static_cast<bool>(opt1) == true);
+        assert(*opt1 == 1);
+        assert(static_cast<bool>(opt2) == true);
+        assert(*opt2 == 2);
+        swap(opt1, 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(swap(opt1, opt2)) == true, "");
+        assert(static_cast<bool>(opt1) == false);
+        assert(static_cast<bool>(opt2) == false);
+        swap(opt1, 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(swap(opt1, opt2)) == true, "");
+        assert(static_cast<bool>(opt1) == true);
+        assert(*opt1 == 1);
+        assert(static_cast<bool>(opt2) == false);
+        X::dtor_called = 0;
+        swap(opt1, 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(swap(opt1, opt2)) == true, "");
+        assert(static_cast<bool>(opt1) == false);
+        assert(static_cast<bool>(opt2) == true);
+        assert(*opt2 == 2);
+        X::dtor_called = 0;
+        swap(opt1, 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(swap(opt1, opt2)) == true, "");
+        assert(static_cast<bool>(opt1) == true);
+        assert(*opt1 == 1);
+        assert(static_cast<bool>(opt2) == true);
+        assert(*opt2 == 2);
+        X::dtor_called = 0;
+        swap(opt1, 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(swap(opt1, opt2)) == false, "");
+        assert(static_cast<bool>(opt1) == false);
+        assert(static_cast<bool>(opt2) == false);
+        swap(opt1, 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(swap(opt1, opt2)) == false, "");
+        assert(static_cast<bool>(opt1) == true);
+        assert(*opt1 == 1);
+        assert(static_cast<bool>(opt2) == false);
+        Y::dtor_called = 0;
+        swap(opt1, 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(swap(opt1, opt2)) == false, "");
+        assert(static_cast<bool>(opt1) == false);
+        assert(static_cast<bool>(opt2) == true);
+        assert(*opt2 == 2);
+        Y::dtor_called = 0;
+        swap(opt1, 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(swap(opt1, opt2)) == false, "");
+        assert(static_cast<bool>(opt1) == true);
+        assert(*opt1 == 1);
+        assert(static_cast<bool>(opt2) == true);
+        assert(*opt2 == 2);
+        Y::dtor_called = 0;
+        swap(opt1, 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(swap(opt1, opt2)) == false, "");
+        assert(static_cast<bool>(opt1) == false);
+        assert(static_cast<bool>(opt2) == false);
+        swap(opt1, 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(swap(opt1, opt2)) == false, "");
+        assert(static_cast<bool>(opt1) == true);
+        assert(*opt1 == 1);
+        assert(static_cast<bool>(opt2) == false);
+        try
+        {
+            swap(opt1, 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(swap(opt1, opt2)) == false, "");
+        assert(static_cast<bool>(opt1) == false);
+        assert(static_cast<bool>(opt2) == true);
+        assert(*opt2 == 2);
+        try
+        {
+            swap(opt1, 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(swap(opt1, opt2)) == false, "");
+        assert(static_cast<bool>(opt1) == true);
+        assert(*opt1 == 1);
+        assert(static_cast<bool>(opt2) == true);
+        assert(*opt2 == 2);
+        try
+        {
+            swap(opt1, 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 // TEST_HAS_NO_EXCEPTIONS
+}
diff --git a/libcxx/test/std/utilities/optional/optional.syn/optional_in_place_t.fail.cpp b/libcxx/test/std/utilities/optional/optional.syn/optional_in_place_t.fail.cpp
new file mode 100644 (file)
index 0000000..20c90c7
--- /dev/null
@@ -0,0 +1,26 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// A program that necessitates the instantiation of template optional for
+// (possibly cv-qualified) in_place_t is ill-formed.
+
+#include <optional>
+
+int main()
+{
+    using std::optional;
+    using std::in_place_t;
+    using std::in_place;
+
+    optional<in_place_t> opt; // expected-note {{requested here}}
+    // expected-error@optional:* {{"instantiation of optional with in_place_t is ill-formed"}}
+}
diff --git a/libcxx/test/std/utilities/optional/optional.syn/optional_includes_initializer_list.pass.cpp b/libcxx/test/std/utilities/optional/optional.syn/optional_includes_initializer_list.pass.cpp
new file mode 100644 (file)
index 0000000..687625e
--- /dev/null
@@ -0,0 +1,22 @@
+//===----------------------------------------------------------------------===//
+//
+//                     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 <initializer_list>
+
+#include <optional>
+
+int main()
+{
+    using std::optional;
+
+    std::initializer_list<int> list;
+}
diff --git a/libcxx/test/std/utilities/optional/optional.syn/optional_nullopt_t.fail.cpp b/libcxx/test/std/utilities/optional/optional.syn/optional_nullopt_t.fail.cpp
new file mode 100644 (file)
index 0000000..56a30cc
--- /dev/null
@@ -0,0 +1,29 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11, c++14
+// <optional>
+
+// A program that necessitates the instantiation of template optional for
+// (possibly cv-qualified) nullopt_t is ill-formed.
+
+#include <optional>
+
+int main()
+{
+    using std::optional;
+    using std::nullopt_t;
+    using std::nullopt;
+
+    optional<nullopt_t> opt; // expected-note 1 {{requested here}}
+    optional<const nullopt_t> opt1; // expected-note 1 {{requested here}}
+    optional<nullopt_t &> opt2; // expected-note 1 {{requested here}}
+    optional<nullopt_t &&> opt3; // expected-note 1 {{requested here}}
+    // expected-error@optional:* 4 {{instantiation of optional with nullopt_t is ill-formed}}
+}
index 5b29404..c09aa70 100644 (file)
 #ifndef TEST_SUPPORT_ARCHETYPES_HPP
 #define TEST_SUPPORT_ARCHETYPES_HPP
 
+#include <type_traits>
+#include <cassert>
+
 #include "test_macros.h"
 
 #if TEST_STD_VER >= 11
 
+namespace ArchetypeBases {
+
+template <bool, class T>
+struct DepType : T {};
+
+struct NullBase {};
+
+template <class Derived, bool Explicit = false>
+struct TestBase {
+    static int alive;
+    static int constructed;
+    static int value_constructed;
+    static int default_constructed;
+    static int copy_constructed;
+    static int move_constructed;
+    static int assigned;
+    static int value_assigned;
+    static int copy_assigned;
+    static int move_assigned;
+    static int destroyed;
+
+    static void reset() {
+        assert(alive == 0);
+        alive = 0;
+        reset_constructors();
+    }
+
+    static void reset_constructors() {
+      constructed = value_constructed = default_constructed =
+        copy_constructed = move_constructed = 0;
+      assigned = value_assigned = copy_assigned = move_assigned = destroyed = 0;
+    }
+
+    TestBase() noexcept : value(0) {
+        ++alive; ++constructed; ++default_constructed;
+    }
+    template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true>
+    explicit TestBase(int x) noexcept : value(x) {
+        ++alive; ++constructed; ++value_constructed;
+    }
+    template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true>
+    TestBase(int x) noexcept : value(x) {
+        ++alive; ++constructed; ++value_constructed;
+    }
+    template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true>
+    explicit TestBase(int x, int y) noexcept : value(y) {
+        ++alive; ++constructed; ++value_constructed;
+    }
+    template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true>
+    TestBase(int x, int y) noexcept : value(y) {
+        ++alive; ++constructed; ++value_constructed;
+    }
+    template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true>
+    explicit TestBase(std::initializer_list<int>& il, int y = 0) noexcept
+      : value(il.size()) {
+        ++alive; ++constructed; ++value_constructed;
+    }
+    template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true>
+    TestBase(std::initializer_list<int>& il, int y = 0) noexcept : value(il.size()) {
+        ++alive; ++constructed; ++value_constructed;
+    }
+    TestBase& operator=(int xvalue) noexcept {
+      value = xvalue;
+      ++assigned; ++value_assigned;
+      return *this;
+    }
+protected:
+    ~TestBase() {
+      assert(value != -999); assert(alive > 0);
+      --alive; ++destroyed; value = -999;
+    }
+    TestBase(TestBase const& o) noexcept : value(o.value) {
+        assert(o.value != -1); assert(o.value != -999);
+        ++alive; ++constructed; ++copy_constructed;
+    }
+    TestBase(TestBase && o) noexcept : value(o.value) {
+        assert(o.value != -1); assert(o.value != -999);
+        ++alive; ++constructed; ++move_constructed;
+        o.value = -1;
+    }
+    TestBase& operator=(TestBase const& o) noexcept {
+      assert(o.value != -1); assert(o.value != -999);
+      ++assigned; ++copy_assigned;
+      value = o.value;
+      return *this;
+    }
+    TestBase& operator=(TestBase&& o) noexcept {
+        assert(o.value != -1); assert(o.value != -999);
+        ++assigned; ++move_assigned;
+        value = o.value;
+        o.value = -1;
+        return *this;
+    }
+public:
+    int value;
+};
+
+template <class D, bool E> int TestBase<D, E>::alive = 0;
+template <class D, bool E> int TestBase<D, E>::constructed = 0;
+template <class D, bool E> int TestBase<D, E>::value_constructed = 0;
+template <class D, bool E> int TestBase<D, E>::default_constructed = 0;
+template <class D, bool E> int TestBase<D, E>::copy_constructed = 0;
+template <class D, bool E> int TestBase<D, E>::move_constructed = 0;
+template <class D, bool E> int TestBase<D, E>::assigned = 0;
+template <class D, bool E> int TestBase<D, E>::value_assigned = 0;
+template <class D, bool E> int TestBase<D, E>::copy_assigned = 0;
+template <class D, bool E> int TestBase<D, E>::move_assigned = 0;
+template <class D, bool E> int TestBase<D, E>::destroyed = 0;
+
+template <bool Explicit = false>
+struct ValueBase {
+    template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true>
+    explicit constexpr ValueBase(int x) : value(x) {}
+    template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true>
+    constexpr ValueBase(int x) : value(x) {}
+    template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true>
+    explicit constexpr ValueBase(int x, int y) : value(y) {}
+    template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true>
+    constexpr ValueBase(int x, int y) : value(y) {}
+    template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true>
+    explicit constexpr ValueBase(std::initializer_list<int>& il, int y = 0) : value(il.size()) {}
+    template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true>
+    constexpr ValueBase(std::initializer_list<int>& il, int y = 0) : value(il.size()) {}
+    constexpr ValueBase& operator=(int xvalue) noexcept {
+        value = xvalue;
+        return *this;
+    }
+    //~ValueBase() { assert(value != -999); value = -999; }
+    int value;
+protected:
+  constexpr ValueBase() noexcept : value(0) {}
+    constexpr ValueBase(ValueBase const& o) noexcept : value(o.value) {
+        assert(o.value != -1); assert(o.value != -999);
+    }
+    constexpr ValueBase(ValueBase && o) noexcept : value(o.value) {
+        assert(o.value != -1); assert(o.value != -999);
+        o.value = -1;
+    }
+    constexpr ValueBase& operator=(ValueBase const& o) noexcept {
+        assert(o.value != -1); assert(o.value != -999);
+        value = o.value;
+        return *this;
+    }
+    constexpr ValueBase& operator=(ValueBase&& o) noexcept {
+        assert(o.value != -1); assert(o.value != -999);
+        value = o.value;
+        o.value = -1;
+        return *this;
+    }
+};
+
+
+template <bool Explicit = false>
+struct TrivialValueBase {
+    template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true>
+    explicit constexpr TrivialValueBase(int x) : value(x) {}
+    template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true>
+    constexpr TrivialValueBase(int x) : value(x) {}
+    template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true>
+    explicit constexpr TrivialValueBase(int x, int y) : value(y) {}
+    template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true>
+    constexpr TrivialValueBase(int x, int y) : value(y) {}
+    template <bool Dummy = true, typename std::enable_if<Dummy && Explicit, bool>::type = true>
+    explicit constexpr TrivialValueBase(std::initializer_list<int>& il, int y = 0) : value(il.size()) {}
+    template <bool Dummy = true, typename std::enable_if<Dummy && !Explicit, bool>::type = true>
+    constexpr TrivialValueBase(std::initializer_list<int>& il, int y = 0) : value(il.size()) {};
+    int value;
+protected:
+    constexpr TrivialValueBase() noexcept : value(0) {}
+};
+
+}
+
 //============================================================================//
 // Trivial Implicit Test Types
 namespace ImplicitTypes {
@@ -18,9 +194,18 @@ namespace ExplicitTypes {
 #include "archetypes.ipp"
 }
 
+
+//============================================================================//
+//
+namespace NonConstexprTypes {
+#define DEFINE_CONSTEXPR
+#include "archetypes.ipp"
+}
+
 //============================================================================//
-// Non-Trivial Implicit Test Types
+// Non-literal implicit test types
 namespace NonLiteralTypes {
+#define DEFINE_ASSIGN_CONSTEXPR
 #define DEFINE_DTOR(Name) ~Name() {}
 #include "archetypes.ipp"
 }
@@ -29,9 +214,144 @@ namespace NonLiteralTypes {
 // Non-Trivially Copyable Implicit Test Types
 namespace NonTrivialTypes {
 #define DEFINE_CTOR {}
+#define DEFINE_ASSIGN { return *this; }
+#define DEFINE_DEFAULT_CTOR = default
+#include "archetypes.ipp"
+}
+
+//============================================================================//
+// Implicit counting types
+namespace TestTypes {
+#define DEFINE_CONSTEXPR
+#define DEFINE_BASE(Name) ::ArchetypeBases::TestBase<Name>
+#include "archetypes.ipp"
+
+using TestType = AllCtors;
+
+// Add equality operators
+template <class Tp>
+constexpr bool operator==(Tp const& L, Tp const& R) noexcept {
+  return L.value == R.value;
+}
+
+template <class Tp>
+constexpr bool operator!=(Tp const& L, Tp const& R) noexcept {
+  return L.value != R.value;
+}
+
+}
+
+//============================================================================//
+// Implicit counting types
+namespace ExplicitTestTypes {
+#define DEFINE_CONSTEXPR
+#define DEFINE_EXPLICIT explicit
+#define DEFINE_BASE(Name) ::ArchetypeBases::TestBase<Name, true>
+#include "archetypes.ipp"
+
+using TestType = AllCtors;
+
+// Add equality operators
+template <class Tp>
+constexpr bool operator==(Tp const& L, Tp const& R) noexcept {
+  return L.value == R.value;
+}
+
+template <class Tp>
+constexpr bool operator!=(Tp const& L, Tp const& R) noexcept {
+  return L.value != R.value;
+}
+
+}
+
+//============================================================================//
+// Implicit value types
+namespace ConstexprTestTypes {
+#define DEFINE_BASE(Name) ::ArchetypeBases::ValueBase<>
+#include "archetypes.ipp"
+
+using TestType = AllCtors;
+
+// Add equality operators
+template <class Tp>
+constexpr bool operator==(Tp const& L, Tp const& R) noexcept {
+  return L.value == R.value;
+}
+
+template <class Tp>
+constexpr bool operator!=(Tp const& L, Tp const& R) noexcept {
+  return L.value != R.value;
+}
+
+} // end namespace ValueTypes
+
+
+//============================================================================//
+//
+namespace ExplicitConstexprTestTypes {
+#define DEFINE_EXPLICIT explicit
+#define DEFINE_BASE(Name) ::ArchetypeBases::ValueBase<true>
+#include "archetypes.ipp"
+
+using TestType = AllCtors;
+
+// Add equality operators
+template <class Tp>
+constexpr bool operator==(Tp const& L, Tp const& R) noexcept {
+  return L.value == R.value;
+}
+
+template <class Tp>
+constexpr bool operator!=(Tp const& L, Tp const& R) noexcept {
+  return L.value != R.value;
+}
+
+} // end namespace ValueTypes
+
+
+//============================================================================//
+//
+namespace TrivialTestTypes {
+#define DEFINE_BASE(Name) ::ArchetypeBases::TrivialValueBase<false>
+#include "archetypes.ipp"
+
+using TestType = AllCtors;
+
+// Add equality operators
+template <class Tp>
+constexpr bool operator==(Tp const& L, Tp const& R) noexcept {
+  return L.value == R.value;
+}
+
+template <class Tp>
+constexpr bool operator!=(Tp const& L, Tp const& R) noexcept {
+  return L.value != R.value;
+}
+
+} // end namespace TrivialValueTypes
+
+//============================================================================//
+//
+namespace ExplicitTrivialTestTypes {
+#define DEFINE_EXPLICIT explicit
+#define DEFINE_BASE(Name) ::ArchetypeBases::TrivialValueBase<true>
 #include "archetypes.ipp"
+
+using TestType = AllCtors;
+
+// Add equality operators
+template <class Tp>
+constexpr bool operator==(Tp const& L, Tp const& R) noexcept {
+  return L.value == R.value;
 }
 
+template <class Tp>
+constexpr bool operator!=(Tp const& L, Tp const& R) noexcept {
+  return L.value != R.value;
+}
+
+} // end namespace ExplicitTrivialTestTypes
+
 #endif // TEST_STD_VER >= 11
 
 #endif // TEST_SUPPORT_ARCHETYPES_HPP
index 094440a..bf66044 100644 (file)
@@ -1,10 +1,22 @@
 
+#ifndef DEFINE_BASE
+#define DEFINE_BASE(Name) ::ArchetypeBases::NullBase
+#endif
 #ifndef DEFINE_EXPLICIT
 #define DEFINE_EXPLICIT
 #endif
+#ifndef DEFINE_CONSTEXPR
+#define DEFINE_CONSTEXPR constexpr
+#endif
+#ifndef DEFINE_ASSIGN_CONSTEXPR
+#define DEFINE_ASSIGN_CONSTEXPR DEFINE_CONSTEXPR
+#endif
 #ifndef DEFINE_CTOR
 #define DEFINE_CTOR = default
 #endif
+#ifndef DEFINE_DEFAULT_CTOR
+#define DEFINE_DEFAULT_CTOR DEFINE_CTOR
+#endif
 #ifndef DEFINE_ASSIGN
 #define DEFINE_ASSIGN = default
 #endif
 #define DEFINE_DTOR(Name)
 #endif
 
-struct NoDefault {
-  DEFINE_EXPLICIT NoDefault() = delete;
+struct AllCtors : DEFINE_BASE(AllCtors) {
+  using Base = DEFINE_BASE(AllCtors);
+  using Base::Base;
+  using Base::operator=;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR AllCtors() DEFINE_DEFAULT_CTOR;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR AllCtors(AllCtors const&) DEFINE_CTOR;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR AllCtors(AllCtors &&) DEFINE_CTOR;
+  DEFINE_ASSIGN_CONSTEXPR AllCtors& operator=(AllCtors const&) DEFINE_ASSIGN;
+  DEFINE_ASSIGN_CONSTEXPR AllCtors& operator=(AllCtors &&) DEFINE_ASSIGN;
+  DEFINE_DTOR(AllCtors)
+};
+
+struct NoCtors : DEFINE_BASE(NoCtors) {
+  using Base = DEFINE_BASE(NoCtors);
+  using Base::Base;
+  DEFINE_EXPLICIT NoCtors() = delete;
+  DEFINE_EXPLICIT NoCtors(NoCtors const&) = delete;
+  NoCtors& operator=(NoCtors const&) = delete;
+  DEFINE_DTOR(NoCtors)
+};
+
+struct NoDefault : DEFINE_BASE(NoDefault) {
+  using Base = DEFINE_BASE(NoDefault);
+  using Base::Base;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR NoDefault() = delete;
   DEFINE_DTOR(NoDefault)
 };
 
-struct AllCtors {
-  DEFINE_EXPLICIT AllCtors() DEFINE_CTOR;
-  DEFINE_EXPLICIT AllCtors(AllCtors const&) DEFINE_CTOR;
-  DEFINE_EXPLICIT AllCtors(AllCtors &&) DEFINE_CTOR;
-  AllCtors& operator=(AllCtors const&) DEFINE_ASSIGN;
-  AllCtors& operator=(AllCtors &&) DEFINE_ASSIGN;
-  DEFINE_DTOR(AllCtors)
+struct DefaultOnly : DEFINE_BASE(DefaultOnly) {
+  using Base = DEFINE_BASE(DefaultOnly);
+  using Base::Base;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR DefaultOnly() DEFINE_DEFAULT_CTOR;
+  DefaultOnly(DefaultOnly const&) = delete;
+  DefaultOnly& operator=(DefaultOnly const&) = delete;
+  DEFINE_DTOR(DefaultOnly)
 };
 
-struct Copyable {
-  DEFINE_EXPLICIT Copyable() DEFINE_CTOR;
-  DEFINE_EXPLICIT Copyable(Copyable const &) DEFINE_CTOR;
+struct Copyable : DEFINE_BASE(Copyable) {
+  using Base = DEFINE_BASE(Copyable);
+  using Base::Base;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR Copyable() DEFINE_DEFAULT_CTOR;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR Copyable(Copyable const &) DEFINE_CTOR;
   Copyable &operator=(Copyable const &) DEFINE_ASSIGN;
   DEFINE_DTOR(Copyable)
 };
 
-struct CopyOnly {
-  DEFINE_EXPLICIT CopyOnly() DEFINE_CTOR;
-  DEFINE_EXPLICIT CopyOnly(CopyOnly const &) DEFINE_CTOR;
-  DEFINE_EXPLICIT CopyOnly(CopyOnly &&) = delete;
+struct CopyOnly : DEFINE_BASE(CopyOnly) {
+  using Base = DEFINE_BASE(CopyOnly);
+  using Base::Base;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR CopyOnly() DEFINE_DEFAULT_CTOR;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR CopyOnly(CopyOnly const &) DEFINE_CTOR;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR CopyOnly(CopyOnly &&) = delete;
   CopyOnly &operator=(CopyOnly const &) DEFINE_ASSIGN;
   CopyOnly &operator=(CopyOnly &&) = delete;
   DEFINE_DTOR(CopyOnly)
 };
 
-struct NonCopyable {
-  DEFINE_EXPLICIT NonCopyable() DEFINE_CTOR;
-  DEFINE_EXPLICIT NonCopyable(NonCopyable const &) = delete;
+struct NonCopyable : DEFINE_BASE(NonCopyable) {
+  using Base = DEFINE_BASE(NonCopyable);
+  using Base::Base;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR NonCopyable() DEFINE_DEFAULT_CTOR;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR NonCopyable(NonCopyable const &) = delete;
   NonCopyable &operator=(NonCopyable const &) = delete;
   DEFINE_DTOR(NonCopyable)
 };
 
-struct MoveOnly {
-  DEFINE_EXPLICIT MoveOnly() DEFINE_CTOR;
-  DEFINE_EXPLICIT MoveOnly(MoveOnly &&) DEFINE_CTOR;
+struct MoveOnly : DEFINE_BASE(MoveOnly) {
+  using Base = DEFINE_BASE(MoveOnly);
+  using Base::Base;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR MoveOnly() DEFINE_DEFAULT_CTOR;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR MoveOnly(MoveOnly &&) DEFINE_CTOR;
   MoveOnly &operator=(MoveOnly &&) DEFINE_ASSIGN;
   DEFINE_DTOR(MoveOnly)
 };
 
-struct CopyAssignable {
-    DEFINE_EXPLICIT CopyAssignable() = delete;
-    CopyAssignable& operator=(CopyAssignable const&) DEFINE_ASSIGN;
-    DEFINE_DTOR(CopyAssignable)
+struct CopyAssignable : DEFINE_BASE(CopyAssignable) {
+  using Base = DEFINE_BASE(CopyAssignable);
+  using Base::Base;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR CopyAssignable() = delete;
+  CopyAssignable& operator=(CopyAssignable const&) DEFINE_ASSIGN;
+  DEFINE_DTOR(CopyAssignable)
 };
 
-struct CopyAssignOnly {
-    DEFINE_EXPLICIT CopyAssignOnly() = delete;
-    CopyAssignOnly& operator=(CopyAssignOnly const&) DEFINE_ASSIGN;
-    CopyAssignOnly& operator=(CopyAssignOnly &&) = delete;
-    DEFINE_DTOR(CopyAssignOnly)
+struct CopyAssignOnly : DEFINE_BASE(CopyAssignOnly) {
+  using Base = DEFINE_BASE(CopyAssignOnly);
+  using Base::Base;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR CopyAssignOnly() = delete;
+  CopyAssignOnly& operator=(CopyAssignOnly const&) DEFINE_ASSIGN;
+  CopyAssignOnly& operator=(CopyAssignOnly &&) = delete;
+  DEFINE_DTOR(CopyAssignOnly)
 };
 
-struct MoveAssignOnly {
-    DEFINE_EXPLICIT MoveAssignOnly() = delete;
-    MoveAssignOnly& operator=(MoveAssignOnly const&) = delete;
-    MoveAssignOnly& operator=(MoveAssignOnly &&) DEFINE_ASSIGN;
-    DEFINE_DTOR(MoveAssignOnly)
+struct MoveAssignOnly : DEFINE_BASE(MoveAssignOnly) {
+  using Base = DEFINE_BASE(MoveAssignOnly);
+  using Base::Base;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR MoveAssignOnly() = delete;
+  MoveAssignOnly& operator=(MoveAssignOnly const&) = delete;
+  MoveAssignOnly& operator=(MoveAssignOnly &&) DEFINE_ASSIGN;
+  DEFINE_DTOR(MoveAssignOnly)
 };
 
-struct ConvertingType {
-  DEFINE_EXPLICIT ConvertingType() DEFINE_CTOR;
-  DEFINE_EXPLICIT ConvertingType(ConvertingType const&) DEFINE_CTOR;
-  DEFINE_EXPLICIT ConvertingType(ConvertingType &&) DEFINE_CTOR;
+struct ConvertingType : DEFINE_BASE(ConvertingType) {
+  using Base = DEFINE_BASE(ConvertingType);
+  using Base::Base;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR ConvertingType() DEFINE_DEFAULT_CTOR;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR ConvertingType(ConvertingType const&) DEFINE_CTOR;
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR ConvertingType(ConvertingType &&) DEFINE_CTOR;
   ConvertingType& operator=(ConvertingType const&) DEFINE_ASSIGN;
   ConvertingType& operator=(ConvertingType &&) DEFINE_ASSIGN;
   template <class ...Args>
-  DEFINE_EXPLICIT ConvertingType(Args&&...) {}
+  DEFINE_EXPLICIT DEFINE_CONSTEXPR ConvertingType(Args&&...) {}
   template <class Arg>
   ConvertingType& operator=(Arg&&) { return *this; }
   DEFINE_DTOR(ConvertingType)
@@ -91,8 +142,10 @@ struct ConvertingType {
 
 template <template <class...> class List>
 using ApplyTypes = List<
-    NoDefault,
     AllCtors,
+    NoCtors,
+    NoDefault,
+    DefaultOnly,
     Copyable,
     CopyOnly,
     NonCopyable,
@@ -103,7 +156,11 @@ using ApplyTypes = List<
     ConvertingType
   >;
 
+#undef DEFINE_BASE
 #undef DEFINE_EXPLICIT
+#undef DEFINE_CONSTEXPR
+#undef DEFINE_ASSIGN_CONSTEXPR
 #undef DEFINE_CTOR
+#undef DEFINE_DEFAULT_CTOR
 #undef DEFINE_ASSIGN
-#undef DEFINE_DTOR
+#undef DEFINE_DTOR
\ No newline at end of file