aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2024-01-19 12:28:30 +0000
committerJonathan Wakely <jwakely@redhat.com>2024-01-19 19:12:38 +0000
commit502a3c03e40e8920afb734c077b045f6c5efd087 (patch)
tree92e6cbf75c07350cd03435aac46a896fdcdf2c30
parentf1e5bf0d83ee4da81b6317c6d7f1278fe7eaa5a0 (diff)
downloadgcc-502a3c03e40e8920afb734c077b045f6c5efd087.zip
gcc-502a3c03e40e8920afb734c077b045f6c5efd087.tar.gz
gcc-502a3c03e40e8920afb734c077b045f6c5efd087.tar.bz2
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.
-rw-r--r--libstdc++-v3/include/std/tuple2
-rw-r--r--libstdc++-v3/testsuite/20_util/tuple/dangling_ref.cc156
2 files changed, 110 insertions, 48 deletions
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index 7a045b3..be92f1e 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 74fdc24..b2dcf35 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 }