On Tue, Apr 07, 2020 at 02:46:52PM -0600, Martin Sebor wrote: > On 4/7/20 1:50 PM, Marek Polacek wrote: > > 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. > > Good catch! That doesn't fail because unlike null data member pointers > which are represented as -1, member function pointers are represented > as a zero. > > I had looked for an API that would answer the question: "is this > expression a pointer?" without having to think of all the different > kinds of them but all I could find was null_node_p(). Is this a rare, > isolated case that having an API like that wouldn't be worth having > or should I add one like in the attached update? > > 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/cp/cp-tree.h (null_pointer_constant_p): New function. (Drop the gcc/cp/.) > +/* Returns true if EXPR is a null pointer constant of any type. */ > + > +inline bool > +null_pointer_constant_p (tree expr) > +{ > + STRIP_ANY_LOCATION_WRAPPER (expr); > + if (expr == null_node) > + return true; > + tree type = TREE_TYPE (expr); > + if (NULLPTR_TYPE_P (type)) > + return true; > + if (POINTER_TYPE_P (type)) > + return integer_zerop (expr); > + return null_member_pointer_value_p (expr); > +} > + We already have a null_ptr_cst_p so it would be sort of confusing to have this as well. But are you really interested in whether it's a null pointer, not just a pointer? Marek