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