gdb::optional unit tests
authorPedro Alves <palves@redhat.com>
Tue, 18 Apr 2017 20:39:24 +0000 (21:39 +0100)
committerPedro Alves <palves@redhat.com>
Tue, 18 Apr 2017 22:49:33 +0000 (23:49 +0100)
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.

17 files changed:
gdb/ChangeLog
gdb/Makefile.in
gdb/unittests/optional-selftests.c [new file with mode: 0644]
gdb/unittests/optional/assignment/1.cc [new file with mode: 0644]
gdb/unittests/optional/assignment/2.cc [new file with mode: 0644]
gdb/unittests/optional/assignment/3.cc [new file with mode: 0644]
gdb/unittests/optional/assignment/4.cc [new file with mode: 0644]
gdb/unittests/optional/assignment/5.cc [new file with mode: 0644]
gdb/unittests/optional/assignment/6.cc [new file with mode: 0644]
gdb/unittests/optional/assignment/7.cc [new file with mode: 0644]
gdb/unittests/optional/cons/copy.cc [new file with mode: 0644]
gdb/unittests/optional/cons/default.cc [new file with mode: 0644]
gdb/unittests/optional/cons/move.cc [new file with mode: 0644]
gdb/unittests/optional/cons/value.cc [new file with mode: 0644]
gdb/unittests/optional/in_place.cc [new file with mode: 0644]
gdb/unittests/optional/observers/1.cc [new file with mode: 0644]
gdb/unittests/optional/observers/2.cc [new file with mode: 0644]

index f0001126db5ba1d898eeaec9a4d0ac5a861638f4..e63ae3901f7bf8230217f9a2f8af0679a17dd8cf 100644 (file)
@@ -1,3 +1,24 @@
+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.
index 291b1a04cc844fa8758f57f6189975485cd4c92d..ed4f58a9b24138daebc7558d8c4b6323eebc4a11 100644 (file)
@@ -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 (file)
index 0000000..76343c6
--- /dev/null
@@ -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 (file)
index 0000000..671004e
--- /dev/null
@@ -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 (file)
index 0000000..1b0bd7a
--- /dev/null
@@ -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 (file)
index 0000000..e047e74
--- /dev/null
@@ -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 (file)
index 0000000..0b196e0
--- /dev/null
@@ -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 (file)
index 0000000..b1dee4f
--- /dev/null
@@ -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 (file)
index 0000000..383ff7e
--- /dev/null
@@ -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 (file)
index 0000000..e23651c
--- /dev/null
@@ -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 (file)
index 0000000..bce423b
--- /dev/null
@@ -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 (file)
index 0000000..b075f5c
--- /dev/null
@@ -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 (file)
index 0000000..5a50b08
--- /dev/null
@@ -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 (file)
index 0000000..52843b0
--- /dev/null
@@ -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 (file)
index 0000000..5ddaece
--- /dev/null
@@ -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 (file)
index 0000000..6c8677e
--- /dev/null
@@ -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 (file)
index 0000000..3af49e6
--- /dev/null
@@ -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