https://gcc.gnu.org/g:f4b60fe6d6a16f54347af476e88d534f3666ea08
commit r16-4275-gf4b60fe6d6a16f54347af476e88d534f3666ea08 Author: Jason Merrill <[email protected]> Date: Sat Oct 4 09:24:29 2025 +0100 c++: new-expr clobber of constant-size array I previously tried to clobber an array as a whole, but fell back on a loop due to issues with std::construct_at following the resolution of LWG3436. But the loop seems to make life hard for the optimizers and it occurs to me that for a one-element array we can just clobber the element type. This also fixes some xfails in Warray-bounds-20.C. gcc/cp/ChangeLog: * init.cc (build_new_1): Clobber a constant-bound array as a whole. gcc/testsuite/ChangeLog: * g++.dg/warn/Warray-bounds-20.C: Remove xfails, add diags. Diff: --- gcc/cp/init.cc | 26 ++++++++++++++++++++++---- gcc/testsuite/g++.dg/warn/Warray-bounds-20.C | 10 +++++----- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc index 3fe476d7eec7..912298728acd 100644 --- a/gcc/cp/init.cc +++ b/gcc/cp/init.cc @@ -3662,11 +3662,11 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, tree clobber_expr = NULL_TREE; if (do_clobber) { - tree clobber = build_clobber (elt_type, CLOBBER_OBJECT_BEGIN); - CONSTRUCTOR_IS_DIRECT_INIT (clobber) = true; - if (array_p) + if (array_p && TREE_CODE (cst_outer_nelts) != INTEGER_CST) { /* Clobber each element rather than the array at once. */ + tree clobber = build_clobber (elt_type, CLOBBER_OBJECT_BEGIN); + CONSTRUCTOR_IS_DIRECT_INIT (clobber) = true; tree maxindex = cp_build_binary_op (input_location, MINUS_EXPR, outer_nelts, integer_one_node, @@ -3677,7 +3677,25 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, } else { - tree targ = cp_build_fold_indirect_ref (data_addr); + tree targ = data_addr; + tree ttype = type; + /* Clobber the array as a whole, except that for a one-element array + just clobber the element type, to avoid problems with code like + construct_at that uses new T[1] for array T to get a pointer to + the array. */ + if (array_p && !integer_onep (cst_outer_nelts)) + { + tree dom + = compute_array_index_type (NULL_TREE, + CONST_CAST_TREE (cst_outer_nelts), + complain); + ttype = build_cplus_array_type (type, dom); + tree ptype = build_pointer_type (ttype); + targ = fold_convert (ptype, targ); + } + targ = cp_build_fold_indirect_ref (targ); + tree clobber = build_clobber (ttype, CLOBBER_OBJECT_BEGIN); + CONSTRUCTOR_IS_DIRECT_INIT (clobber) = true; clobber_expr = cp_build_init_expr (targ, clobber); } } diff --git a/gcc/testsuite/g++.dg/warn/Warray-bounds-20.C b/gcc/testsuite/g++.dg/warn/Warray-bounds-20.C index 643e8014d36e..a57499dd07ae 100644 --- a/gcc/testsuite/g++.dg/warn/Warray-bounds-20.C +++ b/gcc/testsuite/g++.dg/warn/Warray-bounds-20.C @@ -53,18 +53,18 @@ void warn_derived_ctor_access_new_alloc () void warn_derived_ctor_access_new_array_decl () { - char b[sizeof (D1) * 2]; // { dg-message "at offset \\d+ into object 'b' of size 80" "LP64 note" { target { lp64 } xfail { lp64 } } } - // { dg-message "at offset \\d+ into object 'b' of size 40" "LP32 note" { target { ilp32 } xfail { ilp32 } } .-1 } + char b[sizeof (D1) * 2]; // { dg-message "at offset \\d+ into object 'b' of size 80" "LP64 note" { target { lp64 } } } + // { dg-message "at offset \\d+ into object 'b' of size 40" "LP64 note" { target { ilp32 } } .-1 } char *p = b; ++p; - D1 *q = new (p) D1[2]; + D1 *q = new (p) D1[2]; // { dg-message "partly outside array bounds" } sink (q); } void warn_derived_ctor_access_new_array_alloc () { - char *p = new char[sizeof (D1) * 2]; // { dg-message "at offset \\d+ into object of size \\d+ allocated by '\[^\n\r]*operator new\[^\n\r]*" "note" { xfail *-*-* } } + char *p = new char[sizeof (D1) * 2]; // { dg-message "at offset \\d+ into object of size \\d+ allocated by '\[^\n\r]*operator new\[^\n\r]*" "note" } ++p; - D1 *q = new (p) D1[2]; + D1 *q = new (p) D1[2]; // { dg-message "partly outside array bounds" } sink (q); }
