On 5/22/26 5:00 PM, Johannes Natter wrote:
Thanks for the review!

PR created:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125422

 > data_addr isn't equivalent to alloc_node if cookie_size is nonzero;
 > this seems to do the wrong thing in that case.

When cookie_size is nonzero, the block at lines 3618-3652 always
assigns a non-NULL value to cookie_expr.  Line 3951 then wraps rval:

   if (cookie_expr)
     rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), cookie_expr, rval);

This makes rval != data_addr (pointer comparison), so the condition
`if (rval != data_addr)' evaluates to true and the null-check COND_EXPR
is still built.  The cookie case should be handled correctly.

Ah, good point. But then we don't need any of the if (check_new) block in this case, so we could clear check_new if we didn't add any COMPOUND_EXPR to rval, or check rval != data_addr along with check_new?

If you prefer to make the cookie handling more explicit, I can change
the condition to:

   if (rval != data_addr || cookie_size)

cookie_size != 0 always implies rval != data_addr, but it might make
the cookie case easier to see.

 > Do you intend to contribute under FSF copyright assignment or the DCO?

I intend to contribute under the DCO.  Here is the updated patch with
Signed-off-by added:

Great. Please also add a "PR c++/125422" line at the top of the ChangeLog entries. 'git gcc-verify' would complain about that.

 From cfdc00cb416167cbf905f6ca1e3919bf567e663f Mon Sep 17 00:00:00 2001
From: Joe Natter <[email protected]>
Date: Thu, 21 May 2026 20:20:16 +0200
Subject: [PATCH] c++: Avoid spurious -Wduplicated-branches for new (nothrow) T[n] [PR125422]

When allocating an array of a trivial type with new (nothrow),
build_new_1() may emit a compiler-generated COND_EXPR of the form

   (alloc_node != nullptr) ? rval : alloc_node

For trivial arrays without constructors, destructors, or array cookies,
rval remains equal to data_addr and is therefore equivalent to
alloc_node.  This causes both branches of the generated COND_EXPR to be
identical, triggering -Wduplicated-branches on user code.

Avoid building the null-check COND_EXPR when rval == data_addr.

gcc/cp/ChangeLog:

     * init.cc (build_new_1): Avoid building a null-check
     COND_EXPR when rval == data_addr.

gcc/testsuite/ChangeLog:

     * g++.dg/warn/Wduplicated-branches10.C: New test.

Signed-off-by: Joe Natter <[email protected]>
---
  gcc/cp/init.cc                                  | 17 +++++++++++------
  .../g++.dg/warn/Wduplicated-branches10.C        | 15 +++++++++++++++
  2 files changed, 26 insertions(+), 6 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/warn/Wduplicated-branches10.C

diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index d0929c35bfc..2b089524409 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -3961,12 +3961,17 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
      {
        if (check_new)
      {
-      tree ifexp = cp_build_binary_op (input_location,
-                       NE_EXPR, alloc_node,
-                       nullptr_node,
-                       complain);
-      rval = build_conditional_expr (input_location, ifexp, rval,
-                     alloc_node, complain);
+      /* Avoid generating a redundant null-check COND_EXPR
+         when rval == data_addr.  */
+      if (rval != data_addr)
+        {
+          tree ifexp = cp_build_binary_op (input_location,
+                           NE_EXPR, alloc_node,
+                           nullptr_node,
+                           complain);
+          rval = build_conditional_expr (input_location, ifexp, rval,
+                         alloc_node, complain);
+        }
        /* If there's no offset between data_addr and alloc_node, append it
           to help -Wmismatched-new-delete at -O0.  */
        if (!cookie_size)
diff --git a/gcc/testsuite/g++.dg/warn/Wduplicated-branches10.C b/gcc/ testsuite/g++.dg/warn/Wduplicated-branches10.C
new file mode 100644
index 00000000000..0ebccd7d6fe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wduplicated-branches10.C
@@ -0,0 +1,15 @@
+// PR c++/125422
+// { dg-do compile }
+// { dg-options "-Wduplicated-branches" }
+
+// new (nothrow) T[n] with a runtime variable must not trigger
+// -Wduplicated-branches (false positive from compiler-generated COND_EXPR).
+
+#include <new>
+
+void
+test_nothrow (int sz)
+{
+  char *p = new (std::nothrow) char[sz];
+  delete[] p;
+}

Reply via email to