public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
From: Jakub Jelinek <jakub@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org
Subject: [gcc(refs/vendors/redhat/heads/gcc-8-branch)] libstdc++: Fix is_trivially_constructible (PR 94033)
Date: Thu, 17 Sep 2020 17:18:26 +0000 (GMT)	[thread overview]
Message-ID: <20200917171826.08FF8398B8A0@sourceware.org> (raw)

https://gcc.gnu.org/g:ccfe790fda66df542c08ce1f1cbc287d9a487755

commit ccfe790fda66df542c08ce1f1cbc287d9a487755
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Mar 18 23:19:12 2020 +0000

    libstdc++: Fix is_trivially_constructible (PR 94033)
    
    This attempts to make is_nothrow_constructible more robust (and
    efficient to compile) by not depending on is_constructible. Instead the
    __is_constructible intrinsic is used directly. The helper class
    __is_nt_constructible_impl which checks whether the construction is
    non-throwing now takes a bool template parameter that is substituted by
    the result of the instrinsic. This fixes the reported bug by not using
    the already-instantiated (and incorrect) value of std::is_constructible.
    I don't think it really fixes the problem in general, because
    std::is_nothrow_constructible itself could already have been
    instantiated in a context where it gives the wrong result. A proper fix
    needs to be done in the compiler.
    
    Backported to the gcc-8 and gcc-9 branches to fix PR 96999.
    
            PR libstdc++/94033
            * include/std/type_traits (__is_nt_default_constructible_atom): Remove.
            (__is_nt_default_constructible_impl): Remove.
            (__is_nothrow_default_constructible_impl): Remove.
            (__is_nt_constructible_impl): Add bool template parameter. Adjust
            partial specializations.
            (__is_nothrow_constructible_impl): Replace class template with alias
            template.
            (is_nothrow_default_constructible): Derive from alias template
            __is_nothrow_constructible_impl instead of
            __is_nothrow_default_constructible_impl.
            * testsuite/20_util/is_nothrow_constructible/94003.cc: New test.
    
    (cherry picked from commit b3341826531e80e02f194460b4fbe1b0541c0463)

Diff:
---
 libstdc++-v3/include/std/type_traits               | 57 ++++++++++------------
 .../20_util/is_nothrow_constructible/94003.cc      | 46 +++++++++++++++++
 .../is_nothrow_default_constructible/96999.cc      | 54 ++++++++++++++++++++
 3 files changed, 125 insertions(+), 32 deletions(-)

diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index e0394179963..6c32dd4a51f 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -915,55 +915,48 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     : public __is_move_constructible_impl<_Tp>
     { };
 
-  template<typename _Tp>
-    struct __is_nt_default_constructible_atom
-    : public integral_constant<bool, noexcept(_Tp())>
+  template<bool, typename _Tp, typename... _Args>
+    struct __is_nt_constructible_impl
+    : public false_type
     { };
 
-  template<typename _Tp, bool = is_array<_Tp>::value>
-    struct __is_nt_default_constructible_impl;
+  template<typename _Tp, typename... _Args>
+    struct __is_nt_constructible_impl<true, _Tp, _Args...>
+    : public __bool_constant<noexcept(_Tp(std::declval<_Args>()...))>
+    { };
 
-  template<typename _Tp>
-    struct __is_nt_default_constructible_impl<_Tp, true>
-    : public __and_<__is_array_known_bounds<_Tp>,
-		    __is_nt_default_constructible_atom<typename
-                      remove_all_extents<_Tp>::type>>
+  template<typename _Tp, typename _Arg>
+    struct __is_nt_constructible_impl<true, _Tp, _Arg>
+    : public __bool_constant<noexcept(static_cast<_Tp>(std::declval<_Arg>()))>
     { };
 
   template<typename _Tp>
-    struct __is_nt_default_constructible_impl<_Tp, false>
-    : public __is_nt_default_constructible_atom<_Tp>
+    struct __is_nt_constructible_impl<true, _Tp>
+    : public __bool_constant<noexcept(_Tp())>
     { };
 
-  /// is_nothrow_default_constructible
-  template<typename _Tp>
-    struct is_nothrow_default_constructible
-    : public __and_<is_default_constructible<_Tp>,
-                    __is_nt_default_constructible_impl<_Tp>>
+  template<typename _Tp, size_t _Num>
+    struct __is_nt_constructible_impl<true, _Tp[_Num]>
+    : public __bool_constant<noexcept(typename remove_all_extents<_Tp>::type())>
     { };
 
   template<typename _Tp, typename... _Args>
-    struct __is_nt_constructible_impl
-    : public integral_constant<bool, noexcept(_Tp(declval<_Args>()...))>
-    { };
+    using __is_nothrow_constructible_impl
+      = __is_nt_constructible_impl<__is_constructible(_Tp, _Args...),
+				   _Tp, _Args...>;
 
-  template<typename _Tp, typename _Arg>
-    struct __is_nt_constructible_impl<_Tp, _Arg>
-    : public integral_constant<bool,
-                               noexcept(static_cast<_Tp>(declval<_Arg>()))>
+  /// is_nothrow_constructible
+  template<typename _Tp, typename... _Args>
+    struct is_nothrow_constructible
+    : public __is_nothrow_constructible_impl<_Tp, _Args...>::type
     { };
 
+  /// is_nothrow_default_constructible
   template<typename _Tp>
-    struct __is_nt_constructible_impl<_Tp>
-    : public is_nothrow_default_constructible<_Tp>
+    struct is_nothrow_default_constructible
+    : public __is_nothrow_constructible_impl<_Tp>::type
     { };
 
-  /// is_nothrow_constructible
-  template<typename _Tp, typename... _Args>
-    struct is_nothrow_constructible
-    : public __and_<is_constructible<_Tp, _Args...>,
-		    __is_nt_constructible_impl<_Tp, _Args...>>
-    { };
 
   template<typename _Tp, bool = __is_referenceable<_Tp>::value>
     struct __is_nothrow_copy_constructible_impl;
diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_constructible/94003.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_constructible/94003.cc
new file mode 100644
index 00000000000..392a0878ba5
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_nothrow_constructible/94003.cc
@@ -0,0 +1,46 @@
+// Copyright (C) 2020 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/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++17 } }
+
+#include <optional>
+#include <tuple>
+
+template <bool B> struct abc {};
+
+template <typename T>
+
+struct future : public abc<std::is_trivially_constructible_v<std::tuple<T>>> {};
+
+class mutation {
+  mutation();
+  friend class std::optional<mutation>;
+};
+
+using mutation_opt = std::optional<mutation>;
+
+future<mutation_opt> foo();
+
+template <typename Consumer> future<mutation_opt> consume_partitions() {
+  return foo();
+}
+
+future<mutation_opt> bar() { return consume_partitions<int>(); }
+
+future<mutation> zed();
+future<mutation> apply_counter_update() { return zed(); }
diff --git a/libstdc++-v3/testsuite/20_util/is_nothrow_default_constructible/96999.cc b/libstdc++-v3/testsuite/20_util/is_nothrow_default_constructible/96999.cc
new file mode 100644
index 00000000000..9ec42760051
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/is_nothrow_default_constructible/96999.cc
@@ -0,0 +1,54 @@
+// Copyright (C) 2020 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/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++17 } }
+
+// PR libstdc++/96999
+
+#include <variant>
+#include <string>
+
+struct Foo {
+public:
+  explicit Foo(int) noexcept {}
+  Foo(Foo &&) noexcept = default;
+  Foo &operator=(Foo &&) = default;
+private:
+  Foo() noexcept {}
+};
+
+struct Boo {
+public:
+  explicit Boo(int) noexcept {}
+  Boo(Boo &&) noexcept = default;
+  Boo &operator=(Boo &&) = default;
+private:
+  Boo() noexcept {}
+};
+
+
+template<bool X>
+std::variant<Foo, Boo> g(int v, int x) {
+ return  v == 0 ? std::variant<Foo, Boo>{Foo{x}} :
+                                 std::variant<Foo, Boo>{Boo{x}};
+}
+
+int main()
+{
+  std::variant<std::variant<Foo, Boo>, std::string> err{std::string("aaa")};
+}


                 reply	other threads:[~2020-09-17 17:18 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200917171826.08FF8398B8A0@sourceware.org \
    --to=jakub@gcc.gnu.org \
    --cc=gcc-cvs@gcc.gnu.org \
    --cc=libstdc++-cvs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).