On 6/1/26 3:26 PM, Joe Natter wrote:
The alloc_node anchor for -Wmismatched-new-delete (second block)
must run when `check_new' and `!cookie_size': without a cookie, data_addr
and alloc_node may be distinct tree nodes after fold_convert, and
alloc_node must be appended explicitly to remain visible to the diagnostic
-- independently of whether rval equals data_addr.
Do you have a testcase for this argument? If I move the COMPOUND_EXPR back
into the same condition as the COND_EXPR, none of the Wmismatched-new-delete
tests regress.
Unfortunately no. My argument was wrong.
I moved the COMPOUND_EXPR back too and retested => OK
Then I tested your recommendation (clearing check_new) => OK
It seems that I misinterpreted my prior test results.
Given that, I wouldn't add the 'improvement' (const bool, may_return_null),
because it adds unnecessary noise.
Joe
This would be my current approach:
I liked the comment in your previous version, so here's what I'm
pushing. Thanks!
From 3d50a3ee3e8f55bfd240e314e3d62edc17ec5887 Mon Sep 17 00:00:00 2001
From: Joe Natter <[email protected]>
Date: Thu, 21 May 2026 20:20:16 +0200
Subject: [PATCH] c++: Fix spurious -Wduplicated-branches for new (nothrow)
T[n] [PR125422]
To: [email protected]
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:
PR c++/125422
* init.cc (build_new_1): Avoid building a null-check
COND_EXPR when rval == data_addr.
gcc/testsuite/ChangeLog:
PR c++/125422
* g++.dg/warn/Wduplicated-branches10.C: New test.
Signed-off-by: Joe Natter <[email protected]>
Reviewed-by: Jason Merrill <[email protected]>
---
gcc/cp/init.cc | 6 ++++++
.../g++.dg/warn/Wduplicated-branches10.C | 15 +++++++++++++++
2 files changed, 21 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/warn/Wduplicated-branches10.C
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc
index 14ceafa6828..8d0018a31cc 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -3970,6 +3970,12 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
rval = TARGET_EXPR_INITIAL (alloc_expr);
else
{
+ /* Skip the null-check when rval == data_addr: the resulting conditional
+ would be "alloc_node != nullptr ? alloc_node : alloc_node", triggering
+ -Wduplicated-branches (PR125422). */
+ if (rval == data_addr)
+ check_new = 0;
+
if (check_new)
{
tree ifexp = cp_build_binary_op (input_location,
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;
+}
--
2.54.0