aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPedro Alves <palves@redhat.com>2017-04-18 21:39:24 +0100
committerPedro Alves <palves@redhat.com>2017-04-18 23:49:33 +0100
commitd35d19584cf56a50b4833ff9c003597e01022f27 (patch)
treef6b290e1bf598870c929e5399df235b5e1ce17ae
parent22796e972f18c5601cecb0251222411a352836b6 (diff)
downloadgdb-d35d19584cf56a50b4833ff9c003597e01022f27.zip
gdb-d35d19584cf56a50b4833ff9c003597e01022f27.tar.gz
gdb-d35d19584cf56a50b4833ff9c003597e01022f27.tar.bz2
gdb::optional unit tests
I thought I'd add some unit tests to make sure gdb::optional behaved correctly, and started writing some, but then thought/realized that libstdc++ already has extensive testing for C++17 std::optional, which gdb::optional is a subset of, and thought why bother writing something from scratch. So I tried copying over a subset of libstdc++'s tests (that ones that cover the subset supported by gdb::optional), and was positively surprised that they mostly work OOTB. This did help shake out a few bugs from what I was implementing in the previous patch to gdb::optional. Still, it's a good chunk of code being copied over, so if people dislike this copying/duplication, I can drop this patch. gdb/ChangeLog: 2017-04-18 Pedro Alves <palves@redhat.com> * Makefile.in (SUBDIR_UNITTESTS_SRCS): Add unittests/optional-selftests.c. (SUBDIR_UNITTESTS_OBS): Add optional-selftests.o. * unittests/optional-selftests.c: New file. * unittests/optional/assignment/1.cc: New file. * unittests/optional/assignment/2.cc: New file. * unittests/optional/assignment/3.cc: New file. * unittests/optional/assignment/4.cc: New file. * unittests/optional/assignment/5.cc: New file. * unittests/optional/assignment/6.cc: New file. * unittests/optional/assignment/7.cc: New file. * unittests/optional/cons/copy.cc: New file. * unittests/optional/cons/default.cc: New file. * unittests/optional/cons/move.cc: New file. * unittests/optional/cons/value.cc: New file. * unittests/optional/in_place.cc: New file. * unittests/optional/observers/1.cc: New file. * unittests/optional/observers/2.cc: New file.
-rw-r--r--gdb/ChangeLog21
-rw-r--r--gdb/Makefile.in6
-rw-r--r--gdb/unittests/optional-selftests.c94
-rw-r--r--gdb/unittests/optional/assignment/1.cc195
-rw-r--r--gdb/unittests/optional/assignment/2.cc193
-rw-r--r--gdb/unittests/optional/assignment/3.cc156
-rw-r--r--gdb/unittests/optional/assignment/4.cc156
-rw-r--r--gdb/unittests/optional/assignment/5.cc80
-rw-r--r--gdb/unittests/optional/assignment/6.cc90
-rw-r--r--gdb/unittests/optional/assignment/7.cc29
-rw-r--r--gdb/unittests/optional/cons/copy.cc126
-rw-r--r--gdb/unittests/optional/cons/default.cc58
-rw-r--r--gdb/unittests/optional/cons/move.cc124
-rw-r--r--gdb/unittests/optional/cons/value.cc294
-rw-r--r--gdb/unittests/optional/in_place.cc65
-rw-r--r--gdb/unittests/optional/observers/1.cc31
-rw-r--r--gdb/unittests/optional/observers/2.cc35
17 files changed, 1751 insertions, 2 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index f000112..e63ae39 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,26 @@
2017-04-18 Pedro Alves <palves@redhat.com>
+ * Makefile.in (SUBDIR_UNITTESTS_SRCS): Add
+ unittests/optional-selftests.c.
+ (SUBDIR_UNITTESTS_OBS): Add optional-selftests.o.
+ * unittests/optional-selftests.c: New file.
+ * unittests/optional/assignment/1.cc: New file.
+ * unittests/optional/assignment/2.cc: New file.
+ * unittests/optional/assignment/3.cc: New file.
+ * unittests/optional/assignment/4.cc: New file.
+ * unittests/optional/assignment/5.cc: New file.
+ * unittests/optional/assignment/6.cc: New file.
+ * unittests/optional/assignment/7.cc: New file.
+ * unittests/optional/cons/copy.cc: New file.
+ * unittests/optional/cons/default.cc: New file.
+ * unittests/optional/cons/move.cc: New file.
+ * unittests/optional/cons/value.cc: New file.
+ * unittests/optional/in_place.cc: New file.
+ * unittests/optional/observers/1.cc: New file.
+ * unittests/optional/observers/2.cc: New file.
+
+2017-04-18 Pedro Alves <palves@redhat.com>
+
* common/gdb_optional.h: Include common/traits.h.
(in_place_t): New type.
(in_place): New constexpr variable.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 291b1a0..ed4f58a 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -526,12 +526,14 @@ SUBDIR_PYTHON_CFLAGS =
SUBDIR_UNITTESTS_SRCS = \
unittests/function-view-selftests.c \
unittests/offset-type-selftests.c \
- unittests/ptid-selftests.c
+ unittests/ptid-selftests.c \
+ unittests/optional-selftests.c
SUBDIR_UNITTESTS_OBS = \
function-view-selftests.o \
offset-type-selftests.o \
- ptid-selftests.o
+ ptid-selftests.o \
+ optional-selftests.o
# Opcodes currently live in one of two places. Either they are in the
# opcode library, typically ../opcodes, or they are in a header file
diff --git a/gdb/unittests/optional-selftests.c b/gdb/unittests/optional-selftests.c
new file mode 100644
index 0000000..76343c6
--- /dev/null
+++ b/gdb/unittests/optional-selftests.c
@@ -0,0 +1,94 @@
+/* Self tests for optional for GDB, the GNU debugger.
+
+ Copyright (C) 2017 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program 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 of the License, or
+ (at your option) any later version.
+
+ This program 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 program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "defs.h"
+#include "selftest.h"
+#include "common/gdb_optional.h"
+
+/* Used by the included .cc files below. Included here because the
+ included test files are wrapped in a namespace. */
+#include <vector>
+#include <string>
+#include <memory>
+
+/* libstdc++'s testsuite uses VERIFY. */
+#define VERIFY SELF_CHECK
+
+/* Used to disable testing features not supported by
+ gdb::optional. */
+#define GDB_OPTIONAL
+
+namespace selftests {
+namespace optional {
+
+/* The actual tests live in separate files, which were originally
+ copied over from libstdc++'s testsuite. To preserve the structure
+ and help with comparison with the original tests, the file names
+ have been preserved, and only minimal modification was done to have
+ them compile against gdb::optional instead of std::optional:
+
+ - std::optional->gdb:optional, etc.
+ - ATTRIBUTE_UNUSED in a few places
+ - wrap each file in a namespace so they can all be compiled as a
+ single unit.
+ - libstdc++'s license and formatting style was preserved.
+*/
+
+#include "optional/assignment/1.cc"
+#include "optional/assignment/2.cc"
+#include "optional/assignment/3.cc"
+#include "optional/assignment/4.cc"
+#include "optional/assignment/5.cc"
+#include "optional/assignment/6.cc"
+#include "optional/assignment/7.cc"
+#include "optional/cons/copy.cc"
+#include "optional/cons/default.cc"
+#include "optional/cons/move.cc"
+#include "optional/cons/value.cc"
+#include "optional/in_place.cc"
+#include "optional/observers/1.cc"
+#include "optional/observers/2.cc"
+
+static void
+run_tests ()
+{
+ assign_1::test ();
+ assign_2::test ();
+ assign_3::test ();
+ assign_4::test ();
+ assign_5::test ();
+ assign_6::test ();
+ assign_7::test ();
+ cons_copy::test ();
+ cons_default::test ();
+ cons_move::test ();
+ cons_value::test ();
+ in_place::test ();
+ observers_1::test ();
+ observers_2::test ();
+}
+
+} /* namespace optional */
+} /* namespace selftests */
+
+void
+_initialize_optional_selftests ()
+{
+ register_self_test (selftests::optional::run_tests);
+}
diff --git a/gdb/unittests/optional/assignment/1.cc b/gdb/unittests/optional/assignment/1.cc
new file mode 100644
index 0000000..671004e
--- /dev/null
+++ b/gdb/unittests/optional/assignment/1.cc
@@ -0,0 +1,195 @@
+// Copyright (C) 2013-2017 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/>.
+
+namespace assign_1 {
+
+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;
+};
+
+void test()
+{
+ using O = gdb::optional<value_type>;
+ using S = value_type::state_type;
+ auto const make = [](S s = S::zero) { return O { gdb::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 );
+ }
+
+#ifndef GDB_OPTIONAL
+ {
+ O o;
+ VERIFY( !o );
+ o = {};
+ VERIFY( !o );
+ }
+#endif
+
+ // 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 );
+}
+
+} // namespace assign_1
diff --git a/gdb/unittests/optional/assignment/2.cc b/gdb/unittests/optional/assignment/2.cc
new file mode 100644
index 0000000..1b0bd7a
--- /dev/null
+++ b/gdb/unittests/optional/assignment/2.cc
@@ -0,0 +1,193 @@
+// Copyright (C) 2013-2017 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/>.
+
+namespace assign_2 {
+
+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;
+};
+
+void test()
+{
+ using O = gdb::optional<value_type>;
+ using S = value_type::state_type;
+ auto const make = [](S s = S::zero) { return O { gdb::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 );
+ }
+
+#ifndef GDB_OPTIONAL
+ {
+ O o = make(S::zero);
+ VERIFY( o );
+ o = {};
+ VERIFY( !o );
+ }
+#endif
+
+ // 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);
+ }
+
+ {
+ ATTRIBUTE_UNUSED 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);
+ }
+
+ {
+ ATTRIBUTE_UNUSED 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 );
+}
+
+} // namespace assign_2
diff --git a/gdb/unittests/optional/assignment/3.cc b/gdb/unittests/optional/assignment/3.cc
new file mode 100644
index 0000000..e047e74
--- /dev/null
+++ b/gdb/unittests/optional/assignment/3.cc
@@ -0,0 +1,156 @@
+// Copyright (C) 2013-2017 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/>.
+
+namespace assign_3 {
+
+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;
+};
+
+void test()
+{
+ using O = gdb::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 );
+ }
+
+ {
+ ATTRIBUTE_UNUSED 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 );
+ }
+
+ {
+ ATTRIBUTE_UNUSED 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 );
+}
+
+} // namespace assign_3
diff --git a/gdb/unittests/optional/assignment/4.cc b/gdb/unittests/optional/assignment/4.cc
new file mode 100644
index 0000000..0b196e0
--- /dev/null
+++ b/gdb/unittests/optional/assignment/4.cc
@@ -0,0 +1,156 @@
+// Copyright (C) 2013-2017 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/>.
+
+namespace assign_4 {
+
+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;
+};
+
+void test()
+{
+ using O = gdb::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);
+ }
+
+ {
+ ATTRIBUTE_UNUSED 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 );
+ }
+
+ {
+ ATTRIBUTE_UNUSED 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 );
+}
+
+} // namespace assign_4
diff --git a/gdb/unittests/optional/assignment/5.cc b/gdb/unittests/optional/assignment/5.cc
new file mode 100644
index 0000000..b1dee4f
--- /dev/null
+++ b/gdb/unittests/optional/assignment/5.cc
@@ -0,0 +1,80 @@
+// Copyright (C) 2013-2017 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/>.
+
+namespace assign_5 {
+
+int counter = 0;
+
+struct mixin_counter
+{
+ mixin_counter() { ++counter; }
+ mixin_counter(mixin_counter const&) { ++counter; }
+ ~mixin_counter() { --counter; }
+};
+
+struct value_type : private mixin_counter { };
+
+void test()
+{
+ using O = gdb::optional<value_type>;
+
+ // Check std::nullopt_t and 'default' (= {}) assignment
+
+#ifndef GDB_OPTIONAL
+ {
+ O o;
+ o = std::nullopt;
+ VERIFY( !o );
+ }
+#endif
+
+#ifndef GDB_OPTIONAL
+ {
+ O o { gdb::in_place };
+ o = std::nullopt;
+ VERIFY( !o );
+ }
+#endif
+
+#ifndef GDB_OPTIONAL
+ {
+ O o;
+ o = {};
+ VERIFY( !o );
+ }
+#endif
+
+#ifndef GDB_OPTIONAL
+ {
+ O o { gdb::in_place };
+ o = {};
+ VERIFY( !o );
+ }
+#endif
+ {
+ gdb::optional<std::vector<int>> ovi{{1, 2, 3}};
+ VERIFY(ovi->size() == 3);
+ VERIFY((*ovi)[0] == 1 && (*ovi)[1] == 2 && (*ovi)[2] == 3);
+ ovi = {4, 5, 6, 7};
+ VERIFY(ovi->size() == 4);
+ VERIFY((*ovi)[0] == 4 && (*ovi)[1] == 5 &&
+ (*ovi)[2] == 6 && (*ovi)[3] == 7);
+ }
+ VERIFY( counter == 0 );
+}
+
+} // namespace assign_5
diff --git a/gdb/unittests/optional/assignment/6.cc b/gdb/unittests/optional/assignment/6.cc
new file mode 100644
index 0000000..383ff7e
--- /dev/null
+++ b/gdb/unittests/optional/assignment/6.cc
@@ -0,0 +1,90 @@
+// Copyright (C) 2013-2017 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/>.
+
+namespace assign_6 {
+
+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;
+};
+
+void test()
+{
+ using O = gdb::optional<value_type>;
+
+ // Check emplace
+
+ {
+ O o;
+ o.emplace();
+ VERIFY( o && o->state == 0 );
+ }
+ {
+ O o { gdb::in_place, 0 };
+ o.emplace();
+ VERIFY( o && o->state == 0 );
+ }
+
+ {
+ O o;
+ o.emplace(0);
+ VERIFY( o && o->state == 1 );
+ }
+ {
+ O o { gdb::in_place };
+ o.emplace(0);
+ VERIFY( o && o->state == 1 );
+ }
+
+#ifndef GDB_OPTIONAL
+ {
+ O o;
+ o.emplace({ 'a' }, "");
+ VERIFY( o && o->state == 2 );
+ }
+ {
+ O o { gdb::in_place };
+ o.emplace({ 'a' }, "");
+ VERIFY( o && o->state == 2 );
+ }
+#endif
+ {
+ O o;
+ VERIFY(&o.emplace(0) == &*o);
+#ifndef GDB_OPTIONAL
+ VERIFY(&o.emplace({ 'a' }, "") == &*o);
+#endif
+ }
+
+ static_assert( !std::is_constructible<O, std::initializer_list<int>, int>(), "" );
+
+ VERIFY( counter == 0 );
+}
+
+} // namespace assign_6
diff --git a/gdb/unittests/optional/assignment/7.cc b/gdb/unittests/optional/assignment/7.cc
new file mode 100644
index 0000000..e23651c
--- /dev/null
+++ b/gdb/unittests/optional/assignment/7.cc
@@ -0,0 +1,29 @@
+// Copyright (C) 2016-2017 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/>.
+
+namespace assign_7 {
+
+void test()
+{
+ gdb::optional<int> o{666};
+ VERIFY(o && *o == 666);
+ o.reset();
+ VERIFY(!o);
+ static_assert(noexcept(std::declval<gdb::optional<int>>().reset()), "");
+}
+
+} // namespace assign_7
diff --git a/gdb/unittests/optional/cons/copy.cc b/gdb/unittests/optional/cons/copy.cc
new file mode 100644
index 0000000..bce423b
--- /dev/null
+++ b/gdb/unittests/optional/cons/copy.cc
@@ -0,0 +1,126 @@
+// Copyright (C) 2013-2017 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/>.
+
+namespace cons_copy {
+
+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 {}; }
+};
+
+void test()
+{
+ // [20.5.4.1] Constructors
+
+ {
+ gdb::optional<long> o;
+ auto copy = o;
+ VERIFY( !copy );
+ VERIFY( !o );
+ }
+
+ {
+ const long val = 0x1234ABCD;
+ gdb::optional<long> o { gdb::in_place, val};
+ auto copy = o;
+ VERIFY( copy );
+ VERIFY( *copy == val );
+#ifndef GDB_OPTIONAL
+ VERIFY( o && o == val );
+#endif
+ }
+
+ {
+ gdb::optional<tracker> o;
+ auto copy = o;
+ VERIFY( !copy );
+ VERIFY( tracker::count == 0 );
+ VERIFY( !o );
+ }
+
+ {
+ gdb::optional<tracker> o { gdb::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;
+ gdb::optional<throwing_copy> o;
+
+ try
+ {
+ auto copy = o;
+ }
+ catch(exception const&)
+ { result = caught; }
+ catch(...)
+ { result = bad_catch; }
+
+ VERIFY( result == nothrow );
+ }
+
+ {
+ outcome result = nothrow;
+ gdb::optional<throwing_copy> o { gdb::in_place };
+
+ try
+ {
+ auto copy = o;
+ }
+ catch(exception const&)
+ { result = caught; }
+ catch(...)
+ { result = bad_catch; }
+
+ VERIFY( result == caught );
+ }
+
+ VERIFY( tracker::count == 0 );
+}
+
+} // namespace cons_copy
diff --git a/gdb/unittests/optional/cons/default.cc b/gdb/unittests/optional/cons/default.cc
new file mode 100644
index 0000000..b075f5c
--- /dev/null
+++ b/gdb/unittests/optional/cons/default.cc
@@ -0,0 +1,58 @@
+// Copyright (C) 2013-2017 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/>.
+
+namespace cons_default {
+
+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;
+
+void test()
+{
+ // [20.5.4.1] Constructors
+
+ {
+ gdb::optional<tracker> o;
+ VERIFY( !o );
+ }
+
+ {
+ gdb::optional<tracker> o {};
+ VERIFY( !o );
+ }
+
+ {
+ gdb::optional<tracker> o = {};
+ VERIFY( !o );
+ }
+
+ VERIFY( tracker::count == 0 );
+}
+
+} // namespace cons_default
diff --git a/gdb/unittests/optional/cons/move.cc b/gdb/unittests/optional/cons/move.cc
new file mode 100644
index 0000000..5a50b08
--- /dev/null
+++ b/gdb/unittests/optional/cons/move.cc
@@ -0,0 +1,124 @@
+// Copyright (C) 2013-2017 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/>.
+
+namespace cons_move {
+
+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 {}; }
+};
+
+void test()
+{
+ // [20.5.4.1] Constructors
+
+ {
+ gdb::optional<long> o;
+ auto moved_to = std::move(o);
+ VERIFY( !moved_to );
+ VERIFY( !o );
+ }
+
+ {
+ const long val = 0x1234ABCD;
+ gdb::optional<long> o { gdb::in_place, val};
+ auto moved_to = std::move(o);
+ VERIFY( moved_to );
+ VERIFY( *moved_to == val );
+ VERIFY( o && *o == val );
+ }
+
+ {
+ gdb::optional<tracker> o;
+ auto moved_to = std::move(o);
+ VERIFY( !moved_to );
+ VERIFY( tracker::count == 0 );
+ VERIFY( !o );
+ }
+
+ {
+ gdb::optional<tracker> o { gdb::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;
+ gdb::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;
+ gdb::optional<throwing_move> o { gdb::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 );
+}
+
+} // namespace cons_move
diff --git a/gdb/unittests/optional/cons/value.cc b/gdb/unittests/optional/cons/value.cc
new file mode 100644
index 0000000..52843b0
--- /dev/null
+++ b/gdb/unittests/optional/cons/value.cc
@@ -0,0 +1,294 @@
+// Copyright (C) 2013-2017 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/>.
+
+namespace cons_value {
+
+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;
+};
+
+void test()
+{
+ // [20.5.4.1] Constructors
+
+ {
+ auto i = 0x1234ABCD;
+ gdb::optional<long> o { i };
+ VERIFY( o );
+ VERIFY( *o == 0x1234ABCD );
+ VERIFY( i == 0x1234ABCD );
+ }
+
+ {
+ auto i = 0x1234ABCD;
+ gdb::optional<long> o = i;
+ VERIFY( o );
+ VERIFY( *o == 0x1234ABCD );
+ VERIFY( i == 0x1234ABCD );
+ }
+
+ {
+ auto i = 0x1234ABCD;
+ gdb::optional<long> o = { i };
+ VERIFY( o );
+ VERIFY( *o == 0x1234ABCD );
+ VERIFY( i == 0x1234ABCD );
+ }
+
+ {
+ auto i = 0x1234ABCD;
+ gdb::optional<long> o { std::move(i) };
+ VERIFY( o );
+ VERIFY( *o == 0x1234ABCD );
+ VERIFY( i == 0x1234ABCD );
+ }
+
+ {
+ auto i = 0x1234ABCD;
+ gdb::optional<long> o = std::move(i);
+ VERIFY( o );
+ VERIFY( *o == 0x1234ABCD );
+ VERIFY( i == 0x1234ABCD );
+ }
+
+ {
+ auto i = 0x1234ABCD;
+ gdb::optional<long> o = { std::move(i) };
+ VERIFY( o );
+ VERIFY( *o == 0x1234ABCD );
+ VERIFY( i == 0x1234ABCD );
+ }
+
+#ifndef GDB_OPTIONAL
+ {
+ std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
+ gdb::optional<std::vector<int>> o { v };
+ VERIFY( !v.empty() );
+ VERIFY( o->size() == 6 );
+ }
+#endif
+
+ {
+ std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
+ gdb::optional<std::vector<int>> o = v;
+ VERIFY( !v.empty() );
+ VERIFY( o->size() == 6 );
+ }
+
+ {
+ std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
+ gdb::optional<std::vector<int>> o { v };
+ VERIFY( !v.empty() );
+ VERIFY( o->size() == 6 );
+ }
+
+ {
+ std::vector<int> v = { 0, 1, 2, 3, 4, 5 };
+ gdb::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 };
+ gdb::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 };
+ gdb::optional<std::vector<int>> o { std::move(v) };
+ VERIFY( v.empty() );
+ VERIFY( o->size() == 6 );
+ }
+
+ {
+ tracker t { 333 };
+ gdb::optional<tracker> o = t;
+ VERIFY( o->value == 333 );
+ VERIFY( tracker::count == 2 );
+ VERIFY( t.value == 333 );
+ }
+
+ {
+ tracker t { 333 };
+ gdb::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
+ {
+ gdb::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
+ {
+ gdb::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
+ {
+ gdb::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
+ {
+ gdb::optional<throwing_construction> o { std::move(t) };
+ }
+ catch(exception const&)
+ { result = caught; }
+ catch(...)
+ { result = bad_catch; }
+
+ VERIFY( result == caught );
+ }
+
+ {
+#ifndef GDB_OPTIONAL
+ gdb::optional<std::string> os = "foo";
+#endif
+ struct X
+ {
+ explicit X(int) {}
+ X& operator=(int) {return *this;}
+ };
+#ifndef GDB_OPTIONAL
+ gdb::optional<X> ox{42};
+#endif
+ gdb::optional<int> oi{42};
+#ifndef GDB_OPTIONAL
+ gdb::optional<X> ox2{oi};
+#endif
+ gdb::optional<std::string> os2;
+ os2 = "foo";
+#ifndef GDB_OPTIONAL
+ gdb::optional<X> ox3;
+ ox3 = 42;
+ gdb::optional<X> ox4;
+ ox4 = oi;
+#endif
+ }
+ {
+ // no converting construction.
+#ifndef GDB_OPTIONAL
+ gdb::optional<int> oi = gdb::optional<short>();
+ VERIFY(!bool(oi));
+ gdb::optional<std::string> os = gdb::optional<const char*>();
+ VERIFY(!bool(os));
+#endif
+ gdb::optional<gdb::optional<int>> ooi = gdb::optional<int>();
+ VERIFY(bool(ooi));
+ ooi = gdb::optional<int>();
+ VERIFY(bool(ooi));
+ ooi = gdb::optional<int>(42);
+ VERIFY(bool(ooi));
+ VERIFY(bool(*ooi));
+#ifndef GDB_OPTIONAL
+ gdb::optional<gdb::optional<int>> ooi2 = gdb::optional<short>();
+ VERIFY(bool(ooi2));
+ ooi2 = gdb::optional<short>();
+ VERIFY(bool(ooi2));
+ ooi2 = gdb::optional<short>(6);
+ VERIFY(bool(ooi2));
+ VERIFY(bool(*ooi2));
+ gdb::optional<gdb::optional<int>> ooi3 = gdb::optional<int>(42);
+ VERIFY(bool(ooi3));
+ VERIFY(bool(*ooi3));
+ gdb::optional<gdb::optional<int>> ooi4 = gdb::optional<short>(6);
+ VERIFY(bool(ooi4));
+ VERIFY(bool(*ooi4));
+#endif
+ }
+}
+
+} // namespace cons_value
diff --git a/gdb/unittests/optional/in_place.cc b/gdb/unittests/optional/in_place.cc
new file mode 100644
index 0000000..5ddaece
--- /dev/null
+++ b/gdb/unittests/optional/in_place.cc
@@ -0,0 +1,65 @@
+// Copyright (C) 2013-2017 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/>.
+
+namespace in_place {
+
+void test()
+{
+ // [20.5.5] In-place construction
+ {
+ gdb::optional<int> o { gdb::in_place };
+ VERIFY( o );
+ VERIFY( *o == int() );
+
+#ifndef GDB_OPTIONAL
+ static_assert( !std::is_convertible<gdb::in_place_t, gdb::optional<int>>(), "" );
+#endif
+ }
+
+ {
+ gdb::optional<int> o { gdb::in_place, 42 };
+ VERIFY( o );
+ VERIFY( *o == 42 );
+ }
+
+ {
+ gdb::optional<std::vector<int>> o { gdb::in_place, 18, 4 };
+ VERIFY( o );
+ VERIFY( o->size() == 18 );
+ VERIFY( (*o)[17] == 4 );
+ }
+
+#ifndef GDB_OPTIONAL
+ {
+ gdb::optional<std::vector<int>> o { gdb::in_place, { 18, 4 } };
+ VERIFY( o );
+ VERIFY( o->size() == 2 );
+ VERIFY( (*o)[0] == 18 );
+ }
+#endif
+
+#ifndef GDB_OPTIONAL
+ {
+ gdb::optional<std::vector<int>> o { gdb::in_place, { 18, 4 }, std::allocator<int> {} };
+ VERIFY( o );
+ VERIFY( o->size() == 2 );
+ VERIFY( (*o)[0] == 18 );
+ }
+#endif
+}
+
+} // namespace in_place
diff --git a/gdb/unittests/optional/observers/1.cc b/gdb/unittests/optional/observers/1.cc
new file mode 100644
index 0000000..6c8677e
--- /dev/null
+++ b/gdb/unittests/optional/observers/1.cc
@@ -0,0 +1,31 @@
+// Copyright (C) 2013-2017 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/>.
+
+namespace observers_1 {
+
+struct value_type
+{
+ int i;
+};
+
+void test()
+{
+ gdb::optional<value_type> o { value_type { 51 } };
+ VERIFY( (*o).i == 51 );
+}
+
+} // namespace observers_1
diff --git a/gdb/unittests/optional/observers/2.cc b/gdb/unittests/optional/observers/2.cc
new file mode 100644
index 0000000..3af49e6
--- /dev/null
+++ b/gdb/unittests/optional/observers/2.cc
@@ -0,0 +1,35 @@
+// Copyright (C) 2013-2017 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/>.
+
+namespace observers_2 {
+
+struct value_type
+{
+ int i;
+};
+
+void* operator&(const value_type&) = delete;
+
+void test()
+{
+ gdb::optional<value_type> o { value_type { 51 } };
+ VERIFY( o->i == 51 );
+ VERIFY( o->i == (*o).i );
+ VERIFY( &o->i == &(*o).i );
+}
+
+} // namespace observers_2