public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [v3 PATCH] PR libstdc++/77288 and the newest proposed resolution for LWG 2756
@ 2016-08-23 14:17 Ville Voutilainen
  2016-09-06  7:05 ` Ville Voutilainen
  0 siblings, 1 reply; 15+ messages in thread
From: Ville Voutilainen @ 2016-08-23 14:17 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1399 bytes --]

Tested on Linux-x64.

N.B. I know that the assignment operators have constraints in template
parameters, I want to move them to the return type separately.

N.B2. This fixes the bug for std::optional only; I plan to port the fix
to std::experimental::optional in a separate patch, and then backport
that separate fix to 6.x.

N.B3. The newest p/r for LWG 2756 is not up yet in the issue list,
and hasn't been looked at by LEWG/LWG, but neither was the previous
one. :) Nevertheless, this new p/r and the patch are a massive
improvement, and keeps
existing code and expectations working, makes all sorts of interesting types
work, and keeps the conversion functionality.

2016-08-23  Ville Voutilainen  <ville.voutilainen@gmail.com>

    PR libstdc++/77288
    * include/std/optional (__is_optional_impl, __is_optional): Remove.
    (__converts_from_optional, __assigns_from_optional): New.
    (optional(_Up&&)): Use is_same instead of __is_optional.
    (optional(const optional<_Up>&)): Constrain with
    __converts_from_optional.
    (optional(optional<_Up>&&)): Likewise.
    (operator=(_Up&&)): Use is_same instead of __is_optional.
    (operator=(const optional<_Up>&)): Constrain with
    __converts_from_optional and __assigns_from_optional.
    (operator=(optional<_Up>&&)): Likewise.
    * testsuite/20_util/optional/77288.cc: New.
    * testsuite/20_util/optional/cons/value.cc: Adjust.

[-- Attachment #2: lwg2756_2.diff --]
[-- Type: text/plain, Size: 17020 bytes --]

diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional
index 2ff75ea..af716f7 100644
--- a/libstdc++-v3/include/std/optional
+++ b/libstdc++-v3/include/std/optional
@@ -423,19 +423,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
   class optional;
 
-  template<typename>
-    struct __is_optional_impl : false_type
-    { };
-
-  template<typename _Tp>
-  struct __is_optional_impl<optional<_Tp>> : true_type
-    { };
-
-  template<typename _Tp>
-    struct __is_optional
-    : public __is_optional_impl<std::remove_cv_t<std::remove_reference_t<_Tp>>>
-    { };
-
+  template<typename _Tp, typename _Up>
+    using __converts_from_optional =
+      __or_<is_constructible<_Tp, const optional<_Up>&>,
+	    is_constructible<_Tp, optional<_Up>&>,
+	    is_constructible<_Tp, const optional<_Up>&&>,
+	    is_constructible<_Tp, optional<_Up>&&>,
+	    is_convertible<const optional<_Up>&, _Tp>,
+	    is_convertible<optional<_Up>&, _Tp>,
+	    is_convertible<const optional<_Up>&&, _Tp>,
+	    is_convertible<optional<_Up>&&, _Tp>>;
+
+  template<typename _Tp, typename _Up>
+    using __assigns_from_optional =
+      __or_<is_assignable<_Tp&, const optional<_Up>&>,
+	    is_assignable<_Tp&, optional<_Up>&>,
+	    is_assignable<_Tp&, const optional<_Up>&&>,
+	    is_assignable<_Tp&, optional<_Up>&&>>;
 
   /**
     * @brief Class template for optional values.
@@ -474,7 +478,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // Converting constructors for engaged optionals.
       template <typename _Up = _Tp,
                 enable_if_t<__and_<
-			      __not_<__is_optional<decay_t<_Up>>>,
+			      __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
 			      is_constructible<_Tp, _Up&&>,
 			      is_convertible<_Up&&, _Tp>
 			      >::value, bool> = true>
@@ -483,7 +487,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       template <typename _Up = _Tp,
                 enable_if_t<__and_<
-			      __not_<__is_optional<decay_t<_Up>>>,
+			      __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
 			      is_constructible<_Tp, _Up&&>,
 			      __not_<is_convertible<_Up&&, _Tp>>
 			      >::value, bool> = false>
@@ -494,7 +498,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                 enable_if_t<__and_<
 			    __not_<is_same<_Tp, _Up>>,
 			    is_constructible<_Tp, const _Up&>,
-			    is_convertible<const _Up&, _Tp>
+			    is_convertible<const _Up&, _Tp>,
+			    __not_<__converts_from_optional<_Tp, _Up>>
 			    >::value, bool> = true>
       constexpr optional(const optional<_Up>& __t)
         : _Base(__t ? _Base(std::in_place, *__t) : _Base()) { }
@@ -503,7 +508,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                  enable_if_t<__and_<
 			       __not_<is_same<_Tp, _Up>>,
 			       is_constructible<_Tp, const _Up&>,
-			       __not_<is_convertible<const _Up&, _Tp>>
+			       __not_<is_convertible<const _Up&, _Tp>>,
+			       __not_<__converts_from_optional<_Tp, _Up>>
 			       >::value, bool> = false>
       explicit constexpr optional(const optional<_Up>& __t)
         : _Base(__t ? _Base(std::in_place, *__t) : _Base()) { }
@@ -512,7 +518,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                 enable_if_t<__and_<
 			      __not_<is_same<_Tp, _Up>>,
 			      is_constructible<_Tp, _Up&&>,
-			      is_convertible<_Up&&, _Tp>
+			      is_convertible<_Up&&, _Tp>,
+			      __not_<__converts_from_optional<_Tp, _Up>>
 			      >::value, bool> = true>
       constexpr optional(optional<_Up>&& __t)
         : _Base(__t ? _Base(std::in_place, std::move(*__t)) : _Base()) { }
@@ -521,7 +528,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                 enable_if_t<__and_<
 			    __not_<is_same<_Tp, _Up>>,
 			    is_constructible<_Tp, _Up&&>,
-			    __not_<is_convertible<_Up&&, _Tp>>
+			    __not_<is_convertible<_Up&&, _Tp>>,
+			    __not_<__converts_from_optional<_Tp, _Up>>
 			    >::value, bool> = false>
       explicit constexpr optional(optional<_Up>&& __t)
         : _Base(__t ? _Base(std::in_place, std::move(*__t)) : _Base()) { }
@@ -550,7 +558,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       template<typename _Up = _Tp,
                enable_if_t<__and_<
-			     __not_<__is_optional<decay_t<_Up>>>,
+			     __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
 			     is_constructible<_Tp, _Up>,
 			     is_assignable<_Tp&, _Up>>::value,
 			   bool> = true>
@@ -568,8 +576,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       template<typename _Up,
                enable_if_t<__and_<
 			     __not_<is_same<_Tp, _Up>>,
-			     is_constructible<_Tp, _Up>,
-			     is_assignable<_Tp&, _Up>>::value,
+			     is_constructible<_Tp, const _Up&>,
+			     is_assignable<_Tp&, _Up>,
+			     __not_<__converts_from_optional<_Tp, _Up>>,
+			     __not_<__assigns_from_optional<_Tp, _Up>>
+			     >::value,
 			   bool> = true>
         optional&
         operator=(const optional<_Up>& __u)
@@ -592,7 +603,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	       enable_if_t<__and_<
 			     __not_<is_same<_Tp, _Up>>,
 			     is_constructible<_Tp, _Up>,
-			     is_assignable<_Tp&, _Up>>::value,
+			     is_assignable<_Tp&, _Up>,
+			     __not_<__converts_from_optional<_Tp, _Up>>,
+			     __not_<__assigns_from_optional<_Tp, _Up>>
+			     >::value,
 			   bool> = true>
         optional&
         operator=(optional<_Up>&& __u)
diff --git a/libstdc++-v3/testsuite/20_util/optional/77288.cc b/libstdc++-v3/testsuite/20_util/optional/77288.cc
new file mode 100644
index 0000000..54d7cd8
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/optional/77288.cc
@@ -0,0 +1,391 @@
+// { dg-options "-std=gnu++17" }
+// { dg-do run }
+
+// 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 moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <exception>
+#include <optional>
+#include <any>
+
+using std::optional;
+
+#include <testsuite_hooks.h>
+
+void test01()
+{
+    optional<optional<std::exception_ptr>> nested_element;
+    optional<std::exception_ptr> element = {};
+    nested_element = element;
+    VERIFY(nested_element);
+}
+
+template <class T>
+struct service_result
+{
+  static optional<T> get_result()
+  {
+    T sr;
+    return sr;
+  }
+
+  static optional<T> get_result_with_cond(bool cond)
+  {
+    if (cond)
+      return T{};
+    return {};
+  }
+};
+
+void test02()
+{
+  VERIFY(service_result<int>::get_result());
+  VERIFY(service_result<optional<int>>::get_result());
+  VERIFY(service_result<int>::get_result_with_cond(true));
+  VERIFY(service_result<optional<int>>::get_result_with_cond(true));
+  VERIFY(!service_result<int>::get_result_with_cond(false));
+  VERIFY(!service_result<optional<int>>::get_result_with_cond(false));
+}
+
+struct Widget
+{
+  Widget(int) {}
+  Widget(optional<int>) {}
+};
+
+
+void test03()
+{
+  optional<Widget> w;
+  w = optional<int>();
+  VERIFY(w);
+  static_assert(!std::is_assignable_v<optional<Widget>&,
+		optional<short>>);;
+  w = optional<optional<int>>();
+  VERIFY(!w);
+  static_assert(!std::is_assignable_v<optional<Widget>&,
+		optional<optional<short>>>);;
+
+  optional<Widget> w2{optional<int>()};
+  VERIFY(w2);
+  optional<Widget> w3  = optional<int>();
+  VERIFY(w3);
+  optional<Widget> w4{optional<short>()};
+  VERIFY(w4);
+  static_assert(!std::is_convertible_v<optional<short>&&, optional<Widget>>);
+  
+  optional<Widget> w6{optional<optional<int>>()};
+  VERIFY(!w6);
+  optional<Widget> w7  = optional<optional<int>>();
+  VERIFY(!w7);
+  optional<Widget> w8{optional<optional<short>>()};
+  VERIFY(!w8);
+  static_assert(!std::is_convertible_v<optional<optional<short>>&&,
+		optional<Widget>>);
+  optional<Widget> w10{optional<optional<short>>(10)};
+  VERIFY(w10);
+  optional<Widget> w11 = std::nullopt;
+  VERIFY(!w11);
+  optional<Widget> w12 = {};
+  VERIFY(!w12);
+  optional<Widget> w13{std::nullopt};
+  VERIFY(!w13);
+  optional<Widget> w14;
+  w14 = {};
+  VERIFY(!w14);
+}
+
+struct Widget2
+{
+  Widget2(int) {}
+  Widget2(optional<int>) {}
+  Widget2& operator=(int) {return *this;}
+  Widget2& operator=(optional<int>) {return *this;}
+};
+
+void test04()
+{
+  optional<Widget2> w;
+  w = optional<int>();
+  VERIFY(w);
+  w = optional<short>();
+  VERIFY(w);
+  w = optional<optional<int>>();
+  VERIFY(!w);
+  w = optional<optional<short>>();
+  VERIFY(!w);
+  w = optional<optional<short>>(10);
+  optional<Widget2> w2 = std::nullopt;
+  VERIFY(!w2);
+  optional<Widget2> w3 = {};
+  VERIFY(!w3);
+  optional<Widget2> w4{std::nullopt};
+  VERIFY(!w4);
+  optional<Widget2> w5;
+  w5 = {};
+  VERIFY(!w5);
+}
+
+struct Thingy
+{
+  Thingy(int) {}
+  Thingy(Widget) {}
+};
+
+void test05()
+{
+  optional<Thingy> ot;
+
+  static_assert(!std::is_assignable_v<optional<Thingy>&,
+		optional<int>>);
+  static_assert(std::is_assignable_v<optional<Thingy>&,
+		optional<short>>);
+  static_assert(!std::is_assignable_v<optional<Thingy>&,
+		optional<optional<int>>>);
+  ot = optional<Widget>();
+  VERIFY(!ot);
+  optional<Thingy> ot2{optional<int>()};
+  VERIFY(ot2);
+  static_assert(!std::is_convertible_v<optional<int>&&,
+		optional<Thingy>>);
+  optional<Thingy> ot3{optional<short>()};
+  VERIFY(!ot3);
+  optional<Thingy> ot4 = optional<short>();
+  VERIFY(!ot4);
+
+  optional<Thingy> ot5{optional<optional<int>>()};
+  VERIFY(!ot5);
+  static_assert(!std::is_convertible_v<optional<optional<int>>&&,
+		optional<Thingy>>);
+  
+  optional<Thingy> ot7{optional<Widget>()};
+  VERIFY(!ot7);
+  optional<Thingy> ot8 = optional<Widget>();
+  VERIFY(!ot8);
+  static_assert(!std::is_constructible_v<optional<Thingy>,
+		optional<optional<short>>>);
+  static_assert(!std::is_convertible_v<optional<optional<short>>,
+		optional<Thingy>>);
+  static_assert(!std::is_assignable_v<optional<Thingy>&,
+		optional<optional<short>>>);
+  optional<Thingy> ot9 = std::nullopt;
+  VERIFY(!ot9);
+  optional<Thingy> ot10 = {};
+  VERIFY(!ot10);
+  optional<Thingy> ot11{std::nullopt};
+  VERIFY(!ot11);
+  optional<Thingy> ot12;
+  ot12 = {};
+  VERIFY(!ot12);
+}
+
+struct RvalueConstructible
+{
+  RvalueConstructible(int) {}
+  RvalueConstructible(optional<int>&&) {}
+};
+
+void test06()
+{
+  optional<int> oi;
+  optional<RvalueConstructible> ori;
+  static_assert(!std::is_assignable_v<optional<RvalueConstructible>&,
+		optional<int>&>);
+  ori = std::move(oi);
+  VERIFY(ori);
+
+  optional<optional<int>> ooi;
+  static_assert(!std::is_assignable_v<optional<RvalueConstructible>&,
+		optional<optional<int>>&>);
+  ori = std::move(ooi);
+  VERIFY(!ori);
+
+  static_assert(!std::is_constructible_v<optional<RvalueConstructible>,
+		optional<int>&>);
+  static_assert(!std::is_convertible_v<optional<int>&,
+		optional<RvalueConstructible>>);
+
+  optional<RvalueConstructible> ori2(std::move(oi));
+  VERIFY(ori2);
+  optional<RvalueConstructible> ori3 = std::move(oi);
+  VERIFY(ori3);
+
+  static_assert(!std::is_constructible_v<optional<RvalueConstructible>,
+		optional<optional<int>>&>);
+  static_assert(!std::is_convertible_v<optional<optional<int>>&,
+		optional<RvalueConstructible>>);
+  optional<RvalueConstructible> ori6(std::move(ooi));
+  VERIFY(!ori6);
+  optional<RvalueConstructible> ori7 = std::move(ooi);
+  VERIFY(!ori7);
+  optional<RvalueConstructible> ori8 = std::nullopt;
+  VERIFY(!ori8);
+  optional<RvalueConstructible> ori9 = {};
+  VERIFY(!ori9);
+  optional<RvalueConstructible> ori10{std::nullopt};
+  VERIFY(!ori10);
+  optional<RvalueConstructible> ori11;
+  ori11 = {};
+  VERIFY(!ori11);
+}
+
+struct Thingy2
+{
+  Thingy2(int) {}
+  explicit Thingy2(optional<int>) {}
+  Thingy2(Widget) {}
+};
+
+void test07()
+{
+  optional<Thingy2> ot{optional<int>{}};
+  VERIFY(ot);
+  static_assert(!std::is_convertible_v<optional<int>,
+		optional<Thingy2>>);
+  optional<Thingy2> ot2{optional<short>{}};
+  VERIFY(ot2);
+  static_assert(!std::is_convertible_v<optional<short>,
+		optional<Thingy2>>);
+  optional<Thingy2> ot3{optional<optional<int>>{}};
+  VERIFY(!ot3);
+  static_assert(!std::is_convertible_v<optional<optional<int>>,
+		optional<Thingy2>>);
+  optional<Thingy2> ot4{optional<optional<short>>{}};
+  VERIFY(!ot4);
+  static_assert(!std::is_convertible_v<optional<optional<short>>,
+		optional<Thingy2>>);
+  
+  optional<Thingy2> ot5{optional<Widget>{}};
+  VERIFY(!ot5);
+  optional<Thingy2> ot6 = optional<Widget>();
+  VERIFY(!ot6);
+
+  static_assert(!std::is_assignable_v<optional<Thingy2>&,
+		optional<int>>);
+  static_assert(!std::is_assignable_v<optional<Thingy2>&,
+		optional<short>>);
+  static_assert(!std::is_assignable_v<optional<Thingy2>&,
+		optional<optional<int>>>);
+  static_assert(!std::is_assignable_v<optional<Thingy2>&,
+		optional<optional<short>>>);
+  optional<Thingy2> ot7;
+  ot = optional<Widget>();
+  VERIFY(!ot7);
+  optional<Thingy2> ot8 = std::nullopt;
+  VERIFY(!ot8);
+  optional<Thingy2> ot9 = {};
+  VERIFY(!ot9);
+  optional<Thingy2> ot10{std::nullopt};
+  VERIFY(!ot10);
+  optional<Thingy2> ot11;
+  ot11 = {};
+  VERIFY(!ot11);
+}
+
+struct Thingy3
+{
+  Thingy3(int) {}
+  template<class... Args,
+	   std::enable_if_t<std::is_constructible_v<Widget, Args&&...>,
+			    bool> = true>
+  explicit Thingy3(Args&&... args) {}
+  Thingy3(Widget) {}
+};
+
+void test08()
+{
+  optional<Thingy3> ot{optional<int>{}};
+  VERIFY(ot);
+  static_assert(!std::is_convertible_v<optional<int>,
+		optional<Thingy3>>);
+  optional<Thingy3> ot2{optional<short>{}};
+  VERIFY(ot2);
+  static_assert(!std::is_convertible_v<optional<short>,
+		optional<Thingy3>>);
+  optional<Thingy3> ot3{optional<optional<int>>{}};
+  VERIFY(!ot3);
+  static_assert(!std::is_convertible_v<optional<optional<int>>,
+		optional<Thingy3>>);
+  optional<Thingy3> ot4{optional<optional<short>>{}};
+  VERIFY(!ot4);
+  static_assert(!std::is_convertible_v<optional<optional<short>>,
+		optional<Thingy3>>);
+  
+  optional<Thingy3> ot5{optional<Widget>{}};
+  VERIFY(!ot5);
+  optional<Thingy3> ot6 = optional<Widget>();
+  VERIFY(!ot6);
+
+  static_assert(!std::is_assignable_v<optional<Thingy3>&,
+		optional<int>>);
+  static_assert(!std::is_assignable_v<optional<Thingy3>&,
+		optional<short>>);
+  static_assert(!std::is_assignable_v<optional<Thingy3>&,
+		optional<optional<int>>>);
+  static_assert(!std::is_assignable_v<optional<Thingy3>&,
+		optional<optional<short>>>);
+  optional<Thingy3> ot7;
+  ot = optional<Widget>();
+  VERIFY(!ot7);
+  optional<Thingy3> ot8 = std::nullopt;
+  VERIFY(!ot8);
+  optional<Thingy3> ot9 = {};
+  VERIFY(!ot9);
+  optional<Thingy3> ot10{std::nullopt};
+  VERIFY(!ot10);
+  optional<Thingy3> ot11;
+  ot11 = {};
+  VERIFY(!ot11);
+}
+
+void test09()
+{
+  std::any a = 42;
+  optional<std::any> oa2 = a;
+  VERIFY(oa2);
+  VERIFY(std::any_cast<int>(*oa2) == 42);
+  optional<std::any> oa3 = oa2;
+  VERIFY(oa3);
+  VERIFY(std::any_cast<int>(*oa3) == 42);
+  optional<std::any> oa4{oa2};
+  VERIFY(oa4);
+  VERIFY(std::any_cast<int>(*oa4) == 42);
+  optional<std::any> oa5(oa2);
+  VERIFY(oa5);
+  VERIFY(std::any_cast<int>(*oa5) == 42);
+  optional<std::any> oa6;
+  VERIFY(!oa6);
+  optional<std::any> oa7 = oa6;
+  VERIFY(!oa7);
+  optional<std::any> oa8{oa6};
+  VERIFY(!oa8);
+  optional<std::any> oa9(oa6);
+  VERIFY(!oa9);
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+  test05();
+  test06();
+  test07();
+  test08();
+  test09();
+}
diff --git a/libstdc++-v3/testsuite/20_util/optional/cons/value.cc b/libstdc++-v3/testsuite/20_util/optional/cons/value.cc
index 6a2d871..141293c 100644
--- a/libstdc++-v3/testsuite/20_util/optional/cons/value.cc
+++ b/libstdc++-v3/testsuite/20_util/optional/cons/value.cc
@@ -256,17 +256,21 @@ int main()
     ox4 = oi;
   }
   {
+    std::optional<int> oi = std::optional<short>();
+    VERIFY(!bool(oi));
+    std::optional<std::string> os = std::optional<const char*>();
+    VERIFY(!bool(os));
     std::optional<std::optional<int>> ooi = std::optional<int>();
-    VERIFY(!bool(ooi));
+    VERIFY(bool(ooi));
     ooi = std::optional<int>();
-    VERIFY(!bool(ooi));
+    VERIFY(bool(ooi));
     ooi = std::optional<int>(42);
     VERIFY(bool(ooi));
     VERIFY(bool(*ooi));
     std::optional<std::optional<int>> ooi2 = std::optional<short>();
-    VERIFY(!bool(ooi2));
+    VERIFY(bool(ooi2));
     ooi2 = std::optional<short>();
-    VERIFY(!bool(ooi2));
+    VERIFY(bool(ooi2));
     ooi2 = std::optional<short>(6);
     VERIFY(bool(ooi2));
     VERIFY(bool(*ooi2));

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [v3 PATCH] PR libstdc++/77288 and the newest proposed resolution for LWG 2756
  2016-08-23 14:17 [v3 PATCH] PR libstdc++/77288 and the newest proposed resolution for LWG 2756 Ville Voutilainen
@ 2016-09-06  7:05 ` Ville Voutilainen
  2016-09-21  9:43   ` Jonathan Wakely
  0 siblings, 1 reply; 15+ messages in thread
From: Ville Voutilainen @ 2016-09-06  7:05 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1593 bytes --]

On 23 August 2016 at 17:17, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> Tested on Linux-x64.
>
> N.B. I know that the assignment operators have constraints in template
> parameters, I want to move them to the return type separately.
>
> N.B2. This fixes the bug for std::optional only; I plan to port the fix
> to std::experimental::optional in a separate patch, and then backport
> that separate fix to 6.x.
>
> N.B3. The newest p/r for LWG 2756 is not up yet in the issue list,
> and hasn't been looked at by LEWG/LWG, but neither was the previous
> one. :) Nevertheless, this new p/r and the patch are a massive
> improvement, and keeps
> existing code and expectations working, makes all sorts of interesting types
> work, and keeps the conversion functionality.


A minor addition to avoid problems with scalars.

2016-09-06  Ville Voutilainen  <ville.voutilainen@gmail.com>

    PR libstdc++/77288
    * include/std/optional (__is_optional_impl, __is_optional): Remove.
    (__converts_from_optional, __assigns_from_optional): New.
    (optional(_Up&&)): Use is_same instead of __is_optional.
    (optional(const optional<_Up>&)): Constrain with
    __converts_from_optional.
    (optional(optional<_Up>&&)): Likewise.
    (operator=(_Up&&)): Use is_same instead of __is_optional, check
    is_same and is_scalar.
    (operator=(const optional<_Up>&)): Constrain with
    __converts_from_optional and __assigns_from_optional.
    (operator=(optional<_Up>&&)): Likewise.
    * testsuite/20_util/optional/77288.cc: New.
    * testsuite/20_util/optional/cons/value.cc: Adjust.

[-- Attachment #2: lwg2756_3.diff --]
[-- Type: text/plain, Size: 17399 bytes --]

diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional
index 2ff75ea..efb0eb6 100644
--- a/libstdc++-v3/include/std/optional
+++ b/libstdc++-v3/include/std/optional
@@ -423,19 +423,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
   class optional;
 
-  template<typename>
-    struct __is_optional_impl : false_type
-    { };
-
-  template<typename _Tp>
-  struct __is_optional_impl<optional<_Tp>> : true_type
-    { };
-
-  template<typename _Tp>
-    struct __is_optional
-    : public __is_optional_impl<std::remove_cv_t<std::remove_reference_t<_Tp>>>
-    { };
-
+  template<typename _Tp, typename _Up>
+    using __converts_from_optional =
+      __or_<is_constructible<_Tp, const optional<_Up>&>,
+	    is_constructible<_Tp, optional<_Up>&>,
+	    is_constructible<_Tp, const optional<_Up>&&>,
+	    is_constructible<_Tp, optional<_Up>&&>,
+	    is_convertible<const optional<_Up>&, _Tp>,
+	    is_convertible<optional<_Up>&, _Tp>,
+	    is_convertible<const optional<_Up>&&, _Tp>,
+	    is_convertible<optional<_Up>&&, _Tp>>;
+
+  template<typename _Tp, typename _Up>
+    using __assigns_from_optional =
+      __or_<is_assignable<_Tp&, const optional<_Up>&>,
+	    is_assignable<_Tp&, optional<_Up>&>,
+	    is_assignable<_Tp&, const optional<_Up>&&>,
+	    is_assignable<_Tp&, optional<_Up>&&>>;
 
   /**
     * @brief Class template for optional values.
@@ -474,7 +478,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // Converting constructors for engaged optionals.
       template <typename _Up = _Tp,
                 enable_if_t<__and_<
-			      __not_<__is_optional<decay_t<_Up>>>,
+			      __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
 			      is_constructible<_Tp, _Up&&>,
 			      is_convertible<_Up&&, _Tp>
 			      >::value, bool> = true>
@@ -483,7 +487,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       template <typename _Up = _Tp,
                 enable_if_t<__and_<
-			      __not_<__is_optional<decay_t<_Up>>>,
+			      __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
 			      is_constructible<_Tp, _Up&&>,
 			      __not_<is_convertible<_Up&&, _Tp>>
 			      >::value, bool> = false>
@@ -494,7 +498,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                 enable_if_t<__and_<
 			    __not_<is_same<_Tp, _Up>>,
 			    is_constructible<_Tp, const _Up&>,
-			    is_convertible<const _Up&, _Tp>
+			    is_convertible<const _Up&, _Tp>,
+			    __not_<__converts_from_optional<_Tp, _Up>>
 			    >::value, bool> = true>
       constexpr optional(const optional<_Up>& __t)
         : _Base(__t ? _Base(std::in_place, *__t) : _Base()) { }
@@ -503,7 +508,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                  enable_if_t<__and_<
 			       __not_<is_same<_Tp, _Up>>,
 			       is_constructible<_Tp, const _Up&>,
-			       __not_<is_convertible<const _Up&, _Tp>>
+			       __not_<is_convertible<const _Up&, _Tp>>,
+			       __not_<__converts_from_optional<_Tp, _Up>>
 			       >::value, bool> = false>
       explicit constexpr optional(const optional<_Up>& __t)
         : _Base(__t ? _Base(std::in_place, *__t) : _Base()) { }
@@ -512,7 +518,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                 enable_if_t<__and_<
 			      __not_<is_same<_Tp, _Up>>,
 			      is_constructible<_Tp, _Up&&>,
-			      is_convertible<_Up&&, _Tp>
+			      is_convertible<_Up&&, _Tp>,
+			      __not_<__converts_from_optional<_Tp, _Up>>
 			      >::value, bool> = true>
       constexpr optional(optional<_Up>&& __t)
         : _Base(__t ? _Base(std::in_place, std::move(*__t)) : _Base()) { }
@@ -521,7 +528,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
                 enable_if_t<__and_<
 			    __not_<is_same<_Tp, _Up>>,
 			    is_constructible<_Tp, _Up&&>,
-			    __not_<is_convertible<_Up&&, _Tp>>
+			    __not_<is_convertible<_Up&&, _Tp>>,
+			    __not_<__converts_from_optional<_Tp, _Up>>
 			    >::value, bool> = false>
       explicit constexpr optional(optional<_Up>&& __t)
         : _Base(__t ? _Base(std::in_place, std::move(*__t)) : _Base()) { }
@@ -550,8 +558,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       template<typename _Up = _Tp,
                enable_if_t<__and_<
-			     __not_<__is_optional<decay_t<_Up>>>,
+			     __not_<is_same<optional<_Tp>, decay_t<_Up>>>,
 			     is_constructible<_Tp, _Up>,
+			     __not_<__and_<is_scalar<_Tp>,
+					   is_same<_Tp, decay_t<_Up>>>>,
 			     is_assignable<_Tp&, _Up>>::value,
 			   bool> = true>
         optional&
@@ -568,8 +578,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       template<typename _Up,
                enable_if_t<__and_<
 			     __not_<is_same<_Tp, _Up>>,
-			     is_constructible<_Tp, _Up>,
-			     is_assignable<_Tp&, _Up>>::value,
+			     is_constructible<_Tp, const _Up&>,
+			     is_assignable<_Tp&, _Up>,
+			     __not_<__converts_from_optional<_Tp, _Up>>,
+			     __not_<__assigns_from_optional<_Tp, _Up>>
+			     >::value,
 			   bool> = true>
         optional&
         operator=(const optional<_Up>& __u)
@@ -592,7 +605,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	       enable_if_t<__and_<
 			     __not_<is_same<_Tp, _Up>>,
 			     is_constructible<_Tp, _Up>,
-			     is_assignable<_Tp&, _Up>>::value,
+			     is_assignable<_Tp&, _Up>,
+			     __not_<__converts_from_optional<_Tp, _Up>>,
+			     __not_<__assigns_from_optional<_Tp, _Up>>
+			     >::value,
 			   bool> = true>
         optional&
         operator=(optional<_Up>&& __u)
diff --git a/libstdc++-v3/testsuite/20_util/optional/77288.cc b/libstdc++-v3/testsuite/20_util/optional/77288.cc
new file mode 100644
index 0000000..eafafb7
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/optional/77288.cc
@@ -0,0 +1,406 @@
+// { dg-options "-std=gnu++17" }
+// { dg-do run }
+
+// 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 moved_to of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <exception>
+#include <optional>
+#include <any>
+
+using std::optional;
+
+#include <testsuite_hooks.h>
+
+void test01()
+{
+    optional<optional<std::exception_ptr>> nested_element;
+    optional<std::exception_ptr> element = {};
+    nested_element = element;
+    VERIFY(nested_element);
+}
+
+template <class T>
+struct service_result
+{
+  static optional<T> get_result()
+  {
+    T sr;
+    return sr;
+  }
+
+  static optional<T> get_result_with_cond(bool cond)
+  {
+    if (cond)
+      return T{};
+    return {};
+  }
+};
+
+void test02()
+{
+  VERIFY(service_result<int>::get_result());
+  VERIFY(service_result<optional<int>>::get_result());
+  VERIFY(service_result<int>::get_result_with_cond(true));
+  VERIFY(service_result<optional<int>>::get_result_with_cond(true));
+  VERIFY(!service_result<int>::get_result_with_cond(false));
+  VERIFY(!service_result<optional<int>>::get_result_with_cond(false));
+}
+
+struct Widget
+{
+  Widget(int) {}
+  Widget(optional<int>) {}
+};
+
+
+void test03()
+{
+  optional<Widget> w;
+  w = optional<int>();
+  VERIFY(w);
+  static_assert(!std::is_assignable_v<optional<Widget>&,
+		optional<short>>);;
+  w = optional<optional<int>>();
+  VERIFY(!w);
+  static_assert(!std::is_assignable_v<optional<Widget>&,
+		optional<optional<short>>>);;
+
+  optional<Widget> w2{optional<int>()};
+  VERIFY(w2);
+  optional<Widget> w3  = optional<int>();
+  VERIFY(w3);
+  optional<Widget> w4{optional<short>()};
+  VERIFY(w4);
+  static_assert(!std::is_convertible_v<optional<short>&&, optional<Widget>>);
+
+  optional<Widget> w6{optional<optional<int>>()};
+  VERIFY(!w6);
+  optional<Widget> w7  = optional<optional<int>>();
+  VERIFY(!w7);
+  optional<Widget> w8{optional<optional<short>>()};
+  VERIFY(!w8);
+  static_assert(!std::is_convertible_v<optional<optional<short>>&&,
+		optional<Widget>>);
+  optional<Widget> w10{optional<optional<short>>(10)};
+  VERIFY(w10);
+  optional<Widget> w11 = std::nullopt;
+  VERIFY(!w11);
+  optional<Widget> w12 = {};
+  VERIFY(!w12);
+  optional<Widget> w13{std::nullopt};
+  VERIFY(!w13);
+  optional<Widget> w14;
+  w14 = {};
+  VERIFY(!w14);
+}
+
+struct Widget2
+{
+  Widget2(int) {}
+  Widget2(optional<int>) {}
+  Widget2& operator=(int) {return *this;}
+  Widget2& operator=(optional<int>) {return *this;}
+};
+
+void test04()
+{
+  optional<Widget2> w;
+  w = optional<int>();
+  VERIFY(w);
+  w = optional<short>();
+  VERIFY(w);
+  w = optional<optional<int>>();
+  VERIFY(!w);
+  w = optional<optional<short>>();
+  VERIFY(!w);
+  w = optional<optional<short>>(10);
+  optional<Widget2> w2 = std::nullopt;
+  VERIFY(!w2);
+  optional<Widget2> w3 = {};
+  VERIFY(!w3);
+  optional<Widget2> w4{std::nullopt};
+  VERIFY(!w4);
+  optional<Widget2> w5;
+  w5 = {};
+  VERIFY(!w5);
+}
+
+struct Thingy
+{
+  Thingy(int) {}
+  Thingy(Widget) {}
+};
+
+void test05()
+{
+  optional<Thingy> ot;
+
+  static_assert(!std::is_assignable_v<optional<Thingy>&,
+		optional<int>>);
+  static_assert(std::is_assignable_v<optional<Thingy>&,
+		optional<short>>);
+  static_assert(!std::is_assignable_v<optional<Thingy>&,
+		optional<optional<int>>>);
+  ot = optional<Widget>();
+  VERIFY(!ot);
+  optional<Thingy> ot2{optional<int>()};
+  VERIFY(ot2);
+  static_assert(!std::is_convertible_v<optional<int>&&,
+		optional<Thingy>>);
+  optional<Thingy> ot3{optional<short>()};
+  VERIFY(!ot3);
+  optional<Thingy> ot4 = optional<short>();
+  VERIFY(!ot4);
+
+  optional<Thingy> ot5{optional<optional<int>>()};
+  VERIFY(!ot5);
+  static_assert(!std::is_convertible_v<optional<optional<int>>&&,
+		optional<Thingy>>);
+
+  optional<Thingy> ot7{optional<Widget>()};
+  VERIFY(!ot7);
+  optional<Thingy> ot8 = optional<Widget>();
+  VERIFY(!ot8);
+  static_assert(!std::is_constructible_v<optional<Thingy>,
+		optional<optional<short>>>);
+  static_assert(!std::is_convertible_v<optional<optional<short>>,
+		optional<Thingy>>);
+  static_assert(!std::is_assignable_v<optional<Thingy>&,
+		optional<optional<short>>>);
+  optional<Thingy> ot9 = std::nullopt;
+  VERIFY(!ot9);
+  optional<Thingy> ot10 = {};
+  VERIFY(!ot10);
+  optional<Thingy> ot11{std::nullopt};
+  VERIFY(!ot11);
+  optional<Thingy> ot12;
+  ot12 = {};
+  VERIFY(!ot12);
+}
+
+struct RvalueConstructible
+{
+  RvalueConstructible(int) {}
+  RvalueConstructible(optional<int>&&) {}
+};
+
+void test06()
+{
+  optional<int> oi;
+  optional<RvalueConstructible> ori;
+  static_assert(!std::is_assignable_v<optional<RvalueConstructible>&,
+		optional<int>&>);
+  ori = std::move(oi);
+  VERIFY(ori);
+
+  optional<optional<int>> ooi;
+  static_assert(!std::is_assignable_v<optional<RvalueConstructible>&,
+		optional<optional<int>>&>);
+  ori = std::move(ooi);
+  VERIFY(!ori);
+
+  static_assert(!std::is_constructible_v<optional<RvalueConstructible>,
+		optional<int>&>);
+  static_assert(!std::is_convertible_v<optional<int>&,
+		optional<RvalueConstructible>>);
+
+  optional<RvalueConstructible> ori2(std::move(oi));
+  VERIFY(ori2);
+  optional<RvalueConstructible> ori3 = std::move(oi);
+  VERIFY(ori3);
+
+  static_assert(!std::is_constructible_v<optional<RvalueConstructible>,
+		optional<optional<int>>&>);
+  static_assert(!std::is_convertible_v<optional<optional<int>>&,
+		optional<RvalueConstructible>>);
+  optional<RvalueConstructible> ori6(std::move(ooi));
+  VERIFY(!ori6);
+  optional<RvalueConstructible> ori7 = std::move(ooi);
+  VERIFY(!ori7);
+  optional<RvalueConstructible> ori8 = std::nullopt;
+  VERIFY(!ori8);
+  optional<RvalueConstructible> ori9 = {};
+  VERIFY(!ori9);
+  optional<RvalueConstructible> ori10{std::nullopt};
+  VERIFY(!ori10);
+  optional<RvalueConstructible> ori11;
+  ori11 = {};
+  VERIFY(!ori11);
+}
+
+struct Thingy2
+{
+  Thingy2(int) {}
+  explicit Thingy2(optional<int>) {}
+  Thingy2(Widget) {}
+};
+
+void test07()
+{
+  optional<Thingy2> ot{optional<int>{}};
+  VERIFY(ot);
+  static_assert(!std::is_convertible_v<optional<int>,
+		optional<Thingy2>>);
+  optional<Thingy2> ot2{optional<short>{}};
+  VERIFY(ot2);
+  static_assert(!std::is_convertible_v<optional<short>,
+		optional<Thingy2>>);
+  optional<Thingy2> ot3{optional<optional<int>>{}};
+  VERIFY(!ot3);
+  static_assert(!std::is_convertible_v<optional<optional<int>>,
+		optional<Thingy2>>);
+  optional<Thingy2> ot4{optional<optional<short>>{}};
+  VERIFY(!ot4);
+  static_assert(!std::is_convertible_v<optional<optional<short>>,
+		optional<Thingy2>>);
+
+  optional<Thingy2> ot5{optional<Widget>{}};
+  VERIFY(!ot5);
+  optional<Thingy2> ot6 = optional<Widget>();
+  VERIFY(!ot6);
+
+  static_assert(!std::is_assignable_v<optional<Thingy2>&,
+		optional<int>>);
+  static_assert(!std::is_assignable_v<optional<Thingy2>&,
+		optional<short>>);
+  static_assert(!std::is_assignable_v<optional<Thingy2>&,
+		optional<optional<int>>>);
+  static_assert(!std::is_assignable_v<optional<Thingy2>&,
+		optional<optional<short>>>);
+  optional<Thingy2> ot7;
+  ot = optional<Widget>();
+  VERIFY(!ot7);
+  optional<Thingy2> ot8 = std::nullopt;
+  VERIFY(!ot8);
+  optional<Thingy2> ot9 = {};
+  VERIFY(!ot9);
+  optional<Thingy2> ot10{std::nullopt};
+  VERIFY(!ot10);
+  optional<Thingy2> ot11;
+  ot11 = {};
+  VERIFY(!ot11);
+}
+
+struct Thingy3
+{
+  Thingy3(int) {}
+  template<class... Args,
+	   std::enable_if_t<std::is_constructible_v<Widget, Args&&...>,
+			    bool> = true>
+  explicit Thingy3(Args&&... args) {}
+  Thingy3(Widget) {}
+};
+
+void test08()
+{
+  optional<Thingy3> ot{optional<int>{}};
+  VERIFY(ot);
+  static_assert(!std::is_convertible_v<optional<int>,
+		optional<Thingy3>>);
+  optional<Thingy3> ot2{optional<short>{}};
+  VERIFY(ot2);
+  static_assert(!std::is_convertible_v<optional<short>,
+		optional<Thingy3>>);
+  optional<Thingy3> ot3{optional<optional<int>>{}};
+  VERIFY(!ot3);
+  static_assert(!std::is_convertible_v<optional<optional<int>>,
+		optional<Thingy3>>);
+  optional<Thingy3> ot4{optional<optional<short>>{}};
+  VERIFY(!ot4);
+  static_assert(!std::is_convertible_v<optional<optional<short>>,
+		optional<Thingy3>>);
+
+  optional<Thingy3> ot5{optional<Widget>{}};
+  VERIFY(!ot5);
+  optional<Thingy3> ot6 = optional<Widget>();
+  VERIFY(!ot6);
+
+  static_assert(!std::is_assignable_v<optional<Thingy3>&,
+		optional<int>>);
+  static_assert(!std::is_assignable_v<optional<Thingy3>&,
+		optional<short>>);
+  static_assert(!std::is_assignable_v<optional<Thingy3>&,
+		optional<optional<int>>>);
+  static_assert(!std::is_assignable_v<optional<Thingy3>&,
+		optional<optional<short>>>);
+  optional<Thingy3> ot7;
+  ot = optional<Widget>();
+  VERIFY(!ot7);
+  optional<Thingy3> ot8 = std::nullopt;
+  VERIFY(!ot8);
+  optional<Thingy3> ot9 = {};
+  VERIFY(!ot9);
+  optional<Thingy3> ot10{std::nullopt};
+  VERIFY(!ot10);
+  optional<Thingy3> ot11;
+  ot11 = {};
+  VERIFY(!ot11);
+}
+
+void test09()
+{
+  std::any a = 42;
+  optional<std::any> oa2 = a;
+  VERIFY(oa2);
+  VERIFY(std::any_cast<int>(*oa2) == 42);
+  optional<std::any> oa3 = oa2;
+  VERIFY(oa3);
+  VERIFY(std::any_cast<int>(*oa3) == 42);
+  optional<std::any> oa4{oa2};
+  VERIFY(oa4);
+  VERIFY(std::any_cast<int>(*oa4) == 42);
+  optional<std::any> oa5(oa2);
+  VERIFY(oa5);
+  VERIFY(std::any_cast<int>(*oa5) == 42);
+  optional<std::any> oa6;
+  VERIFY(!oa6);
+  optional<std::any> oa7 = oa6;
+  VERIFY(!oa7);
+  optional<std::any> oa8{oa6};
+  VERIFY(!oa8);
+  optional<std::any> oa9(oa6);
+  VERIFY(!oa9);
+}
+
+void test10()
+{
+  struct X {};
+  optional<int> oi(std::in_place);
+  oi = {};
+  VERIFY(oi.has_value() == false);
+  optional<X> ot(std::in_place);
+  ot = {};
+  VERIFY(ot.has_value() == false);
+  optional<int> oi2(std::in_place);
+  short int si = 6;
+  oi2 = si;
+}
+
+int main()
+{
+  test01();
+  test02();
+  test03();
+  test04();
+  test05();
+  test06();
+  test07();
+  test08();
+  test09();
+  test10();
+}
diff --git a/libstdc++-v3/testsuite/20_util/optional/cons/value.cc b/libstdc++-v3/testsuite/20_util/optional/cons/value.cc
index 6a2d871..141293c 100644
--- a/libstdc++-v3/testsuite/20_util/optional/cons/value.cc
+++ b/libstdc++-v3/testsuite/20_util/optional/cons/value.cc
@@ -256,17 +256,21 @@ int main()
     ox4 = oi;
   }
   {
+    std::optional<int> oi = std::optional<short>();
+    VERIFY(!bool(oi));
+    std::optional<std::string> os = std::optional<const char*>();
+    VERIFY(!bool(os));
     std::optional<std::optional<int>> ooi = std::optional<int>();
-    VERIFY(!bool(ooi));
+    VERIFY(bool(ooi));
     ooi = std::optional<int>();
-    VERIFY(!bool(ooi));
+    VERIFY(bool(ooi));
     ooi = std::optional<int>(42);
     VERIFY(bool(ooi));
     VERIFY(bool(*ooi));
     std::optional<std::optional<int>> ooi2 = std::optional<short>();
-    VERIFY(!bool(ooi2));
+    VERIFY(bool(ooi2));
     ooi2 = std::optional<short>();
-    VERIFY(!bool(ooi2));
+    VERIFY(bool(ooi2));
     ooi2 = std::optional<short>(6);
     VERIFY(bool(ooi2));
     VERIFY(bool(*ooi2));

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [v3 PATCH] PR libstdc++/77288 and the newest proposed resolution for LWG 2756
  2016-09-06  7:05 ` Ville Voutilainen
@ 2016-09-21  9:43   ` Jonathan Wakely
  2016-09-21 19:51     ` Ville Voutilainen
  0 siblings, 1 reply; 15+ messages in thread
From: Jonathan Wakely @ 2016-09-21  9:43 UTC (permalink / raw)
  To: Ville Voutilainen; +Cc: libstdc++, gcc-patches

On 06/09/16 09:00 +0300, Ville Voutilainen wrote:
>    PR libstdc++/77288
>    * include/std/optional (__is_optional_impl, __is_optional): Remove.
>    (__converts_from_optional, __assigns_from_optional): New.
>    (optional(_Up&&)): Use is_same instead of __is_optional.
>    (optional(const optional<_Up>&)): Constrain with
>    __converts_from_optional.
>    (optional(optional<_Up>&&)): Likewise.
>    (operator=(_Up&&)): Use is_same instead of __is_optional, check
>    is_same and is_scalar.
>    (operator=(const optional<_Up>&)): Constrain with
>    __converts_from_optional and __assigns_from_optional.
>    (operator=(optional<_Up>&&)): Likewise.
>    * testsuite/20_util/optional/77288.cc: New.
>    * testsuite/20_util/optional/cons/value.cc: Adjust.

OK for trunk, thanks.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [v3 PATCH] PR libstdc++/77288 and the newest proposed resolution for LWG 2756
  2016-09-21  9:43   ` Jonathan Wakely
@ 2016-09-21 19:51     ` Ville Voutilainen
  2016-09-22  9:01       ` Christophe Lyon
  0 siblings, 1 reply; 15+ messages in thread
From: Ville Voutilainen @ 2016-09-21 19:51 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: libstdc++, gcc-patches

On 21 September 2016 at 12:31, Jonathan Wakely <jwakely@redhat.com> wrote:
> On 06/09/16 09:00 +0300, Ville Voutilainen wrote:
>>
>>    PR libstdc++/77288
>>    * include/std/optional (__is_optional_impl, __is_optional): Remove.
>>    (__converts_from_optional, __assigns_from_optional): New.
>>    (optional(_Up&&)): Use is_same instead of __is_optional.
>>    (optional(const optional<_Up>&)): Constrain with
>>    __converts_from_optional.
>>    (optional(optional<_Up>&&)): Likewise.
>>    (operator=(_Up&&)): Use is_same instead of __is_optional, check
>>    is_same and is_scalar.
>>    (operator=(const optional<_Up>&)): Constrain with
>>    __converts_from_optional and __assigns_from_optional.
>>    (operator=(optional<_Up>&&)): Likewise.
>>    * testsuite/20_util/optional/77288.cc: New.
>>    * testsuite/20_util/optional/cons/value.cc: Adjust.
>
>
> OK for trunk, thanks.

Thanks, applied - I will cook up a separate patch for making the same
fix for experimental::optional.
The plan is to then backport that one to the gcc-6 branch.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [v3 PATCH] PR libstdc++/77288 and the newest proposed resolution for LWG 2756
  2016-09-21 19:51     ` Ville Voutilainen
@ 2016-09-22  9:01       ` Christophe Lyon
  2016-09-22  9:21         ` Ville Voutilainen
  0 siblings, 1 reply; 15+ messages in thread
From: Christophe Lyon @ 2016-09-22  9:01 UTC (permalink / raw)
  To: Ville Voutilainen; +Cc: Jonathan Wakely, libstdc++, gcc-patches

Hi,


On 21 September 2016 at 21:42, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> On 21 September 2016 at 12:31, Jonathan Wakely <jwakely@redhat.com> wrote:
>> On 06/09/16 09:00 +0300, Ville Voutilainen wrote:
>>>
>>>    PR libstdc++/77288
>>>    * include/std/optional (__is_optional_impl, __is_optional): Remove.
>>>    (__converts_from_optional, __assigns_from_optional): New.
>>>    (optional(_Up&&)): Use is_same instead of __is_optional.
>>>    (optional(const optional<_Up>&)): Constrain with
>>>    __converts_from_optional.
>>>    (optional(optional<_Up>&&)): Likewise.
>>>    (operator=(_Up&&)): Use is_same instead of __is_optional, check
>>>    is_same and is_scalar.
>>>    (operator=(const optional<_Up>&)): Constrain with
>>>    __converts_from_optional and __assigns_from_optional.
>>>    (operator=(optional<_Up>&&)): Likewise.
>>>    * testsuite/20_util/optional/77288.cc: New.
>>>    * testsuite/20_util/optional/cons/value.cc: Adjust.
>>
>>
>> OK for trunk, thanks.
>
> Thanks, applied - I will cook up a separate patch for making the same
> fix for experimental::optional.
> The plan is to then backport that one to the gcc-6 branch.


The new test 77288.cc fails on old arm targets (armv5t):
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/20_util/optional/77288.cc:
In function 'void test01()':
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/20_util/optional/77288.cc:31:
error: 'exception_ptr' is not a member of 'std'
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/20_util/optional/77288.cc:31:
error: template argument 1 is invalid
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/20_util/optional/77288.cc:31:
error: template argument 1 is invalid
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/20_util/optional/77288.cc:32:
error: 'exception_ptr' is not a member of 'std'
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/20_util/optional/77288.cc:32:
error: template argument 1 is invalid

Christophe

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [v3 PATCH] PR libstdc++/77288 and the newest proposed resolution for LWG 2756
  2016-09-22  9:01       ` Christophe Lyon
@ 2016-09-22  9:21         ` Ville Voutilainen
  2016-09-22  9:43           ` Christophe Lyon
  0 siblings, 1 reply; 15+ messages in thread
From: Ville Voutilainen @ 2016-09-22  9:21 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: Jonathan Wakely, libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 979 bytes --]

On 22 September 2016 at 11:55, Christophe Lyon
<christophe.lyon@linaro.org> wrote:
> The new test 77288.cc fails on old arm targets (armv5t):
> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/20_util/optional/77288.cc:
> In function 'void test01()':
> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/20_util/optional/77288.cc:31:
> error: 'exception_ptr' is not a member of 'std'
> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/20_util/optional/77288.cc:31:
> error: template argument 1 is invalid
> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/20_util/optional/77288.cc:31:
> error: template argument 1 is invalid
> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/20_util/optional/77288.cc:32:
> error: 'exception_ptr' is not a member of 'std'
> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/20_util/optional/77288.cc:32:
> error: template argument 1 is invalid


Does the attached patch fix the problem?

[-- Attachment #2: 77288-test-fix.diff --]
[-- Type: text/x-patch, Size: 736 bytes --]

diff --git a/libstdc++-v3/testsuite/20_util/optional/77288.cc b/libstdc++-v3/testsuite/20_util/optional/77288.cc
index eafafb7..0df74a9 100644
--- a/libstdc++-v3/testsuite/20_util/optional/77288.cc
+++ b/libstdc++-v3/testsuite/20_util/optional/77288.cc
@@ -18,7 +18,6 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-#include <exception>
 #include <optional>
 #include <any>
 
@@ -28,8 +27,8 @@ using std::optional;
 
 void test01()
 {
-    optional<optional<std::exception_ptr>> nested_element;
-    optional<std::exception_ptr> element = {};
+    optional<optional<int>> nested_element;
+    optional<int> element = {};
     nested_element = element;
     VERIFY(nested_element);
 }

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [v3 PATCH] PR libstdc++/77288 and the newest proposed resolution for LWG 2756
  2016-09-22  9:21         ` Ville Voutilainen
@ 2016-09-22  9:43           ` Christophe Lyon
  2016-09-22 10:03             ` Ville Voutilainen
  0 siblings, 1 reply; 15+ messages in thread
From: Christophe Lyon @ 2016-09-22  9:43 UTC (permalink / raw)
  To: Ville Voutilainen; +Cc: Jonathan Wakely, libstdc++, gcc-patches

On 22 September 2016 at 11:05, Ville Voutilainen
<ville.voutilainen@gmail.com> wrote:
> On 22 September 2016 at 11:55, Christophe Lyon
> <christophe.lyon@linaro.org> wrote:
>> The new test 77288.cc fails on old arm targets (armv5t):
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/20_util/optional/77288.cc:
>> In function 'void test01()':
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/20_util/optional/77288.cc:31:
>> error: 'exception_ptr' is not a member of 'std'
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/20_util/optional/77288.cc:31:
>> error: template argument 1 is invalid
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/20_util/optional/77288.cc:31:
>> error: template argument 1 is invalid
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/20_util/optional/77288.cc:32:
>> error: 'exception_ptr' is not a member of 'std'
>> /aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/20_util/optional/77288.cc:32:
>> error: template argument 1 is invalid
>
>
> Does the attached patch fix the problem?

Yes, thanks!

Christophe

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [v3 PATCH] PR libstdc++/77288 and the newest proposed resolution for LWG 2756
  2016-09-22  9:43           ` Christophe Lyon
@ 2016-09-22 10:03             ` Ville Voutilainen
  2016-09-22 10:36               ` Jonathan Wakely
  0 siblings, 1 reply; 15+ messages in thread
From: Ville Voutilainen @ 2016-09-22 10:03 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: Jonathan Wakely, libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 410 bytes --]

On 22 September 2016 at 12:37, Christophe Lyon
<christophe.lyon@linaro.org> wrote:
>> Does the attached patch fix the problem?
>
> Yes, thanks!

Here be the changelog. Jonathan, ok for trunk? Patch attached again
for convenience.

2016-09-22  Ville Voutilainen  <ville.voutilainen@gmail.com>

    Fix tests on old arm platforms for optional.
    * testsuite/20_util/optional/77288.cc: Don't use exception_ptr.

[-- Attachment #2: 77288-test-fix.diff --]
[-- Type: text/x-patch, Size: 736 bytes --]

diff --git a/libstdc++-v3/testsuite/20_util/optional/77288.cc b/libstdc++-v3/testsuite/20_util/optional/77288.cc
index eafafb7..0df74a9 100644
--- a/libstdc++-v3/testsuite/20_util/optional/77288.cc
+++ b/libstdc++-v3/testsuite/20_util/optional/77288.cc
@@ -18,7 +18,6 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-#include <exception>
 #include <optional>
 #include <any>
 
@@ -28,8 +27,8 @@ using std::optional;
 
 void test01()
 {
-    optional<optional<std::exception_ptr>> nested_element;
-    optional<std::exception_ptr> element = {};
+    optional<optional<int>> nested_element;
+    optional<int> element = {};
     nested_element = element;
     VERIFY(nested_element);
 }

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [v3 PATCH] PR libstdc++/77288 and the newest proposed resolution for LWG 2756
  2016-09-22 10:03             ` Ville Voutilainen
@ 2016-09-22 10:36               ` Jonathan Wakely
  2016-09-22 11:38                 ` Jonathan Wakely
  0 siblings, 1 reply; 15+ messages in thread
From: Jonathan Wakely @ 2016-09-22 10:36 UTC (permalink / raw)
  To: Ville Voutilainen; +Cc: Christophe Lyon, libstdc++, gcc-patches

On 22/09/16 12:41 +0300, Ville Voutilainen wrote:
>On 22 September 2016 at 12:37, Christophe Lyon
><christophe.lyon@linaro.org> wrote:
>>> Does the attached patch fix the problem?
>>
>> Yes, thanks!
>
>Here be the changelog. Jonathan, ok for trunk? Patch attached again
>for convenience.

OK, thanks.

(Somebody should fix PR58938 so exception_ptr is portable).

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [v3 PATCH] PR libstdc++/77288 and the newest proposed resolution for LWG 2756
  2016-09-22 10:36               ` Jonathan Wakely
@ 2016-09-22 11:38                 ` Jonathan Wakely
  2016-09-22 13:32                   ` Jonathan Wakely
  2016-09-22 20:32                   ` Christophe Lyon
  0 siblings, 2 replies; 15+ messages in thread
From: Jonathan Wakely @ 2016-09-22 11:38 UTC (permalink / raw)
  To: Ville Voutilainen; +Cc: Christophe Lyon, libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 593 bytes --]

On 22/09/16 11:16 +0100, Jonathan Wakely wrote:
>(Somebody should fix PR58938 so exception_ptr is portable).

Christophe, would you be able to test this patch?

It uses a single global mutex for exception_ptr objects, which doesn't
scale well but that probably isn't a problem for processors without
lock-free atomics for single words.

This also solves the problem of mismatched -march options, where the
header is compiled for a CPU that supports the atomics but
libstdc++.so was built for an older CPU that doesn't support them, and
linking fails (as in https://gcc.gnu.org/PR58938#c13).



[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 9380 bytes --]

diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index e9bb0ce..363900a 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,5 +1,26 @@
 2016-09-22  Jonathan Wakely  <jwakely@redhat.com>
 
+	PR libstdc++/58938
+	* libsupc++/eh_ptr.cc [ATOMIC_INT_LOCK_FREE < 2] (eh_ptr_mutex)
+	(exception_ptr::_M_addref, exception_ptr::_M_release): Use mutex if
+	atomic builtins not available.
+	* libsupc++/exception_ptr.h [ATOMIC_INT_LOCK_FREE < 2]: Remove #error.
+	* testsuite/18_support/exception_ptr/40296.cc: Remove
+	dg-require-atomic-builtins directive.
+	* testsuite/18_support/exception_ptr/60612-terminate.cc: Likewise.
+	* testsuite/18_support/exception_ptr/60612-unexpected.cc: Likewise.
+	* testsuite/18_support/exception_ptr/62258.cc: Likewise.
+	* testsuite/18_support/exception_ptr/64241.cc: Likewise.
+	* testsuite/18_support/exception_ptr/current_exception.cc: Likewise.
+	* testsuite/18_support/exception_ptr/lifespan.cc: Likewise.
+	* testsuite/18_support/exception_ptr/make_exception_ptr.cc: Likewise.
+	* testsuite/18_support/exception_ptr/move.cc: Likewise.
+	* testsuite/18_support/exception_ptr/requirements.cc: Likewise.
+	* testsuite/18_support/exception_ptr/requirements_neg.cc: Likewise.
+	* testsuite/18_support/exception_ptr/rethrow_exception.cc: Likewise.
+
+2016-09-22  Jonathan Wakely  <jwakely@redhat.com>
+
 	* python/libstdcxx/v6/printers.py (StdVariantPrinter): Adjust for
 	recent change to _Variant_storage.
 	* testsuite/libstdc++-prettyprinters/cxx17.cc: Test variant with
diff --git a/libstdc++-v3/libsupc++/eh_ptr.cc b/libstdc++-v3/libsupc++/eh_ptr.cc
index 3b8e0a01..ac4e375 100644
--- a/libstdc++-v3/libsupc++/eh_ptr.cc
+++ b/libstdc++-v3/libsupc++/eh_ptr.cc
@@ -25,14 +25,23 @@
 #include <bits/c++config.h>
 #include <bits/atomic_lockfree_defines.h>
 
-#if ATOMIC_INT_LOCK_FREE > 1
-
 #define _GLIBCXX_EH_PTR_COMPAT
 
 #include <exception>
 #include <bits/exception_ptr.h>
 #include "unwind-cxx.h"
 
+#if ATOMIC_INT_LOCK_FREE < 2
+# include <ext/concurrence.h>
+# define USE_EH_PTR_MUTEX
+static inline __gnu_cxx::__mutex& eh_ptr_mutex()
+{
+    static __gnu_cxx::__mutex mx;
+    return mx;
+}
+using __gnu_cxx::__scoped_lock;
+#endif
+
 using namespace __cxxabiv1;
 
 // Verify assumptions about member layout in exception types
@@ -103,7 +112,12 @@ std::__exception_ptr::exception_ptr::_M_addref() _GLIBCXX_USE_NOEXCEPT
     {
       __cxa_refcounted_exception *eh =
 	__get_refcounted_exception_header_from_obj (_M_exception_object);
+#ifdef USE_EH_PTR_MUTEX
+      __scoped_lock lock(eh_ptr_mutex());
+      ++eh->referenceCount;
+#else
       __atomic_add_fetch (&eh->referenceCount, 1, __ATOMIC_ACQ_REL);
+#endif
     }
 }
 
@@ -115,7 +129,12 @@ std::__exception_ptr::exception_ptr::_M_release() _GLIBCXX_USE_NOEXCEPT
     {
       __cxa_refcounted_exception *eh =
 	__get_refcounted_exception_header_from_obj (_M_exception_object);
+#ifdef USE_EH_PTR_MUTEX
+      auto count = (__scoped_lock(eh_ptr_mutex()), --eh->referenceCount);
+      if (count == 0)
+#else
       if (__atomic_sub_fetch (&eh->referenceCount, 1, __ATOMIC_ACQ_REL) == 0)
+#endif
         {
 	  if (eh->exc.exceptionDestructor)
 	    eh->exc.exceptionDestructor (_M_exception_object);
@@ -260,5 +279,3 @@ std::rethrow_exception(std::exception_ptr ep)
 }
 
 #undef _GLIBCXX_EH_PTR_COMPAT
-
-#endif
diff --git a/libstdc++-v3/libsupc++/exception_ptr.h b/libstdc++-v3/libsupc++/exception_ptr.h
index 21e4e8b..ae8fb1f5 100644
--- a/libstdc++-v3/libsupc++/exception_ptr.h
+++ b/libstdc++-v3/libsupc++/exception_ptr.h
@@ -39,10 +39,6 @@
 #include <typeinfo>
 #include <new>
 
-#if ATOMIC_INT_LOCK_FREE < 2
-#  error This platform does not support exception propagation.
-#endif
-
 extern "C++" {
 
 namespace std 
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/40296.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/40296.cc
index 74307cc..a6659b8 100644
--- a/libstdc++-v3/testsuite/18_support/exception_ptr/40296.cc
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/40296.cc
@@ -1,5 +1,4 @@
 // { dg-do compile { target c++11 } }
-// { dg-require-atomic-builtins "" }
 
 // Copyright (C) 2009-2016 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/60612-terminate.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/60612-terminate.cc
index c00e287..d58f32d 100644
--- a/libstdc++-v3/testsuite/18_support/exception_ptr/60612-terminate.cc
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/60612-terminate.cc
@@ -1,5 +1,4 @@
 // { dg-do run { target c++11 } }
-// { dg-require-atomic-builtins "" }
 
 // Copyright (C) 2014-2016 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/60612-unexpected.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/60612-unexpected.cc
index 2b5ec2d..cfaea5d4 100644
--- a/libstdc++-v3/testsuite/18_support/exception_ptr/60612-unexpected.cc
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/60612-unexpected.cc
@@ -1,5 +1,4 @@
 // { dg-do run { target c++11 } }
-// { dg-require-atomic-builtins "" }
 
 // Copyright (C) 2014-2016 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/62258.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/62258.cc
index c83d5fb..5c15b48 100644
--- a/libstdc++-v3/testsuite/18_support/exception_ptr/62258.cc
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/62258.cc
@@ -1,5 +1,4 @@
 // { dg-do run { target c++11 } }
-// { dg-require-atomic-builtins "" }
 
 // Copyright (C) 2015-2016 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/64241.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/64241.cc
index fbb01ae..b7352ed 100644
--- a/libstdc++-v3/testsuite/18_support/exception_ptr/64241.cc
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/64241.cc
@@ -17,7 +17,6 @@
 
 // { dg-options "-fno-exceptions -O0" }
 // { dg-do run { target c++11 } }
-// { dg-require-atomic-builtins "" }
 
 #include <exception>
 #include <testsuite_hooks.h>
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/current_exception.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/current_exception.cc
index 2383cee..02bcd27 100644
--- a/libstdc++-v3/testsuite/18_support/exception_ptr/current_exception.cc
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/current_exception.cc
@@ -1,5 +1,4 @@
 // { dg-do run { target c++11 } }
-// { dg-require-atomic-builtins "" }
 
 // 2008-05-25  Sebastian Redl  <sebastian.redl@getdesigned.at>
 
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/lifespan.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/lifespan.cc
index e350df3..5c8cb11 100644
--- a/libstdc++-v3/testsuite/18_support/exception_ptr/lifespan.cc
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/lifespan.cc
@@ -1,5 +1,4 @@
 // { dg-do run { target c++11 } }
-// { dg-require-atomic-builtins "" }
 
 // 2008-05-25  Sebastian Redl  <sebastian.redl@getdesigned.at>
 
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/make_exception_ptr.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/make_exception_ptr.cc
index b496bb3..b9538e6 100644
--- a/libstdc++-v3/testsuite/18_support/exception_ptr/make_exception_ptr.cc
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/make_exception_ptr.cc
@@ -1,5 +1,4 @@
 // { dg-do run { target c++11 } }
-// { dg-require-atomic-builtins "" }
 
 // Copyright (C) 2010-2016 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/move.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/move.cc
index 6318bc4..80c6e3e 100644
--- a/libstdc++-v3/testsuite/18_support/exception_ptr/move.cc
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/move.cc
@@ -1,5 +1,4 @@
 // { dg-do run { target c++11 } }
-// { dg-require-atomic-builtins "" }
 
 // Copyright (C) 2009-2016 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/requirements.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/requirements.cc
index b3b9e0c..5f5f054 100644
--- a/libstdc++-v3/testsuite/18_support/exception_ptr/requirements.cc
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/requirements.cc
@@ -1,5 +1,4 @@
 // { dg-do run { target c++11 } }
-// { dg-require-atomic-builtins "" }
 
 // Copyright (C) 2010-2016 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/requirements_neg.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/requirements_neg.cc
index b80d688..95ec8ab 100644
--- a/libstdc++-v3/testsuite/18_support/exception_ptr/requirements_neg.cc
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/requirements_neg.cc
@@ -1,5 +1,4 @@
 // { dg-do compile { target c++11 } }
-// { dg-require-atomic-builtins "" }
 
 // Copyright (C) 2010-2016 Free Software Foundation, Inc.
 //
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/rethrow_exception.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/rethrow_exception.cc
index f0b61b1..c3ce206 100644
--- a/libstdc++-v3/testsuite/18_support/exception_ptr/rethrow_exception.cc
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/rethrow_exception.cc
@@ -1,5 +1,4 @@
 // { dg-do run { target c++11 } }
-// { dg-require-atomic-builtins "" }
 
 // 2008-05-25  Sebastian Redl  <sebastian.redl@getdesigned.at>
 

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [v3 PATCH] PR libstdc++/77288 and the newest proposed resolution for LWG 2756
  2016-09-22 11:38                 ` Jonathan Wakely
@ 2016-09-22 13:32                   ` Jonathan Wakely
  2016-09-22 19:10                     ` Christophe Lyon
  2016-09-22 20:32                   ` Christophe Lyon
  1 sibling, 1 reply; 15+ messages in thread
From: Jonathan Wakely @ 2016-09-22 13:32 UTC (permalink / raw)
  To: Ville Voutilainen; +Cc: Christophe Lyon, libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1180 bytes --]

On 22/09/16 12:15 +0100, Jonathan Wakely wrote:
>On 22/09/16 11:16 +0100, Jonathan Wakely wrote:
>>(Somebody should fix PR58938 so exception_ptr is portable).
>
>Christophe, would you be able to test this patch?
>
>It uses a single global mutex for exception_ptr objects, which doesn't
>scale well but that probably isn't a problem for processors without
>lock-free atomics for single words.
>
>This also solves the problem of mismatched -march options, where the
>header is compiled for a CPU that supports the atomics but
>libstdc++.so was built for an older CPU that doesn't support them, and
>linking fails (as in https://gcc.gnu.org/PR58938#c13).

We'd also need something like this extra piece, to ensure we don't
leak exceptions. Currently __gxx_exception_cleanup assumes that if
ATOMIC_INT_LOCK_FREE < 2 the referenceCount can never be greater than
1, because there are not exception_ptr objects that could increase it.

If we enable exception_ptr unconditionally then that assumption
doesn't hold. This patch uses the exception_ptr code to do the
cleanup, under the same mutex as any other increments and decrements
of the reference count.

It's a bit of a hack though.


[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 2144 bytes --]

diff --git a/libstdc++-v3/libsupc++/Makefile.am b/libstdc++-v3/libsupc++/Makefile.am
index 2df31ff..dbfd00f 100644
--- a/libstdc++-v3/libsupc++/Makefile.am
+++ b/libstdc++-v3/libsupc++/Makefile.am
@@ -155,9 +155,9 @@ eh_terminate.o: eh_terminate.cc
 	$(CXXCOMPILE) -std=gnu++11 -c $<
 
 eh_throw.lo: eh_throw.cc
-	$(LTCXXCOMPILE) -std=gnu++11 -c $<
+	$(LTCXXCOMPILE) -std=gnu++11 -fno-access-control -c $<
 eh_throw.o: eh_throw.cc
-	$(CXXCOMPILE) -std=gnu++11 -c $<
+	$(CXXCOMPILE) -std=gnu++11 -fno-access-control -c $<
 
 guard.lo: guard.cc
 	$(LTCXXCOMPILE) -std=gnu++11 -c $<
diff --git a/libstdc++-v3/libsupc++/Makefile.in b/libstdc++-v3/libsupc++/Makefile.in
index e828ed9..f3e2193 100644
--- a/libstdc++-v3/libsupc++/Makefile.in
+++ b/libstdc++-v3/libsupc++/Makefile.in
@@ -884,9 +884,9 @@ eh_terminate.o: eh_terminate.cc
 	$(CXXCOMPILE) -std=gnu++11 -c $<
 
 eh_throw.lo: eh_throw.cc
-	$(LTCXXCOMPILE) -std=gnu++11 -c $<
+	$(LTCXXCOMPILE) -std=gnu++11 -fno-access-control -c $<
 eh_throw.o: eh_throw.cc
-	$(CXXCOMPILE) -std=gnu++11 -c $<
+	$(CXXCOMPILE) -std=gnu++11 -fno-access-control -c $<
 
 guard.lo: guard.cc
 	$(LTCXXCOMPILE) -std=gnu++11 -c $<
diff --git a/libstdc++-v3/libsupc++/eh_throw.cc b/libstdc++-v3/libsupc++/eh_throw.cc
index a05f4eb..0f61fbf 100644
--- a/libstdc++-v3/libsupc++/eh_throw.cc
+++ b/libstdc++-v3/libsupc++/eh_throw.cc
@@ -24,6 +24,7 @@
 
 #include <bits/c++config.h>
 #include "unwind-cxx.h"
+#include "exception_ptr.h"
 
 using namespace __cxxabiv1;
 
@@ -42,17 +43,8 @@ __gxx_exception_cleanup (_Unwind_Reason_Code code, _Unwind_Exception *exc)
   if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON)
     __terminate (header->exc.terminateHandler);
 
-#if ATOMIC_INT_LOCK_FREE > 1
-  if (__atomic_sub_fetch (&header->referenceCount, 1, __ATOMIC_ACQ_REL) == 0)
-    {
-#endif
-      if (header->exc.exceptionDestructor)
-	header->exc.exceptionDestructor (header + 1);
-
-      __cxa_free_exception (header + 1);
-#if ATOMIC_INT_LOCK_FREE > 1
-    }
-#endif
+  std::__exception_ptr::exception_ptr ptr;
+  ptr._M_exception_object = header + 1;
 }
 
 extern "C" __cxa_refcounted_exception*

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [v3 PATCH] PR libstdc++/77288 and the newest proposed resolution for LWG 2756
  2016-09-22 13:32                   ` Jonathan Wakely
@ 2016-09-22 19:10                     ` Christophe Lyon
  2016-09-23 10:48                       ` Jonathan Wakely
  0 siblings, 1 reply; 15+ messages in thread
From: Christophe Lyon @ 2016-09-22 19:10 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: Ville Voutilainen, libstdc++, gcc-patches

On 22 September 2016 at 15:25, Jonathan Wakely <jwakely@redhat.com> wrote:
> On 22/09/16 12:15 +0100, Jonathan Wakely wrote:
>>
>> On 22/09/16 11:16 +0100, Jonathan Wakely wrote:
>>>
>>> (Somebody should fix PR58938 so exception_ptr is portable).
>>
>>
>> Christophe, would you be able to test this patch?
>>
>> It uses a single global mutex for exception_ptr objects, which doesn't
>> scale well but that probably isn't a problem for processors without
>> lock-free atomics for single words.
>>
>> This also solves the problem of mismatched -march options, where the
>> header is compiled for a CPU that supports the atomics but
>> libstdc++.so was built for an older CPU that doesn't support them, and
>> linking fails (as in https://gcc.gnu.org/PR58938#c13).
>
>
> We'd also need something like this extra piece, to ensure we don't
> leak exceptions. Currently __gxx_exception_cleanup assumes that if
> ATOMIC_INT_LOCK_FREE < 2 the referenceCount can never be greater than
> 1, because there are not exception_ptr objects that could increase it.
>
> If we enable exception_ptr unconditionally then that assumption
> doesn't hold. This patch uses the exception_ptr code to do the
> cleanup, under the same mutex as any other increments and decrements
> of the reference count.
>
> It's a bit of a hack though.
>
Should I have applied this one on top of the other?

I ran a validation with it alone, and
arm-none-eabi with default mode, cpu, and fpu does not build:
In file included from
/tmp/9260164_29.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/libsupc++/eh_throw.cc:27:0:
/tmp/9260164_29.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/libsupc++/exception_ptr.h:43:4:
error: #error This platform does
not support exception propagation.
 #  error This platform does not support exception propagation.
    ^~~~~
make[4]: *** [eh_throw.lo] Error 1


In addition, on arm-none-eabi --with-mode=thumb --with-cpu=cortex-a9,
I've noticed a regression in c++
  - PASS now FAIL             [PASS => FAIL]:

  g++.dg/opt/pr36449.C  -std=gnu++11 execution test
  g++.dg/opt/pr36449.C  -std=gnu++14 execution test
  g++.dg/opt/pr36449.C  -std=gnu++98 execution test

My logs show:
qemu: uncaught target signal 11 (Segmentation fault) - core dumped

The validation of the other patch is still running: I had to re-run it
because the
patch didn't apply because of the ChangeLog entry.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [v3 PATCH] PR libstdc++/77288 and the newest proposed resolution for LWG 2756
  2016-09-22 11:38                 ` Jonathan Wakely
  2016-09-22 13:32                   ` Jonathan Wakely
@ 2016-09-22 20:32                   ` Christophe Lyon
  1 sibling, 0 replies; 15+ messages in thread
From: Christophe Lyon @ 2016-09-22 20:32 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: Ville Voutilainen, libstdc++, gcc-patches

On 22 September 2016 at 13:15, Jonathan Wakely <jwakely@redhat.com> wrote:
> On 22/09/16 11:16 +0100, Jonathan Wakely wrote:
>>
>> (Somebody should fix PR58938 so exception_ptr is portable).
>
>
> Christophe, would you be able to test this patch?
>
> It uses a single global mutex for exception_ptr objects, which doesn't
> scale well but that probably isn't a problem for processors without
> lock-free atomics for single words.
>
> This also solves the problem of mismatched -march options, where the
> header is compiled for a CPU that supports the atomics but
> libstdc++.so was built for an older CPU that doesn't support them, and
> linking fails (as in https://gcc.gnu.org/PR58938#c13).
>
>
Hi Jonathan,

This is not quite right.
In most cases, it moves
18_support/exception_ptr/requirements_neg.cc  (test for errors, line 30)
to line 27 (not sure why, since you removed 1 line only)

but on older arm architectures, the tests you updated fail to compile:
  18_support/exception_ptr/40296.cc (test for excess errors)
  18_support/exception_ptr/60612-terminate.cc (test for excess errors)
  18_support/exception_ptr/60612-unexpected.cc (test for excess errors)
  18_support/exception_ptr/62258.cc (test for excess errors)
  18_support/exception_ptr/64241.cc (test for excess errors)
  18_support/exception_ptr/current_exception.cc (test for excess errors)
  18_support/exception_ptr/lifespan.cc (test for excess errors)
  18_support/exception_ptr/make_exception_ptr.cc (test for excess errors)
  18_support/exception_ptr/move.cc (test for excess errors)
  18_support/exception_ptr/requirements.cc (test for excess errors)
  18_support/exception_ptr/requirements_neg.cc  (test for errors, line 27)
  18_support/exception_ptr/requirements_neg.cc  (test for errors, line 28)
  18_support/exception_ptr/requirements_neg.cc  (test for errors, line 29)
  18_support/exception_ptr/requirements_neg.cc (test for excess errors)
  18_support/exception_ptr/rethrow_exception.cc (test for excess errors)

For instance:
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/18_support/exception_ptr/40296.cc:
In function 'bool test01()':
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/18_support/exception_ptr/40296.cc:25:
error: 'exception_ptr' is not a member of 'std'
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/18_support/exception_ptr/40296.cc:25:
note: suggested alternative: 'fexcept_t'
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/18_support/exception_ptr/40296.cc:27:
error: 'p' was not declared in this scope

/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/18_support/exception_ptr/60612-terminate.cc:
In function 'void f()':
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/18_support/exception_ptr/60612-terminate.cc:34:
error: 'rethrow_exception' is not a member of 'std'
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/18_support/exception_ptr/60612-terminate.cc:34:
note: suggested alternative: '__exception'
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/18_support/exception_ptr/60612-terminate.cc:34:
error: 'current_exception' is not a member of 'std'
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/18_support/exception_ptr/60612-terminate.cc:34:
note: suggested alternative: '_ZTISt9exception'

For more details:
http://people.linaro.org/~christophe.lyon/cross-validation/gcc-test-patches/240339-pr58938-v2/report-build-info.html

Thanks,

Christophe

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [v3 PATCH] PR libstdc++/77288 and the newest proposed resolution for LWG 2756
  2016-09-22 19:10                     ` Christophe Lyon
@ 2016-09-23 10:48                       ` Jonathan Wakely
  2016-09-27  0:22                         ` Christophe Lyon
  0 siblings, 1 reply; 15+ messages in thread
From: Jonathan Wakely @ 2016-09-23 10:48 UTC (permalink / raw)
  To: Christophe Lyon; +Cc: Ville Voutilainen, libstdc++, gcc-patches

On 22/09/16 20:22 +0200, Christophe Lyon wrote:
>On 22 September 2016 at 15:25, Jonathan Wakely <jwakely@redhat.com> wrote:
>> On 22/09/16 12:15 +0100, Jonathan Wakely wrote:
>>>
>>> On 22/09/16 11:16 +0100, Jonathan Wakely wrote:
>>>>
>>>> (Somebody should fix PR58938 so exception_ptr is portable).
>>>
>>>
>>> Christophe, would you be able to test this patch?
>>>
>>> It uses a single global mutex for exception_ptr objects, which doesn't
>>> scale well but that probably isn't a problem for processors without
>>> lock-free atomics for single words.
>>>
>>> This also solves the problem of mismatched -march options, where the
>>> header is compiled for a CPU that supports the atomics but
>>> libstdc++.so was built for an older CPU that doesn't support them, and
>>> linking fails (as in https://gcc.gnu.org/PR58938#c13).
>>
>>
>> We'd also need something like this extra piece, to ensure we don't
>> leak exceptions. Currently __gxx_exception_cleanup assumes that if
>> ATOMIC_INT_LOCK_FREE < 2 the referenceCount can never be greater than
>> 1, because there are not exception_ptr objects that could increase it.
>>
>> If we enable exception_ptr unconditionally then that assumption
>> doesn't hold. This patch uses the exception_ptr code to do the
>> cleanup, under the same mutex as any other increments and decrements
>> of the reference count.
>>
>> It's a bit of a hack though.
>>
>Should I have applied this one on top of the other?
>
>I ran a validation with it alone, and
>arm-none-eabi with default mode, cpu, and fpu does not build:

That's expected, the second patch requires the first one (you can't
use exception_ptr unconditionally if it's only defined conditionally
:-)


>In file included from
>/tmp/9260164_29.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/libsupc++/eh_throw.cc:27:0:
>/tmp/9260164_29.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/libsupc++/exception_ptr.h:43:4:
>error: #error This platform does
>not support exception propagation.
> #  error This platform does not support exception propagation.
>    ^~~~~
>make[4]: *** [eh_throw.lo] Error 1
>
>
>In addition, on arm-none-eabi --with-mode=thumb --with-cpu=cortex-a9,
>I've noticed a regression in c++
>  - PASS now FAIL             [PASS => FAIL]:
>
>  g++.dg/opt/pr36449.C  -std=gnu++11 execution test
>  g++.dg/opt/pr36449.C  -std=gnu++14 execution test
>  g++.dg/opt/pr36449.C  -std=gnu++98 execution test
>
>My logs show:
>qemu: uncaught target signal 11 (Segmentation fault) - core dumped

Strange, I don't see how my patch could cause that.


>The validation of the other patch is still running: I had to re-run it
>because the
>patch didn't apply because of the ChangeLog entry.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [v3 PATCH] PR libstdc++/77288 and the newest proposed resolution for LWG 2756
  2016-09-23 10:48                       ` Jonathan Wakely
@ 2016-09-27  0:22                         ` Christophe Lyon
  0 siblings, 0 replies; 15+ messages in thread
From: Christophe Lyon @ 2016-09-27  0:22 UTC (permalink / raw)
  To: Jonathan Wakely; +Cc: Ville Voutilainen, libstdc++, gcc-patches

Hi Jonathan,


On 23 September 2016 at 12:41, Jonathan Wakely <jwakely@redhat.com> wrote:
> On 22/09/16 20:22 +0200, Christophe Lyon wrote:
>>
>> On 22 September 2016 at 15:25, Jonathan Wakely <jwakely@redhat.com> wrote:
>>>
>>> On 22/09/16 12:15 +0100, Jonathan Wakely wrote:
>>>>
>>>>
>>>> On 22/09/16 11:16 +0100, Jonathan Wakely wrote:
>>>>>
>>>>>
>>>>> (Somebody should fix PR58938 so exception_ptr is portable).
>>>>
>>>>
>>>>
>>>> Christophe, would you be able to test this patch?
>>>>
>>>> It uses a single global mutex for exception_ptr objects, which doesn't
>>>> scale well but that probably isn't a problem for processors without
>>>> lock-free atomics for single words.
>>>>
>>>> This also solves the problem of mismatched -march options, where the
>>>> header is compiled for a CPU that supports the atomics but
>>>> libstdc++.so was built for an older CPU that doesn't support them, and
>>>> linking fails (as in https://gcc.gnu.org/PR58938#c13).
>>>
>>>
>>>
>>> We'd also need something like this extra piece, to ensure we don't
>>> leak exceptions. Currently __gxx_exception_cleanup assumes that if
>>> ATOMIC_INT_LOCK_FREE < 2 the referenceCount can never be greater than
>>> 1, because there are not exception_ptr objects that could increase it.
>>>
>>> If we enable exception_ptr unconditionally then that assumption
>>> doesn't hold. This patch uses the exception_ptr code to do the
>>> cleanup, under the same mutex as any other increments and decrements
>>> of the reference count.
>>>
>>> It's a bit of a hack though.
>>>
>> Should I have applied this one on top of the other?
>>
>> I ran a validation with it alone, and
>> arm-none-eabi with default mode, cpu, and fpu does not build:
>
>
> That's expected, the second patch requires the first one (you can't
> use exception_ptr unconditionally if it's only defined conditionally
> :-)
>
>
>> In file included from
>>
>> /tmp/9260164_29.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/libsupc++/eh_throw.cc:27:0:
>>
>> /tmp/9260164_29.tmpdir/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/libsupc++/exception_ptr.h:43:4:
>> error: #error This platform does
>> not support exception propagation.
>> #  error This platform does not support exception propagation.
>>    ^~~~~
>> make[4]: *** [eh_throw.lo] Error 1
>>
>>
>> In addition, on arm-none-eabi --with-mode=thumb --with-cpu=cortex-a9,
>> I've noticed a regression in c++
>>  - PASS now FAIL             [PASS => FAIL]:
>>
>>  g++.dg/opt/pr36449.C  -std=gnu++11 execution test
>>  g++.dg/opt/pr36449.C  -std=gnu++14 execution test
>>  g++.dg/opt/pr36449.C  -std=gnu++98 execution test
>>
>> My logs show:
>> qemu: uncaught target signal 11 (Segmentation fault) - core dumped
>
>
> Strange, I don't see how my patch could cause that.
>

I've run validations with the 2 patches applied, and you can see the
results here:
http://people.linaro.org/~christophe.lyon/cross-validation/gcc-test-patches/240339-pr58938-v3/report-build-info.html

As you can see there are several regressions, including:
  18_support/exception_ptr/40296.cc (test for excess errors)
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/18_support/exception_ptr/40296.cc:
In function 'bool test01()':
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/18_support/exception_ptr/40296.cc:25:
error: 'exception_ptr' is not a member of 'std'
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/18_support/exception_ptr/40296.cc:25:
note: suggested alternative: 'fexcept_t'
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/testsuite/18_support/exception_ptr/40296.cc:27:
error: 'p' was not declared in this scope

when compiling with -march=armv5t on arm*linux* targets.

On arm-none-eabi, I still see the regressions I reported when gcc is configured
--with-mode=thumb --with-cpu=cortex-a9
  g++.dg/opt/pr36449.C  -std=gnu++11 execution test
  g++.dg/opt/pr36449.C  -std=gnu++14 execution test
  g++.dg/opt/pr36449.C  -std=gnu++98 execution test
I have no detail besides
qemu: uncaught target signal 11 (Segmentation fault) - core dumped

Finally, on arm-none-eabi using default mode/cpu, some tests no longer
compile because:
/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-arm-none-eabi/gcc3/arm-none-eabi/./libstdc++-v3/src/.libs/libstdc++.a(eh_ptr.o):
In function `__gx
x_dependent_exception_cleanup':
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/libsupc++/eh_ptr.cc:241:
undefined reference to `__atomic_fetch_sub_4'
/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-arm-none-eabi/gcc3/arm-none-eabi/./libstdc++-v3/src/.libs/libstdc++.a(eh_ptr.o):
In function `eh_p
tr_mutex':
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/libsupc++/eh_ptr.cc:39:
undefined reference to `__sync_synchronize'
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/libsupc++/eh_ptr.cc:39:
undefined reference to `__sync_synchronize'
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/libsupc++/eh_ptr.cc:39:
undefined reference to `__sync_synchronize'
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/libsupc++/eh_ptr.cc:39:
undefined reference to `__sync_synchronize'
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/libsupc++/eh_ptr.cc:39:
undefined reference to `__sync_synchronize'
/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-arm-none-eabi/gcc3/arm-none-eabi/./libstdc++-v3/src/.libs/libstdc++.a(eh_ptr.o):/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/libsupc++/eh_ptr.cc:39:
more undefined references to `__sync_synchronize' follow
/aci-gcc-fsf/builds/gcc-fsf-gccsrc/obj-arm-none-eabi/gcc3/arm-none-eabi/./libstdc++-v3/src/.libs/libstdc++.a(eh_ptr.o):
In function `std::rethrow_exception(std::__exception_ptr::exception_ptr)':
/aci-gcc-fsf/sources/gcc-fsf/gccsrc/libstdc++-v3/libsupc++/eh_ptr.cc:260:
undefined reference to `__atomic_fetch_add_4'
collect2: error: ld returned 1 exit status

FAIL: g++.dg/abi/arm_cxa_vec1.C  -std=c++98 (test for excess errors)

Does this help?

Hopefully the above link will be easy enough for you to access to the
information you need. It's available for the next 2 months.

Thanks,

Christophe





>
>
>> The validation of the other patch is still running: I had to re-run it
>> because the
>> patch didn't apply because of the ChangeLog entry.

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2016-09-27  0:05 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-23 14:17 [v3 PATCH] PR libstdc++/77288 and the newest proposed resolution for LWG 2756 Ville Voutilainen
2016-09-06  7:05 ` Ville Voutilainen
2016-09-21  9:43   ` Jonathan Wakely
2016-09-21 19:51     ` Ville Voutilainen
2016-09-22  9:01       ` Christophe Lyon
2016-09-22  9:21         ` Ville Voutilainen
2016-09-22  9:43           ` Christophe Lyon
2016-09-22 10:03             ` Ville Voutilainen
2016-09-22 10:36               ` Jonathan Wakely
2016-09-22 11:38                 ` Jonathan Wakely
2016-09-22 13:32                   ` Jonathan Wakely
2016-09-22 19:10                     ` Christophe Lyon
2016-09-23 10:48                       ` Jonathan Wakely
2016-09-27  0:22                         ` Christophe Lyon
2016-09-22 20:32                   ` Christophe Lyon

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).