Re: [v3 PATCH] Cross-port exception-safety and move fixes of std::any to std::experimental::any.

2016-10-24 Thread Jonathan Wakely

On 24/10/16 02:35 +0300, Ville Voutilainen wrote:

On 24 October 2016 at 02:33, Ville Voutilainen
 wrote:

* include/std/any (operator=(const any&)):


No sir, that's not what the patch modifies:

2016-10-24  Ville Voutilainen  

   Cross-port exception-safety and move fixes of std::any to
   std::experimental::any.
   * include/experimental/any (operator=(const any&)):
   Make strongly exception-safe.
   (operator=(any&&)): clear() unconditionally in the case where
   rhs has a value.
   (_Manager_internal<_Tp>::_S_manage): Move in _Op_xfer, don't copy.
   * testsuite/experimental/any/assign/2.cc: Adjust.
   * testsuite/experimental/any/assign/exception.cc: New.
   * testsuite/experimental/any/cons/2.cc: Adjust.
   * testsuite/experimental/any/misc/any_cast_neg.cc: Ajust.


OK with this changelog, thanks.




Re: [v3 PATCH] Cross-port exception-safety and move fixes of std::any to std::experimental::any.

2016-10-23 Thread Ville Voutilainen
On 24 October 2016 at 02:33, Ville Voutilainen
 wrote:
> * include/std/any (operator=(const any&)):

No sir, that's not what the patch modifies:

2016-10-24  Ville Voutilainen  

Cross-port exception-safety and move fixes of std::any to
std::experimental::any.
* include/experimental/any (operator=(const any&)):
Make strongly exception-safe.
(operator=(any&&)): clear() unconditionally in the case where
rhs has a value.
(_Manager_internal<_Tp>::_S_manage): Move in _Op_xfer, don't copy.
* testsuite/experimental/any/assign/2.cc: Adjust.
* testsuite/experimental/any/assign/exception.cc: New.
* testsuite/experimental/any/cons/2.cc: Adjust.
* testsuite/experimental/any/misc/any_cast_neg.cc: Ajust.


[v3 PATCH] Cross-port exception-safety and move fixes of std::any to std::experimental::any.

2016-10-23 Thread Ville Voutilainen
Tested on Linux-x64. Ok for trunk?

I don't plan to backport this unless somebody shouts.

2016-10-24  Ville Voutilainen  

Cross-port exception-safety and move fixes of std::any to
std::experimental::any.
* include/std/any (operator=(const any&)):
Make strongly exception-safe.
(operator=(any&&)): clear() unconditionally in the case where
rhs has a value.
(_Manager_internal<_Tp>::_S_manage): Move in _Op_xfer, don't copy.
* testsuite/experimental/any/assign/2.cc: Adjust.
* testsuite/experimental/any/assign/exception.cc: New.
* testsuite/experimental/any/cons/2.cc: Adjust.
* testsuite/experimental/any/misc/any_cast_neg.cc: Ajust.
diff --git a/libstdc++-v3/include/experimental/any 
b/libstdc++-v3/include/experimental/any
index 5e091a4..8fd66e2 100644
--- a/libstdc++-v3/include/experimental/any
+++ b/libstdc++-v3/include/experimental/any
@@ -191,16 +191,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 /// Copy the state of another object.
 any& operator=(const any& __rhs)
 {
-  if (__rhs.empty())
-   clear();
-  else if (this != &__rhs)
-   {
- if (!empty())
-   _M_manager(_Op_destroy, this, nullptr);
- _Arg __arg;
- __arg._M_any = this;
- __rhs._M_manager(_Op_clone, &__rhs, &__arg);
-   }
+  *this = any(__rhs);
   return *this;
 }
 
@@ -215,8 +206,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
clear();
   else if (this != &__rhs)
{
- if (!empty())
-   _M_manager(_Op_destroy, this, nullptr);
+ clear();
  _Arg __arg;
  __arg._M_any = this;
  __rhs._M_manager(_Op_xfer, &__rhs, &__arg);
@@ -485,7 +475,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__ptr->~_Tp();
break;
   case _Op_xfer:
-   ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp(*__ptr);
+   ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp
+ (std::move(*const_cast<_Tp*>(__ptr)));
__ptr->~_Tp();
__arg->_M_any->_M_manager = __any->_M_manager;
const_cast(__any)->_M_manager = nullptr;
diff --git a/libstdc++-v3/testsuite/experimental/any/assign/2.cc 
b/libstdc++-v3/testsuite/experimental/any/assign/2.cc
index 7022878..0232af6 100644
--- a/libstdc++-v3/testsuite/experimental/any/assign/2.cc
+++ b/libstdc++-v3/testsuite/experimental/any/assign/2.cc
@@ -23,28 +23,70 @@
 using std::experimental::any;
 using std::experimental::any_cast;
 
+bool moved = false;
+bool copied = false;
+
+
 struct X
 {
-  bool moved = false;
-  bool moved_from = false;
   X() = default;
-  X(const X&) = default;
-  X(X&& x) : moved(true) { x.moved_from = true; }
+  X(const X&) { copied = true; }
+  X(X&& x) { moved = true; }
+};
+
+struct X2
+{
+  X2() = default;
+  X2(const X2&) { copied = true; }
+  X2(X2&& x) noexcept { moved = true; }
 };
 
 void test01()
 {
+  moved = false;
   X x;
   any a1;
   a1 = x;
-  VERIFY(x.moved_from == false);
+  VERIFY(moved == false);
   any a2;
+  copied = false;
   a2 = std::move(x);
-  VERIFY(x.moved_from == true);
-  VERIFY(any_cast(a2).moved == true );
+  VERIFY(moved == true);
+  VERIFY(copied == false);
 }
 
+void test02()
+{
+  moved = false;
+  X x;
+  any a1;
+  a1 = x;
+  VERIFY(moved == false);
+  any a2;
+  copied = false;
+  a2 = std::move(a1);
+  VERIFY(moved == false);
+  VERIFY(copied == false);
+}
+
+void test03()
+{
+  moved = false;
+  X2 x;
+  any a1;
+  a1 = x;
+  VERIFY(copied && moved);
+  any a2;
+  moved = false;
+  copied = false;
+  a2 = std::move(a1);
+  VERIFY(moved == true);
+  VERIFY(copied == false);
+ }
+
 int main()
 {
   test01();
+  test02();
+  test03();
 }
diff --git a/libstdc++-v3/testsuite/experimental/any/assign/exception.cc 
b/libstdc++-v3/testsuite/experimental/any/assign/exception.cc
new file mode 100644
index 000..f125213
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/any/assign/exception.cc
@@ -0,0 +1,77 @@
+// { dg-do run { target c++14 } }
+
+// Copyright (C) 2016 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
+// .
+
+#include 
+#include 
+
+using std::experimental::any;
+using std::experimental::any_cast;
+
+bool should_throw = false;
+struct Bad
+{
+  Bad() = default;
+  Bad(const Bad&) {if (should_throw) throw 666;}
+};
+
+struct Bad2
+{
+