From: Jonathan Wakely Date: Fri, 19 Jan 2024 12:28:30 +0000 (+0000) Subject: libstdc++: Fix P2255R2 dangling checks for std::tuple in C++17 [PR108822] X-Git-Tag: basepoints/gcc-15~1847 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=502a3c03e40e8920afb734c077b045f6c5efd087;p=thirdparty%2Fgcc.git 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 --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 7a045b3e6a13..be92f1eb973d 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 74fdc2423493..b2dcf3594385 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, long>); static_assert(!std::is_constructible_v, long, int>); static_assert(!std::is_constructible_v, int, long>); static_assert(!std::is_constructible_v, @@ -30,76 +31,137 @@ static_assert(!std::is_constructible_v, void test_ary_ctors() { - std::tuple t1(1L, 2); - // { dg-error "here" "" { target { c++17_down && hosted } } 33 } - // { dg-error "use of deleted function" "" { target c++20 } 33 } + std::tuple t1(1L); + // { dg-error "here" "" { target { c++17_down && hosted } } 34 } + // { dg-error "use of deleted function" "" { target c++20 } 34 } - std::tuple t2(1, 2L); - // { dg-error "here" "" { target { c++17_down && hosted } } 37 } - // { dg-error "use of deleted function" "" { target c++20 } 37 } + std::tuple t2(1L, 2); + // { dg-error "here" "" { target { c++17_down && hosted } } 38 } + // { dg-error "use of deleted function" "" { target c++20 } 38 } - std::tuple t3(1L, 2L); - // { dg-error "here" "" { target { c++17_down && hosted } } 41 } - // { dg-error "use of deleted function" "" { target c++20 } 41 } + std::tuple t3(1, 2L); + // { dg-error "here" "" { target { c++17_down && hosted } } 42 } + // { dg-error "use of deleted function" "" { target c++20 } 42 } - std::tuple t4(std::pair{}); - // { dg-error "here" "" { target { c++17_down && hosted } } 45 } - // { dg-error "use of deleted function" "" { target c++20 } 45 } + std::tuple t4(1L, 2L); + // { dg-error "here" "" { target { c++17_down && hosted } } 46 } + // { dg-error "use of deleted function" "" { target c++20 } 46 } - std::pair p; - std::tuple t5(p); + std::tuple t5(std::pair{}); // { dg-error "here" "" { target { c++17_down && hosted } } 50 } // { dg-error "use of deleted function" "" { target c++20 } 50 } + + std::pair p; + std::tuple t6(p); + // { dg-error "here" "" { target { c++17_down && hosted } } 55 } + // { dg-error "use of deleted function" "" { target c++20 } 55 } + + std::tuple 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 t0; + std::tuple t10; + + std::tuple t11(t10); + // { dg-error "here" "" { target { c++17_down && hosted } } 69 } + // { dg-error "use of deleted function" "" { target c++20 } 69 } + + std::tuple 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 t1(t0); - // { dg-error "here" "" { target { c++17_down && hosted } } 60 } - // { dg-error "use of deleted function" "" { target c++20 } 60 } + std::tuple t20; - std::tuple t2(t0); - // { dg-error "here" "" { target { c++17_down && hosted } } 64 } - // { dg-error "use of deleted function" "" { target c++20 } 64 } + std::tuple t21(t20); + // { dg-error "here" "" { target { c++17_down && hosted } } 79 } + // { dg-error "use of deleted function" "" { target c++20 } 79 } - std::tuple t3(t0); - // { dg-error "here" "" { target { c++17_down && hosted } } 68 } - // { dg-error "use of deleted function" "" { target c++20 } 68 } + std::tuple t22(t20); + // { dg-error "here" "" { target { c++17_down && hosted } } 83 } + // { dg-error "use of deleted function" "" { target c++20 } 83 } - std::tuple 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 t23(t20); + // { dg-error "here" "" { target { c++17_down && hosted } } 87 } + // { dg-error "use of deleted function" "" { target c++20 } 87 } - std::tuple 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 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 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 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 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 p0; - std::tuple t7(p0); - // { dg-error "here" "" { target { c++17_down && hosted } } 85 } - // { dg-error "use of deleted function" "" { target c++20 } 85 } + std::tuple t27(p0); + // { dg-error "here" "" { target { c++17_down && hosted } } 104 } + // { dg-error "use of deleted function" "" { target c++20 } 104 } - std::tuple t8(p0); - // { dg-error "here" "" { target { c++17_down && hosted } } 89 } - // { dg-error "use of deleted function" "" { target c++20 } 89 } + std::tuple t28(p0); + // { dg-error "here" "" { target { c++17_down && hosted } } 108 } + // { dg-error "use of deleted function" "" { target c++20 } 108 } - std::tuple 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 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 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 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 + +void +test_allocator_extended_ctors() +{ + std::allocator a; + + std::tuple 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 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 tl; + + std::tuple 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 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 tll; + + std::tuple 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 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 pll; + + std::tuple 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 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 }