>> 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: >From 6f9efcf6d6af7b422911b66b98a34b25cdd29376 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] 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]> --- gcc/cp/init.cc | 3 +++ .../g++.dg/warn/Wduplicated-branches10.C | 15 +++++++++++++++ 2 files changed, 18 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 d0929c35bfc..3c74cd2a757 100644 --- a/gcc/cp/init.cc +++ b/gcc/cp/init.cc @@ -3959,6 +3959,9 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts, rval = TARGET_EXPR_INITIAL (alloc_expr); else { + 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.34.1
