https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125845
--- Comment #2 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Jakub Jelinek <[email protected]>: https://gcc.gnu.org/g:a8c97564fbc39b5c52dffaa3c8229c396632e28d commit r17-4132-ga8c97564fbc39b5c52dffaa3c8229c396632e28d Author: Jakub Jelinek <[email protected]> Date: Thu Sep 10 16:47:57 2026 +0200 c++, libstdc++: Implement C++26 P3726R2 - Adjustments to Union Lifetime Rules [PR125845] The following patch attempts to implement the C++26 P3726R2 - Adjustments to Union Lifetime Rules paper except 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). For std::start_lifetime I've added a FE builtin which unlike the standard function template takes a pointer rather than reference, because it needs to be type-generic and for (...) it would attempt to pass a copy of the referenced object rather than the reference. As I didn't want to duplicate most of the cxx_eval_store_expression function for its constant evaluation, I'm calling cxx_eval_store_expression on an artificial MODOP_EXPR with lhs as first operand and init as second operand and cxx_eval_store_expression handles MODOP_EXPR as __builtin_start_lifetime where needed, in some cases it doesn't do anything (if already within lifetime), otherwise can set an element to an empty CONSTRUCTOR_NO_CLEARING CONSTRUCTOR_OMITTED_NOT_WITHIN_LIFETIME_P CONSTRUCTOR. CONSTRUCTOR_OMITTED_NOT_WITHIN_LIFETIME_P is a new flag which says that the (sub)object represented by the CONSTRUCTOR is within lifetime, but its omitted elements are not. The builtin will be non-constant if there is a containing object of the referenced subobject and the containing object is not within lifetime. In reduced_constant_expression_p the patch also implements the second part of P3726R2, the changes to union elemental subobject handling, where it ignores holes for C++26 in arrays (possibly multi-dimensional) directly nested inside of union if they aren't active. 2026-09-10 Jakub Jelinek <[email protected]> P3726R2 PR c++/125845 gcc/c-family/ * c-cppbuiltin.cc (c_cpp_builtins): For C++26 predefine __cpp_trivial_union to 202603L. gcc/cp/ * cp-tree.h: Implement C++26 P3726R2 - Adjustments to Union Lifetime Rules. Document some generic flags used in C++ specific way on some trees in the toplevel comment. (CONSTRUCTOR_OMITTED_NOT_WITHIN_LIFETIME_P): Define. (enum cp_built_in_function): Add CP_BUILT_IN_START_LIFETIME. (reduced_constant_expression_p): Add a bool argument defaulted to false. * tree.cc (builtin_valid_in_constant_expr_p): Handle CP_BUILT_IN_START_LIFETIME. * decl.cc (cxx_init_decl_processing): Create __builtin_start_lifetime decl. * cp-gimplify.cc (cp_gimplify_expr): Handle CP_BUILT_IN_START_LIFETIME. * semantics.cc (check_frontend_builtin): New function. (finish_call_expr): Use it. * constexpr.cc (is_within_lifetime): New function. (cxx_eval_is_within_lifetime): Use it. Add fun argument and pass it to that function. (cxx_eval_start_lifetime): New function. (cxx_eval_builtin_function_call): Handle CP_BUILT_IN_START_LIFETIME. Pass fun to cxx_eval_is_within_lifetime. (is_std_allocator_allocate): Only return true for std::allocator<T>::allocate and not for std::allocator<T>::deallocate. (is_std_allocator_allocate_deallocate): New functions. (cxx_eval_call_expression): Use is_std_allocator_allocate_deallocate rather than is_std_allocator_allocate. (reduced_constant_expression_p): Add union_elemental_subobject argument and propagate it to recursive calls. If set, ignore for C++26 holes in array initializers which aren't within lifetime. (modifying_const_object_p): Change != MODIFY_EXPR test to == INIT_EXPR. (cxx_eval_store_expression): Handle MODOP_EXPR next to INIT_EXPR and MODIFY_EXPR, meaning start_lifetime. Don't preevaluate init in that case, return void_node early if *valp is already non-NULL/void_node and within lifetime. (cxx_eval_constant_expression): For std::allocator<T>::allocate start lifetime of the created array but not of its subobjects. Use is_std_allocator_allocate_deallocate rather than is_std_allocator_allocate where appropriate. (potential_constant_expression_1): Likewise. gcc/testsuite/ * g++.dg/cpp26/feat-cxx26.C: Adjust __cpp_trivial_union checking. * g++.dg/cpp26/trivial-union3.C: New test. * g++.dg/cpp26/trivial-union4.C: New test. * g++.dg/cpp26/trivial-union5.C: New test. * g++.dg/cpp26/trivial-union6.C: New test. * g++.dg/cpp26/within-lifetime3.C: Remove #if 0 and #endif. * g++.dg/cpp26/within-lifetime8.C: New test. * g++.dg/cpp26/within-lifetime9.C: New test. * g++.dg/cpp29/feat-cxx29.C: Adjust __cpp_trivial_union checking. libstdc++-v3/ * include/bits/version.def (start_lifetime): New. * include/bits/version.h: Regenerate. * include/bits/stl_construct.h (std::start_lifetime): New function template. * include/std/memory: Define __glibcxx_want_start_lifetime before including bits/version.h. * src/c++23/std.cc.in: Add export std::start_lifetime. Reviewed-by: Jason Merrill <[email protected]>
