https://gcc.gnu.org/g:ca6cd7cb48512d60c28024174b319df4580498ce

commit r17-671-gca6cd7cb48512d60c28024174b319df4580498ce
Author: Jakub Jelinek <[email protected]>
Date:   Fri May 22 10:15:45 2026 +0200

    c++, libstdc++: Implement C++26 P3074R7 and CWG3189 - trivial unions 
[PR119059]
    
    The following patch attempts to implement the C++26
    P3074R7 - trivial unions (was std::uninitialized<T>)
    paperand proposed resolution of
    CWG3189 - Implicitly deleted destructors for union-like classes
    with the exception of the
      #define __cpp_lib_constexpr_inplace_vector 2025XXL // also in 
<inplace_vector>
    addition and possibly needed <inplace_vector> changes (will defer that to
    Jonathan / Tomasz) and except for the changes in [class.default.ctor]/4 
which
    were reverted by P3726R2 later on .
    
    There is one change which doesn't affect just C++26 but also older versions
    of the standard, https://eel.is/c++draft/class.default.ctor#2.2 or its older
    counterparts, e.g. C++11 had in [class.ctor]/5
    "any non-variant non-static data member of const-qualified type (or array 
thereof)
    with no brace-or-equal-initializer does not have a user-provided default
    constructor"
    but we've been ignoring the "non-variant" part thereof and diagnosing it
    for variant members too.  Note, this is related to the other unimplemented
    rule I've posted a patch earlier for that was dismissed (reject
    all variant members const before C++26), so some cases which we've rejected
    for a wrong reason will now be accepted when they are still invalid before
    C++26.
    
    2026-05-22  Jakub Jelinek  <[email protected]>
    
            PR c++/119059
    gcc/c-family/
            * c-cppbuiltin.cc (c_cpp_builtins): For C++26 predefine
            __cpp_trivial_union to 202502L.
    gcc/cp/
            * method.cc: Implement C++26 P3074R7 - trivial unions (was
            std::uninitialized<T>) (except the sentence removed again in 
P3726R2)
            and proposed resolution of CWG3189 - Implicitly deleted destructors
            for union-like classes.
            (walk_field_subobs): Don't do default_init_uninitialized_part checks
            for variant members.  Don't check subobject ctor/dtor for variant
            members for ctor/inheriting ctor or when subobject doesn't have 
member
            initializer for dtor and it is either the dtor_from_ctor case or
            the current class doesn't have user provided ctors.
            * class.cc (check_field_decl): Don't or in
            TYPE_HAS_NONTRIVIAL_DESTRUCTOR or TYPE_HAS_DEFAULT_CONSTRUCTOR of
            variant subobjects for C++26.
    gcc/testsuite/
            * g++.dg/DRs/dr2581-1.C: Expect warning for __cpp_trivial_union.
            * g++.dg/DRs/dr2581-2.C: Expect error for __cpp_trivial_union.
            * g++.dg/cpp26/feat-cxx26.C: Add __cpp_trivial_union checking.
            * g++.dg/cpp26/trivial-union1.C: New test.
            * g++.dg/cpp26/trivial-union2.C: New test.
            * g++.dg/reflect/trivial-union1.C: New test.
            * g++.dg/reflect/type_trait6.C: Adjust expected result of
            one is_destructible_type and two is_nothrow_destructible_type calls.
            * g++.dg/reflect/is_constructible_type1.C: Adjust expected result
            of one is_constructible_type call.
            * g++.dg/init/pr43719.C: Don't expect one error.
            * g++.dg/init/pr25811.C: Don't expect 3 diagnostic messages,
            instead expect a different one for C++98 only.
            * g++.dg/other/anon-union2.C: Only expect one diagnostic for
            C++23 and older.
            * g++.dg/cpp0x/union1.C: Only expect 6 diagnostic messages for
            C++23 and older.
            * g++.dg/cpp0x/union4.C: Only expect 3 diagnostic messages for
            C++23 and older.
            * g++.dg/cpp0x/defaulted2.C: Only expect 2 diagnostic messages for
            C++23 and older.
    
    Reviewed-by: Jason Merrill <[email protected]>

Diff:
---
 gcc/c-family/c-cppbuiltin.cc                       |   1 +
 gcc/cp/class.cc                                    |  21 +-
 gcc/cp/method.cc                                   |  54 ++++++
 gcc/testsuite/g++.dg/DRs/dr2581-1.C                |   2 +-
 gcc/testsuite/g++.dg/DRs/dr2581-2.C                |   2 +-
 gcc/testsuite/g++.dg/cpp0x/defaulted2.C            |   4 +-
 gcc/testsuite/g++.dg/cpp0x/union1.C                |  12 +-
 gcc/testsuite/g++.dg/cpp0x/union4.C                |   6 +-
 gcc/testsuite/g++.dg/cpp26/feat-cxx26.C            |   6 +
 gcc/testsuite/g++.dg/cpp26/trivial-union1.C        | 133 +++++++++++++
 gcc/testsuite/g++.dg/cpp26/trivial-union2.C        |   7 +
 gcc/testsuite/g++.dg/init/pr25811.C                |   7 +-
 gcc/testsuite/g++.dg/init/pr43719.C                |   2 +-
 gcc/testsuite/g++.dg/other/anon-union2.C           |   2 +-
 .../g++.dg/reflect/is_constructible_type1.C        |   2 +-
 gcc/testsuite/g++.dg/reflect/trivial-union1.C      | 214 +++++++++++++++++++++
 gcc/testsuite/g++.dg/reflect/type_trait6.C         |   6 +-
 17 files changed, 453 insertions(+), 28 deletions(-)

diff --git a/gcc/c-family/c-cppbuiltin.cc b/gcc/c-family/c-cppbuiltin.cc
index 74cbeecb165e..608b6ba5774b 100644
--- a/gcc/c-family/c-cppbuiltin.cc
+++ b/gcc/c-family/c-cppbuiltin.cc
@@ -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=202502L");
        }
       if (flag_concepts && cxx_dialect > cxx14)
        cpp_define (pfile, "__cpp_concepts=202002L");
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index c9a7eb5c76ec..6e4dc3cb0930 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -3903,17 +3903,28 @@ 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.
+            Before C++26, non-trivial default ctor or dtor of a variant
+            member makes it deleted with the exception of default ctor
+            when DMI is present, but in that case default ctor is
+            non-trivial.   */
+         if (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)
diff --git a/gcc/cp/method.cc b/gcc/cp/method.cc
index fe26b5130ff2..ccfcfb202aa4 100644
--- a/gcc/cp/method.cc
+++ b/gcc/cp/method.cc
@@ -2692,6 +2692,7 @@ walk_field_subobs (tree fields, special_function_kind 
sfk, tree fnname,
   enum { unknown, no, yes }
   only_dmi_mem = (sfk == sfk_constructor && TREE_CODE (ctx) == UNION_TYPE
                  ? unknown : no);
+  int has_user_provided_ctor = -1;
 
  again:
   for (tree field = fields; field; field = DECL_CHAIN (field))
@@ -2771,6 +2772,7 @@ walk_field_subobs (tree fields, special_function_kind 
sfk, tree fnname,
 
          bad = false;
          if (CP_TYPE_CONST_P (mem_type)
+             && TREE_CODE (ctx) != UNION_TYPE
              && default_init_uninitialized_part (mem_type))
            {
              if (diag)
@@ -2847,6 +2849,58 @@ walk_field_subobs (tree fields, special_function_kind 
sfk, tree fnname,
       else
        argtype = NULL_TREE;
 
+      if (cxx_dialect >= cxx26 && TREE_CODE (ctx) == UNION_TYPE)
+       {
+         /* C++26 [class.default.ctor]/2:
+            A defaulted default constructor for class X is defined as deleted
+            if
+            ...
+            - any non-variant potentially constructed subobject, except for
+              a non-static data member with a brace-or-equal-initializer, has
+              class type M (or possibly multidimensional array thereof) and
+              overload resolution as applied to find M's corresponding
+              constructor does not result in a usable candidate,
+            So, for C++26 this ignores default constructors of variant
+            members.  */
+         if (sfk == sfk_constructor || sfk == sfk_inheriting_constructor)
+           continue;
+
+         /* C++26 [class.default.ctor]/2:
+            ...
+            - any potentially constructed subobject S has class type M (or
+              possibly multidimensional array thereof), M has a destructor
+              that is deleted or inaccessible from the defaulted default
+              constructor, and either S is non-variant or S has a default
+              member initializer.
+            This is the dtor_from_ctor case, so ignore destructors of
+            variant members unless they have a DMI.
+            C++26 with CWG3189 [class.dtor]/4:
+            A defaulted destructor for a class X is defined as deleted if
+            ...
+            - X is has a non-union class and any non-variant potentially
+              constructed subobject has S of class type M (or possibly
+              multidimensional array thereof) where either
+              - S is not a variant member and M has a destructor that is
+                deleted or is inaccessible from the defaulted destructor, or
+              - S is a variant member, M has a destructor that is deleted,
+                inaccessible from the defaulted destructor, or non-trivial,
+                and either
+                - V S has a default member initializer or
+                - X has a user-provided constructor.
+            This is the !dtor_from_ctor case, so ignore destructors of
+            variant members unless they have a DMI or X has user-provided
+            constructor.  */
+         if (sfk == sfk_destructor)
+           {
+             if (!dtor_from_ctor && has_user_provided_ctor == -1)
+               has_user_provided_ctor
+                 = type_has_user_provided_constructor (current_class_type);
+             if (DECL_INITIAL (field) == NULL_TREE
+                 && (dtor_from_ctor || !has_user_provided_ctor))
+               continue;
+           }
+       }
+
       rval = locate_fn_flags (mem_type, fnname, argtype, flags, complain);
 
       process_subob_fn (rval, sfk, spec_p, trivial_p, deleted_p,
diff --git a/gcc/testsuite/g++.dg/DRs/dr2581-1.C 
b/gcc/testsuite/g++.dg/DRs/dr2581-1.C
index cb761b7378ec..7298f3162b5b 100644
--- a/gcc/testsuite/g++.dg/DRs/dr2581-1.C
+++ b/gcc/testsuite/g++.dg/DRs/dr2581-1.C
@@ -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 } }
diff --git a/gcc/testsuite/g++.dg/DRs/dr2581-2.C 
b/gcc/testsuite/g++.dg/DRs/dr2581-2.C
index 0f2aec0e4255..74041c8c3cb3 100644
--- a/gcc/testsuite/g++.dg/DRs/dr2581-2.C
+++ b/gcc/testsuite/g++.dg/DRs/dr2581-2.C
@@ -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 202502L            // { 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 } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted2.C 
b/gcc/testsuite/g++.dg/cpp0x/defaulted2.C
index b7b31438491c..da1e77e1212d 100644
--- a/gcc/testsuite/g++.dg/cpp0x/defaulted2.C
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted2.C
@@ -55,7 +55,7 @@ G::G() = default;
 
 union U
 {
-  G g;                         // { dg-error "union member.*non-trivial" }
+  G g;                         // { dg-error "union member.*non-trivial" "" { 
target c++23_down } }
 };
 
 int main()
@@ -63,7 +63,7 @@ int main()
   F f;
   F f2(f);                     // { dg-error "use" }
   const B* b = new const B;            // { dg-error "uninitialized const" }
-  U u;                         // { dg-error "deleted" }
+  U u;                         // { dg-error "deleted" "" { target c++23_down 
} }
 }
 
 // { dg-prune-output "implicitly deleted because" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/union1.C 
b/gcc/testsuite/g++.dg/cpp0x/union1.C
index ff415fc57369..fa13c18c69e9 100644
--- a/gcc/testsuite/g++.dg/cpp0x/union1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/union1.C
@@ -14,7 +14,7 @@ union B
   A a;                         // { dg-error "union member" }
 };
 
-B b;                           // { dg-error "B::B\\(\\)" "B::B" }
+B b;                           // { dg-error "B::B\\(\\)" "B::B" { target 
c++23_down } }
 B b2(b);                       // { dg-error "B::B\\(const B&\\)" "B::B" }
 
 struct C
@@ -25,10 +25,10 @@ struct C
   };
 };
 
-C c;                           // { dg-error "C::C\\(\\)" "C::C" }
+C c;                           // { dg-error "C::C\\(\\)" "C::C" { target 
c++23_down } }
 C c2(c);                       // { dg-error "C::C\\(const C&\\)" "C::C" }
 
-// { dg-error "B::~B" "B::~B" { target *-*-* } 17 }
-// { dg-error "B::~B" "B::~B" { target *-*-* } 18 }
-// { dg-error "C::~C" "C::~C" { target *-*-* } 28 }
-// { dg-error "C::~C" "C::~C" { target *-*-* } 29 }
+// { dg-error "B::~B" "B::~B" { target c++23_down } 17 }
+// { dg-error "B::~B" "B::~B" { target c++23_down } 18 }
+// { dg-error "C::~C" "C::~C" { target c++23_down } 28 }
+// { dg-error "C::~C" "C::~C" { target c++23_down } 29 }
diff --git a/gcc/testsuite/g++.dg/cpp0x/union4.C 
b/gcc/testsuite/g++.dg/cpp0x/union4.C
index cf9916dc3673..45be643b2e39 100644
--- a/gcc/testsuite/g++.dg/cpp0x/union4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/union4.C
@@ -3,15 +3,15 @@
 
 struct SFoo
 {
-  SFoo() =delete;              // { dg-message "declared" }
+  SFoo() =delete;              // { dg-message "declared" "" { target 
c++23_down } }
 };
 
-union UFoo                     // { dg-error "deleted" }
+union UFoo                     // { dg-error "deleted" "" { target c++23_down 
} }
 {
   SFoo foo;
 };
 
 int main()
 {
-  UFoo();                      // { dg-error "deleted" }
+  UFoo();                      // { dg-error "deleted" "" { target c++23_down 
} }
 }
diff --git a/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C 
b/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C
index 248116699617..d3ab72901240 100644
--- a/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C
+++ b/gcc/testsuite/g++.dg/cpp26/feat-cxx26.C
@@ -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 != 202502
+#  error "__cpp_trivial_union != 202502"
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp26/trivial-union1.C 
b/gcc/testsuite/g++.dg/cpp26/trivial-union1.C
new file mode 100644
index 000000000000..7f1e75ed167b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/trivial-union1.C
@@ -0,0 +1,133 @@
+// P3074R7 - trivial unions (was std::uninitialized<T>)
+// { 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
+union M { M (); int a; int b; };
+static_assert (std::is_default_constructible <M>::value, "");
+static_assert (!std::is_trivially_default_constructible <M>::value, "");
+static_assert (std::is_destructible <M>::value, "");
+static_assert (std::is_trivially_destructible <M>::value, "");
+union N { N (); int a; G b; };
+static_assert (!std::is_default_constructible <N>::value, "");
+static_assert (!std::is_trivially_default_constructible <N>::value, "");
+static_assert (!std::is_destructible <N>::value, "");
+static_assert (!std::is_trivially_destructible <N>::value, "");
+struct O { O (); union { int a; int b; }; };
+static_assert (std::is_default_constructible <O>::value, "");
+static_assert (!std::is_trivially_default_constructible <O>::value, "");
+static_assert (std::is_destructible <O>::value, "");
+static_assert (std::is_trivially_destructible <O>::value, "");
+struct P { P (); union { int a; G b; }; };
+static_assert (!std::is_default_constructible <P>::value, "");
+static_assert (!std::is_trivially_default_constructible <P>::value, "");
+static_assert (!std::is_destructible <P>::value, "");
+static_assert (!std::is_trivially_destructible <P>::value, "");
+struct Q { Q (int); union { int a; G b; }; };
+static_assert (!std::is_default_constructible <Q>::value, "");
+static_assert (!std::is_trivially_default_constructible <Q>::value, "");
+static_assert (!std::is_destructible <Q>::value, "");
+static_assert (!std::is_trivially_destructible <Q>::value, "");
+struct R { R () = default; R (int); union { int a; G b; }; };
+static_assert (!std::is_default_constructible <R>::value, "");
+static_assert (!std::is_trivially_default_constructible <R>::value, "");
+static_assert (!std::is_destructible <R>::value, "");
+static_assert (!std::is_trivially_destructible <R>::value, "");
+struct S { S (int); ~S (); };
+union T { T (); int a; int b = 42; };
+static_assert (std::is_default_constructible <T>::value, "");
+static_assert (!std::is_trivially_default_constructible <T>::value, "");
+static_assert (std::is_destructible <T>::value, "");
+static_assert (std::is_trivially_destructible <T>::value, "");
+union U { U (); int a; S b = 42; };
+static_assert (!std::is_default_constructible <U>::value, "");
+static_assert (!std::is_trivially_default_constructible <U>::value, "");
+static_assert (!std::is_destructible <U>::value, "");
+static_assert (!std::is_trivially_destructible <U>::value, "");
+struct V { V (); union { int a; int b = 42; }; };
+static_assert (std::is_default_constructible <V>::value, "");
+static_assert (!std::is_trivially_default_constructible <V>::value, "");
+static_assert (std::is_destructible <V>::value, "");
+static_assert (std::is_trivially_destructible <V>::value, "");
+struct W { W (); union { int a; S b = 42; }; };
+static_assert (!std::is_default_constructible <W>::value, "");
+static_assert (!std::is_trivially_default_constructible <W>::value, "");
+static_assert (!std::is_destructible <W>::value, "");
+static_assert (!std::is_trivially_destructible <W>::value, "");
+struct X { X (int); union { int a; S b = 42; }; };
+static_assert (!std::is_default_constructible <X>::value, "");
+static_assert (!std::is_trivially_default_constructible <X>::value, "");
+static_assert (!std::is_destructible <X>::value, "");
+static_assert (!std::is_trivially_destructible <X>::value, "");
+struct Y { Y () = default; Y (int); union { int a; S b = 42; }; };
+static_assert (!std::is_default_constructible <Y>::value, "");
+static_assert (!std::is_trivially_default_constructible <Y>::value, "");
+static_assert (!std::is_destructible <Y>::value, "");
+static_assert (!std::is_trivially_destructible <Y>::value, "");
diff --git a/gcc/testsuite/g++.dg/cpp26/trivial-union2.C 
b/gcc/testsuite/g++.dg/cpp26/trivial-union2.C
new file mode 100644
index 000000000000..c1a64dac7377
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/trivial-union2.C
@@ -0,0 +1,7 @@
+// P3074R7 - trivial unions (was std::uninitialized<T>)
+// { dg-do compile { target c++20 } }
+
+union U { int a, b; };
+template<U u> class X {};
+constexpr U make() { U u; return u; }
+void f(X<make()>) {}
diff --git a/gcc/testsuite/g++.dg/init/pr25811.C 
b/gcc/testsuite/g++.dg/init/pr25811.C
index 853eeae3feb6..8864f7a1a6fe 100644
--- a/gcc/testsuite/g++.dg/init/pr25811.C
+++ b/gcc/testsuite/g++.dg/init/pr25811.C
@@ -124,10 +124,9 @@ struct Z // { dg-error "deleted" "" { target c++11 } }
   Z5 z5;
 };
 
-union U // { dg-message "implicitly deleted" "" { target c++11 } }
-       // { dg-error "uninitialized" "" { target c++11 } .-1 }
+union U
 {
-  int const i; // { dg-message "should be initialized" }
+  int const i;
 };
 
 void f1 ()
@@ -207,5 +206,5 @@ void f15 ()
 
 void f16 ()
 {
-  new U; // { dg-error "deleted|uninitialized const member" }
+  new U; // { dg-error "uninitialized const member in 'union U' using 'new' 
without new-initializer" "" { target c++98_only } }
 }
diff --git a/gcc/testsuite/g++.dg/init/pr43719.C 
b/gcc/testsuite/g++.dg/init/pr43719.C
index c8cebc2de153..522a8cc52f70 100644
--- a/gcc/testsuite/g++.dg/init/pr43719.C
+++ b/gcc/testsuite/g++.dg/init/pr43719.C
@@ -109,7 +109,7 @@ struct Z            // { dg-error "deleted" "" { target 
c++11 } }
   Z5 z5;
 };
 
-union U // { dg-error "uninitialized" "" { target c++11 } }
+union U
 {
   int const i; // { dg-message "should be initialized" }
 };
diff --git a/gcc/testsuite/g++.dg/other/anon-union2.C 
b/gcc/testsuite/g++.dg/other/anon-union2.C
index 31bb74fa99c3..6f4842688a66 100644
--- a/gcc/testsuite/g++.dg/other/anon-union2.C
+++ b/gcc/testsuite/g++.dg/other/anon-union2.C
@@ -6,5 +6,5 @@ struct S {
 };
 
 void f() {
-  union { S a; };              // { dg-error "constructor|no match" }
+  union { S a; };              // { dg-error "constructor|no match" "" { 
target c++23_down } }
 }
diff --git a/gcc/testsuite/g++.dg/reflect/is_constructible_type1.C 
b/gcc/testsuite/g++.dg/reflect/is_constructible_type1.C
index 0b9d3e047793..36e13b3614fe 100644
--- a/gcc/testsuite/g++.dg/reflect/is_constructible_type1.C
+++ b/gcc/testsuite/g++.dg/reflect/is_constructible_type1.C
@@ -603,7 +603,7 @@ static_assert (!is_constructible_type (^^DelnAny, { ^^int, 
^^void * }));
 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 }));
diff --git a/gcc/testsuite/g++.dg/reflect/trivial-union1.C 
b/gcc/testsuite/g++.dg/reflect/trivial-union1.C
new file mode 100644
index 000000000000..6c9282a2ccf4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/reflect/trivial-union1.C
@@ -0,0 +1,214 @@
+// P3074R7 - trivial unions (was std::uninitialized<T>)
+// { 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; int 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));
+union N { N (); int a; G b; };
+static_assert (!is_default_constructible_type (^^N));
+static_assert (!is_trivially_default_constructible_type (^^N));
+static_assert (!is_destructible_type (^^N));
+static_assert (!is_trivially_destructible_type (^^N));
+constexpr auto Nctor = (members_of (^^N, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Ndtor = (members_of (^^N, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (!is_defaulted (Nctor) && !is_deleted (Nctor));
+static_assert (is_defaulted (Ndtor) && is_deleted (Ndtor));
+struct O { O (); union { int a; int 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));
+struct P { P (); union { int a; G b; }; };
+static_assert (!is_default_constructible_type (^^P));
+static_assert (!is_trivially_default_constructible_type (^^P));
+static_assert (!is_destructible_type (^^P));
+static_assert (!is_trivially_destructible_type (^^P));
+constexpr auto Pctor = (members_of (^^P, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Pdtor = (members_of (^^P, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (!is_defaulted (Pctor) && !is_deleted (Pctor));
+static_assert (is_defaulted (Pdtor) && is_deleted (Pdtor));
+struct Q { Q (int); union { int a; G b; }; };
+static_assert (!is_default_constructible_type (^^Q));
+static_assert (!is_trivially_default_constructible_type (^^Q));
+static_assert (!is_destructible_type (^^Q));
+static_assert (!is_trivially_destructible_type (^^Q));
+static_assert ((members_of (^^Q, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ()).size () == 0);
+constexpr auto Qdtor = (members_of (^^Q, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (is_defaulted (Qdtor) && is_deleted (Qdtor));
+struct R { R () = default; R (int); union { int a; G b; }; };
+static_assert (!is_default_constructible_type (^^R));
+static_assert (!is_trivially_default_constructible_type (^^R));
+static_assert (!is_destructible_type (^^R));
+static_assert (!is_trivially_destructible_type (^^R));
+constexpr auto Rctor = (members_of (^^R, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Rdtor = (members_of (^^R, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (is_defaulted (Rctor) && !is_deleted (Rctor));
+static_assert (is_defaulted (Rdtor) && is_deleted (Rdtor));
+struct S { S (int); ~S (); };
+union T { T (); int a; int b = 42; };
+static_assert (is_default_constructible_type (^^T));
+static_assert (!is_trivially_default_constructible_type (^^T));
+static_assert (is_destructible_type (^^T));
+static_assert (is_trivially_destructible_type (^^T));
+constexpr auto Tctor = (members_of (^^T, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Tdtor = (members_of (^^T, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (!is_defaulted (Tctor) && !is_deleted (Tctor));
+static_assert (is_defaulted (Tdtor) && !is_deleted (Tdtor));
+union U { U (); int a; S b = 42; };
+static_assert (!is_default_constructible_type (^^U));
+static_assert (!is_trivially_default_constructible_type (^^U));
+static_assert (!is_destructible_type (^^U));
+static_assert (!is_trivially_destructible_type (^^U));
+constexpr auto Uctor = (members_of (^^U, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Udtor = (members_of (^^U, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (!is_defaulted (Uctor) && !is_deleted (Uctor));
+static_assert (is_defaulted (Udtor) && is_deleted (Udtor));
+struct V { V (); union { int a; int b = 42; }; };
+static_assert (is_default_constructible_type (^^V));
+static_assert (!is_trivially_default_constructible_type (^^V));
+static_assert (is_destructible_type (^^V));
+static_assert (is_trivially_destructible_type (^^V));
+constexpr auto Vctor = (members_of (^^V, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Vdtor = (members_of (^^V, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (!is_defaulted (Vctor) && !is_deleted (Vctor));
+static_assert (is_defaulted (Vdtor) && !is_deleted (Vdtor));
+struct W { W (); union { int a; S b = 42; }; };
+static_assert (!is_default_constructible_type (^^W));
+static_assert (!is_trivially_default_constructible_type (^^W));
+static_assert (!is_destructible_type (^^W));
+static_assert (!is_trivially_destructible_type (^^W));
+constexpr auto Wctor = (members_of (^^W, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Wdtor = (members_of (^^W, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (!is_defaulted (Wctor) && !is_deleted (Wctor));
+static_assert (is_defaulted (Wdtor) && is_deleted (Wdtor));
+struct X { X (int); union { int a; S b = 42; }; };
+static_assert (!is_default_constructible_type (^^X));
+static_assert (!is_trivially_default_constructible_type (^^X));
+static_assert (!is_destructible_type (^^X));
+static_assert (!is_trivially_destructible_type (^^X));
+static_assert ((members_of (^^X, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ()).size () == 0);
+constexpr auto Xdtor = (members_of (^^X, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (is_defaulted (Xdtor) && is_deleted (Xdtor));
+struct Y { Y () = default; Y (int); union { int a; S b = 42; }; };
+static_assert (!is_default_constructible_type (^^Y));
+static_assert (!is_trivially_default_constructible_type (^^Y));
+static_assert (!is_destructible_type (^^Y));
+static_assert (!is_trivially_destructible_type (^^Y));
+constexpr auto Yctor = (members_of (^^Y, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto Ydtor = (members_of (^^Y, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (is_defaulted (Yctor) && !is_deleted (Yctor));
+static_assert (is_defaulted (Ydtor) && is_deleted (Ydtor));
+union AA { AA (); int a; long b; };
+static_assert (is_default_constructible_type (^^AA));
+static_assert (!is_trivially_default_constructible_type (^^AA));
+static_assert (is_destructible_type (^^AA));
+static_assert (is_trivially_destructible_type (^^AA));
+constexpr auto AActor = (members_of (^^AA, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto AAdtor = (members_of (^^AA, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (!is_defaulted (AActor) && !is_deleted (AActor));
+static_assert (is_defaulted (AAdtor) && !is_deleted (AAdtor));
+struct AB { AB () = default; AB (const AB &) = default; int a; ~AB (); };
+union AC { AC (); int a; AB b; };
+static_assert (!is_default_constructible_type (^^AC));
+static_assert (!is_trivially_default_constructible_type (^^AC));
+static_assert (!is_destructible_type (^^AC));
+static_assert (!is_trivially_destructible_type (^^AC));
+constexpr auto ACctor = (members_of (^^AC, ctx) | std::views::filter 
(is_default_constructor) | std::ranges::to <std::vector> ())[0];
+constexpr auto ACdtor = (members_of (^^AC, ctx) | std::views::filter 
(is_destructor) | std::ranges::to <std::vector> ())[0];
+static_assert (!is_defaulted (ACctor) && !is_deleted (ACctor));
+static_assert (is_defaulted (ACdtor) && is_deleted (ACdtor));
diff --git a/gcc/testsuite/g++.dg/reflect/type_trait6.C 
b/gcc/testsuite/g++.dg/reflect/type_trait6.C
index e1b466f3cb60..2f3527c14103 100644
--- a/gcc/testsuite/g++.dg/reflect/type_trait6.C
+++ b/gcc/testsuite/g++.dg/reflect/type_trait6.C
@@ -985,7 +985,7 @@ static_assert (!is_destructible_type (^^N2::Del [1]));
 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_type (^^N2::TD2));
 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));

Reply via email to