https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99934
--- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> --- For the non-global replaceable operator new call, we put the outer_nelts_check already into the size argument before we actually look up the call: tree errval = TYPE_MAX_VALUE (sizetype); if (cxx_dialect >= cxx11 && flag_exceptions) errval = throw_bad_array_new_length (); if (outer_nelts_check != NULL_TREE) size = fold_build3 (COND_EXPR, sizetype, outer_nelts_check, size, errval); ... alloc_call = build_new_method_call (dummy, fns, &align_args, /*conversion_path=*/NULL_TREE, LOOKUP_NORMAL, &alloc_fn, tf_none); ... alloc_call = build_new_method_call (dummy, fns, placement, /*conversion_path=*/NULL_TREE, LOOKUP_NORMAL, &alloc_fn, complain); So I guess either we should after alloc_call is built look whether it is noexcept/throw() and if so, wrap it into another COND_EXPR with unshare_expr of outer_nelts_check and alloc_call, build_zero_cst (TREE_TYPE (alloc_call)), or perhaps that + at that point try to simplify the size argument of the call. But I think any kind of CSE in GIMPLE or RTL optimizations should optimize that already and so the FE doesn't need to duplicate such optimization. Plus verify what happens with the global replaceable operators. And another thing is constant expression evaluation, http://eel.is/c++draft/expr.new#9.5 says we should reject it during constant expression evaluation, but if we represent it as COND_EXPR something, operator new (...), nullptr then I'm afraid constant expression evaluation would accept it and evaluate to nullptr.