public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
From: Jonathan Wakely <redi@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org
Subject: [gcc r14-8292] libstdc++: Fix P2255R2 dangling checks for std::tuple in C++17 [PR108822]
Date: Fri, 19 Jan 2024 19:13:32 +0000 (GMT)	[thread overview]
Message-ID: <20240119191332.61EC83858C98@sourceware.org> (raw)

https://gcc.gnu.org/g:502a3c03e40e8920afb734c077b045f6c5efd087

commit r14-8292-g502a3c03e40e8920afb734c077b045f6c5efd087
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Jan 19 12:28:30 2024 +0000

    libstdc++: Fix P2255R2 dangling checks for std::tuple in C++17 [PR108822]
    
    I accidentally used && in a fold-expression instead of || which meant
    that in C++17 the tuple(UElements&&...) constructor only failed its
    debug assertion if all tuple elements were dangling references. Some
    missing tests (noted as "TODO") meant this wasn't tested.
    
    This fixes the fold expression and adds the missing tests.
    
    libstdc++-v3/ChangeLog:
    
            PR libstdc++/108822
            * include/std/tuple (__glibcxx_no_dangling_refs) [C++17]: Fix
            wrong fold-operator.
            * testsuite/20_util/tuple/dangling_ref.cc: Check tuples with one
            element and three elements. Check allocator-extended
            constructors.

Diff:
---
 libstdc++-v3/include/std/tuple                     |   2 +-
 .../testsuite/20_util/tuple/dangling_ref.cc        | 156 ++++++++++++++-------
 2 files changed, 110 insertions(+), 48 deletions(-)

diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 7a045b3e6a1..be92f1eb973 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -1299,7 +1299,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // Error if construction from U... would create a dangling ref.
 # if __cpp_fold_expressions
 #  define __glibcxx_dangling_refs(U) \
-  (__reference_constructs_from_temporary(_Elements, U) && ...)
+  (__reference_constructs_from_temporary(_Elements, U) || ...)
 # else
 #  define __glibcxx_dangling_refs(U) \
   __or_<__bool_constant<__reference_constructs_from_temporary(_Elements, U) \
diff --git a/libstdc++-v3/testsuite/20_util/tuple/dangling_ref.cc b/libstdc++-v3/testsuite/20_util/tuple/dangling_ref.cc
index 74fdc242349..b2dcf359438 100644
--- a/libstdc++-v3/testsuite/20_util/tuple/dangling_ref.cc
+++ b/libstdc++-v3/testsuite/20_util/tuple/dangling_ref.cc
@@ -7,6 +7,7 @@
 
 #if __cplusplus >= 202002L
 // For C++20 and later, constructors are constrained to disallow dangling.
+static_assert(!std::is_constructible_v<std::tuple<const int&>, long>);
 static_assert(!std::is_constructible_v<std::tuple<const int&, int>, long, int>);
 static_assert(!std::is_constructible_v<std::tuple<int, const int&>, int, long>);
 static_assert(!std::is_constructible_v<std::tuple<const int&, int>,
@@ -30,76 +31,137 @@ static_assert(!std::is_constructible_v<std::tuple<int, const int&>,
 void
 test_ary_ctors()
 {
-  std::tuple<const int&, int> t1(1L, 2);
-  // { dg-error "here" "" { target { c++17_down && hosted } } 33 }
-  // { dg-error "use of deleted function" "" { target c++20 } 33 }
+  std::tuple<const int&> t1(1L);
+  // { dg-error "here" "" { target { c++17_down && hosted } } 34 }
+  // { dg-error "use of deleted function" "" { target c++20 } 34 }
 
-  std::tuple<int, const int&> t2(1, 2L);
-  // { dg-error "here" "" { target { c++17_down && hosted } } 37 }
-  // { dg-error "use of deleted function" "" { target c++20 } 37 }
+  std::tuple<const int&, int> t2(1L, 2);
+  // { dg-error "here" "" { target { c++17_down && hosted } } 38 }
+  // { dg-error "use of deleted function" "" { target c++20 } 38 }
 
-  std::tuple<const int&, const int&> t3(1L, 2L);
-  // { dg-error "here" "" { target { c++17_down && hosted } } 41 }
-  // { dg-error "use of deleted function" "" { target c++20 } 41 }
+  std::tuple<int, const int&> t3(1, 2L);
+  // { dg-error "here" "" { target { c++17_down && hosted } } 42 }
+  // { dg-error "use of deleted function" "" { target c++20 } 42 }
 
-  std::tuple<const int&, const int&> t4(std::pair<long, int>{});
-  // { dg-error "here" "" { target { c++17_down && hosted } } 45 }
-  // { dg-error "use of deleted function" "" { target c++20 } 45 }
+  std::tuple<const int&, const int&> t4(1L, 2L);
+  // { dg-error "here" "" { target { c++17_down && hosted } } 46 }
+  // { dg-error "use of deleted function" "" { target c++20 } 46 }
 
-  std::pair<int, long> p;
-  std::tuple<const int&, const int&> t5(p);
+  std::tuple<const int&, const int&> t5(std::pair<long, int>{});
   // { dg-error "here" "" { target { c++17_down && hosted } } 50 }
   // { dg-error "use of deleted function" "" { target c++20 } 50 }
+
+  std::pair<int, long> p;
+  std::tuple<const int&, const int&> t6(p);
+  // { dg-error "here" "" { target { c++17_down && hosted } } 55 }
+  // { dg-error "use of deleted function" "" { target c++20 } 55 }
+
+  std::tuple<const int&, int, int> t7(1L, 2, 3);
+  // { dg-error "here" "" { target { c++17_down && hosted } } 59 }
+  // { dg-error "use of deleted function" "" { target c++20 } 59 }
 }
 
 void
 test_converting_ctors()
 {
-  std::tuple<long, long> t0;
+  std::tuple<long> t10;
+
+  std::tuple<const int&> t11(t10);
+  // { dg-error "here" "" { target { c++17_down && hosted } } 69 }
+  // { dg-error "use of deleted function" "" { target c++20 } 69 }
+
+  std::tuple<const int&> t12(std::move(t10));
+  // { dg-error "here" "" { target { c++17_down && hosted } } 73 }
+  // { dg-error "use of deleted function" "" { target c++20 } 73 }
 
-  std::tuple<const int&, int> t1(t0);
-  // { dg-error "here" "" { target { c++17_down && hosted } } 60 }
-  // { dg-error "use of deleted function" "" { target c++20 } 60 }
+  std::tuple<long, long> t20;
 
-  std::tuple<int, const int&> t2(t0);
-  // { dg-error "here" "" { target { c++17_down && hosted } } 64 }
-  // { dg-error "use of deleted function" "" { target c++20 } 64 }
+  std::tuple<const int&, int> t21(t20);
+  // { dg-error "here" "" { target { c++17_down && hosted } } 79 }
+  // { dg-error "use of deleted function" "" { target c++20 } 79 }
 
-  std::tuple<const int&, const int&> t3(t0);
-  // { dg-error "here" "" { target { c++17_down && hosted } } 68 }
-  // { dg-error "use of deleted function" "" { target c++20 } 68 }
+  std::tuple<int, const int&> t22(t20);
+  // { dg-error "here" "" { target { c++17_down && hosted } } 83 }
+  // { dg-error "use of deleted function" "" { target c++20 } 83 }
 
-  std::tuple<const int&, int> t4(std::move(t0));
-  // { dg-error "here" "" { target { c++17_down && hosted } } 72 }
-  // { dg-error "use of deleted function" "" { target c++20 } 72 }
+  std::tuple<const int&, const int&> t23(t20);
+  // { dg-error "here" "" { target { c++17_down && hosted } } 87 }
+  // { dg-error "use of deleted function" "" { target c++20 } 87 }
 
-  std::tuple<int, const int&> t5(std::move(t0));
-  // { dg-error "here" "" { target { c++17_down && hosted } } 76 }
-  // { dg-error "use of deleted function" "" { target c++20 } 76 }
+  std::tuple<const int&, int> t24(std::move(t20));
+  // { dg-error "here" "" { target { c++17_down && hosted } } 91 }
+  // { dg-error "use of deleted function" "" { target c++20 } 91 }
 
-  std::tuple<const int&, const int&> t6(std::move(t0));
-  // { dg-error "here" "" { target { c++17_down && hosted } } 80 }
-  // { dg-error "use of deleted function" "" { target c++20 } 80 }
+  std::tuple<int, const int&> t25(std::move(t20));
+  // { dg-error "here" "" { target { c++17_down && hosted } } 95 }
+  // { dg-error "use of deleted function" "" { target c++20 } 95 }
+
+  std::tuple<const int&, const int&> t26(std::move(t20));
+  // { dg-error "here" "" { target { c++17_down && hosted } } 99 }
+  // { dg-error "use of deleted function" "" { target c++20 } 99 }
 
   std::pair<long, long> p0;
-  std::tuple<const int&, int> t7(p0);
-  // { dg-error "here" "" { target { c++17_down && hosted } } 85 }
-  // { dg-error "use of deleted function" "" { target c++20 } 85 }
+  std::tuple<const int&, int> t27(p0);
+  // { dg-error "here" "" { target { c++17_down && hosted } } 104 }
+  // { dg-error "use of deleted function" "" { target c++20 } 104 }
 
-  std::tuple<int, const int&> t8(p0);
-  // { dg-error "here" "" { target { c++17_down && hosted } } 89 }
-  // { dg-error "use of deleted function" "" { target c++20 } 89 }
+  std::tuple<int, const int&> t28(p0);
+  // { dg-error "here" "" { target { c++17_down && hosted } } 108 }
+  // { dg-error "use of deleted function" "" { target c++20 } 108 }
 
-  std::tuple<const int&, int> t9(std::move(p0));
-  // { dg-error "here" "" { target { c++17_down && hosted } } 93 }
-  // { dg-error "use of deleted function" "" { target c++20 } 93 }
+  std::tuple<const int&, int> t29(std::move(p0));
+  // { dg-error "here" "" { target { c++17_down && hosted } } 112 }
+  // { dg-error "use of deleted function" "" { target c++20 } 112 }
 
-  std::tuple<int, const int&> t10(std::move(p0));
-  // { dg-error "here" "" { target { c++17_down && hosted } } 97 }
-  // { dg-error "use of deleted function" "" { target c++20 } 97 }
+  std::tuple<int, const int&> t210(std::move(p0));
+  // { dg-error "here" "" { target { c++17_down && hosted } } 116 }
+  // { dg-error "use of deleted function" "" { target c++20 } 116 }
 }
 
-// TODO: test allocator-extended ctors
-// TODO: test 1-tuple or 3-tuple, not just 2-tuple
+#include <memory>
+
+void
+test_allocator_extended_ctors()
+{
+  std::allocator<int> a;
+
+  std::tuple<const int&> t1(std::allocator_arg, a, 1L);
+  // { dg-error "here" "" { target { c++17_down && hosted } } 128 }
+  // { dg-error "use of deleted function" "" { target c++20 } 128 }
+
+  std::tuple<const int&, int> t2(std::allocator_arg, a, 1L, 2);
+  // { dg-error "here" "" { target { c++17_down && hosted } } 132 }
+  // { dg-error "use of deleted function" "" { target c++20 } 132 }
+
+  std::tuple<long> tl;
+
+  std::tuple<const int&> t3(std::allocator_arg, a, tl);
+  // { dg-error "here" "" { target { c++17_down && hosted } } 138 }
+  // { dg-error "use of deleted function" "" { target c++20 } 138 }
+
+  std::tuple<const int&> t4(std::allocator_arg, a, std::move(tl));
+  // { dg-error "here" "" { target { c++17_down && hosted } } 142 }
+  // { dg-error "use of deleted function" "" { target c++20 } 142 }
+
+  std::tuple<long, long> tll;
+
+  std::tuple<const int&, int> t5(std::allocator_arg, a, tll);
+  // { dg-error "here" "" { target { c++17_down && hosted } } 148 }
+  // { dg-error "use of deleted function" "" { target c++20 } 148 }
+
+  std::tuple<const int&, int> t6(std::allocator_arg, a, std::move(tll));
+  // { dg-error "here" "" { target { c++17_down && hosted } } 152 }
+  // { dg-error "use of deleted function" "" { target c++20 } 152 }
+
+  std::pair<long, long> pll;
+
+  std::tuple<const int&, int> t7(std::allocator_arg, a, pll);
+  // { dg-error "here" "" { target { c++17_down && hosted } } 158 }
+  // { dg-error "use of deleted function" "" { target c++20 } 158 }
+
+  std::tuple<const int&, int> t8(std::allocator_arg, a, std::move(pll));
+  // { dg-error "here" "" { target { c++17_down && hosted } } 162 }
+  // { dg-error "use of deleted function" "" { target c++20 } 162 }
+}
 
 // { dg-error "static assert.* dangling reference" "" { target { c++17_down && hosted } } 0 }

                 reply	other threads:[~2024-01-19 19:13 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=20240119191332.61EC83858C98@sourceware.org \
    --to=redi@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).