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

Reply via email to