Hi!

Here is an updated patch.  It implements the P3074R7 wording without the later  
                                                                                
                                   
removed sentence in https://eel.is/c++draft/class.mem#class.default.ctor-4      
                                                                                
                      
and https://eel.is/c++draft/class.dtor#7.1                                      
                                                                                
                      
                                                                                
                                                                                
                      
<del>X is a non-union class and </del>any <del>non-variant </del>               
                                                                                
                      
potentially constructed subobject <ins>S </ins>has class type M (or possibly    
                                                                                
                      
multidimensional array thereof) where M has a destructor that is                
                                                                                
                      
deleted or is inaccessible from the defaulted destructor,                       
                                                                                
                      
<ins> and either S is non-variant or S has a default member initializer,</ins>  
                                                                                
                      
                                                                                
                                                                                
                      
and                                                                             
                                                                                
                      
                                                                                
                                                                                
                      
https://eel.is/c++draft/class.dtor#7.2.1                                        
                                                                                
                      
overload resolution to select a constructor to default-initialize an object     
                                                                                
                      
of type X either fails or selects a constructor that is either deleted or       
                                                                                
                      
<del>not trivial</del><ins>user-provided</ins>, or                              
                                                                                
                      

To make this work, I had to work around it in <optional> header, where
we have user-provided union ctor and defaulted dtor.

If we change the standard further to make that valid (e.g. with the
discussed rule that if all variant subobjects have accessible destructor
which is trivial, then we don't delete the defaulted dtor just because
default ctor is user-provided, further changes will be needed.

Note, I had to do this deletion because of user-provided default ctor
in two places, because sometimes in synthesized_method_walk it is too early,
the ctors might not have been cloned at all (and looking up ctor_identifier
and trying to call it with a bool argument doesn't work).

This doesn't implement anything from P3726R2 yet (and only tested on the
changed tests and reflect/* so far).

2026-05-06  Jakub Jelinek  <[email protected]>

gcc/c-family/
        * c-cppbuiltin.cc (c_cpp_builtins): Predefine __cpp_trivial_union
        202603L for C++26.
gcc/cp/
        * method.cc (walk_field_subobs): Don't check
        default_init_uninitialized_part for variant members.  Avoid
        locate_fn_flags/process_subob_fn for variant members for default ctor 
        or, if without member initializer, for dtor too.
        (synthesized_method_walk): Make dtor deleted for C++26 if a union
        in a complete class doesn't have usable default ctor or has it
        user-provided.
        * class.cc (check_field_decl): Don't adjust
        TYPE_HAS_NONTRIVIAL_DESTRUCTOR or TYPE_HAS_COMPLEX_DFLT for variant
        members in C++26.
        (clone_constructors_and_destructors): Make defaulted dtor deleted
        for C++26 if a union doesn't have usable default ctor or has it
        user-provided.
gcc/testsuite/
        * g++.dg/DRs/dr2581-1.C (__cpp_trivial_union): Expect a warning.
        * g++.dg/DRs/dr2581-2.C (__cpp_trivial_union): Likewise.
        * g++.dg/cpp26/feat-cxx26.C (__cpp_trivial_union): New test.
        * g++.dg/cpp26/trivial-union1.C: New test.
        * g++.dg/reflect/trivial-union1.C: New test.
        * g++.dg/reflect/type_trait6.C: Change 3 static_asserts.
        * g++.dg/reflect/is_constructible_type1.C: Change 1 static_assert.
libstdc++-v3/
        * include/std/optional
        (std::_Optional_payload_base<_Tp, bool>::_Storage <_Up>): For C++26
        make ctor defaulted instead of inline user provided and add member
        initializer for _M_empty member in that case.

--- gcc/c-family/c-cppbuiltin.cc.jj     2026-05-06 10:38:27.594915980 +0200
+++ gcc/c-family/c-cppbuiltin.cc        2026-05-06 12:27:41.897327631 +0200
@@ -1122,6 +1122,7 @@ c_cpp_builtins (cpp_reader *pfile)
            cpp_define (pfile, "__cpp_impl_reflection=202603L");
          else
            cpp_warn (pfile, "__cpp_impl_reflection");
+         cpp_define (pfile, "__cpp_trivial_union=202603L");
        }
       if (flag_concepts && cxx_dialect > cxx14)
        cpp_define (pfile, "__cpp_concepts=202002L");
--- gcc/cp/method.cc.jj 2026-05-06 10:38:27.603915832 +0200
+++ gcc/cp/method.cc    2026-05-06 15:52:25.085718750 +0200
@@ -2771,6 +2771,7 @@ walk_field_subobs (tree fields, special_
 
          bad = false;
          if (CP_TYPE_CONST_P (mem_type)
+             && TREE_CODE (ctx) != UNION_TYPE
              && default_init_uninitialized_part (mem_type))
            {
              if (diag)
@@ -2847,6 +2848,15 @@ walk_field_subobs (tree fields, special_
       else
        argtype = NULL_TREE;
 
+      if (cxx_dialect >= cxx26 && TREE_CODE (ctx) == UNION_TYPE)
+       {
+         if (sfk == sfk_constructor || sfk == sfk_inheriting_constructor)
+           continue;
+
+         if (sfk == sfk_destructor && DECL_INITIAL (field) == NULL_TREE)
+           continue;
+       }
+
       rval = locate_fn_flags (mem_type, fnname, argtype, flags, complain);
 
       process_subob_fn (rval, sfk, spec_p, trivial_p, deleted_p,
@@ -2985,6 +2995,38 @@ synthesized_method_walk (tree ctype, spe
       /* The synthesized method will call base dtors, but check complete
         here to avoid having to deal with VTT.  */
       fnname = complete_dtor_identifier;
+
+      if (TREE_CODE (ctype) == UNION_TYPE
+         && cxx_dialect >= cxx26
+         && deleted_p
+         /* For still incomplete types defer this until ctor cloning.  */
+         && COMPLETE_TYPE_P (ctype))
+       {
+         /* [class.dtor]/(7.2.1):
+            A defaulted destructor for a class X is defined as deleted if X
+            is a union and
+            -- overload resolution to select a constructor to
+               default-initialize an object of type X either fails or selects
+               a constructor that is either deleted or user-provided.  */
+         tree ctor = locate_ctor (ctype);
+         if (ctor == NULL_TREE)
+           {
+             *deleted_p = true;
+             if (diag)
+               inform (DECL_SOURCE_LOCATION (TYPE_NAME (ctype)),
+                       "default constructor of %qT unusable", ctype);
+             return;
+           }
+         else if (user_provided_p (ctor))
+           {
+             *deleted_p = true;
+             if (diag)
+               inform (DECL_SOURCE_LOCATION (TYPE_NAME (ctype)),
+                       "default constructor of %qT is user-provided",
+                       ctype);
+             return;
+           }
+       }
     }
   else if (SFK_ASSIGN_P (sfk))
     fnname = assign_op_identifier;
--- gcc/cp/class.cc.jj  2026-05-06 10:38:27.597915931 +0200
+++ gcc/cp/class.cc     2026-05-06 16:03:31.068876166 +0200
@@ -3903,17 +3903,25 @@ check_field_decl (tree field,
       else
        {
          TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type);
-         TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
-           |= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type);
          TYPE_HAS_COMPLEX_COPY_ASSIGN (t)
            |= (TYPE_HAS_COMPLEX_COPY_ASSIGN (type)
                || !TYPE_HAS_COPY_ASSIGN (type));
          TYPE_HAS_COMPLEX_COPY_CTOR (t) |= (TYPE_HAS_COMPLEX_COPY_CTOR (type)
                                             || !TYPE_HAS_COPY_CTOR (type));
-         TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) |= TYPE_HAS_COMPLEX_MOVE_ASSIGN 
(type);
+         TYPE_HAS_COMPLEX_MOVE_ASSIGN (t)
+           |= TYPE_HAS_COMPLEX_MOVE_ASSIGN (type);
          TYPE_HAS_COMPLEX_MOVE_CTOR (t) |= TYPE_HAS_COMPLEX_MOVE_CTOR (type);
-         TYPE_HAS_COMPLEX_DFLT (t) |= (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type)
-                                       || TYPE_HAS_COMPLEX_DFLT (type));
+         /* In C++26, triviality of default ctor or dtor of a variant member
+            doesn't matter for triviality of the t's default ctor or dtor.  */
+         if (cxx_dialect < cxx26
+             || TREE_CODE (DECL_CONTEXT (field)) != UNION_TYPE)
+           {
+             TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
+               |= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type);
+             TYPE_HAS_COMPLEX_DFLT (t)
+               |= (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type)
+                   || TYPE_HAS_COMPLEX_DFLT (type));
+           }
        }
 
       if (TYPE_HAS_COPY_CTOR (type)
@@ -5528,7 +5536,26 @@ clone_constructors_and_destructors (tree
     clone_cdtor (fn, /*update_methods=*/true);
 
   if (tree dtor = CLASSTYPE_DESTRUCTOR (t))
-    clone_cdtor (dtor, /*update_methods=*/true);
+    {
+      if (cxx_dialect >= cxx26
+         && TREE_CODE (t) == UNION_TYPE
+         && DECL_DEFAULTED_IN_CLASS_P (dtor)
+         && !DECL_DELETED_FN (dtor))
+       {
+         /* [class.dtor]/(7.2.1):
+            A defaulted destructor for a class X is defined as deleted if X
+            is a union and
+            -- overload resolution to select a constructor to
+               default-initialize an object of type X either fails or selects
+               a constructor that is either deleted or user-provided.
+            This isn't done by synthesized_method_walk for incomplete types
+            because the default ctor is not yet cloned.  */
+         tree ctor = locate_ctor (t);
+         if (ctor == NULL_TREE || user_provided_p (ctor))
+           DECL_DELETED_FN (dtor) = true;
+       }
+      clone_cdtor (dtor, /*update_methods=*/true);
+    }
 }
 
 /* Deduce noexcept for a destructor DTOR.  */
--- gcc/testsuite/g++.dg/DRs/dr2581-1.C.jj      2026-05-06 10:38:27.614915651 
+0200
+++ gcc/testsuite/g++.dg/DRs/dr2581-1.C 2026-05-06 12:27:41.930583042 +0200
@@ -94,7 +94,7 @@
 #undef __cpp_template_parameters
 #undef __cpp_template_template_args    // { dg-warning "undefining 
'__cpp_template_template_args'" "" { target c++20 } }
 #undef __cpp_threadsafe_static_init    // { dg-warning "undefining 
'__cpp_threadsafe_static_init'" "" { target c++20 } }
-#undef __cpp_trivial_union
+#undef __cpp_trivial_union             // { dg-warning "undefining 
'__cpp_trivial_union'" "" { target c++26 } }
 #undef __cpp_unicode_characters                // { dg-warning "undefining 
'__cpp_unicode_characters'" "" { target c++20 } }
 #undef __cpp_unicode_literals          // { dg-warning "undefining 
'__cpp_unicode_literals'" "" { target c++20 } }
 #undef __cpp_user_defined_literals     // { dg-warning "undefining 
'__cpp_user_defined_literals'" "" { target c++20 } }
--- gcc/testsuite/g++.dg/DRs/dr2581-2.C.jj      2026-05-06 10:38:27.615915634 
+0200
+++ gcc/testsuite/g++.dg/DRs/dr2581-2.C 2026-05-06 12:27:41.932288299 +0200
@@ -95,7 +95,7 @@
 #define __cpp_template_parameters 202502L
 #define __cpp_template_template_args 201611L   // { dg-error 
"'__cpp_template_template_args' redefined" "" { target c++20 } }
 #define __cpp_threadsafe_static_init 200806L   // { dg-error 
"'__cpp_threadsafe_static_init' redefined" "" { target c++20 } }
-#define __cpp_trivial_union 202502L
+#define __cpp_trivial_union 202603L            // { dg-error 
"'__cpp_trivial_union' redefined" "" { target c++26 } }
 #define __cpp_unicode_characters 200704L       // { dg-error 
"'__cpp_unicode_characters' redefined" "" { target c++17 } }
 #define __cpp_unicode_literals 200710L         // { dg-error 
"'__cpp_unicode_literals' redefined" "" { target c++20 } }
 #define __cpp_user_defined_literals 200809L    // { dg-error 
"'__cpp_user_defined_literals' redefined" "" { target c++20 } }
--- gcc/testsuite/g++.dg/cpp26/feat-cxx26.C.jj  2026-05-06 10:38:27.621915535 
+0200
+++ gcc/testsuite/g++.dg/cpp26/feat-cxx26.C     2026-05-06 12:27:41.932699175 
+0200
@@ -652,3 +652,9 @@
 #elif __cpp_expansion_statements != 202506
 #  error "__cpp_expansion_statements != 202506"
 #endif
+
+#ifndef __cpp_trivial_union
+#  error "__cpp_trivial_union"
+#elif __cpp_trivial_union != 202603
+#  error "__cpp_trivial_union != 202603"
+#endif
--- gcc/testsuite/g++.dg/cpp26/trivial-union1.C.jj      2026-05-06 
12:27:41.932834170 +0200
+++ gcc/testsuite/g++.dg/cpp26/trivial-union1.C 2026-05-06 12:27:41.932834170 
+0200
@@ -0,0 +1,73 @@
+// P3074R7 - trivial unions (was std::uninitialized<T>)
+// P3726R2 - Adjustments to Union Lifetime Rules
+// { dg-do compile { target c++11 } }
+
+#include <type_traits>
+
+// These two were incorrectly deleted.
+union A { int a; const int b; };
+static_assert (std::is_default_constructible <A>::value, "");
+static_assert (std::is_trivially_default_constructible <A>::value, "");
+static_assert (std::is_destructible <A>::value, "");
+static_assert (std::is_trivially_destructible <A>::value, "");
+struct B { int a; union { int b; const int c; }; };
+static_assert (std::is_default_constructible <B>::value, "");
+static_assert (std::is_trivially_default_constructible <B>::value, "");
+static_assert (std::is_destructible <B>::value, "");
+static_assert (std::is_trivially_destructible <B>::value, "");
+// C::C() is incorrectly not deleted in C++11 to 23, but in C++26 it should
+// not be deleted.
+union C { const int a = 42; const long b; ~C (); };
+#if __cpp_trivial_union >= 202502L
+static_assert (std::is_default_constructible <C>::value, "");
+static_assert (!std::is_trivially_default_constructible <C>::value, "");
+static_assert (std::is_destructible <C>::value, "");
+static_assert (!std::is_trivially_destructible <C>::value, "");
+#endif
+struct D { D () = delete; D (int); ~D () = default; };
+union E { D a = 42; D b; ~E (); };
+static_assert (std::is_default_constructible <E>::value, "");
+static_assert (std::is_destructible <E>::value, "");
+struct F { int a; union { D b = 42; D c; }; };
+static_assert (std::is_default_constructible <F>::value, "");
+static_assert (std::is_destructible <F>::value, "");
+struct G { G (); ~G (); };
+union I { int a; const int b; ~I (); };
+static_assert (std::is_default_constructible <I>::value, "");
+static_assert (!std::is_trivially_default_constructible <I>::value, "");
+static_assert (std::is_destructible <I>::value, "");
+static_assert (!std::is_trivially_destructible <I>::value, "");
+union J { D a; int b; };
+#if __cpp_trivial_union >= 202502L
+static_assert (std::is_default_constructible <J>::value, "");
+static_assert (std::is_trivially_default_constructible <J>::value, "");
+#else
+static_assert (!std::is_default_constructible <J>::value, "");
+static_assert (!std::is_trivially_default_constructible <J>::value, "");
+#endif
+static_assert (std::is_destructible <J>::value, "");
+static_assert (std::is_trivially_destructible <J>::value, "");
+union K { G a; int b; };
+#if __cpp_trivial_union >= 202502L
+static_assert (std::is_default_constructible <K>::value, "");
+static_assert (std::is_trivially_default_constructible <K>::value, "");
+static_assert (std::is_destructible <K>::value, "");
+static_assert (std::is_trivially_destructible <K>::value, "");
+#else
+static_assert (!std::is_default_constructible <K>::value, "");
+static_assert (!std::is_trivially_default_constructible <K>::value, "");
+static_assert (!std::is_destructible <K>::value, "");
+static_assert (!std::is_trivially_destructible <K>::value, "");
+#endif
+struct L { int a; union { G b; int c; }; };
+#if __cpp_trivial_union >= 202502L
+static_assert (std::is_default_constructible <L>::value, "");
+static_assert (std::is_trivially_default_constructible <L>::value, "");
+static_assert (std::is_destructible <L>::value, "");
+static_assert (std::is_trivially_destructible <L>::value, "");
+#else
+static_assert (!std::is_default_constructible <L>::value, "");
+static_assert (!std::is_trivially_default_constructible <L>::value, "");
+static_assert (!std::is_destructible <L>::value, "");
+static_assert (!std::is_trivially_destructible <L>::value, "");
+#endif
--- gcc/testsuite/g++.dg/reflect/trivial-union1.C.jj    2026-05-06 
12:27:41.933015207 +0200
+++ gcc/testsuite/g++.dg/reflect/trivial-union1.C       2026-05-06 
16:12:08.912460173 +0200
@@ -0,0 +1,108 @@
+// P3074R7 - trivial unions (was std::uninitialized<T>)
+// P3726R2 - Adjustments to Union Lifetime Rules
+// { dg-do compile { target c++26 } }
+// { dg-additional-options "-freflection" }
+
+#include <meta>
+#include <ranges>
+
+using namespace std::meta;
+constexpr auto ctx = std::meta::access_context::unchecked ();
+union A { int a; const int b; };
+static_assert (is_default_constructible_type (^^A));
+static_assert (is_trivially_default_constructible_type (^^A));
+static_assert (is_destructible_type (^^A));
+static_assert (is_trivially_destructible_type (^^A));
+constexpr auto Actor = (members_of (^^A, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Adtor = (members_of (^^A, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (is_defaulted (Actor) && !is_deleted (Actor));
+static_assert (is_defaulted (Adtor) && !is_deleted (Adtor));
+struct B { int a; union { int b; const int c; }; };
+static_assert (is_default_constructible_type (^^B));
+static_assert (is_trivially_default_constructible_type (^^B));
+static_assert (is_destructible_type (^^B));
+static_assert (is_trivially_destructible_type (^^B));
+constexpr auto Bctor = (members_of (^^B, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Bdtor = (members_of (^^B, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (is_defaulted (Bctor) && !is_deleted (Bctor));
+static_assert (is_defaulted (Bdtor) && !is_deleted (Bdtor));
+union C { const int a = 42; const long b; ~C (); };
+static_assert (is_default_constructible_type (^^C));
+static_assert (!is_trivially_default_constructible_type (^^C));
+static_assert (is_destructible_type (^^C));
+static_assert (!is_trivially_destructible_type (^^C));
+constexpr auto Cctor = (members_of (^^C, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Cdtor = (members_of (^^C, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (is_defaulted (Cctor) && !is_deleted (Cctor));
+static_assert (!is_defaulted (Cdtor) && !is_deleted (Cdtor));
+struct D { D () = delete; D (int); ~D () = default; };
+union E { D a = 42; D b; ~E (); };
+static_assert (is_default_constructible_type (^^E));
+static_assert (is_destructible_type (^^E));
+constexpr auto Ector = (members_of (^^E, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Edtor = (members_of (^^E, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (is_defaulted (Ector) && !is_deleted (Ector));
+static_assert (!is_defaulted (Edtor) && !is_deleted (Edtor));
+struct F { int a; union { D b = 42; D c; }; };
+static_assert (is_default_constructible_type (^^F));
+static_assert (is_destructible_type (^^F));
+constexpr auto Fctor = (members_of (^^F, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Fdtor = (members_of (^^F, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (is_defaulted (Fctor) && !is_deleted (Fctor));
+static_assert (is_defaulted (Fdtor) && !is_deleted (Fdtor));
+struct G { G (); ~G (); };
+union I { int a; const int b; ~I (); };
+static_assert (is_default_constructible_type (^^I));
+static_assert (!is_trivially_default_constructible_type (^^I));
+static_assert (is_destructible_type (^^I));
+static_assert (!is_trivially_destructible_type (^^I));
+constexpr auto Ictor = (members_of (^^I, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Idtor = (members_of (^^I, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (is_defaulted (Ictor) && !is_deleted (Ictor));
+static_assert (!is_defaulted (Idtor) && !is_deleted (Idtor));
+union J { D a; int b; };
+static_assert (is_default_constructible_type (^^J));
+static_assert (is_trivially_default_constructible_type (^^J));
+static_assert (is_destructible_type (^^J));
+static_assert (is_trivially_destructible_type (^^J));
+constexpr auto Jctor = (members_of (^^J, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Jdtor = (members_of (^^J, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (is_defaulted (Jctor) && !is_deleted (Jctor));
+static_assert (is_defaulted (Jdtor) && !is_deleted (Jdtor));
+union K { G a; int b; };
+static_assert (is_default_constructible_type (^^K));
+static_assert (is_trivially_default_constructible_type (^^K));
+static_assert (is_destructible_type (^^K));
+static_assert (is_trivially_destructible_type (^^K));
+constexpr auto Kctor = (members_of (^^K, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Kdtor = (members_of (^^K, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (is_defaulted (Kctor) && !is_deleted (Kctor));
+static_assert (is_defaulted (Kdtor) && !is_deleted (Kdtor));
+struct L { int a; union { G b; int c; }; };
+static_assert (is_default_constructible_type (^^L));
+static_assert (is_trivially_default_constructible_type (^^L));
+static_assert (is_destructible_type (^^L));
+static_assert (is_trivially_destructible_type (^^L));
+constexpr auto Lctor = (members_of (^^L, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Ldtor = (members_of (^^L, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (is_defaulted (Lctor) && !is_deleted (Lctor));
+static_assert (is_defaulted (Ldtor) && !is_deleted (Ldtor));
+union M { M (); int a; long b; };
+static_assert (!is_default_constructible_type (^^M));
+static_assert (!is_trivially_default_constructible_type (^^M));
+static_assert (!is_destructible_type (^^M));
+static_assert (!is_trivially_destructible_type (^^M));
+constexpr auto Mctor = (members_of (^^M, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Mdtor = (members_of (^^M, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (!is_defaulted (Mctor) && !is_deleted (Mctor));
+static_assert (is_defaulted (Mdtor) && is_deleted (Mdtor));
+struct N { N () = default; N (const N &) = default; int a; ~N (); };
+union O { O (); int a; N b; };
+static_assert (!is_default_constructible_type (^^O));
+static_assert (!is_trivially_default_constructible_type (^^O));
+static_assert (!is_destructible_type (^^O));
+static_assert (!is_trivially_destructible_type (^^O));
+constexpr auto Octor = (members_of (^^O, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Odtor = (members_of (^^O, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (!is_defaulted (Octor) && !is_deleted (Octor));
+static_assert (is_defaulted (Odtor) && is_deleted (Odtor));
--- gcc/testsuite/g++.dg/reflect/type_trait6.C.jj       2026-03-27 
10:17:16.145297923 +0100
+++ gcc/testsuite/g++.dg/reflect/type_trait6.C  2026-05-06 16:15:31.957157388 
+0200
@@ -985,7 +985,7 @@ static_assert (!is_destructible_type (^^
 static_assert (!is_destructible_type (^^const N2::Del [1]));
 static_assert (!is_destructible_type (^^N2::Del []));
 static_assert (!is_destructible_type (^^const N2::Del []));
-static_assert (!is_destructible_type (^^N2::NontrivialUnion));
+static_assert (is_destructible_type (^^N2::NontrivialUnion));
 static_assert (is_destructible_type (^^N2::UnusualCopy));
 
 static_assert (is_trivially_default_constructible_type (^^int));
@@ -1367,8 +1367,8 @@ static_assert (!is_nothrow_destructible_
 static_assert (!is_nothrow_destructible_type (^^N2::Aggr2));
 static_assert (!is_nothrow_destructible_type (^^N2::Aggr2 [1]));
 static_assert (!is_nothrow_destructible_type (^^N2::TD1 [1][2]));
-static_assert (!is_nothrow_destructible_type (^^N2::Ut));
-static_assert (!is_nothrow_destructible_type (^^N2::Ut [3]));
+static_assert (is_nothrow_destructible_type (^^N2::Ut));
+static_assert (is_nothrow_destructible_type (^^N2::Ut [3]));
 static_assert (!is_nothrow_destructible_type (^^N2::AbstractDelDtor));
 static_assert (!is_nothrow_destructible_type (^^N2::Abstract2));
 static_assert (!is_nothrow_destructible_type (^^N2::Abstract3));
--- gcc/testsuite/g++.dg/reflect/is_constructible_type1.C.jj    2026-03-27 
10:17:16.128298201 +0100
+++ gcc/testsuite/g++.dg/reflect/is_constructible_type1.C       2026-05-06 
16:15:59.526708933 +0200
@@ -603,7 +603,7 @@ static_assert (!is_constructible_type (^
 static_assert (!is_constructible_type (^^const DelnAny, { ^^int, ^^void * }));
 static_assert (!is_constructible_type (^^DelnAny, { ^^Empty, ^^B, ^^D }));
 static_assert (!is_constructible_type (^^const DelnAny, { ^^Empty, ^^B, ^^D 
}));
-static_assert (!is_constructible_type (^^NontrivialUnion, {}));
+static_assert (is_constructible_type (^^NontrivialUnion, {}));
 static_assert (!is_constructible_type (^^NontrivialUnion, { ^^const 
NontrivialUnion & }));
 static_assert (!is_constructible_type (^^UnusualCopy, {}));
 static_assert (!is_constructible_type (^^UnusualCopy, { ^^UnusualCopy }));
--- libstdc++-v3/include/std/optional.jj        2026-05-06 10:38:27.623915503 
+0200
+++ libstdc++-v3/include/std/optional   2026-05-06 12:27:41.933204607 +0200
@@ -221,7 +221,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       template<typename _Up, bool = is_trivially_destructible_v<_Up>>
        union _Storage
        {
+#if __cpp_trivial_union >= 202502L
+         constexpr _Storage() noexcept = default;
+#else
          constexpr _Storage() noexcept : _M_empty() { }
+#endif
 
          template<typename... _Args>
            constexpr
@@ -258,7 +262,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
          _Storage& operator=(_Storage&&) = default;
 #endif
 
+#if __cpp_trivial_union >= 202502L
+         _Empty_byte _M_empty = {};
+#else
          _Empty_byte _M_empty;
+#endif
          _Up _M_value;
        };
 

        Jakub

Reply via email to