From: Tomasz Kamiński Date: Mon, 8 Dec 2025 07:49:45 +0000 (+0100) Subject: libstdc++: Refactor _Variadic_union so _Unitialized is not needed [PR112591]. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=09bece00d0ec981d1b0b47ba93a67a745de3f062;p=thirdparty%2Fgcc.git libstdc++: Refactor _Variadic_union so _Unitialized is not needed [PR112591]. The changes the _Variadic_union implementation, in a way that the _Unitialized partial specialization for non-trivial types is not necessary. This is simply done by separating the specialization for __trivially_destructible being true and false, and for the later defining an empty destructor (similarly as it was done using concepts). We also reduce the number of specialization of _Variadic_union, so specialization (int, int) is reused by (string, int, int) and (int, int). This is done by initialization __trivially_destructible with conjunction of is_trivially_destructible_v for remaining components. This is only necessary for non-trivial (false) specialization, as if both _First and _Rest... are trivially destructible, then _Rest must also be. The above change does not regress the fix r14-7259-g2d55d94e5df389 for template depth, and both before and after the change template depth is 266. I have added dg-options to the 87619.cc to catch future regressions. This also add test for PR112591. PR libstdc++/112591 libstdc++-v3/ChangeLog: * include/std/variant (_Variadic_union): Separate specializations for for union of only trivially destructible types (true as first template argument). Unconditionally define destructor for _Variadic_union. * testsuite/20_util/variant/87619.cc: Add limit for the template depth. * testsuite/20_util/variant/112591.cc: New test. Reviewed-by: Jonathan Wakely Signed-off-by: Tomasz Kamiński --- diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant index 2f44f9700283..f2f55837461b 100644 --- a/libstdc++-v3/include/std/variant +++ b/libstdc++-v3/include/std/variant @@ -393,8 +393,29 @@ namespace __variant _Variadic_union(in_place_index_t<_Np>, _Args&&...) = delete; }; - template - union _Variadic_union<__trivially_destructible, _First, _Rest...> + template + union _Variadic_union + { + constexpr _Variadic_union() : _M_rest() { } + + template + constexpr + _Variadic_union(in_place_index_t<0>, _Args&&... __args) + : _M_first(in_place_index<0>, std::forward<_Args>(__args)...) + { } + + template + constexpr + _Variadic_union(in_place_index_t<_Np>, _Args&&... __args) + : _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...) + { } + + _Uninitialized<_First> _M_first; + _Variadic_union _M_rest; + }; + + template + union _Variadic_union { constexpr _Variadic_union() : _M_rest() { } @@ -410,24 +431,19 @@ namespace __variant : _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...) { } -#if __cpp_lib_variant >= 202106L _Variadic_union(const _Variadic_union&) = default; _Variadic_union(_Variadic_union&&) = default; _Variadic_union& operator=(const _Variadic_union&) = default; _Variadic_union& operator=(_Variadic_union&&) = default; - ~_Variadic_union() = default; - // If any alternative type is not trivially destructible then we need a // user-provided destructor that does nothing. The active alternative // will be destroyed by _Variant_storage::_M_reset() instead of here. - constexpr ~_Variadic_union() - requires (!__trivially_destructible) + _GLIBCXX20_CONSTEXPR ~_Variadic_union() { } -#endif _Uninitialized<_First> _M_first; - _Variadic_union<__trivially_destructible, _Rest...> _M_rest; + _Variadic_union<(is_trivially_destructible_v<_Rest> && ...), _Rest...> _M_rest; }; // _Never_valueless_alt is true for variant alternatives that can diff --git a/libstdc++-v3/testsuite/20_util/variant/112591.cc b/libstdc++-v3/testsuite/20_util/variant/112591.cc new file mode 100644 index 000000000000..b1b07c4f46e2 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/variant/112591.cc @@ -0,0 +1,32 @@ +// { dg-do run { target c++17 } } + +#include +#include + +struct NonEmpty { int x; }; +struct TrivialEmpty {}; +struct NonTrivialEmpty { ~NonTrivialEmpty() {} }; + +template +struct Compose : T +{ + std::variant v; +}; + +template +bool testAlias() +{ + Compose c; + return static_cast(&c) == &std::get(c.v); +} + +int main() +{ + VERIFY( !testAlias() ); + VERIFY( !testAlias() ); +#if __cplusplus >= 202002L + VERIFY( !testAlias() ); +#else + VERIFY( testAlias() ); +#endif +} diff --git a/libstdc++-v3/testsuite/20_util/variant/87619.cc b/libstdc++-v3/testsuite/20_util/variant/87619.cc index d988925532d4..ac7dd46e42f4 100644 --- a/libstdc++-v3/testsuite/20_util/variant/87619.cc +++ b/libstdc++-v3/testsuite/20_util/variant/87619.cc @@ -16,6 +16,7 @@ // . // { dg-do compile { target c++17 } } +// { dg-options "-ftemplate-depth=270" } #include #include @@ -23,6 +24,7 @@ template struct S { + ~S() {} }; template