[PATCH] reject scalar array initialization with nullptr [PR94510]

Marek Polacek polacek@redhat.com
Tue Apr 7 19:50:51 GMT 2020


On Tue, Apr 07, 2020 at 12:50:48PM -0600, Martin Sebor via Gcc-patches wrote:
> Among the numerous regressions introduced by the change committed
> to GCC 9 to allow string literals as template arguments is a failure
> to recognize the C++ nullptr and GCC's __null constants as pointers.
> For one, I didn't realize that nullptr, being a null pointer constant,
> doesn't have a pointer type, and two, I didn't think of __null (which
> is a special integer constant that NULL sometimes expands to).
> 
> The attached patch adjusts the special handling of trailing zero
> initializers in reshape_init_array_1 to recognize both kinds of
> constants and avoid treating them as zeros of the array integer
> element type.  This restores the expected diagnostics when either
> constant is used in the initializer list.
> 
> Martin

> PR c++/94510 - nullptr_t implicitly cast to zero twice in std::array
> 
> gcc/cp/ChangeLog:
> 
> 	PR c++/94510
> 	* decl.c (reshape_init_array_1): Exclude mismatches with all kinds
> 	of pointers.
> 
> gcc/testsuite/ChangeLog:
> 
> 	PR c++/94510
> 	* g++.dg/init/array57.C: New test.
> 	* g++.dg/init/array58.C: New test.
> 
> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> index a127734af69..692c8ed73f4 100644
> --- a/gcc/cp/decl.c
> +++ b/gcc/cp/decl.c
> @@ -6041,9 +6041,14 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
>  	TREE_CONSTANT (new_init) = false;
>  
>        /* Pointers initialized to strings must be treated as non-zero
> -	 even if the string is empty.  */
> +	 even if the string is empty.  Handle all kinds of pointers,
> +	 including std::nullptr and GCC's __nullptr, neither of which
> +	 has a pointer type.  */
>        tree init_type = TREE_TYPE (elt_init);
> -      if (POINTER_TYPE_P (elt_type) != POINTER_TYPE_P (init_type)
> +      bool init_is_ptr = (POINTER_TYPE_P (init_type)
> +			  || NULLPTR_TYPE_P (init_type)
> +			  || null_node_p (elt_init));
> +      if (POINTER_TYPE_P (elt_type) != init_is_ptr
>  	  || !type_initializer_zero_p (elt_type, elt_init))
>  	last_nonzero = index;

It looks like this still won't handle e.g. pointers to member functions,
e.g.

struct S { };
int arr[3] = { (void (S::*) ()) 0, 0, 0 };

would still be accepted.  You could use TYPE_PTR_OR_PTRMEM_P instead of
POINTER_TYPE_P to catch this case.

Marek



More information about the Gcc-patches mailing list