diff mbox

Implementation of n3793 <experimental/optional>

Message ID CAH6eHdQ9bwMD0Awh9bivCTb83na8i1od6pyqRMULmY48a2-x-A@mail.gmail.com
State New
Headers show

Commit Message

Jonathan Wakely Nov. 1, 2013, 8:09 p.m. UTC
Here's the final version of Luc's optional implementation that I'm
committing, tested on x86_64-linux.

(It occurs to me that we might want to move the contents of
include/tr2 to include/experimental and namespace experimental, since
there isn't going to be a "TR2" now.)
commit f4eb1898b7ca32e18b4c00aeb30ae655e2c1b989
Author: Jonathan Wakely <jwakely.gcc@gmail.com>
Date:   Thu Oct 31 19:55:40 2013 +0000

    2013-10-31  Michael Brune  <lucdanton@free.fr>
    
    	* include/bits/enable_special_members.h: New.
    	* include/experimental/optional: New.
    	* include/Makefile.am: Handle include/experimental.
    	* include/Makefile.in: Regenerate.
    	* testsuite/libstdc++-dg/conformance.exp: Run tests from
    	testsuite/experimental sub-directory.
    	* testsuite/experimental/optional/assignment/1.cc: New.
    	* testsuite/experimental/optional/assignment/2.cc: New.
    	* testsuite/experimental/optional/assignment/3.cc: New.
    	* testsuite/experimental/optional/assignment/4.cc: New.
    	* testsuite/experimental/optional/assignment/5.cc: New.
    	* testsuite/experimental/optional/assignment/6.cc: New.
    	* testsuite/experimental/optional/cons/copy.cc: New.
    	* testsuite/experimental/optional/cons/default.cc: New.
    	* testsuite/experimental/optional/cons/move.cc: New.
    	* testsuite/experimental/optional/cons/value.cc: New.
    	* testsuite/experimental/optional/constexpr/cons/default.cc: New.
    	* testsuite/experimental/optional/constexpr/cons/value.cc: New.
    	* testsuite/experimental/optional/constexpr/in_place.cc: New.
    	* testsuite/experimental/optional/constexpr/make_optional.cc: New.
    	* testsuite/experimental/optional/constexpr/nullopt.cc: New.
    	* testsuite/experimental/optional/constexpr/observers/1.cc: New.
    	* testsuite/experimental/optional/constexpr/observers/2.cc: New.
    	* testsuite/experimental/optional/constexpr/observers/3.cc: New.
    	* testsuite/experimental/optional/constexpr/observers/4.cc: New.
    	* testsuite/experimental/optional/constexpr/observers/5.cc: New.
    	* testsuite/experimental/optional/constexpr/relops/1.cc: New.
    	* testsuite/experimental/optional/constexpr/relops/2.cc: New.
    	* testsuite/experimental/optional/constexpr/relops/3.cc: New.
    	* testsuite/experimental/optional/constexpr/relops/4.cc: New.
    	* testsuite/experimental/optional/constexpr/relops/5.cc: New.
    	* testsuite/experimental/optional/constexpr/relops/6.cc: New.
    	* testsuite/experimental/optional/in_place.cc: New.
    	* testsuite/experimental/optional/make_optional.cc: New.
    	* testsuite/experimental/optional/nullopt.cc: New.
    	* testsuite/experimental/optional/observers/1.cc: New.
    	* testsuite/experimental/optional/observers/2.cc: New.
    	* testsuite/experimental/optional/observers/3.cc: New.
    	* testsuite/experimental/optional/observers/4.cc: New.
    	* testsuite/experimental/optional/observers/5.cc: New.
    	* testsuite/experimental/optional/relops/1.cc: New.
    	* testsuite/experimental/optional/relops/2.cc: New.
    	* testsuite/experimental/optional/relops/3.cc: New.
    	* testsuite/experimental/optional/relops/4.cc: New.
    	* testsuite/experimental/optional/relops/5.cc: New.
    	* testsuite/experimental/optional/relops/6.cc: New.
    	* testsuite/experimental/optional/requirements.cc: New.
    	* testsuite/experimental/optional/swap/1.cc: New.

Comments

Jonathan Wakely Nov. 1, 2013, 8:11 p.m. UTC | #1
Doh, that had yesterday's date on the ChangeLog entry, I've just fixed
it with the next commit.

On 1 November 2013 20:09, Jonathan Wakely <jwakely.gcc@gmail.com> wrote:
> Here's the final version of Luc's optional implementation that I'm
> committing, tested on x86_64-linux.
>
> (It occurs to me that we might want to move the contents of
> include/tr2 to include/experimental and namespace experimental, since
> there isn't going to be a "TR2" now.)
Paolo Carlini Nov. 1, 2013, 8:46 p.m. UTC | #2
Hi,

> Il giorno 01/nov/2013, alle ore 21:09, Jonathan Wakely <jwakely.gcc@gmail.com> ha scritto:
> 
> Here's the final version of Luc's optional implementation that I'm
> committing, tested on x86_64-linux.

Great. Just noticed a minor nit: the fallback __constexpr_addressof appears not to be inline.

Paolo
Luc Danton Nov. 2, 2013, 5:54 p.m. UTC | #3
On 2013-11-01 21:46, Paolo Carlini wrote:
> Hi,
>
>> Il giorno 01/nov/2013, alle ore 21:09, Jonathan Wakely <jwakely.gcc@gmail.com> ha scritto:
>>
>> Here's the final version of Luc's optional implementation that I'm
>> committing, tested on x86_64-linux.
> Great. Just noticed a minor nit: the fallback __constexpr_addressof appears not to be inline.
>
> Paolo

Can you expand? I think it's just as much inline as the other overload 
-- does it need to be different?
Paolo Carlini Nov. 2, 2013, 6:02 p.m. UTC | #4
>Can you expand? I think it's just as much inline as the other overload
>-- does it need to be different?

The other overload is constexpr thus it's implicitly inline. The fall back is very simple too and I think it should be declared inline, unless you analyzed the assembly and believe it normally boils down to more than, say, 5 instructions.

Paolo
Luc Danton Nov. 2, 2013, 10:18 p.m. UTC | #5
On 2013-11-02 19:02, Paolo Carlini wrote:
>
>> Can you expand? I think it's just as much inline as the other overload
>> -- does it need to be different?
> The other overload is constexpr thus it's implicitly inline. The fall back is very simple too and I think it should be declared inline, unless you analyzed the assembly and believe it normally boils down to more than, say, 5 instructions.
>
> Paolo
>

I see. It didn't occur to me to declare it inline, as I only ever use 
the keyword to satisfy
ODR requirements. E.g. the non-member swap isn't declared inline either.

For future reference, is there a rule of thumb in use?
Paolo Carlini Nov. 2, 2013, 10:31 p.m. UTC | #6
Hi

>I see. It didn't occur to me to declare it inline, as I only ever use
>the keyword to satisfy
>ODR requirements. E.g. the non-member swap isn't declared inline
>either.
>
>For future reference, is there a rule of thumb in use?

In general we are very careful with code bloat, but free functions which just forward to other functions should be definiyely inline, otherwise typically at widely used optimization levels like -O2 users get suboptimal performance for no reason. But please feel free to experiment and report your findings on the mailing list!

Paolo
Andreas Schwab Nov. 3, 2013, 9:49 a.m. UTC | #7
Jonathan Wakely <jwakely.gcc@gmail.com> writes:

> +  {
> +    std::experimental::optional<long> o { std::experimental::in_place, 0x1234ABCDF1E2D3C4 };
> +    auto copy = o;
> +    VERIFY( copy );
> +    VERIFY( *copy == 0x1234ABCDF1E2D3C4 );
> +    VERIFY( o && o == 0x1234ABCDF1E2D3C4 );
> +  }

experimental/optional/cons/copy.cc:70:20: error: no match for 'operator==' (operand types are 'std::experimental::optional<long int>' and 'long long int')
     VERIFY( o && o == 0x1234ABCDF1E2D3C4 );
                    ^

Andreas.
Jonathan Wakely Nov. 3, 2013, 11:19 a.m. UTC | #8
On 3 November 2013 09:49, Andreas Schwab wrote:
> Jonathan Wakely <jwakely.gcc@gmail.com> writes:
>
>> +  {
>> +    std::experimental::optional<long> o { std::experimental::in_place, 0x1234ABCDF1E2D3C4 };
>> +    auto copy = o;
>> +    VERIFY( copy );
>> +    VERIFY( *copy == 0x1234ABCDF1E2D3C4 );
>> +    VERIFY( o && o == 0x1234ABCDF1E2D3C4 );
>> +  }
>
> experimental/optional/cons/copy.cc:70:20: error: no match for 'operator==' (operand types are 'std::experimental::optional<long int>' and 'long long int')
>      VERIFY( o && o == 0x1234ABCDF1E2D3C4 );
>                     ^

Yes, Paolo pointed out these are failing on 32-bit targets, I've got a
patch coming.  Luc is there any reason not to just replace all those
large constants with 0x1234ABCD, which fits in a long on 32-bit
targets?
Luc Danton Nov. 4, 2013, 2:36 a.m. UTC | #9
On 2013-11-03 12:19, Jonathan Wakely wrote:
> On 3 November 2013 09:49, Andreas Schwab wrote:
>> Jonathan Wakely <jwakely.gcc@gmail.com> writes:
>>
>>> +  {
>>> +    std::experimental::optional<long> o { std::experimental::in_place, 0x1234ABCDF1E2D3C4 };
>>> +    auto copy = o;
>>> +    VERIFY( copy );
>>> +    VERIFY( *copy == 0x1234ABCDF1E2D3C4 );
>>> +    VERIFY( o && o == 0x1234ABCDF1E2D3C4 );
>>> +  }
>> experimental/optional/cons/copy.cc:70:20: error: no match for 'operator==' (operand types are 'std::experimental::optional<long int>' and 'long long int')
>>       VERIFY( o && o == 0x1234ABCDF1E2D3C4 );
>>                      ^
> Yes, Paolo pointed out these are failing on 32-bit targets, I've got a
> patch coming.  Luc is there any reason not to just replace all those
> large constants with 0x1234ABCD, which fits in a long on 32-bit
> targets?

The value is arbitrary, it's fine to proceed.
diff mbox

Patch

diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 0ddc8b5..505679a 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -94,6 +94,7 @@  bits_headers = \
 	${bits_srcdir}/concept_check.h \
 	${bits_srcdir}/cpp_type_traits.h \
 	${bits_srcdir}/deque.tcc \
+	${bits_srcdir}/enable_special_members.h \
 	${bits_srcdir}/forward_list.h \
 	${bits_srcdir}/forward_list.tcc \
 	${bits_srcdir}/fstream.tcc \
@@ -633,6 +634,12 @@  decimal_headers = \
 	${decimal_srcdir}/decimal \
 	${decimal_srcdir}/decimal.h
 
+# Post-C++11 TS's
+experimental_srcdir = ${glibcxx_srcdir}/include/experimental
+experimental_builddir = ./experimental
+experimental_headers = \
+	${experimental_srcdir}/optional
+
 # This is the common subset of C++ files that all three "C" header models use.
 c_base_srcdir = $(C_INCLUDE_DIR)
 c_base_builddir = .
@@ -910,8 +917,8 @@  endif
 allstamped = \
 	stamp-std stamp-bits stamp-bits-sup stamp-c_base stamp-c_compatibility \
 	stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-tr2 stamp-decimal \
-	stamp-debug stamp-parallel stamp-profile stamp-profile-impl \
-	stamp-host
+	stamp-experimental stamp-debug stamp-parallel stamp-profile \
+	stamp-profile-impl stamp-host
 
 # List of all files that are created by explicit building, editing, or
 # catenation.
@@ -1034,6 +1041,11 @@  stamp-decimal: ${decimal_headers}
 	@-cd ${decimal_builddir} && $(LN_S) $? . 2>/dev/null
 	@$(STAMP) stamp-decimal
 
+stamp-experimental: ${experimental_headers}
+	@-mkdir -p ${experimental_builddir}
+	@-cd ${experimental_builddir} && $(LN_S) $? . 2>/dev/null
+	@$(STAMP) stamp-experimental
+
 stamp-debug: ${debug_headers}
 	@-mkdir -p ${debug_builddir}
 	@-cd ${debug_builddir} && $(LN_S) $? . 2>/dev/null
@@ -1277,6 +1289,9 @@  install-headers:
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${decimal_builddir}
 	for file in ${decimal_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${decimal_builddir}; done
+	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${experimental_builddir}
+	for file in ${experimental_headers}; do \
+	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${experimental_builddir}; done
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${c_base_builddir}
 	for file in ${c_base_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${c_base_builddir}; done
@@ -1322,9 +1337,10 @@  clean-local:
 # directory. (This is more of an example of how this kind of rule can
 # be made.)
 .PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers) $(tr2_headers)
-	   $(decimal_headers) $(ext_headers)
+	   $(decimal_headers) $(ext_headers) $(experimental_headers)
 $(std_headers): ; @:
 $(c_base_headers): ; @:
 $(tr1_headers): ; @:
 $(decimal_headers): ; @:
 $(ext_headers): ; @:
+$(experimental_headers): ; @:
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index a1fd1d3..1f5daba 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -361,6 +361,7 @@  bits_headers = \
 	${bits_srcdir}/concept_check.h \
 	${bits_srcdir}/cpp_type_traits.h \
 	${bits_srcdir}/deque.tcc \
+	${bits_srcdir}/enable_special_members.h \
 	${bits_srcdir}/forward_list.h \
 	${bits_srcdir}/forward_list.tcc \
 	${bits_srcdir}/fstream.tcc \
@@ -899,6 +900,13 @@  decimal_headers = \
 	${decimal_srcdir}/decimal.h
 
 
+# Post-C++11 TS's
+experimental_srcdir = ${glibcxx_srcdir}/include/experimental
+experimental_builddir = ./experimental
+experimental_headers = \
+	${experimental_srcdir}/optional
+
+
 # This is the common subset of C++ files that all three "C" header models use.
 c_base_srcdir = $(C_INCLUDE_DIR)
 c_base_builddir = .
@@ -1166,8 +1174,8 @@  PCHFLAGS = -x c++-header -nostdinc++ $(CXXFLAGS) $(VTV_PCH_CXXFLAGS)
 allstamped = \
 	stamp-std stamp-bits stamp-bits-sup stamp-c_base stamp-c_compatibility \
 	stamp-backward stamp-ext stamp-pb stamp-tr1 stamp-tr2 stamp-decimal \
-	stamp-debug stamp-parallel stamp-profile stamp-profile-impl \
-	stamp-host
+	stamp-experimental stamp-debug stamp-parallel stamp-profile \
+	stamp-profile-impl stamp-host
 
 
 # List of all files that are created by explicit building, editing, or
@@ -1452,6 +1460,11 @@  stamp-decimal: ${decimal_headers}
 	@-cd ${decimal_builddir} && $(LN_S) $? . 2>/dev/null
 	@$(STAMP) stamp-decimal
 
+stamp-experimental: ${experimental_headers}
+	@-mkdir -p ${experimental_builddir}
+	@-cd ${experimental_builddir} && $(LN_S) $? . 2>/dev/null
+	@$(STAMP) stamp-experimental
+
 stamp-debug: ${debug_headers}
 	@-mkdir -p ${debug_builddir}
 	@-cd ${debug_builddir} && $(LN_S) $? . 2>/dev/null
@@ -1680,6 +1693,9 @@  install-headers:
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${decimal_builddir}
 	for file in ${decimal_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${decimal_builddir}; done
+	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${experimental_builddir}
+	for file in ${experimental_headers}; do \
+	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${experimental_builddir}; done
 	$(mkinstalldirs) $(DESTDIR)${gxx_include_dir}/${c_base_builddir}
 	for file in ${c_base_headers}; do \
 	  $(INSTALL_DATA) $${file} $(DESTDIR)${gxx_include_dir}/${c_base_builddir}; done
@@ -1722,12 +1738,13 @@  clean-local:
 # directory. (This is more of an example of how this kind of rule can
 # be made.)
 .PRECIOUS: $(std_headers) $(c_base_headers) $(tr1_headers) $(tr2_headers)
-	   $(decimal_headers) $(ext_headers)
+	   $(decimal_headers) $(ext_headers) $(experimental_headers)
 $(std_headers): ; @:
 $(c_base_headers): ; @:
 $(tr1_headers): ; @:
 $(decimal_headers): ; @:
 $(ext_headers): ; @:
+$(experimental_headers): ; @:
 
 # Tell versions [3.59,3.63) of GNU make to not export all variables.
 # Otherwise a system limit (for SysV at least) may be exceeded.
diff --git a/libstdc++-v3/include/bits/enable_special_members.h b/libstdc++-v3/include/bits/enable_special_members.h
new file mode 100644
index 0000000..eb90037
--- /dev/null
+++ b/libstdc++-v3/include/bits/enable_special_members.h
@@ -0,0 +1,278 @@ 
+// <bits/enable_special_members.h> -*- C++ -*-
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/enable_special_members.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly.
+ */
+
+#ifndef _ENABLE_SPECIAL_MEMBERS_H
+#define _ENABLE_SPECIAL_MEMBERS_H 1
+
+#pragma GCC system_header
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+/**
+  * @brief A mixin helper to conditionally enable or disable the default
+  * constructor.
+  * @sa _Enable_special_members
+  */
+template<bool _Switch, typename _Tag = void>
+  struct _Enable_default_constructor { };
+
+
+/**
+  * @brief A mixin helper to conditionally enable or disable the default
+  * destructor.
+  * @sa _Enable_special_members
+  */
+template<bool _Switch, typename _Tag = void>
+  struct _Enable_destructor { };
+
+/**
+  * @brief A mixin helper to conditionally enable or disable the copy/move
+  * special members.
+  * @sa _Enable_special_members
+  */
+template<bool _Copy, bool _CopyAssignment,
+         bool _Move, bool _MoveAssignment,
+         typename _Tag = void>
+  struct _Enable_copy_move { };
+
+/**
+  * @brief A mixin helper to conditionally enable or disable the special
+  * members.
+  *
+  * The @c _Tag type parameter is to make mixin bases unique and thus avoid
+  * ambiguities.
+  */
+template<bool _Default, bool _Destructor,
+         bool _Copy, bool _CopyAssignment,
+         bool _Move, bool _MoveAssignment,
+         typename _Tag = void>
+  struct _Enable_special_members
+  : private _Enable_default_constructor<_Default, _Tag>,
+    private _Enable_destructor<_Destructor, _Tag>,
+    private _Enable_copy_move<_Copy, _CopyAssignment,
+                              _Move, _MoveAssignment,
+                              _Tag>
+  { };
+
+// Boilerplate follows.
+
+template<typename _Tag>
+  struct _Enable_default_constructor<false, _Tag>
+  { constexpr _Enable_default_constructor() noexcept = delete; };
+
+template<typename _Tag>
+  struct _Enable_destructor<false, _Tag>
+  { ~_Enable_destructor() noexcept = delete; };
+
+template<typename _Tag>
+  struct _Enable_copy_move<false, true, true, true, _Tag>
+  {
+    constexpr _Enable_copy_move() noexcept                          = default;
+    constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept  = delete;
+    constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept       = default;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move const&) noexcept                    = default;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move&&) noexcept                         = default;
+  };
+
+template<typename _Tag>
+  struct _Enable_copy_move<true, false, true, true, _Tag>
+  {
+    constexpr _Enable_copy_move() noexcept                          = default;
+    constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept  = default;
+    constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept       = default;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move const&) noexcept                    = delete;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move&&) noexcept                         = default;
+  };
+
+template<typename _Tag>
+  struct _Enable_copy_move<false, false, true, true, _Tag>
+  {
+    constexpr _Enable_copy_move() noexcept                          = default;
+    constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept  = delete;
+    constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept       = default;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move const&) noexcept                    = delete;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move&&) noexcept                         = default;
+  };
+
+template<typename _Tag>
+  struct _Enable_copy_move<true, true, false, true, _Tag>
+  {
+    constexpr _Enable_copy_move() noexcept                          = default;
+    constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept  = default;
+    constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept       = delete;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move const&) noexcept                    = default;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move&&) noexcept                         = default;
+  };
+
+template<typename _Tag>
+  struct _Enable_copy_move<false, true, false, true, _Tag>
+  {
+    constexpr _Enable_copy_move() noexcept                          = default;
+    constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept  = delete;
+    constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept       = delete;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move const&) noexcept                    = default;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move&&) noexcept                         = default;
+  };
+
+template<typename _Tag>
+  struct _Enable_copy_move<true, false, false, true, _Tag>
+  {
+    constexpr _Enable_copy_move() noexcept                          = default;
+    constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept  = default;
+    constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept       = delete;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move const&) noexcept                    = delete;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move&&) noexcept                         = default;
+  };
+
+template<typename _Tag>
+  struct _Enable_copy_move<false, false, false, true, _Tag>
+  {
+    constexpr _Enable_copy_move() noexcept                          = default;
+    constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept  = delete;
+    constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept       = delete;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move const&) noexcept                    = delete;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move&&) noexcept                         = default;
+  };
+
+template<typename _Tag>
+  struct _Enable_copy_move<true, true, true, false, _Tag>
+  {
+    constexpr _Enable_copy_move() noexcept                          = default;
+    constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept  = default;
+    constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept       = default;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move const&) noexcept                    = default;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move&&) noexcept                         = delete;
+  };
+
+template<typename _Tag>
+  struct _Enable_copy_move<false, true, true, false, _Tag>
+  {
+    constexpr _Enable_copy_move() noexcept                          = default;
+    constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept  = delete;
+    constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept       = default;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move const&) noexcept                    = default;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move&&) noexcept                         = delete;
+  };
+
+template<typename _Tag>
+  struct _Enable_copy_move<true, false, true, false, _Tag>
+  {
+    constexpr _Enable_copy_move() noexcept                          = default;
+    constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept  = default;
+    constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept       = default;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move const&) noexcept                    = delete;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move&&) noexcept                         = delete;
+  };
+
+template<typename _Tag>
+  struct _Enable_copy_move<false, false, true, false, _Tag>
+  {
+    constexpr _Enable_copy_move() noexcept                          = default;
+    constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept  = delete;
+    constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept       = default;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move const&) noexcept                    = delete;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move&&) noexcept                         = delete;
+  };
+
+template<typename _Tag>
+  struct _Enable_copy_move<true, true, false, false, _Tag>
+  {
+    constexpr _Enable_copy_move() noexcept                          = default;
+    constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept  = default;
+    constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept       = delete;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move const&) noexcept                    = default;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move&&) noexcept                         = delete;
+  };
+
+template<typename _Tag>
+  struct _Enable_copy_move<false, true, false, false, _Tag>
+  {
+    constexpr _Enable_copy_move() noexcept                          = default;
+    constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept  = delete;
+    constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept       = delete;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move const&) noexcept                    = default;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move&&) noexcept                         = delete;
+  };
+
+template<typename _Tag>
+  struct _Enable_copy_move<true, false, false, false, _Tag>
+  {
+    constexpr _Enable_copy_move() noexcept                          = default;
+    constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept  = default;
+    constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept       = delete;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move const&) noexcept                    = delete;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move&&) noexcept                         = delete;
+  };
+
+template<typename _Tag>
+  struct _Enable_copy_move<false, false, false, false, _Tag>
+  {
+    constexpr _Enable_copy_move() noexcept                          = default;
+    constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept  = delete;
+    constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept       = delete;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move const&) noexcept                    = delete;
+    _Enable_copy_move&
+    operator=(_Enable_copy_move&&) noexcept                         = delete;
+  };
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif // _ENABLE_SPECIAL_MEMBERS_H
diff --git a/libstdc++-v3/include/experimental/optional b/libstdc++-v3/include/experimental/optional
new file mode 100644
index 0000000..5915892
--- /dev/null
+++ b/libstdc++-v3/include/experimental/optional
@@ -0,0 +1,828 @@ 
+// <optional> -*- C++ -*-
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file experimental/optional
+ *  This is a TS C++ Library header.
+ */
+
+#ifndef _GLIBCXX_EXPERIMENTAL_OPTIONAL
+#define _GLIBCXX_EXPERIMENTAL_OPTIONAL 1
+
+/**
+ * @defgroup experimental Experimental
+ *
+ * Components specified by various Technical Specifications.
+ */
+
+#if __cplusplus <= 201103L
+# include <bits/c++14_warning.h>
+#else
+
+#include <utility>
+#include <type_traits>
+#include <stdexcept>
+#include <new>
+#include <initializer_list>
+#include <bits/functexcept.h>
+#include <bits/functional_hash.h>
+#include <bits/enable_special_members.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+namespace experimental
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  /**
+   * @defgroup optional Optional values
+   * @ingroup experimental
+   *
+   * Class template for optional values and surrounding facilities, as
+   * described in n3793 "A proposal to add a utility class to represent
+   * optional objects (Revision 5)".
+   *
+   * @{
+   */
+
+  // All subsequent [X.Y.n] references are against n3793.
+
+  // [X.Y.4]
+  template<typename _Tp>
+    class optional;
+
+  // [X.Y.5]
+  /// Tag type for in-place construction.
+  struct in_place_t { };
+
+  /// Tag for in-place construction.
+  constexpr in_place_t in_place { };
+
+  // [X.Y.6]
+  /// Tag type to disengage optional objects.
+  struct nullopt_t
+  {
+    // Do not user-declare default constructor at all for
+    // optional_value = {} syntax to work.
+    // nullopt_t() = delete;
+
+    // Used for constructing nullopt.
+    enum class _Construct { _Token };
+
+    // Must be constexpr for nullopt_t to be literal.
+    explicit constexpr nullopt_t(_Construct) { }
+  };
+
+  // [X.Y.6]
+  /// Tag to disengage optional objects.
+  constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token };
+
+  // [X.Y.7]
+  /**
+   *  @brief Exception class thrown when a disengaged optional object is
+   *  dereferenced.
+   *  @ingroup exceptions
+   */
+  class bad_optional_access : public logic_error
+  {
+  public:
+    // XXX Should not be inline
+    explicit bad_optional_access(const string& __arg) : logic_error(__arg) { }
+
+    explicit bad_optional_access(const char* __arg) : logic_error(__arg) { }
+
+    virtual ~bad_optional_access() noexcept = default;
+  };
+
+  void
+  __throw_bad_optional_access(const char*)
+  __attribute__((__noreturn__));
+
+  // XXX Does not belong here.
+  inline void
+  __throw_bad_optional_access(const char* __s)
+  { _GLIBCXX_THROW_OR_ABORT(bad_optional_access(__s)); }
+
+  template<typename _Tp, typename _Sfinae = void>
+    struct _Has_addressof_impl : std::false_type { };
+
+  template<typename _Tp>
+    struct _Has_addressof_impl<_Tp,
+      decltype( std::declval<const _Tp&>().operator&(), void() )>
+    : std::true_type { };
+
+  /**
+    * @brief Trait that detects the presence of an overloaded unary operator&.
+    *
+    * Practically speaking this detects the presence of such an operator when
+    * called on a const-qualified lvalue (i.e.
+    * declval<_Tp * const&>().operator&()).
+    */
+  template<typename _Tp>
+    struct _Has_addressof : _Has_addressof_impl<_Tp>::type { };
+
+  /**
+    * @brief An overload that attempts to take the address of an lvalue as a
+    * constant expression. Falls back to __addressof in the presence of an
+    * overloaded addressof operator (unary operator&), in which case the call
+    * will not be a constant expression.
+    */
+  template<typename _Tp, typename enable_if<!_Has_addressof<_Tp>::value,
+                                            int>::type...>
+    constexpr _Tp* __constexpr_addressof(_Tp& __t)
+    { return &__t; }
+
+  /**
+    * @brief Fallback overload that defers to __addressof.
+    */
+  template<typename _Tp, typename enable_if<_Has_addressof<_Tp>::value,
+                                            int>::type...>
+    _Tp* __constexpr_addressof(_Tp& __t)
+    { return std::__addressof(__t); }
+
+  /**
+    * @brief Class template that holds the necessary state for @ref optional
+    * and that has the responsibility for construction and the special members.
+    *
+    * Such a separate base class template is necessary in order to
+    * conditionally enable the special members (e.g. copy/move constructors).
+    * Note that this means that @ref _Optional_base implements the
+    * functionality for copy and move assignment, but not for converting
+    * assignment.
+    *
+    * @see optional, _Enable_special_members
+    */
+  template<typename _Tp, bool _ShouldProvideDestructor =
+	   !is_trivially_destructible<_Tp>::value>
+    class _Optional_base
+    {
+    private:
+      // Remove const to avoid prohibition of reusing object storage for
+      // const-qualified types in [3.8/9]. This is strictly internal
+      // and even optional itself is oblivious to it.
+      using _Stored_type = typename remove_const<_Tp>::type;
+
+    public:
+      // [X.Y.4.1] Constructors.
+
+      // Constructors for disengaged optionals.
+      constexpr _Optional_base() noexcept
+      : _M_empty{} { }
+
+      constexpr _Optional_base(nullopt_t) noexcept
+      : _Optional_base{} { }
+
+      // Constructors for engaged optionals.
+      constexpr _Optional_base(const _Tp& __t)
+      : _M_payload(__t), _M_engaged(true) { }
+
+      constexpr _Optional_base(_Tp&& __t)
+      : _M_payload(std::move(__t)), _M_engaged(true) { }
+
+      template<typename... _Args>
+        constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
+        : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
+
+      template<typename _Up, typename... _Args,
+               typename enable_if<is_constructible<_Tp,
+                                                   initializer_list<_Up>&,
+                                                   _Args&&...>::value,
+                                  int>::type...>
+        constexpr explicit _Optional_base(in_place_t,
+                                          initializer_list<_Up> __il,
+                                          _Args&&... __args)
+        : _M_payload(__il, std::forward<_Args>(__args)...),
+          _M_engaged(true) { }
+
+      // Copy and move constructors.
+      _Optional_base(const _Optional_base& __other)
+      {
+        if (__other._M_engaged)
+          this->_M_construct(__other._M_get());
+      }
+
+      _Optional_base(_Optional_base&& __other)
+      noexcept(is_nothrow_move_constructible<_Tp>())
+      {
+        if (__other._M_engaged)
+          this->_M_construct(std::move(__other._M_get()));
+      }
+
+      // [X.Y.4.3] (partly) Assignment.
+      _Optional_base&
+      operator=(const _Optional_base& __other)
+      {
+        if (this->_M_engaged && __other._M_engaged)
+          this->_M_get() = __other._M_get();
+        else
+        {
+          if (__other._M_engaged)
+            this->_M_construct(__other._M_get());
+          else
+            this->_M_reset();
+        }
+
+        return *this;
+      }
+
+      _Optional_base&
+      operator=(_Optional_base&& __other)
+      noexcept(is_nothrow_move_constructible<_Tp>()
+               && is_nothrow_move_assignable<_Tp>())
+      {
+        if (this->_M_engaged && __other._M_engaged)
+          this->_M_get() = std::move(__other._M_get());
+        else
+        {
+          if (__other._M_engaged)
+            this->_M_construct(std::move(__other._M_get()));
+          else
+            this->_M_reset();
+        }
+
+        return *this;
+      }
+
+      // [X.Y.4.2] Destructor.
+      ~_Optional_base()
+      {
+        if (this->_M_engaged)
+          this->_M_payload.~_Stored_type();
+      }
+
+      // The following functionality is also needed by optional, hence the
+      // protected accessibility.
+    protected:
+      constexpr bool _M_is_engaged() const noexcept
+      { return this->_M_engaged; }
+
+      // The _M_get operations have _M_engaged as a precondition.
+      _Tp&
+      _M_get() noexcept
+      { return _M_payload; }
+
+      constexpr const _Tp&
+      _M_get() const noexcept
+      { return _M_payload; }
+
+      // The _M_construct operation has !_M_engaged as a precondition
+      // while _M_destruct has _M_engaged as a precondition.
+      template<typename... _Args>
+        void
+        _M_construct(_Args&&... __args)
+        noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
+        {
+          ::new (std::__addressof(this->_M_payload))
+            _Stored_type(std::forward<_Args>(__args)...);
+          this->_M_engaged = true;
+        }
+
+      void
+      _M_destruct()
+      {
+        this->_M_engaged = false;
+        this->_M_payload.~_Stored_type();
+      }
+
+      // _M_reset is a 'safe' operation with no precondition.
+      void
+      _M_reset()
+      {
+        if (this->_M_engaged)
+          this->_M_destruct();
+      }
+
+    private:
+      struct _Empty_byte { };
+      union {
+          _Empty_byte _M_empty;
+          _Stored_type _M_payload;
+      };
+      bool _M_engaged = false;
+    };
+
+  /// Partial specialization that is exactly identical to the primary template
+  /// save for not providing a destructor, to fulfill triviality requirements.
+  template<typename _Tp>
+    class _Optional_base<_Tp, false>
+    {
+    private:
+      using _Stored_type = typename remove_const<_Tp>::type;
+
+    public:
+      constexpr _Optional_base() noexcept
+      : _M_empty{} { }
+
+      constexpr _Optional_base(nullopt_t) noexcept
+      : _Optional_base{} { }
+
+      constexpr _Optional_base(const _Tp& __t)
+      : _M_payload(__t), _M_engaged(true) { }
+
+      constexpr _Optional_base(_Tp&& __t)
+      : _M_payload(std::move(__t)), _M_engaged(true) { }
+
+      template<typename... _Args>
+        constexpr explicit _Optional_base(in_place_t, _Args&&... __args)
+        : _M_payload(std::forward<_Args>(__args)...), _M_engaged(true) { }
+
+      template<typename _Up, typename... _Args,
+               typename enable_if<is_constructible<_Tp,
+                                                   initializer_list<_Up>&,
+                                                   _Args&&...>::value,
+                                  int>::type...>
+        constexpr explicit _Optional_base(in_place_t,
+                                          initializer_list<_Up> __il,
+                                          _Args&&... __args)
+        : _M_payload(__il, std::forward<_Args>(__args)...),
+          _M_engaged(true) { }
+
+      _Optional_base(const _Optional_base& __other)
+      {
+        if (__other._M_engaged)
+          this->_M_construct(__other._M_get());
+      }
+
+      _Optional_base(_Optional_base&& __other)
+      noexcept(is_nothrow_move_constructible<_Tp>())
+      {
+        if (__other._M_engaged)
+          this->_M_construct(std::move(__other._M_get()));
+      }
+
+      _Optional_base&
+      operator=(const _Optional_base& __other)
+      {
+        if (this->_M_engaged && __other._M_engaged)
+          this->_M_get() = __other._M_get();
+        else
+        {
+          if (__other._M_engaged)
+            this->_M_construct(__other._M_get());
+          else
+            this->_M_reset();
+        }
+
+        return *this;
+      }
+
+      _Optional_base&
+      operator=(_Optional_base&& __other)
+      noexcept(is_nothrow_move_constructible<_Tp>()
+               && is_nothrow_move_assignable<_Tp>())
+      {
+        if (this->_M_engaged && __other._M_engaged)
+          this->_M_get() = std::move(__other._M_get());
+        else
+        {
+          if (__other._M_engaged)
+            this->_M_construct(std::move(__other._M_get()));
+          else
+            this->_M_reset();
+        }
+
+        return *this;
+      }
+
+      // Sole difference
+      // ~_Optional_base() noexcept = default;
+
+    protected:
+      constexpr bool _M_is_engaged() const noexcept
+      { return this->_M_engaged; }
+
+      _Tp&
+      _M_get() noexcept
+      { return _M_payload; }
+
+      constexpr const _Tp&
+      _M_get() const noexcept
+      { return _M_payload; }
+
+      template<typename... _Args>
+        void
+        _M_construct(_Args&&... __args)
+        noexcept(is_nothrow_constructible<_Stored_type, _Args...>())
+        {
+          ::new (std::__addressof(this->_M_payload))
+            _Stored_type(std::forward<_Args>(__args)...);
+          this->_M_engaged = true;
+        }
+
+      void
+      _M_destruct()
+      {
+        this->_M_engaged = false;
+        this->_M_payload.~_Stored_type();
+      }
+
+      void
+      _M_reset()
+      {
+        if (this->_M_engaged)
+          this->_M_destruct();
+      }
+
+    private:
+      struct _Empty_byte { };
+      union {
+          _Empty_byte _M_empty;
+          _Stored_type _M_payload;
+      };
+      bool _M_engaged = false;
+    };
+
+  /**
+    * @brief Class template for optional values.
+    */
+  template<typename _Tp>
+    class optional
+    : private _Optional_base<_Tp>,
+      private _Enable_copy_move<
+        // Copy constructor.
+        is_copy_constructible<_Tp>::value,
+        // Copy assignment.
+        is_copy_constructible<_Tp>::value
+        && is_copy_assignable<_Tp>::value,
+        // Move constructor.
+        is_move_constructible<_Tp>::value,
+        // Move assignment.
+        is_move_constructible<_Tp>::value
+        && is_move_assignable<_Tp>::value,
+        // Unique tag type.
+        optional<_Tp>>
+    {
+      static_assert(!is_same<typename remove_cv<_Tp>::type,
+                             nullopt_t>()
+                    && !is_same<typename remove_cv<_Tp>::type,
+                             in_place_t>()
+                    && !is_reference<_Tp>(),
+                    "Invalid instantiation of optional<T>.");
+
+    private:
+      using _Base = _Optional_base<_Tp>;
+
+    public:
+      using value_type = _Tp;
+
+      // _Optional_base has the responsibility for construction.
+      using _Base::_Base;
+
+      // [X.Y.4.3] (partly) Assignment.
+      optional&
+      operator=(nullopt_t) noexcept
+      {
+        this->_M_reset();
+        return *this;
+      }
+
+      template<typename _Up>
+        typename enable_if<
+                 is_same<_Tp, typename decay<_Up>::type>::value,
+                 optional&
+               >::type
+        operator=(_Up&& __u)
+        {
+          static_assert(is_constructible<_Tp, _Up>()
+                        && is_assignable<_Tp&, _Up>(),
+                        "Cannot assign to value type from argument.");
+
+          if (this->_M_is_engaged())
+            this->_M_get() = std::forward<_Up>(__u);
+          else
+            this->_M_construct(std::forward<_Up>(__u));
+
+          return *this;
+        }
+
+      template<typename... _Args>
+	void
+	emplace(_Args&&... __args)
+	{
+	  static_assert(is_constructible<_Tp, _Args&&...>(),
+			"Cannot emplace value type from arguments.");
+
+	  this->_M_reset();
+	  this->_M_construct(std::forward<_Args>(__args)...);
+	}
+
+      template<typename _Up, typename... _Args>
+        typename enable_if<
+                 is_constructible<_Tp,
+                                  initializer_list<_Up>&,
+                                  _Args&&...>::value
+               >::type
+	emplace(initializer_list<_Up> __il, _Args&&... __args)
+	{
+	  this->_M_reset();
+	  this->_M_construct(__il, std::forward<_Args>(__args)...);
+	}
+
+      // [X.Y.4.2] Destructor is implicit, implemented in _Optional_base.
+
+      // [X.Y.4.4] Swap.
+      void
+      swap(optional& __other)
+      noexcept(is_nothrow_move_constructible<_Tp>()
+               && noexcept(swap(declval<_Tp&>(), declval<_Tp&>())))
+      {
+        using std::swap;
+
+        if (this->_M_is_engaged() && __other._M_is_engaged())
+          swap(this->_M_get(), __other._M_get());
+        else if (this->_M_is_engaged())
+        {
+          __other._M_construct(std::move(this->_M_get()));
+          this->_M_destruct();
+        }
+        else if (__other._M_is_engaged())
+        {
+          this->_M_construct(std::move(__other._M_get()));
+          __other._M_destruct();
+        }
+      }
+
+      // [X.Y.4.5] Observers.
+      constexpr const _Tp*
+      operator->() const
+      { return __constexpr_addressof(this->_M_get()); }
+
+      _Tp*
+      operator->()
+      { return std::__addressof(this->_M_get()); }
+
+      constexpr const _Tp&
+      operator*() const
+      { return this->_M_get(); }
+
+      _Tp&
+      operator*()
+      { return this->_M_get(); }
+
+      constexpr explicit operator bool() const noexcept
+      { return this->_M_is_engaged(); }
+
+      constexpr const _Tp&
+      value() const
+      {
+        return this->_M_is_engaged() ?
+          this->_M_get() :
+          (__throw_bad_optional_access("Attempt to access value of a disengaged"
+                                       " optional object."),
+           this->_M_get());
+      }
+
+      _Tp&
+      value()
+      {
+        if (this->_M_is_engaged())
+          return this->_M_get();
+
+        __throw_bad_optional_access("Attempt to access value of a disengaged"
+                                    " optional object.");
+      }
+
+      template<typename _Up>
+	constexpr _Tp
+	value_or(_Up&& __u) const&
+	{
+	  static_assert(is_copy_constructible<_Tp>()
+			&& is_convertible<_Up&&, _Tp>(),
+			"Cannot return value.");
+
+	  return this->_M_is_engaged() ?
+	    this->_M_get() :
+	    static_cast<_Tp>(std::forward<_Up>(__u));
+	}
+
+      template<typename _Up>
+	_Tp
+	value_or(_Up&& __u) &&
+	{
+	  static_assert( is_move_constructible<_Tp>()
+			&& is_convertible<_Up&&, _Tp>(),
+			"Cannot return value." );
+
+	  return this->_M_is_engaged() ?
+	    std::move(this->_M_get()) :
+	    static_cast<_Tp>(std::forward<_Up>(__u));
+	}
+    };
+
+  // [X.Y.8] Comparisons between optional values.
+  template<typename _Tp>
+    constexpr bool
+    operator==(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
+    {
+      return static_cast<bool>(__lhs) == static_cast<bool>(__rhs)
+        && (!__lhs || *__lhs == *__rhs);
+    }
+
+  template<typename _Tp>
+    constexpr bool
+    operator!=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
+    { return !(__lhs == __rhs); }
+
+  template<typename _Tp>
+    constexpr bool
+    operator<(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
+    {
+      return static_cast<bool>(__rhs)
+        && (!__lhs || *__lhs < *__rhs);
+    }
+
+  template<typename _Tp>
+    constexpr bool
+    operator>(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
+    { return __rhs < __lhs; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator<=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
+    { return !(__rhs < __lhs); }
+
+  template<typename _Tp>
+    constexpr bool
+    operator>=(const optional<_Tp>& __lhs, const optional<_Tp>& __rhs)
+    { return !(__lhs < __rhs); }
+
+  // [X.Y.9] Comparisons with nullopt.
+  template<typename _Tp>
+    constexpr bool
+    operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept
+    { return !__lhs; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept
+    { return !__rhs; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept
+    { return static_cast<bool>(__lhs); }
+
+  template<typename _Tp>
+    constexpr bool
+    operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept
+    { return static_cast<bool>(__rhs); }
+
+  template<typename _Tp>
+    constexpr bool
+    operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
+    { return false; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept
+    { return static_cast<bool>(__rhs); }
+
+  template<typename _Tp>
+    constexpr bool
+    operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept
+    { return static_cast<bool>(__lhs); }
+
+  template<typename _Tp>
+    constexpr bool
+    operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
+    { return false; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept
+    { return !__lhs; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept
+    { return true; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept
+    { return true; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept
+    { return !__rhs; }
+
+  // [X.Y.10] Comparisons with value type.
+  template<typename _Tp>
+    constexpr bool
+    operator==(const optional<_Tp>& __lhs, const _Tp& __rhs)
+    { return __lhs && *__lhs == __rhs; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator==(const _Tp& __lhs, const optional<_Tp>& __rhs)
+    { return __rhs && __lhs == *__rhs; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator!=(const optional<_Tp>& __lhs, _Tp const& __rhs)
+    { return !__lhs || *__lhs != __rhs; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator!=(const _Tp& __lhs, const optional<_Tp>& __rhs)
+    { return !__rhs || __lhs != *__rhs; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator<(const optional<_Tp>& __lhs, const _Tp& __rhs)
+    { return !__lhs || *__lhs < __rhs; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator<(const _Tp& __lhs, const optional<_Tp>& __rhs)
+    { return __rhs && __lhs < *__rhs; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator>(const optional<_Tp>& __lhs, const _Tp& __rhs)
+    { return __lhs && __rhs < *__lhs; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator>(const _Tp& __lhs, const optional<_Tp>& __rhs)
+    { return !__rhs || *__rhs < __lhs; }
+
+  template<typename _Tp>
+    constexpr bool
+    operator<=(const optional<_Tp>& __lhs, const _Tp& __rhs)
+    { return !__lhs || !(__rhs < *__lhs); }
+
+  template<typename _Tp>
+    constexpr bool
+    operator<=(const _Tp& __lhs, const optional<_Tp>& __rhs)
+    { return __rhs && !(*__rhs < __lhs); }
+
+  template<typename _Tp>
+    constexpr bool
+    operator>=(const optional<_Tp>& __lhs, const _Tp& __rhs)
+    { return __lhs && !(*__lhs < __rhs); }
+
+  template<typename _Tp>
+    constexpr bool
+    operator>=(const _Tp& __lhs, const optional<_Tp>& __rhs)
+    { return !__rhs || !(__lhs < *__rhs); }
+
+  // [X.Y.11]
+  template<typename _Tp>
+    void
+    swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs)
+    noexcept(noexcept(__lhs.swap(__rhs)))
+    { __lhs.swap(__rhs); }
+
+  template<typename _Tp>
+    constexpr optional<typename decay<_Tp>::type>
+    make_optional(_Tp&& __t)
+    { return optional<typename decay<_Tp>::type> { std::forward<_Tp>(__t) }; }
+
+  // @} group optional
+_GLIBCXX_END_NAMESPACE_VERSION
+}
+
+  // [X.Y.12]
+  template<typename _Tp>
+    struct hash<experimental::optional<_Tp>>
+    {
+      using result_type = size_t;
+      using argument_type = experimental::optional<_Tp>;
+
+      size_t
+      operator()(const experimental::optional<_Tp>& __t) const
+      noexcept(noexcept(hash<_Tp> {}(*__t)))
+      {
+        // We pick an arbitrary hash for disengaged optionals which hopefully
+        // usual values of _Tp won't typically hash to.
+        constexpr size_t __magic_disengaged_hash = static_cast<size_t>(-3333);
+        return __t ? hash<_Tp> {}(*__t) : __magic_disengaged_hash;
+      }
+    };
+}
+
+#endif // C++14
+
+#endif // _GLIBCXX_EXPERIMENTAL_OPTIONAL
diff --git a/libstdc++-v3/testsuite/experimental/optional/assignment/1.cc b/libstdc++-v3/testsuite/experimental/optional/assignment/1.cc
new file mode 100644
index 0000000..b09e0ac
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/assignment/1.cc
@@ -0,0 +1,195 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct exception {};
+
+int counter = 0;
+
+struct mixin_counter
+{
+  mixin_counter() { ++counter; }
+  mixin_counter(mixin_counter const&) { ++counter; }
+  ~mixin_counter() { --counter; }
+};
+
+struct value_type : private mixin_counter
+{
+  enum state_type
+  {
+    zero,
+    moved_from,
+    throwing_construction,
+    throwing_copy,
+    throwing_copy_assignment,
+    throwing_move,
+    throwing_move_assignment,
+    threw,
+  };
+
+  value_type() = default;
+
+  explicit value_type(state_type state_)
+  : state(state_)
+  {
+    throw_if(throwing_construction);
+  }
+
+  value_type(value_type const& other)
+  : state(other.state)
+  {
+    throw_if(throwing_copy);
+  }
+
+  value_type&
+  operator=(value_type const& other)
+  {
+    state = other.state;
+    throw_if(throwing_copy_assignment);
+    return *this;
+  }
+
+  value_type(value_type&& other)
+  : state(other.state)
+  {
+    other.state = moved_from;
+    throw_if(throwing_move);
+  }
+
+  value_type&
+  operator=(value_type&& other)
+  {
+    state = other.state;
+    other.state = moved_from;
+    throw_if(throwing_move_assignment);
+    return *this;
+  }
+
+  void throw_if(state_type match)
+  {
+    if(state == match)
+    {
+      state = threw;
+      throw exception {};
+    }
+  }
+
+  state_type state = zero;
+};
+
+int main()
+{
+  using O = std::experimental::optional<value_type>;
+  using S = value_type::state_type;
+  auto const make = [](S s = S::zero) { return O { std::experimental::in_place, s }; };
+
+  enum outcome_type { nothrow, caught, bad_catch };
+
+  // Check copy/move assignment for disengaged optional
+
+  // From disengaged optional
+  {
+    O o;
+    VERIFY( !o );
+    O p;
+    o = p;
+    VERIFY( !o );
+    VERIFY( !p );
+  }
+
+  {
+    O o;
+    VERIFY( !o );
+    O p;
+    o = std::move(p);
+    VERIFY( !o );
+    VERIFY( !p );
+  }
+
+  {
+    O o;
+    VERIFY( !o );
+    o = {};
+    VERIFY( !o );
+  }
+
+  // From engaged optional
+  {
+    O o;
+    VERIFY( !o );
+    O p = make(S::throwing_copy_assignment);
+    o = p;
+    VERIFY( o && o->state == S::throwing_copy_assignment );
+    VERIFY( p && p->state == S::throwing_copy_assignment );
+  }
+
+  {
+    O o;
+    VERIFY( !o );
+    O p = make(S::throwing_move_assignment);
+    o = std::move(p);
+    VERIFY( o && o->state == S::throwing_move_assignment );
+    VERIFY( p && p->state == S::moved_from );
+  }
+
+  {
+    outcome_type outcome {};
+    O o;
+    VERIFY( !o );
+    O p = make(S::throwing_copy);
+
+    try
+    {
+      o = p;
+    }
+    catch(exception const&)
+    { outcome = caught; }
+    catch(...)
+    { outcome = bad_catch; }
+
+    VERIFY( outcome == caught );
+    VERIFY( !o );
+    VERIFY( p && p->state == S::throwing_copy );
+  }
+
+  {
+    outcome_type outcome {};
+    O o;
+    VERIFY( !o );
+    O p = make(S::throwing_move);
+
+    try
+    {
+      o = std::move(p);
+    }
+    catch(exception const&)
+    { outcome = caught; }
+    catch(...)
+    { outcome = bad_catch; }
+
+    VERIFY( outcome == caught );
+    VERIFY( !o );
+    VERIFY( p && p->state == S::moved_from );
+  }
+
+  VERIFY( counter == 0 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/assignment/2.cc b/libstdc++-v3/testsuite/experimental/optional/assignment/2.cc
new file mode 100644
index 0000000..7985fff
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/assignment/2.cc
@@ -0,0 +1,193 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct exception {};
+
+int counter = 0;
+
+struct mixin_counter
+{
+  mixin_counter() { ++counter; }
+  mixin_counter(mixin_counter const&) { ++counter; }
+  ~mixin_counter() { --counter; }
+};
+
+struct value_type : private mixin_counter
+{
+  enum state_type
+  {
+    zero,
+    moved_from,
+    throwing_construction,
+    throwing_copy,
+    throwing_copy_assignment,
+    throwing_move,
+    throwing_move_assignment,
+    threw,
+  };
+
+  value_type() = default;
+
+  explicit value_type(state_type state_)
+  : state(state_)
+  {
+    throw_if(throwing_construction);
+  }
+
+  value_type(value_type const& other)
+  : state(other.state)
+  {
+    throw_if(throwing_copy);
+  }
+
+  value_type&
+  operator=(value_type const& other)
+  {
+    state = other.state;
+    throw_if(throwing_copy_assignment);
+    return *this;
+  }
+
+  value_type(value_type&& other)
+  : state(other.state)
+  {
+    other.state = moved_from;
+    throw_if(throwing_move);
+  }
+
+  value_type&
+  operator=(value_type&& other)
+  {
+    state = other.state;
+    other.state = moved_from;
+    throw_if(throwing_move_assignment);
+    return *this;
+  }
+
+  void throw_if(state_type match)
+  {
+    if(state == match)
+    {
+      state = threw;
+      throw exception {};
+    }
+  }
+
+  state_type state = zero;
+};
+
+int main()
+{
+  using O = std::experimental::optional<value_type>;
+  using S = value_type::state_type;
+  auto const make = [](S s = S::zero) { return O { std::experimental::in_place, s }; };
+
+  enum outcome_type { nothrow, caught, bad_catch };
+
+  // Check copy/move assignment for engaged optional
+
+  // From disengaged optional
+  {
+    O o = make(S::zero);
+    VERIFY( o );
+    O p;
+    o = p;
+    VERIFY( !o );
+    VERIFY( !p );
+  }
+
+  {
+    O o = make(S::zero);
+    VERIFY( o );
+    O p;
+    o = std::move(p);
+    VERIFY( !o );
+    VERIFY( !p );
+  }
+
+  {
+    O o = make(S::zero);
+    VERIFY( o );
+    o = {};
+    VERIFY( !o );
+  }
+
+  // From engaged optional
+  {
+    O o = make(S::zero);
+    VERIFY( o );
+    O p = make(S::throwing_copy);
+    o = p;
+    VERIFY( o && o->state == S::throwing_copy);
+    VERIFY( p && p->state == S::throwing_copy);
+  }
+
+  {
+    O o = make(S::zero);
+    VERIFY( o );
+    O p = make(S::throwing_move);
+    o = std::move(p);
+    VERIFY( o && o->state == S::throwing_move);
+    VERIFY( p && p->state == S::moved_from);
+  }
+
+  {
+    outcome_type outcome {};
+    O o = make(S::zero);
+    VERIFY( o );
+    O p = make(S::throwing_copy_assignment);
+
+    try
+    {
+      o = p;
+    }
+    catch(exception const&)
+    { outcome = caught; }
+    catch(...)
+    { outcome = bad_catch; }
+
+    VERIFY( o && o->state == S::threw);
+    VERIFY( p && p->state == S::throwing_copy_assignment);
+  }
+
+  {
+    outcome_type outcome {};
+    O o = make(S::zero);
+    VERIFY( o );
+    O p = make(S::throwing_move_assignment);
+
+    try
+    {
+      o = std::move(p);
+    }
+    catch(exception const&)
+    { outcome = caught; }
+    catch(...)
+    { outcome = bad_catch; }
+
+    VERIFY( o && o->state == S::threw);
+    VERIFY( p && p->state == S::moved_from);
+  }
+
+  VERIFY( counter == 0 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/assignment/3.cc b/libstdc++-v3/testsuite/experimental/optional/assignment/3.cc
new file mode 100644
index 0000000..d631886
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/assignment/3.cc
@@ -0,0 +1,158 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct exception {};
+
+int counter = 0;
+
+struct mixin_counter
+{
+  mixin_counter() { ++counter; }
+  mixin_counter(mixin_counter const&) { ++counter; }
+  ~mixin_counter() { --counter; }
+};
+
+struct value_type : private mixin_counter
+{
+  enum state_type
+  {
+    zero,
+    moved_from,
+    throwing_construction,
+    throwing_copy,
+    throwing_copy_assignment,
+    throwing_move,
+    throwing_move_assignment,
+    threw,
+  };
+
+  value_type() = default;
+
+  explicit value_type(state_type state_)
+  : state(state_)
+  {
+    throw_if(throwing_construction);
+  }
+
+  value_type(value_type const& other)
+  : state(other.state)
+  {
+    throw_if(throwing_copy);
+  }
+
+  value_type&
+  operator=(value_type const& other)
+  {
+    state = other.state;
+    throw_if(throwing_copy_assignment);
+    return *this;
+  }
+
+  value_type(value_type&& other)
+  : state(other.state)
+  {
+    other.state = moved_from;
+    throw_if(throwing_move);
+  }
+
+  value_type&
+  operator=(value_type&& other)
+  {
+    state = other.state;
+    other.state = moved_from;
+    throw_if(throwing_move_assignment);
+    return *this;
+  }
+
+  void throw_if(state_type match)
+  {
+    if(state == match)
+    {
+      state = threw;
+      throw exception {};
+    }
+  }
+
+  state_type state = zero;
+};
+
+int main()
+{
+  using O = std::experimental::optional<value_type>;
+  using S = value_type::state_type;
+  auto const make = [](S s = S::zero) { return value_type { s }; };
+
+  enum outcome_type { nothrow, caught, bad_catch };
+
+  // Check value assignment for disengaged optional
+
+  {
+    O o;
+    value_type v = make(S::throwing_copy_assignment);
+    o = v;
+    VERIFY( o && o->state == S::throwing_copy_assignment );
+  }
+
+  {
+    O o;
+    value_type v = make(S::throwing_move_assignment);
+    o = std::move(v);
+    VERIFY( o && o->state == S::throwing_move_assignment );
+  }
+
+  {
+    outcome_type outcome {};
+    O o;
+    value_type v = make(S::throwing_copy);
+
+    try
+    {
+      o = v;
+    }
+    catch(exception const&)
+    { outcome = caught; }
+    catch(...)
+    { outcome = bad_catch; }
+
+    VERIFY( !o );
+  }
+
+  {
+    outcome_type outcome {};
+    O o;
+    value_type v = make(S::throwing_move);
+
+    try
+    {
+      o = std::move(v);
+    }
+    catch(exception const&)
+    { outcome = caught; }
+    catch(...)
+    { outcome = bad_catch; }
+
+    VERIFY( !o );
+  }
+
+  VERIFY( counter == 0 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/assignment/4.cc b/libstdc++-v3/testsuite/experimental/optional/assignment/4.cc
new file mode 100644
index 0000000..e5f1f16
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/assignment/4.cc
@@ -0,0 +1,158 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct exception {};
+
+int counter = 0;
+
+struct mixin_counter
+{
+  mixin_counter() { ++counter; }
+  mixin_counter(mixin_counter const&) { ++counter; }
+  ~mixin_counter() { --counter; }
+};
+
+struct value_type : private mixin_counter
+{
+  enum state_type
+  {
+    zero,
+    moved_from,
+    throwing_construction,
+    throwing_copy,
+    throwing_copy_assignment,
+    throwing_move,
+    throwing_move_assignment,
+    threw,
+  };
+
+  value_type() = default;
+
+  explicit value_type(state_type state_)
+  : state(state_)
+  {
+    throw_if(throwing_construction);
+  }
+
+  value_type(value_type const& other)
+  : state(other.state)
+  {
+    throw_if(throwing_copy);
+  }
+
+  value_type&
+  operator=(value_type const& other)
+  {
+    state = other.state;
+    throw_if(throwing_copy_assignment);
+    return *this;
+  }
+
+  value_type(value_type&& other)
+  : state(other.state)
+  {
+    other.state = moved_from;
+    throw_if(throwing_move);
+  }
+
+  value_type&
+  operator=(value_type&& other)
+  {
+    state = other.state;
+    other.state = moved_from;
+    throw_if(throwing_move_assignment);
+    return *this;
+  }
+
+  void throw_if(state_type match)
+  {
+    if(state == match)
+    {
+      state = threw;
+      throw exception {};
+    }
+  }
+
+  state_type state = zero;
+};
+
+int main()
+{
+  using O = std::experimental::optional<value_type>;
+  using S = value_type::state_type;
+  auto const make = [](S s = S::zero) { return value_type { s }; };
+
+  enum outcome_type { nothrow, caught, bad_catch };
+
+  // Check value assignment for engaged optional
+
+  {
+    O o = make();
+    value_type v = make(S::throwing_copy);
+    o = v;
+    VERIFY( o && o->state == S::throwing_copy);
+  }
+
+  {
+    O o = make();
+    value_type v = make(S::throwing_move);
+    o = std::move(v);
+    VERIFY( o && o->state == S::throwing_move);
+  }
+
+  {
+    outcome_type outcome {};
+    O o = make();
+    value_type v = make(S::throwing_copy_assignment);
+
+    try
+    {
+      o = v;
+    }
+    catch(exception const&)
+    { outcome = caught; }
+    catch(...)
+    { outcome = bad_catch; }
+
+    VERIFY( o && o->state == S::threw );
+  }
+
+  {
+    outcome_type outcome {};
+    O o = make();
+    value_type v = make(S::throwing_move_assignment);
+
+    try
+    {
+      o = std::move(v);
+    }
+    catch(exception const&)
+    { outcome = caught; }
+    catch(...)
+    { outcome = bad_catch; }
+
+    VERIFY( o && o->state == S::threw );
+  }
+
+  VERIFY( counter == 0 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/assignment/5.cc b/libstdc++-v3/testsuite/experimental/optional/assignment/5.cc
new file mode 100644
index 0000000..d6e268f
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/assignment/5.cc
@@ -0,0 +1,66 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+int counter = 0;
+
+struct mixin_counter
+{
+  mixin_counter() { ++counter; }
+  mixin_counter(mixin_counter const&) { ++counter; }
+  ~mixin_counter() { --counter; }
+};
+
+struct value_type : private mixin_counter { };
+
+int main()
+{
+  using O = std::experimental::optional<value_type>;
+
+  // Check std::experimental::nullopt_t and 'default' (= {}) assignment
+
+  {
+    O o;
+    o = std::experimental::nullopt;
+    VERIFY( !o );
+  }
+
+  {
+    O o { std::experimental::in_place };
+    o = std::experimental::nullopt;
+    VERIFY( !o );
+  }
+
+  {
+    O o;
+    o = {};
+    VERIFY( !o );
+  }
+
+  {
+    O o { std::experimental::in_place };
+    o = {};
+    VERIFY( !o );
+  }
+
+  VERIFY( counter == 0 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/assignment/6.cc b/libstdc++-v3/testsuite/experimental/optional/assignment/6.cc
new file mode 100644
index 0000000..55be89d
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/assignment/6.cc
@@ -0,0 +1,83 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+int counter = 0;
+
+struct mixin_counter
+{
+  mixin_counter() { ++counter; }
+  mixin_counter(mixin_counter const&) { ++counter; }
+  ~mixin_counter() { --counter; }
+};
+
+struct value_type : private mixin_counter
+{
+  value_type() = default;
+  value_type(int) : state(1) { }
+  value_type(std::initializer_list<char>, const char*) : state(2) { }
+  int state = 0;
+};
+
+int main()
+{
+  using O = std::experimental::optional<value_type>;
+
+  // Check emplace
+
+  {
+    O o;
+    o.emplace();
+    VERIFY( o && o->state == 0 );
+  }
+  {
+    O o { std::experimental::in_place, 0 };
+    o.emplace();
+    VERIFY( o && o->state == 0 );
+  }
+
+  {
+    O o;
+    o.emplace(0);
+    VERIFY( o && o->state == 1 );
+  }
+  {
+    O o { std::experimental::in_place };
+    o.emplace(0);
+    VERIFY( o && o->state == 1 );
+  }
+
+  {
+    O o;
+    o.emplace({ 'a' }, "");
+    VERIFY( o && o->state == 2 );
+  }
+  {
+    O o { std::experimental::in_place };
+    o.emplace({ 'a' }, "");
+    VERIFY( o && o->state == 2 );
+  }
+
+  static_assert( !std::is_constructible<O, std::initializer_list<int>, int>(), "" );
+
+  VERIFY( counter == 0 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/cons/copy.cc b/libstdc++-v3/testsuite/experimental/optional/cons/copy.cc
new file mode 100644
index 0000000..bbd9328
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/cons/copy.cc
@@ -0,0 +1,125 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct tracker
+{
+  tracker(int value) : value(value) { ++count; }
+  ~tracker() { --count; }
+
+  tracker(tracker const& other) : value(other.value) { ++count; }
+  tracker(tracker&& other) : value(other.value)
+  {
+    other.value = -1;
+    ++count;
+  }
+
+  tracker& operator=(tracker const&) = default;
+  tracker& operator=(tracker&&) = default;
+
+  int value;
+
+  static int count;
+};
+
+int tracker::count = 0;
+
+struct exception { };
+
+struct throwing_copy
+{
+  throwing_copy() = default;
+  throwing_copy(throwing_copy const&) { throw exception {}; }
+};
+
+int main()
+{
+  // [20.5.4.1] Constructors
+
+  {
+    std::experimental::optional<long> o;
+    auto copy = o;
+    VERIFY( !copy );
+    VERIFY( !o );
+  }
+
+  {
+    std::experimental::optional<long> o { std::experimental::in_place, 0x1234ABCDF1E2D3C4 };
+    auto copy = o;
+    VERIFY( copy );
+    VERIFY( *copy == 0x1234ABCDF1E2D3C4 );
+    VERIFY( o && o == 0x1234ABCDF1E2D3C4 );
+  }
+
+  {
+    std::experimental::optional<tracker> o;
+    auto copy = o;
+    VERIFY( !copy );
+    VERIFY( tracker::count == 0 );
+    VERIFY( !o );
+  }
+
+  {
+    std::experimental::optional<tracker> o { std::experimental::in_place, 333 };
+    auto copy = o;
+    VERIFY( copy );
+    VERIFY( copy->value == 333 );
+    VERIFY( tracker::count == 2 );
+    VERIFY( o && o->value == 333 );
+  }
+
+  enum outcome { nothrow, caught, bad_catch };
+
+  {
+    outcome result = nothrow;
+    std::experimental::optional<throwing_copy> o;
+
+    try
+    {
+      auto copy = o;
+    }
+    catch(exception const&)
+    { result = caught; }
+    catch(...)
+    { result = bad_catch; }
+
+    VERIFY( result == nothrow );
+  }
+
+  {
+    outcome result = nothrow;
+    std::experimental::optional<throwing_copy> o { std::experimental::in_place };
+
+    try
+    {
+      auto copy = o;
+    }
+    catch(exception const&)
+    { result = caught; }
+    catch(...)
+    { result = bad_catch; }
+
+    VERIFY( result == caught );
+  }
+
+  VERIFY( tracker::count == 0 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/cons/default.cc b/libstdc++-v3/testsuite/experimental/optional/cons/default.cc
new file mode 100644
index 0000000..452f2d0
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/cons/default.cc
@@ -0,0 +1,60 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct tracker
+{
+  tracker() { ++count; }
+  ~tracker() { --count; }
+
+  tracker(tracker const&) { ++count; }
+  tracker(tracker&&) { ++count; }
+
+  tracker& operator=(tracker const&) = default;
+  tracker& operator=(tracker&&) = default;
+
+  static int count;
+};
+
+int tracker::count = 0;
+
+int main()
+{
+  // [20.5.4.1] Constructors
+
+  {
+    std::experimental::optional<tracker> o;
+    VERIFY( !o );
+  }
+
+  {
+    std::experimental::optional<tracker> o {};
+    VERIFY( !o );
+  }
+
+  {
+    std::experimental::optional<tracker> o = {};
+    VERIFY( !o );
+  }
+
+  VERIFY( tracker::count == 0 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/cons/move.cc b/libstdc++-v3/testsuite/experimental/optional/cons/move.cc
new file mode 100644
index 0000000..75d7677
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/cons/move.cc
@@ -0,0 +1,125 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct tracker
+{
+  tracker(int value) : value(value) { ++count; }
+  ~tracker() { --count; }
+
+  tracker(tracker const& other) : value(other.value) { ++count; }
+  tracker(tracker&& other) : value(other.value)
+  {
+    other.value = -1;
+    ++count;
+  }
+
+  tracker& operator=(tracker const&) = default;
+  tracker& operator=(tracker&&) = default;
+
+  int value;
+
+  static int count;
+};
+
+int tracker::count = 0;
+
+struct exception { };
+
+struct throwing_move
+{
+  throwing_move() = default;
+  throwing_move(throwing_move const&) { throw exception {}; }
+};
+
+int main()
+{
+  // [20.5.4.1] Constructors
+
+  {
+    std::experimental::optional<long> o;
+    auto moved_to = std::move(o);
+    VERIFY( !moved_to );
+    VERIFY( !o );
+  }
+
+  {
+    std::experimental::optional<long> o { std::experimental::in_place, 0x1234ABCDF1E2D3C4 };
+    auto moved_to = std::move(o);
+    VERIFY( moved_to );
+    VERIFY( *moved_to == 0x1234ABCDF1E2D3C4 );
+    VERIFY( o && *o == 0x1234ABCDF1E2D3C4 );
+  }
+
+  {
+    std::experimental::optional<tracker> o;
+    auto moved_to = std::move(o);
+    VERIFY( !moved_to );
+    VERIFY( tracker::count == 0 );
+    VERIFY( !o );
+  }
+
+  {
+    std::experimental::optional<tracker> o { std::experimental::in_place, 333 };
+    auto moved_to = std::move(o);
+    VERIFY( moved_to );
+    VERIFY( moved_to->value == 333 );
+    VERIFY( tracker::count == 2 );
+    VERIFY( o && o->value == -1 );
+  }
+
+  enum outcome { nothrow, caught, bad_catch };
+
+  {
+    outcome result = nothrow;
+    std::experimental::optional<throwing_move> o;
+
+    try
+    {
+      auto moved_to = std::move(o);
+    }
+    catch(exception const&)
+    { result = caught; }
+    catch(...)
+    { result = bad_catch; }
+
+    VERIFY( result == nothrow );
+  }
+
+  {
+    outcome result = nothrow;
+    std::experimental::optional<throwing_move> o { std::experimental::in_place };
+
+    try
+    {
+      auto moved_to = std::move(o);
+    }
+    catch(exception const&)
+    { result = caught; }
+    catch(...)
+    { result = bad_catch; }
+
+    VERIFY( result == caught );
+  }
+
+  VERIFY( tracker::count == 0 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/cons/value.cc b/libstdc++-v3/testsuite/experimental/optional/cons/value.cc
new file mode 100644
index 0000000..339c120
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/cons/value.cc
@@ -0,0 +1,239 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+#include <vector>
+
+struct tracker
+{
+  tracker(int value) : value(value) { ++count; }
+  ~tracker() { --count; }
+
+  tracker(tracker const& other) : value(other.value) { ++count; }
+  tracker(tracker&& other) : value(other.value)
+  {
+    other.value = -1;
+    ++count;
+  }
+
+  tracker& operator=(tracker const&) = default;
+  tracker& operator=(tracker&&) = default;
+
+  int value;
+
+  static int count;
+};
+
+int tracker::count = 0;
+
+struct exception { };
+
+struct throwing_construction
+{
+  explicit throwing_construction(bool propagate) : propagate(propagate) { }
+
+  throwing_construction(throwing_construction const& other)
+  : propagate(other.propagate)
+  {
+    if(propagate)
+      throw exception {};
+  }
+
+  bool propagate;
+};
+
+int main()
+{
+  // [20.5.4.1] Constructors
+
+  {
+    auto i = 0x1234ABCDF1E2D3C4;
+    std::experimental::optional<long> o { i };
+    VERIFY( o );
+    VERIFY( *o == 0x1234ABCDF1E2D3C4 );
+    VERIFY( i == 0x1234ABCDF1E2D3C4 );
+  }
+
+  {
+    auto i = 0x1234ABCDF1E2D3C4;
+    std::experimental::optional<long> o = i;
+    VERIFY( o );
+    VERIFY( *o == 0x1234ABCDF1E2D3C4 );
+    VERIFY( i == 0x1234ABCDF1E2D3C4 );
+  }
+
+  {
+    auto i = 0x1234ABCDF1E2D3C4;
+    std::experimental::optional<long> o = { i };
+    VERIFY( o );
+    VERIFY( *o == 0x1234ABCDF1E2D3C4 );
+    VERIFY( i == 0x1234ABCDF1E2D3C4 );
+  }
+
+  {
+    auto i = 0x1234ABCDF1E2D3C4;
+    std::experimental::optional<long> o { std::move(i) };
+    VERIFY( o );
+    VERIFY( *o == 0x1234ABCDF1E2D3C4 );
+    VERIFY( i == 0x1234ABCDF1E2D3C4 );
+  }
+
+  {
+    auto i = 0x1234ABCDF1E2D3C4;
+    std::experimental::optional<long> o = std::move(i);
+    VERIFY( o );
+    VERIFY( *o == 0x1234ABCDF1E2D3C4 );
+    VERIFY( i == 0x1234ABCDF1E2D3C4 );
+  }
+
+  {
+    auto i = 0x1234ABCDF1E2D3C4;
+    std::experimental::optional<long> o = { std::move(i) };
+    VERIFY( o );
+    VERIFY( *o == 0x1234ABCDF1E2D3C4 );
+    VERIFY( i == 0x1234ABCDF1E2D3C4 );
+  }
+
+  {
+    std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
+    std::experimental::optional<std::vector<int>> o { v };
+    VERIFY( !v.empty() );
+    VERIFY( o->size() == 6 );
+  }
+
+  {
+    std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
+    std::experimental::optional<std::vector<int>> o = v;
+    VERIFY( !v.empty() );
+    VERIFY( o->size() == 6 );
+  }
+
+  {
+    std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
+    std::experimental::optional<std::vector<int>> o { v };
+    VERIFY( !v.empty() );
+    VERIFY( o->size() == 6 );
+  }
+
+  {
+    std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
+    std::experimental::optional<std::vector<int>> o { std::move(v) };
+    VERIFY( v.empty() );
+    VERIFY( o->size() == 6 );
+  }
+
+  {
+    std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
+    std::experimental::optional<std::vector<int>> o = std::move(v);
+    VERIFY( v.empty() );
+    VERIFY( o->size() == 6 );
+  }
+
+  {
+    std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
+    std::experimental::optional<std::vector<int>> o { std::move(v) };
+    VERIFY( v.empty() );
+    VERIFY( o->size() == 6 );
+  }
+
+  {
+    tracker t { 333 };
+    std::experimental::optional<tracker> o = t;
+    VERIFY( o->value == 333 );
+    VERIFY( tracker::count == 2 );
+    VERIFY( t.value == 333 );
+  }
+
+  {
+    tracker t { 333 };
+    std::experimental::optional<tracker> o = std::move(t);
+    VERIFY( o->value == 333 );
+    VERIFY( tracker::count == 2 );
+    VERIFY( t.value == -1 );
+  }
+
+  enum outcome { nothrow, caught, bad_catch };
+
+  {
+    outcome result = nothrow;
+    throwing_construction t { false };
+
+    try
+    {
+      std::experimental::optional<throwing_construction> o { t };
+    }
+    catch(exception const&)
+    { result = caught; }
+    catch(...)
+    { result = bad_catch; }
+
+    VERIFY( result == nothrow );
+  }
+
+  {
+    outcome result = nothrow;
+    throwing_construction t { true };
+
+    try
+    {
+      std::experimental::optional<throwing_construction> o { t };
+    }
+    catch(exception const&)
+    { result = caught; }
+    catch(...)
+    { result = bad_catch; }
+
+    VERIFY( result == caught );
+  }
+
+  {
+    outcome result = nothrow;
+    throwing_construction t { false };
+
+    try
+    {
+      std::experimental::optional<throwing_construction> o { std::move(t) };
+    }
+    catch(exception const&)
+    { result = caught; }
+    catch(...)
+    { result = bad_catch; }
+
+    VERIFY( result == nothrow );
+  }
+
+  {
+    outcome result = nothrow;
+    throwing_construction t { true };
+
+    try
+    {
+      std::experimental::optional<throwing_construction> o { std::move(t) };
+    }
+    catch(exception const&)
+    { result = caught; }
+    catch(...)
+    { result = bad_catch; }
+
+    VERIFY( result == caught );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/cons/default.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/cons/default.cc
new file mode 100644
index 0000000..d437cd8
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/cons/default.cc
@@ -0,0 +1,42 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+int main()
+{
+  // [20.5.4.1] Constructors
+
+  {
+    constexpr std::experimental::optional<int> o;
+    static_assert( !o, "" );
+  }
+
+  {
+    constexpr std::experimental::optional<int> o {};
+    static_assert( !o, "" );
+  }
+
+  {
+    constexpr std::experimental::optional<int> o = {};
+    static_assert( !o, "" );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/cons/value.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/cons/value.cc
new file mode 100644
index 0000000..98e0a22
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/cons/value.cc
@@ -0,0 +1,69 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+int main()
+{
+  // [20.5.4.1] Constructors
+
+  {
+    constexpr auto i = 0x1234ABCDF1E2D3C4;
+    constexpr std::experimental::optional<long> o { i };
+    static_assert( o, "" );
+    static_assert( *o == 0x1234ABCDF1E2D3C4, "" );
+  }
+
+  {
+    constexpr auto i = 0x1234ABCDF1E2D3C4;
+    constexpr std::experimental::optional<long> o = i;
+    static_assert( o, "" );
+    static_assert( *o == 0x1234ABCDF1E2D3C4, "" );
+  }
+
+  {
+    constexpr auto i = 0x1234ABCDF1E2D3C4;
+    constexpr std::experimental::optional<long> o = { i };
+    static_assert( o, "" );
+    static_assert( *o == 0x1234ABCDF1E2D3C4, "" );
+  }
+
+  {
+    constexpr auto i = 0x1234ABCDF1E2D3C4;
+    constexpr std::experimental::optional<long> o { std::move(i) };
+    static_assert( o, "" );
+    static_assert( *o == 0x1234ABCDF1E2D3C4, "" );
+  }
+
+  {
+    constexpr auto i = 0x1234ABCDF1E2D3C4;
+    constexpr std::experimental::optional<long> o = std::move(i);
+    static_assert( o, "" );
+    static_assert( *o == 0x1234ABCDF1E2D3C4, "" );
+  }
+
+  {
+    constexpr auto i = 0x1234ABCDF1E2D3C4;
+    constexpr std::experimental::optional<long> o = { std::move(i) };
+    static_assert( o, "" );
+    static_assert( *o == 0x1234ABCDF1E2D3C4, "" );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/in_place.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/in_place.cc
new file mode 100644
index 0000000..f2bb8fd
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/in_place.cc
@@ -0,0 +1,43 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+int main()
+{
+  // [20.5.5] In-place construction
+  static_assert( std::is_same<decltype(std::experimental::in_place), const std::experimental::in_place_t>(), "" );
+  static_assert( std::is_empty<std::experimental::in_place_t>(), "" );
+
+  {
+    constexpr std::experimental::optional<int> o { std::experimental::in_place };
+    static_assert( o, "" );
+    static_assert( *o == int {}, "" );
+
+    static_assert( !std::is_convertible<std::experimental::in_place_t, std::experimental::optional<int>>(), "" );
+  }
+
+  {
+    constexpr std::experimental::optional<int> o { std::experimental::in_place, 42 };
+    static_assert( o, "" );
+    static_assert( *o == 42, "" );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/make_optional.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/make_optional.cc
new file mode 100644
index 0000000..4b59ba9
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/make_optional.cc
@@ -0,0 +1,33 @@ 
+// { dg-options "-std=gnu++1y" }
+// XFAIL pending resolution of PR libstdc++/58777
+// { dg-do compile { xfail *-*-* } }
+// { dg-excess-errors "" }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+int main()
+{
+  constexpr int i = 42;
+  constexpr auto o = std::experimental::make_optional(i);
+  static_assert( std::is_same<decltype(o), const std::experimental::optional<int>>(), "" );
+  static_assert( o && *o == 42, "" );
+  static_assert( &*o != &i, "" );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/nullopt.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/nullopt.cc
new file mode 100644
index 0000000..08566e1
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/nullopt.cc
@@ -0,0 +1,46 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+int main()
+{
+  // [20.5.6] Disengaged state indicator
+  static_assert( std::is_same<decltype(std::experimental::nullopt), const std::experimental::nullopt_t>(), "" );
+  static_assert( std::is_empty<std::experimental::nullopt_t>(), "" );
+  static_assert( std::is_literal_type<std::experimental::nullopt_t>(), "" );
+  static_assert( !std::is_default_constructible<std::experimental::nullopt_t>(), "" );
+
+  {
+    constexpr std::experimental::optional<int> o = std::experimental::nullopt;
+    static_assert( !o, "" );
+  }
+
+  {
+    constexpr std::experimental::optional<int> o = { std::experimental::nullopt };
+    static_assert( !o, "" );
+  }
+
+  {
+    constexpr std::experimental::optional<int> o { std::experimental::nullopt };
+    static_assert( !o, "" );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/1.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/1.cc
new file mode 100644
index 0000000..5943a35
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/1.cc
@@ -0,0 +1,33 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+  int i;
+};
+
+int main()
+{
+  constexpr std::experimental::optional<value_type> o { value_type { 51 } };
+  static_assert( (*o).i == 51, "" );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/2.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/2.cc
new file mode 100644
index 0000000..3df68d3
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/2.cc
@@ -0,0 +1,37 @@ 
+// { dg-options "-std=gnu++1y" }
+// XFAIL pending resolution of PR libstdc++/58777
+// { dg-do compile { xfail *-*-* } }
+// { dg-excess-errors "" }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+  int i;
+};
+
+int main()
+{
+  constexpr std::experimental::optional<value_type> o { value_type { 51 } };
+  static_assert( o->i == 51, "" );
+  static_assert( o->i == (*o).i, "" );
+  static_assert( &o->i == &(*o).i, "" );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/3.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/3.cc
new file mode 100644
index 0000000..6528d99
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/3.cc
@@ -0,0 +1,37 @@ 
+// { dg-options "-std=gnu++1y" }
+// XFAIL pending resolution of PR libstdc++/58777
+// { dg-do compile { xfail *-*-* } }
+// { dg-excess-errors "" }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+  int i;
+};
+
+int main()
+{
+  constexpr std::experimental::optional<value_type> o { value_type { 51 } };
+  static_assert( o.value().i == 51, "" );
+  static_assert( o.value().i == (*o).i, "" );
+  static_assert( &o.value().i == &(*o).i, "" );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/4.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/4.cc
new file mode 100644
index 0000000..9098c0c
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/4.cc
@@ -0,0 +1,35 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+  int i;
+};
+
+int main()
+{
+  constexpr std::experimental::optional<value_type> o { value_type { 51 } };
+  constexpr value_type fallback { 3 };
+  static_assert( o.value_or(fallback).i == 51, "" );
+  static_assert( o.value_or(fallback).i == (*o).i, "" );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/5.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/5.cc
new file mode 100644
index 0000000..e86d040
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/5.cc
@@ -0,0 +1,40 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+  int i;
+};
+
+int main()
+{
+  {
+    constexpr std::experimental::optional<value_type> o = std::experimental::nullopt;
+    static_assert( !o, "" );
+  }
+
+  {
+    constexpr std::experimental::optional<value_type> o { value_type { 51 } };
+    static_assert( o, "" );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/1.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/1.cc
new file mode 100644
index 0000000..591eb13
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/1.cc
@@ -0,0 +1,99 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+namespace ns
+{
+  struct value_type
+  {
+    int i;
+    const char* s;
+  };
+
+  constexpr bool
+  strcmp(const char* lhs, const char* rhs)
+  {
+    return *lhs == *rhs && (!*lhs || strcmp(lhs + 1, rhs + 1));
+  }
+
+  constexpr bool
+  strrel(const char* lhs, const char* rhs)
+  {
+    return (*rhs && (!*lhs || (*lhs < *rhs)))
+      || ((*lhs && *rhs && !(*rhs < *lhs)) && strrel(lhs + 1, rhs + 1));
+  }
+
+  constexpr bool
+  operator==(value_type const& lhs, value_type const& rhs)
+  { return (lhs.i == rhs.i) && strcmp(lhs.s, rhs.s); }
+
+  constexpr bool
+  operator!=(value_type const& lhs, value_type const& rhs)
+  { return !(lhs == rhs); }
+
+  constexpr bool
+  operator<(value_type const& lhs, value_type const& rhs)
+  { return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); }
+
+} // namespace ns
+
+int main()
+{
+  using ns::value_type;
+  using O = std::experimental::optional<value_type>;
+
+  {
+    constexpr O o, p;
+    static_assert( o == p, "" );
+    static_assert( !(o != p), "" );
+  }
+
+  {
+    constexpr O o { value_type { 42, "forty-two" } }, p;
+    static_assert( !(o == p), "" );
+    static_assert( o != p, "" );
+  }
+
+  {
+    constexpr O o, p { value_type { 42, "forty-two" } };
+    static_assert( !(o == p), "" );
+    static_assert( o != p, "" );
+  }
+
+  {
+    constexpr O o { value_type { 11, "eleventy" } }, p { value_type { 42, "forty-two" } };
+    static_assert( !(o == p), "" );
+    static_assert( o != p, "" );
+  }
+
+  {
+    constexpr O o { value_type { 42, "forty-two" } }, p { value_type { 11, "eleventy" } };
+    static_assert( !(o == p), "" );
+    static_assert( o != p, "" );
+  }
+
+  {
+    constexpr O o { value_type { 42, "forty-two" } }, p { value_type { 42, "forty-two" } };
+    static_assert( o == p, "" );
+    static_assert( !(o != p), "" );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/2.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/2.cc
new file mode 100644
index 0000000..9bc140d
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/2.cc
@@ -0,0 +1,111 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+namespace ns
+{
+  struct value_type
+  {
+    int i;
+    const char* s;
+  };
+
+  constexpr bool
+  strcmp(const char* lhs, const char* rhs)
+  {
+    return *lhs == *rhs && (!*lhs || strcmp(lhs + 1, rhs + 1));
+  }
+
+  constexpr bool
+  strrel(const char* lhs, const char* rhs)
+  {
+    return (*rhs && (!*lhs || (*lhs < *rhs)))
+      || ((*lhs && *rhs && !(*rhs < *lhs)) && strrel(lhs + 1, rhs + 1));
+  }
+
+  constexpr bool
+  operator==(value_type const& lhs, value_type const& rhs)
+  { return (lhs.i == rhs.i) && strcmp(lhs.s, rhs.s); }
+
+  constexpr bool
+  operator!=(value_type const& lhs, value_type const& rhs)
+  { return !(lhs == rhs); }
+
+  constexpr bool
+  operator<(value_type const& lhs, value_type const& rhs)
+  { return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); }
+
+} // namespace ns
+
+int main()
+{
+  using ns::value_type;
+  using O = std::experimental::optional<value_type>;
+
+  {
+    constexpr O o, p;
+    static_assert( !(o < p), "" );
+    static_assert( !(o > p), "" );
+    static_assert( o <= p, "" );
+    static_assert( o >= p, "" );
+  }
+
+  {
+    constexpr O o { value_type { 42, "forty-two" } }, p;
+    static_assert( !(o < p), "" );
+    static_assert( o > p, "" );
+    static_assert( !(o <= p), "" );
+    static_assert( o >= p, "" );
+  }
+
+  {
+    constexpr O o, p { value_type { 42, "forty-two" } };
+    static_assert( o < p, "" );
+    static_assert( !(o > p), "" );
+    static_assert( o <= p, "" );
+    static_assert( !(o >= p), "" );
+  }
+
+  {
+    constexpr O o { value_type { 11, "eleventy" } }, p { value_type { 42, "forty-two" } };
+    static_assert( o < p, "" );
+    static_assert( !(o > p), "" );
+    static_assert( o <= p, "" );
+    static_assert( !(o >= p), "" );
+  }
+
+  {
+    constexpr O o { value_type { 42, "forty-two" } }, p { value_type { 11, "eleventy" } };
+    static_assert( !(o < p), "" );
+    static_assert( o > p, "" );
+    static_assert( !(o <= p), "" );
+    static_assert( o >= p, "" );
+  }
+
+  {
+    constexpr O o { value_type { 42, "forty-two" } }, p { value_type { 42, "forty-two" } };
+    static_assert( !(o < p), "" );
+    static_assert( !(o > p), "" );
+    static_assert( o <= p, "" );
+    static_assert( o >= p, "" );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/3.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/3.cc
new file mode 100644
index 0000000..6ffd2b6
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/3.cc
@@ -0,0 +1,89 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+namespace ns
+{
+  struct value_type
+  {
+    int i;
+    const char* s;
+  };
+
+  constexpr bool
+  strcmp(const char* lhs, const char* rhs)
+  {
+    return *lhs == *rhs && (!*lhs || strcmp(lhs + 1, rhs + 1));
+  }
+
+  constexpr bool
+  strrel(const char* lhs, const char* rhs)
+  {
+    return (*rhs && (!*lhs || (*lhs < *rhs)))
+      || ((*lhs && *rhs && !(*rhs < *lhs)) && strrel(lhs + 1, rhs + 1));
+  }
+
+  constexpr bool
+  operator==(value_type const& lhs, value_type const& rhs)
+  { return (lhs.i == rhs.i) && strcmp(lhs.s, rhs.s); }
+
+  constexpr bool
+  operator!=(value_type const& lhs, value_type const& rhs)
+  { return !(lhs == rhs); }
+
+  constexpr bool
+  operator<(value_type const& lhs, value_type const& rhs)
+  { return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); }
+
+} // namespace ns
+
+int main()
+{
+  using ns::value_type;
+  using O = std::experimental::optional<value_type>;
+
+  constexpr value_type reference { 42, "forty-two" };
+
+  {
+    constexpr O o;
+    static_assert( !(o == reference), "" );
+    static_assert( !(reference == o), "" );
+    static_assert( o != reference, "" );
+    static_assert( reference != o, "" );
+  }
+
+  {
+    constexpr O o { value_type { 11, "eleventy" } };
+    static_assert( !(o == reference), "" );
+    static_assert( !(reference == o), "" );
+    static_assert( o != reference, "" );
+    static_assert( reference != o, "" );
+  }
+
+  {
+    constexpr O o { value_type { 42, "forty-two" } };
+    static_assert( o == reference, "" );
+    static_assert( reference == o, "" );
+    static_assert( !(o != reference), "" );
+    static_assert( !(reference != o), "" );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/4.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/4.cc
new file mode 100644
index 0000000..8df602c
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/4.cc
@@ -0,0 +1,101 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+namespace ns
+{
+  struct value_type
+  {
+    int i;
+    const char* s;
+  };
+
+  constexpr bool
+  strcmp(const char* lhs, const char* rhs)
+  {
+    return *lhs == *rhs && (!*lhs || strcmp(lhs + 1, rhs + 1));
+  }
+
+  constexpr bool
+  strrel(const char* lhs, const char* rhs)
+  {
+    return (*rhs && (!*lhs || (*lhs < *rhs)))
+      || ((*lhs && *rhs && !(*rhs < *lhs)) && strrel(lhs + 1, rhs + 1));
+  }
+
+  constexpr bool
+  operator==(value_type const& lhs, value_type const& rhs)
+  { return (lhs.i == rhs.i) && strcmp(lhs.s, rhs.s); }
+
+  constexpr bool
+  operator!=(value_type const& lhs, value_type const& rhs)
+  { return !(lhs == rhs); }
+
+  constexpr bool
+  operator<(value_type const& lhs, value_type const& rhs)
+  { return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); }
+
+} // namespace ns
+
+int main()
+{
+  using ns::value_type;
+  using O = std::experimental::optional<value_type>;
+
+  constexpr value_type reference { 42, "forty-two" };
+
+  {
+    constexpr O o;
+    static_assert( o < reference, "" );
+    static_assert( !(reference < o), "" );
+    static_assert( !(o > reference), "" );
+    static_assert( reference > o, "" );
+    static_assert( o <= reference, "" );
+    static_assert( !(reference <= o), "" );
+    static_assert( !(o >= reference), "" );
+    static_assert( reference >= o, "" );
+  }
+
+  {
+    constexpr O o { value_type { 11, "eleventy" } };
+    static_assert( o < reference, "" );
+    static_assert( !(reference < o), "" );
+    static_assert( !(o > reference), "" );
+    static_assert( reference > o, "" );
+    static_assert( o <= reference, "" );
+    static_assert( !(reference <= o), "" );
+    static_assert( !(o >= reference), "" );
+    static_assert( reference >= o, "" );
+  }
+
+  {
+    constexpr O o { value_type { 42, "forty-two" } };
+    static_assert( !(o < reference), "" );
+    static_assert( !(reference < o), "" );
+    static_assert( !(o > reference), "" );
+    static_assert( !(reference > o), "" );
+    static_assert( o <= reference, "" );
+    static_assert( reference <= o, "" );
+    static_assert( o >= reference, "" );
+    static_assert( reference >= o, "" );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/5.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/5.cc
new file mode 100644
index 0000000..241a71b
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/5.cc
@@ -0,0 +1,80 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+namespace ns
+{
+  struct value_type
+  {
+    int i;
+    const char* s;
+  };
+
+  constexpr bool
+  strcmp(const char* lhs, const char* rhs)
+  {
+    return *lhs == *rhs && (!*lhs || strcmp(lhs + 1, rhs + 1));
+  }
+
+  constexpr bool
+  strrel(const char* lhs, const char* rhs)
+  {
+    return (*rhs && (!*lhs || (*lhs < *rhs)))
+      || ((*lhs && *rhs && !(*rhs < *lhs)) && strrel(lhs + 1, rhs + 1));
+  }
+
+  constexpr bool
+  operator==(value_type const& lhs, value_type const& rhs)
+  { return (lhs.i == rhs.i) && strcmp(lhs.s, rhs.s); }
+
+  constexpr bool
+  operator!=(value_type const& lhs, value_type const& rhs)
+  { return !(lhs == rhs); }
+
+  constexpr bool
+  operator<(value_type const& lhs, value_type const& rhs)
+  { return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); }
+
+} // namespace ns
+
+int main()
+{
+  using ns::value_type;
+  using O = std::experimental::optional<value_type>;
+  using std::experimental::nullopt;
+
+  {
+    constexpr O o;
+    static_assert( o == nullopt, "" );
+    static_assert( nullopt == o, "" );
+    static_assert( !(o != nullopt), "" );
+    static_assert( !(nullopt != o), "" );
+  }
+
+  {
+    constexpr O o { std::experimental::in_place };
+    static_assert( !(o == nullopt), "" );
+    static_assert( !(nullopt == o), "" );
+    static_assert( o != nullopt, "" );
+    static_assert( nullopt != o, "" );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/6.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/6.cc
new file mode 100644
index 0000000..a4282d8
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/relops/6.cc
@@ -0,0 +1,88 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do compile }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+namespace ns
+{
+  struct value_type
+  {
+    int i;
+    const char* s;
+  };
+
+  constexpr bool
+  strcmp(const char* lhs, const char* rhs)
+  {
+    return *lhs == *rhs && (!*lhs || strcmp(lhs + 1, rhs + 1));
+  }
+
+  constexpr bool
+  strrel(const char* lhs, const char* rhs)
+  {
+    return (*rhs && (!*lhs || (*lhs < *rhs)))
+      || ((*lhs && *rhs && !(*rhs < *lhs)) && strrel(lhs + 1, rhs + 1));
+  }
+
+  constexpr bool
+  operator==(value_type const& lhs, value_type const& rhs)
+  { return (lhs.i == rhs.i) && strcmp(lhs.s, rhs.s); }
+
+  constexpr bool
+  operator!=(value_type const& lhs, value_type const& rhs)
+  { return !(lhs == rhs); }
+
+  constexpr bool
+  operator<(value_type const& lhs, value_type const& rhs)
+  { return (lhs.i < rhs.i) || (!(rhs.i < lhs.i) && strrel(lhs.s, rhs.s)); }
+
+} // namespace ns
+
+int main()
+{
+  using ns::value_type;
+  using O = std::experimental::optional<value_type>;
+  using std::experimental::nullopt;
+
+  {
+    constexpr O o;
+    static_assert( !(o < nullopt), "" );
+    static_assert( !(nullopt < o), "" );
+    static_assert( !(o > nullopt), "" );
+    static_assert( !(nullopt > o), "" );
+    static_assert( o <= nullopt, "" );
+    static_assert( nullopt <= o, "" );
+    static_assert( o >= nullopt, "" );
+    static_assert( nullopt >= o, "" );
+  }
+
+  {
+    constexpr O o { std::experimental::in_place };
+    static_assert( !(o < nullopt), "" );
+    static_assert( nullopt < o, "" );
+    static_assert( o > nullopt, "" );
+    static_assert( !(nullopt > o), "" );
+    static_assert( !(o <= nullopt), "" );
+    static_assert( nullopt <= o, "" );
+    static_assert( o >= nullopt, "" );
+    static_assert( !(nullopt >= o), "" );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/in_place.cc b/libstdc++-v3/testsuite/experimental/optional/in_place.cc
new file mode 100644
index 0000000..ceaa97d
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/in_place.cc
@@ -0,0 +1,66 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+#include <vector>
+
+int main()
+{
+  // [20.5.5] In-place construction
+  static_assert( std::is_same<decltype(std::experimental::in_place), const std::experimental::in_place_t>(), "" );
+  static_assert( std::is_empty<std::experimental::in_place_t>(), "" );
+
+  {
+    std::experimental::optional<int> o { std::experimental::in_place };
+    VERIFY( o );
+    VERIFY( *o == int() );
+
+    static_assert( !std::is_convertible<std::experimental::in_place_t, std::experimental::optional<int>>(), "" );
+  }
+
+  {
+    std::experimental::optional<int> o { std::experimental::in_place, 42 };
+    VERIFY( o );
+    VERIFY( *o == 42 );
+  }
+
+  {
+    std::experimental::optional<std::vector<int>> o { std::experimental::in_place, 18, 4 };
+    VERIFY( o );
+    VERIFY( o->size() == 18 );
+    VERIFY( (*o)[17] == 4 );
+  }
+
+  {
+    std::experimental::optional<std::vector<int>> o { std::experimental::in_place, { 18, 4 } };
+    VERIFY( o );
+    VERIFY( o->size() == 2 );
+    VERIFY( (*o)[0] == 18 );
+  }
+
+  {
+    std::experimental::optional<std::vector<int>> o { std::experimental::in_place, { 18, 4 }, std::allocator<int> {} };
+    VERIFY( o );
+    VERIFY( o->size() == 2 );
+    VERIFY( (*o)[0] == 18 );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/make_optional.cc b/libstdc++-v3/testsuite/experimental/optional/make_optional.cc
new file mode 100644
index 0000000..90ebe6c
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/make_optional.cc
@@ -0,0 +1,31 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+int main()
+{
+  const int i = 42;
+  auto o = std::experimental::make_optional(i);
+  static_assert( std::is_same<decltype(o), std::experimental::optional<int>>(), "" );
+  VERIFY( o && *o == 42 );
+  VERIFY( &*o != &i );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/nullopt.cc b/libstdc++-v3/testsuite/experimental/optional/nullopt.cc
new file mode 100644
index 0000000..f1b1bb6
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/nullopt.cc
@@ -0,0 +1,46 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+int main()
+{
+  // [20.5.6] Disengaged state indicator
+  static_assert( std::is_same<decltype(std::experimental::nullopt), const std::experimental::nullopt_t>(), "" );
+  static_assert( std::is_empty<std::experimental::nullopt_t>(), "" );
+  static_assert( std::is_literal_type<std::experimental::nullopt_t>(), "" );
+  static_assert( !std::is_default_constructible<std::experimental::nullopt_t>(), "" );
+
+  {
+    std::experimental::optional<int> o = std::experimental::nullopt;
+    VERIFY( !o );
+  }
+
+  {
+    std::experimental::optional<int> o = { std::experimental::nullopt };
+    VERIFY( !o );
+  }
+
+  {
+    std::experimental::optional<int> o { std::experimental::nullopt };
+    VERIFY( !o );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/observers/1.cc b/libstdc++-v3/testsuite/experimental/optional/observers/1.cc
new file mode 100644
index 0000000..5ffa3a5
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/observers/1.cc
@@ -0,0 +1,33 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+  int i;
+};
+
+int main()
+{
+  std::experimental::optional<value_type> o { value_type { 51 } };
+  VERIFY( (*o).i == 51 );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/observers/2.cc b/libstdc++-v3/testsuite/experimental/optional/observers/2.cc
new file mode 100644
index 0000000..444a141
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/observers/2.cc
@@ -0,0 +1,35 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+  int i;
+};
+
+int main()
+{
+  std::experimental::optional<value_type> o { value_type { 51 } };
+  VERIFY( o->i == 51 );
+  VERIFY( o->i == (*o).i );
+  VERIFY( &o->i == &(*o).i );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/observers/3.cc b/libstdc++-v3/testsuite/experimental/optional/observers/3.cc
new file mode 100644
index 0000000..b82142d
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/observers/3.cc
@@ -0,0 +1,58 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+  int i;
+};
+
+int main()
+{
+  {
+    std::experimental::optional<value_type> o { value_type { 51 } };
+    VERIFY( o.value().i == 51 );
+    VERIFY( o.value().i == (*o).i );
+    VERIFY( &o.value().i == &(*o).i );
+  }
+
+  {
+    enum outcome_type { nothrow, caught, bad_catch };
+
+    outcome_type outcome {};
+    std::experimental::optional<value_type> o = std::experimental::nullopt;
+    bool called = false;
+    auto const eat = [&called](int) { called = true; };
+
+    try
+    {
+      eat(o.value().i);
+    }
+    catch(std::experimental::bad_optional_access const&)
+    { outcome = caught; }
+    catch(...)
+    { outcome = bad_catch; }
+
+    VERIFY( outcome == caught );
+    VERIFY( !called );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/observers/4.cc b/libstdc++-v3/testsuite/experimental/optional/observers/4.cc
new file mode 100644
index 0000000..3b43c77
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/observers/4.cc
@@ -0,0 +1,35 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+  int i;
+};
+
+int main()
+{
+  std::experimental::optional<value_type> o { value_type { 51 } };
+  value_type fallback { 3 };
+  VERIFY( o.value_or(fallback).i == 51 );
+  VERIFY( o.value_or(fallback).i == (*o).i );
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/observers/5.cc b/libstdc++-v3/testsuite/experimental/optional/observers/5.cc
new file mode 100644
index 0000000..c6957ec
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/observers/5.cc
@@ -0,0 +1,40 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct value_type
+{
+  int i;
+};
+
+int main()
+{
+  {
+    std::experimental::optional<value_type> o = std::experimental::nullopt;
+    VERIFY( !o );
+  }
+
+  {
+    std::experimental::optional<value_type> o { value_type { 51 } };
+    VERIFY( o );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/relops/1.cc b/libstdc++-v3/testsuite/experimental/optional/relops/1.cc
new file mode 100644
index 0000000..6f0c60f
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/relops/1.cc
@@ -0,0 +1,89 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+#include <tuple>
+#include <string>
+
+namespace ns
+{
+  struct value_type
+  {
+    int i;
+    std::string s;
+  };
+
+  bool
+  operator==(value_type const& lhs, value_type const& rhs)
+  { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); }
+
+  bool
+  operator!=(value_type const& lhs, value_type const& rhs)
+  { return !(lhs == rhs); }
+
+  bool
+  operator<(value_type const& lhs, value_type const& rhs)
+  { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); }
+
+} // namespace ns
+
+int main()
+{
+  using ns::value_type;
+  using O = std::experimental::optional<value_type>;
+
+  {
+    O o, p;
+    VERIFY( o == p );
+    VERIFY( !(o != p) );
+  }
+
+  {
+    O o { value_type { 42, "forty-two" } }, p;
+    VERIFY( !(o == p) );
+    VERIFY( o != p );
+  }
+
+  {
+    O o, p { value_type { 42, "forty-two" } };
+    VERIFY( !(o == p) );
+    VERIFY( o != p );
+  }
+
+  {
+    O o { value_type { 11, "eleventy" } }, p { value_type { 42, "forty-two" } };
+    VERIFY( !(o == p) );
+    VERIFY( o != p );
+  }
+
+  {
+    O o { value_type { 42, "forty-two" } }, p { value_type { 11, "eleventy" } };
+    VERIFY( !(o == p) );
+    VERIFY( o != p );
+  }
+
+  {
+    O o { value_type { 42, "forty-two" } }, p { value_type { 42, "forty-two" } };
+    VERIFY( o == p );
+    VERIFY( !(o != p) );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/relops/2.cc b/libstdc++-v3/testsuite/experimental/optional/relops/2.cc
new file mode 100644
index 0000000..b1ae705
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/relops/2.cc
@@ -0,0 +1,101 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+#include <tuple>
+#include <string>
+
+namespace ns
+{
+  struct value_type
+  {
+    int i;
+    std::string s;
+  };
+
+  bool
+  operator==(value_type const& lhs, value_type const& rhs)
+  { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); }
+
+  bool
+  operator!=(value_type const& lhs, value_type const& rhs)
+  { return !(lhs == rhs); }
+
+  bool
+  operator<(value_type const& lhs, value_type const& rhs)
+  { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); }
+
+} // namespace ns
+
+int main()
+{
+  using ns::value_type;
+  using O = std::experimental::optional<value_type>;
+
+  {
+    O o, p;
+    VERIFY( !(o < p) );
+    VERIFY( !(o > p) );
+    VERIFY( o <= p );
+    VERIFY( o >= p );
+  }
+
+  {
+    O o { value_type { 42, "forty-two" } }, p;
+    VERIFY( !(o < p) );
+    VERIFY( o > p );
+    VERIFY( !(o <= p) );
+    VERIFY( o >= p );
+  }
+
+  {
+    O o, p { value_type { 42, "forty-two" } };
+    VERIFY( o < p );
+    VERIFY( !(o > p) );
+    VERIFY( o <= p );
+    VERIFY( !(o >= p) );
+  }
+
+  {
+    O o { value_type { 11, "eleventy" } }, p { value_type { 42, "forty-two" } };
+    VERIFY( o < p );
+    VERIFY( !(o > p) );
+    VERIFY( o <= p );
+    VERIFY( !(o >= p) );
+  }
+
+  {
+    O o { value_type { 42, "forty-two" } }, p { value_type { 11, "eleventy" } };
+    VERIFY( !(o < p) );
+    VERIFY( o > p );
+    VERIFY( !(o <= p) );
+    VERIFY( o >= p );
+  }
+
+  {
+    O o { value_type { 42, "forty-two" } }, p { value_type { 42, "forty-two" } };
+    VERIFY( !(o < p) );
+    VERIFY( !(o > p) );
+    VERIFY( o <= p );
+    VERIFY( o >= p );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/relops/3.cc b/libstdc++-v3/testsuite/experimental/optional/relops/3.cc
new file mode 100644
index 0000000..6b361df
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/relops/3.cc
@@ -0,0 +1,79 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+#include <tuple>
+#include <string>
+
+namespace ns
+{
+  struct value_type
+  {
+    int i;
+    std::string s;
+  };
+
+  bool
+  operator==(value_type const& lhs, value_type const& rhs)
+  { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); }
+
+  bool
+  operator!=(value_type const& lhs, value_type const& rhs)
+  { return !(lhs == rhs); }
+
+  bool
+  operator<(value_type const& lhs, value_type const& rhs)
+  { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); }
+
+} // namespace ns
+
+int main()
+{
+  using ns::value_type;
+  using O = std::experimental::optional<value_type>;
+
+  value_type const reference { 42, "forty-two" };
+
+  {
+    O o;
+    VERIFY( !(o == reference) );
+    VERIFY( !(reference == o) );
+    VERIFY( o != reference );
+    VERIFY( reference != o );
+  }
+
+  {
+    O o { value_type { 11, "eleventy" } };
+    VERIFY( !(o == reference) );
+    VERIFY( !(reference == o) );
+    VERIFY( o != reference );
+    VERIFY( reference != o );
+  }
+
+  {
+    O o { value_type { 42, "forty-two" } };
+    VERIFY( o == reference );
+    VERIFY( reference == o );
+    VERIFY( !(o != reference) );
+    VERIFY( !(reference != o) );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/relops/4.cc b/libstdc++-v3/testsuite/experimental/optional/relops/4.cc
new file mode 100644
index 0000000..9f316f1
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/relops/4.cc
@@ -0,0 +1,91 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+#include <tuple>
+#include <string>
+
+namespace ns
+{
+  struct value_type
+  {
+    int i;
+    std::string s;
+  };
+
+  bool
+  operator==(value_type const& lhs, value_type const& rhs)
+  { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); }
+
+  bool
+  operator!=(value_type const& lhs, value_type const& rhs)
+  { return !(lhs == rhs); }
+
+  bool
+  operator<(value_type const& lhs, value_type const& rhs)
+  { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); }
+
+} // namespace ns
+
+int main()
+{
+  using ns::value_type;
+  using O = std::experimental::optional<value_type>;
+
+  value_type const reference { 42, "forty-two" };
+
+  {
+    O o;
+    VERIFY( o < reference );
+    VERIFY( !(reference < o) );
+    VERIFY( !(o > reference) );
+    VERIFY( reference > o );
+    VERIFY( o <= reference );
+    VERIFY( !(reference <= o) );
+    VERIFY( !(o >= reference) );
+    VERIFY( reference >= o );
+  }
+
+  {
+    O o { value_type { 11, "eleventy" } };
+    VERIFY( o < reference );
+    VERIFY( !(reference < o) );
+    VERIFY( !(o > reference) );
+    VERIFY( reference > o );
+    VERIFY( o <= reference );
+    VERIFY( !(reference <= o) );
+    VERIFY( !(o >= reference) );
+    VERIFY( reference >= o );
+  }
+
+  {
+    O o { value_type { 42, "forty-two" } };
+    VERIFY( !(o < reference) );
+    VERIFY( !(reference < o) );
+    VERIFY( !(o > reference) );
+    VERIFY( !(reference > o) );
+    VERIFY( o <= reference );
+    VERIFY( reference <= o );
+    VERIFY( o >= reference );
+    VERIFY( reference >= o );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/relops/5.cc b/libstdc++-v3/testsuite/experimental/optional/relops/5.cc
new file mode 100644
index 0000000..c7b27bb
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/relops/5.cc
@@ -0,0 +1,70 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+#include <tuple>
+#include <string>
+
+namespace ns
+{
+  struct value_type
+  {
+    int i;
+    std::string s;
+  };
+
+  bool
+  operator==(value_type const& lhs, value_type const& rhs)
+  { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); }
+
+  bool
+  operator!=(value_type const& lhs, value_type const& rhs)
+  { return !(lhs == rhs); }
+
+  bool
+  operator<(value_type const& lhs, value_type const& rhs)
+  { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); }
+
+} // namespace ns
+
+int main()
+{
+  using ns::value_type;
+  using O = std::experimental::optional<value_type>;
+  using std::experimental::nullopt;
+
+  {
+    O o;
+    VERIFY( o == nullopt );
+    VERIFY( nullopt == o );
+    VERIFY( !(o != nullopt) );
+    VERIFY( !(nullopt != o) );
+  }
+
+  {
+    O o { std::experimental::in_place };
+    VERIFY( !(o == nullopt) );
+    VERIFY( !(nullopt == o) );
+    VERIFY( o != nullopt );
+    VERIFY( nullopt != o );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/relops/6.cc b/libstdc++-v3/testsuite/experimental/optional/relops/6.cc
new file mode 100644
index 0000000..d8a4f6f
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/relops/6.cc
@@ -0,0 +1,78 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+#include <tuple>
+#include <string>
+
+namespace ns
+{
+  struct value_type
+  {
+    int i;
+    std::string s;
+  };
+
+  bool
+  operator==(value_type const& lhs, value_type const& rhs)
+  { return std::tie(lhs.i, lhs.s) == std::tie(rhs.i, rhs.s); }
+
+  bool
+  operator!=(value_type const& lhs, value_type const& rhs)
+  { return !(lhs == rhs); }
+
+  bool
+  operator<(value_type const& lhs, value_type const& rhs)
+  { return std::tie(lhs.i, lhs.s) < std::tie(rhs.i, rhs.s); }
+
+} // namespace ns
+
+int main()
+{
+  using ns::value_type;
+  using O = std::experimental::optional<value_type>;
+  using std::experimental::nullopt;
+
+  {
+    O o;
+    VERIFY( !(o < nullopt) );
+    VERIFY( !(nullopt < o) );
+    VERIFY( !(o > nullopt) );
+    VERIFY( !(nullopt > o) );
+    VERIFY( o <= nullopt );
+    VERIFY( nullopt <= o );
+    VERIFY( o >= nullopt );
+    VERIFY( nullopt >= o );
+  }
+
+  {
+    O o { std::experimental::in_place };
+    VERIFY( !(o < nullopt) );
+    VERIFY( nullopt < o );
+    VERIFY( o > nullopt );
+    VERIFY( !(nullopt > o) );
+    VERIFY( !(o <= nullopt) );
+    VERIFY( nullopt <= o );
+    VERIFY( o >= nullopt );
+    VERIFY( !(nullopt >= o) );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/requirements.cc b/libstdc++-v3/testsuite/experimental/optional/requirements.cc
new file mode 100644
index 0000000..c97cde5
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/requirements.cc
@@ -0,0 +1,256 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+#include <tuple>
+
+struct trivially_destructible
+{
+  trivially_destructible() = delete;
+  trivially_destructible(trivially_destructible const&) = delete;
+  trivially_destructible& operator=(trivially_destructible const&) = delete;
+  trivially_destructible(trivially_destructible&&) = delete;
+  trivially_destructible& operator=(trivially_destructible&&) = delete;
+  ~trivially_destructible() noexcept = default;
+};
+
+static_assert( std::is_trivially_destructible<trivially_destructible>(), "" );
+
+struct no_default_constructor
+{
+  no_default_constructor() = delete;
+};
+
+struct no_copy_constructor
+{
+  no_copy_constructor() = default;
+  no_copy_constructor(no_copy_constructor const&) = delete;
+  no_copy_constructor& operator=(no_copy_constructor const&) = default;
+  no_copy_constructor(no_copy_constructor&&) = default;
+  no_copy_constructor& operator=(no_copy_constructor&&) = default;
+};
+
+struct no_copy_assignment
+{
+  no_copy_assignment() = default;
+  no_copy_assignment(no_copy_assignment const&) = default;
+  no_copy_assignment(no_copy_assignment&&) = default;
+  no_copy_assignment& operator=(no_copy_assignment&&) = default;
+};
+
+struct no_move_constructor
+{
+  no_move_constructor() = default;
+  no_move_constructor(no_move_constructor const&) = default;
+  no_move_constructor& operator=(no_move_constructor const&) = default;
+  no_move_constructor(no_move_constructor&&) = delete;
+  no_move_constructor& operator=(no_move_constructor&&) = default;
+};
+
+struct no_move_assignment
+{
+  no_move_assignment() = default;
+  no_move_assignment(no_move_assignment const&) = default;
+  no_move_assignment& operator=(no_move_assignment const&) = default;
+  no_move_assignment(no_move_assignment&&) = default;
+  no_move_assignment& operator=(no_move_assignment&&) = delete;
+};
+
+struct no_copy : no_copy_constructor, no_copy_assignment { };
+struct no_move : no_move_constructor, no_move_assignment { };
+
+// Laxest possible model of a value type for optional
+struct only_destructible
+{
+  only_destructible(only_destructible&&) = delete;
+};
+
+int main()
+{
+  {
+    static_assert( std::is_trivially_destructible<std::experimental::optional<trivially_destructible>>(), "" );
+  }
+
+  {
+    using T = no_default_constructor;
+    using O = std::experimental::optional<T>;
+    static_assert( std::is_same<O::value_type, T>(), "" );
+    static_assert( std::is_default_constructible<O>(), "" );
+    { O o; }
+    static_assert( std::is_copy_constructible<O>(), "" );
+    { O o; auto copy = o; }
+    static_assert( std::is_copy_assignable<O>(), "" );
+    { O o, p; p = o; }
+    static_assert( std::is_move_constructible<O>(), "" );
+    { O o; auto moved_to = std::move(o); }
+    static_assert( std::is_move_assignable<O>(), "" );
+    { O o, p; p = std::move(o); }
+  }
+
+  {
+    using T = no_copy_constructor;
+    using O = std::experimental::optional<T>;
+    static_assert( std::is_same<O::value_type, T>(), "" );
+    static_assert( std::is_default_constructible<O>(), "" );
+    { O o; }
+    static_assert( !std::is_copy_constructible<O>(), "" );
+    static_assert( !std::is_copy_assignable<O>(), "" );
+    static_assert( std::is_move_constructible<O>(), "" );
+    { O o; auto moved_to = std::move(o); }
+    static_assert( std::is_move_assignable<O>(), "" );
+    { O o, p; p = std::move(o); }
+  }
+
+  {
+    using T = no_copy_assignment;
+    using O = std::experimental::optional<T>;
+    static_assert( std::is_default_constructible<O>(), "" );
+    { O o; }
+    static_assert( std::is_copy_constructible<O>(), "" );
+    { O o; auto copy = o; }
+    static_assert( !std::is_copy_assignable<O>(), "" );
+    static_assert( std::is_move_constructible<O>(), "" );
+    { O o; auto moved_to = std::move(o); }
+    static_assert( std::is_move_assignable<O>(), "" );
+    { O o, p; p = std::move(o); }
+  }
+
+  {
+    using T = no_copy;
+    using O = std::experimental::optional<T>;
+    static_assert( std::is_same<O::value_type, T>(), "" );
+    static_assert( std::is_default_constructible<O>(), "" );
+    { O o; }
+    static_assert( !std::is_copy_constructible<O>(), "" );
+    static_assert( !std::is_copy_assignable<O>(), "" );
+    static_assert( std::is_move_constructible<O>(), "" );
+    { O o; auto moved_to = std::move(o); }
+    static_assert( std::is_move_assignable<O>(), "" );
+    { O o, p; p = std::move(o); }
+  }
+
+  {
+    using T = no_move_constructor;
+    using O = std::experimental::optional<T>;
+    static_assert( std::is_same<O::value_type, T>(), "" );
+    static_assert( std::is_default_constructible<O>(), "" );
+    { O o; }
+    static_assert( std::is_copy_constructible<O>(), "" );
+    { O o; auto copy = o; }
+    static_assert( std::is_copy_assignable<O>(), "" );
+    /*
+     * T should be move constructible due to [12.8/11], which is a new rule in C++1y
+     * not yet implemented by GCC. Because there is already a special exception in C++11
+     * for the generation of the special members that GCC implements (at least some of the
+     * time), this does not affect the std::experimental::optional implementation however. So the assertion
+     * for T should be changed (or removed altogether) when the time comes, but the rest
+     * should however remain correct and unchanged.
+     */
+    static_assert( !std::is_move_constructible<T>(), "" );
+    static_assert( std::is_move_constructible<O>(), "" );
+    { O o; auto moved_to = std::move(o); }
+    static_assert( std::is_move_assignable<O>(), "" );
+    { O o, p; p = std::move(o); }
+  }
+
+  {
+    using T = no_move_assignment;
+    using O = std::experimental::optional<T>;
+    static_assert( std::is_same<O::value_type, T>(), "" );
+    static_assert( std::is_default_constructible<O>(), "" );
+    { O o; }
+    static_assert( std::is_copy_constructible<O>(), "" );
+    { O o; auto copy = o; }
+    static_assert( std::is_copy_assignable<O>(), "" );
+    { O o, p; p = o; }
+    static_assert( std::is_move_constructible<O>(), "" );
+    { O o; auto moved_to = std::move(o); }
+    /*
+     * Paragraph 23 of same leads to a similar situation but with respect to move
+     * assignment.
+     */
+    static_assert( !std::is_move_assignable<T>(), "" );
+    static_assert( std::is_move_assignable<O>(), "" );
+    { O o, p; p = std::move(o); }
+  }
+
+  {
+    using T = no_move;
+    using O = std::experimental::optional<T>;
+    static_assert( std::is_same<O::value_type, T>(), "" );
+    static_assert( std::is_default_constructible<O>(), "" );
+    { O o; }
+    static_assert( std::is_copy_constructible<O>(), "" );
+    { O o; auto copy = o; }
+    static_assert( std::is_copy_assignable<O>(), "" );
+    { O o, p; p = o; }
+    static_assert( std::is_move_constructible<O>(), "" );
+    { O o; auto moved_to = std::move(o); }
+    static_assert( std::is_move_assignable<O>(), "" );
+    { O o, p; p = std::move(o); }
+  }
+
+  {
+    using T = only_destructible;
+    using O = std::experimental::optional<T>;
+    static_assert( std::is_same<O::value_type, T>(), "" );
+    static_assert( std::is_default_constructible<O>(), "" );
+    { O o; }
+    static_assert( !std::is_copy_constructible<O>(), "" );
+    static_assert( !std::is_copy_assignable<O>(), "" );
+    static_assert( !std::is_move_constructible<O>(), "" );
+    static_assert( !std::is_move_assignable<O>(), "" );
+  }
+
+  {
+    /*
+     * Should not complain about 'invalid' specializations as long as
+     * they're not instantiated.
+     */
+    using A = std::experimental::optional<int&>;
+    using B = std::experimental::optional<int&&>;
+    using C1 = std::experimental::optional<std::experimental::in_place_t>;
+    using C2 = std::experimental::optional<std::experimental::in_place_t const>;
+    using C3 = std::experimental::optional<std::experimental::in_place_t volatile>;
+    using C4 = std::experimental::optional<std::experimental::in_place_t const volatile>;
+    using D1 = std::experimental::optional<std::experimental::nullopt_t>;
+    using D2 = std::experimental::optional<std::experimental::nullopt_t const>;
+    using D3 = std::experimental::optional<std::experimental::nullopt_t volatile>;
+    using D4 = std::experimental::optional<std::experimental::nullopt_t const volatile>;
+
+    using X = std::tuple<A, B, C1, C2, C3, C4, D1, D2, D3, D4>;
+  }
+
+  {
+    std::experimental::optional<const int> o { 42 };
+    static_assert( std::is_same<decltype(o)::value_type, const int>(), "" );
+    VERIFY( o );
+    VERIFY( *o == 42 );
+  }
+
+  {
+    constexpr std::experimental::optional<const int> o { 33 };
+    static_assert( std::is_same<decltype(o)::value_type, const int>(), "" );
+    static_assert( o, "" );
+    static_assert( *o == 33, "" );
+  }
+}
diff --git a/libstdc++-v3/testsuite/experimental/optional/swap/1.cc b/libstdc++-v3/testsuite/experimental/optional/swap/1.cc
new file mode 100644
index 0000000..95235b3
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/optional/swap/1.cc
@@ -0,0 +1,95 @@ 
+// { dg-options "-std=gnu++1y" }
+// { dg-do run }
+
+// Copyright (C) 2013 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <experimental/optional>
+#include <testsuite_hooks.h>
+
+struct exception {};
+
+int counter = 0;
+
+struct mixin_counter
+{
+  mixin_counter() { ++counter; }
+  mixin_counter(mixin_counter const&) { ++counter; }
+  ~mixin_counter() { --counter; }
+};
+
+namespace ns
+{
+
+struct value_type : private mixin_counter
+{
+  explicit value_type(int state) : state(state) { }
+  int state;
+};
+
+int swaps = 0;
+
+void
+swap(value_type& lhs, value_type& rhs)
+{
+  ++swaps;
+  using std::swap;
+  swap(lhs.state, rhs.state);
+}
+
+} // namespace ns
+
+int main()
+{
+  using O = std::experimental::optional<ns::value_type>;
+
+  VERIFY( ns::swaps == 0 );
+
+  {
+    O o, p;
+    swap(o, p);
+    VERIFY( !o );
+    VERIFY( !p );
+  }
+
+  {
+    O o { std::experimental::in_place, 45 }, p;
+    swap(o, p);
+    VERIFY( !o );
+    VERIFY( p && p->state == 45 );
+  }
+
+  {
+    O o, p { std::experimental::in_place, 45 };
+    swap(o, p);
+    VERIFY( o && o->state == 45 );
+    VERIFY( !p );
+  }
+
+  {
+    O o { std::experimental::in_place, 167 }, p { std::experimental::in_place, 999 };
+    VERIFY( ns::swaps == 0 );
+
+    swap(o, p);
+
+    VERIFY( o && o->state == 999 );
+    VERIFY( p && p->state == 167 );
+    VERIFY( ns::swaps == 1 );
+  }
+
+  VERIFY( counter == 0 );
+}
diff --git a/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp b/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
index 5e7ba3a..b6976fc 100644
--- a/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
+++ b/libstdc++-v3/testsuite/libstdc++-dg/conformance.exp
@@ -60,6 +60,7 @@  if {[info exists tests_file] && [file exists $tests_file]} {
     lappend subdirs "$srcdir/tr1"
     lappend subdirs "$srcdir/tr2"
     lappend subdirs "$srcdir/decimal"
+    lappend subdirs "$srcdir/experimental"
     verbose "subdirs are $subdirs"
 
     # Find all the tests.