From 5b19ba5ddb483bb8ae1ebdfb7f39815802ecd267 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]

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.

Bootstrapped and tested on x86_64-pc-linux-gnu.

[No PR yet; Bugzilla account request is pending.]
---
 gcc/cp/init.cc                                  | 17 +++++++++++------
 .../g++.dg/warn/Wduplicated-branches10.C        | 14 ++++++++++++++
 2 files changed, 25 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..6b051867c31
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wduplicated-branches10.C
@@ -0,0 +1,14 @@
+// { 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;
+}
--
2.34.1

Reply via email to