https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125422
Bug ID: 125422
Summary: False positive -Wduplicated-branches with new
(nothrow) T[runtime_variable]
Product: gcc
Version: 16.1.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: johannes.natter at outlook dot at
Target Milestone: ---
Created attachment 64531
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=64531&action=edit
Preprocessed source (g++ -save-temps -Wduplicated-branches main.cpp)
When using `new (std::nothrow) T[n]` where `n` is a runtime variable (not a
compile-time constant), GCC incorrectly fires -Wduplicated-branches. The code
is valid C++ and contains no if/else written by the user.
The warning does not appear when `n` is a compile-time constant (e.g. a macro
or literal).
Test case (g++ -Wduplicated-branches -Werror main.cpp):
#include <new>
using namespace std;
// g++ -Wduplicated-branches -Werror -DWORKS=1 main.cpp -> OK
// g++ -Wduplicated-branches -Werror main.cpp -> false positive
#ifndef WORKS
#define WORKS 0
#endif
int main()
{
#if WORKS
char *p = new (nothrow) char[10];
#else
int sz = 10;
char *p = new (nothrow) char[sz];
#endif
if (!p) return 1;
delete[] p;
return 0;
}
Actual output:
main.cpp: In function 'int main()':
main.cpp:18:40: error: this condition has identical branches
[-Werror=duplicated-branches]
18 | char *p = new (nothrow) char[sz];
| ^
Expected: no warning -- the code is correct, there is no if/else in user code.
Affected Compiler Versions
$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/local/gcc-16/libexec/gcc/x86_64-pc-linux-gnu/16.1.1/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../gcc/configure --prefix=/usr/local/gcc-16
--enable-languages=c,c++ --disable-multilib --disable-bootstrap
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 16.1.1 20260519 (GCC)
$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/local/gcc-full/libexec/gcc/x86_64-pc-linux-gnu/17.0.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: ../gcc/configure --prefix=/usr/local/gcc-full
--enable-languages=c,c++
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 17.0.0 20260519 (experimental) (GCC)
Root cause:
In gcc/cp/init.cc, function build_new_1(), when building `new (nothrow) T[n]`
for a type without a destructor (no array cookie), no initializer and no
clobber, the following holds:
data_addr == alloc_node (semantically)
rval == data_addr
The check_new block then unconditionally builds a COND_EXPR:
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);
which expands to:
(alloc_node != nullptr) ? alloc_node : alloc_node
Both branches are semantically identical, so do_warn_duplicated_branches()
correctly detects them as equal -- but the COND_EXPR was compiler-generated,
not written by the user.
A patch has been submitted to [email protected]:
https://gcc.gnu.org/pipermail/gcc-patches/2026-May/717605.html