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);
 }

Reply via email to