public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [committed] libstdc++: Fix P2255R2 dangling checks for std::tuple in C++17 [PR108822]
@ 2024-01-19 19:13 Jonathan Wakely
  0 siblings, 0 replies; only message in thread
From: Jonathan Wakely @ 2024-01-19 19:13 UTC (permalink / raw)
  To: libstdc++, gcc-patches

Tested powerp64le-linux. Pushed to trunk.

-- >8 --

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.
---
 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&, int> t1(t0);
-  // { dg-error "here" "" { target { c++17_down && hosted } } 60 }
-  // { dg-error "use of deleted function" "" { target c++20 } 60 }
+  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<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&> 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&, 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<long, long> t20;
 
-  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&, int> t21(t20);
+  // { dg-error "here" "" { target { c++17_down && hosted } } 79 }
+  // { dg-error "use of deleted function" "" { target c++20 } 79 }
 
-  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<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&, 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<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<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<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 }
-- 
2.43.0


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2024-01-19 19:13 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-19 19:13 [committed] libstdc++: Fix P2255R2 dangling checks for std::tuple in C++17 [PR108822] Jonathan Wakely

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).