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

Reply via email to