]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Fix P2255R2 dangling checks for std::tuple in C++17 [PR108822]
authorJonathan Wakely <jwakely@redhat.com>
Fri, 19 Jan 2024 12:28:30 +0000 (12:28 +0000)
committerJonathan Wakely <jwakely@redhat.com>
Fri, 19 Jan 2024 19:12:38 +0000 (19:12 +0000)
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
libstdc++-v3/testsuite/20_util/tuple/dangling_ref.cc

index 7a045b3e6a13ca6381e699f4a4f5348d4fe564f8..be92f1eb973d24a0c68f3a3dfc95bec58acb1ae3 100644 (file)
@@ -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) \
index 74fdc24234932275eab2e81874e349cf856f8f1c..b2dcf35943852aee658ab8a11c652c0056a4bdd4 100644 (file)
@@ -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 }