[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