https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127046
--- Comment #2 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The trunk branch has been updated by Jason Merrill <[email protected]>: https://gcc.gnu.org/g:40cbcd4eedce587c089492213711f4b85ac35843 commit r17-3765-g40cbcd4eedce587c089492213711f4b85ac35843 Author: Vincenzo Calabretta <[email protected]> Date: Sat Aug 29 08:24:25 2026 +0200 c++: unshare RANGE_EXPR CONSTRUCTOR index [PR127046] unshare_constructor creates an unshared copy of a CONSTRUCTOR and its nested CONSTRUCTOR values. The implementation copies the tree and the constructor elements vector, but not constructor_elt::index, which remains shared due to the shallow copy. For an array whose elements share the same initializer, build_vec_init generates a single constructor element with a RANGE_EXPR index. When find_array_ctor_elt splits the RANGE_EXPR, it assumes that the CONSTRUCTOR being mutated is private. Since the index is still shared, the tree from which the CONSTRUCTOR was unshared is also mutated. Since r16-3022-gbc42128330c, cxx_eval_store_expression handles CLOBBER_OBJECT_END for a subobject instead of immediately returning. When the clobber targets an array element, control flow proceeds to get_or_insert_ctor_field. find_array_ctor_elt splits the RANGE_EXPR to create a separate constructor element for the affected array element. The new element is added only to the unshared constructor elements vector, but the range index remains shared and is also mutated in the original tree. Gimplification of the original tree can omit initialization by the NSDMI for elements not covered by the mutated range. The change copies RANGE_EXPR indexes in unshare_constructor, so that subsequent mutations do not affect the original tree. Bootstrapped and tested on x86_64-pc-linux-gnu. PR c++/127046 gcc/cp/ChangeLog: * constexpr.cc (unshare_constructor): Copy RANGE_EXPR indexes. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/constexpr-dtor20.C: New test. Signed-off-by: Vincenzo Calabretta <[email protected]>
