[PATCH] c++: Consider addresses of heap artificial vars always non-NULL [PR98988]
Jason Merrill
jason@redhat.com
Tue Feb 9 20:00:20 GMT 2021
On 2/9/21 3:25 AM, Jakub Jelinek wrote:
> Hi!
>
> With -fno-delete-null-pointer-checks which is e.g. implied by
> -fsanitize=undefined or default on some embedded targets, the middle-end
> folder doesn't consider addresses of global VAR_DECLs to be non-NULL, as one
> of them could have address 0.
Hmm, are these VAR_DECLs going into the symtab? That seems undesirable.
> Still, I think malloc/operator new (at least
> the nonthrowing) relies on NULL returns meaning allocation failure rather
> than success. Furthermore, the artificial VAR_DECLs we create for
> constexpr new never actually live in the address space of the program,
> so we can pretend they will never be NULL too.
> The following patch does that, so that one can actually use constexpr
> new/delete even with -fno-delete-null-pointer-checks or sanitizers
> - otherwise delete itself tests whether the passed address is non-NULL and
> that wouldn't fold to true if the pointer has been allocated with constexpr
> new.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2021-02-09 Jakub Jelinek <jakub@redhat.com>
>
> PR c++/98988
> * constexpr.c (cxx_eval_binary_expression): Fold equality comparison
> of address of heap artificial VAR_DECL against nullptr.
>
> * g++.dg/cpp2a/constexpr-new16.C: New test.
>
> --- gcc/cp/constexpr.c.jj 2021-02-02 09:52:10.535234056 +0100
> +++ gcc/cp/constexpr.c 2021-02-08 17:24:28.774467744 +0100
> @@ -3157,6 +3157,32 @@ cxx_eval_binary_expression (const conste
> lhs = cplus_expand_constant (lhs);
> else if (TREE_CODE (rhs) == PTRMEM_CST)
> rhs = cplus_expand_constant (rhs);
> + if (r == NULL_TREE && POINTER_TYPE_P (TREE_TYPE (lhs)))
> + {
> + tree op0 = lhs;
> + tree op1 = rhs;
> + if (integer_zerop (op0))
> + std::swap (op0, op1);
> + /* With -fno-delete-null-pointer-checks, generic folders
> + assume addresses of non-automatic VAR_DECLs could be NULL.
> + For constexpr new, as the vars aren't really living in
> + target memory, assume they will never be NULL. */
> + if (integer_zerop (op1))
> + {
> + STRIP_NOPS (op0);
> + if (TREE_CODE (op0) == ADDR_EXPR)
> + {
> + op0 = get_base_address (TREE_OPERAND (op0, 0));
> + if (op0
> + && VAR_P (op0)
> + && (DECL_NAME (op0) == heap_identifier
> + || DECL_NAME (op0) == heap_uninit_identifier
> + || DECL_NAME (op0) == heap_vec_identifier
> + || DECL_NAME (op0) == heap_vec_uninit_identifier))
> + r = constant_boolean_node (!is_code_eq, type);
> + }
> + }
> + }
> }
> if (code == POINTER_PLUS_EXPR && !*non_constant_p
> && integer_zerop (lhs) && !integer_zerop (rhs))
> --- gcc/testsuite/g++.dg/cpp2a/constexpr-new16.C.jj 2021-02-08 17:25:37.130699213 +0100
> +++ gcc/testsuite/g++.dg/cpp2a/constexpr-new16.C 2021-02-08 17:26:49.175889198 +0100
> @@ -0,0 +1,13 @@
> +// PR c++/98988
> +// { dg-do compile { target c++20 } }
> +// { dg-options "-fno-delete-null-pointer-checks" }
> +
> +constexpr bool
> +foo ()
> +{
> + auto ptr = new int();
> + delete ptr;
> + return true;
> +}
> +
> +static_assert (foo ());
>
> Jakub
>
More information about the Gcc-patches
mailing list