On 2/11/19 2:21 PM, Marek Polacek wrote:
On Fri, Feb 08, 2019 at 05:37:00PM -0500, Jason Merrill wrote:
On 2/8/19 12:21 PM, Marek Polacek wrote:
r256999 removed early bailout for pointer-to-member-function types, so we
now try to tsubst each element of a pointer-to-member-function CONSTRUCTOR.

That's fine but the problem here is that we end up converting a null pointer
to pointer-to-member-function type and that crashes in fold_convert:

16035     case INTEGER_CST:
16039       {
16040         /* Instantiate any typedefs in the type.  */
16041         tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
16042         r = fold_convert (type, t);

It seems obvious to use cp_fold_convert which handles TYPE_PTRMEM_P, but
that then ICEs too, the infamous "canonical types differ for identical types":
type is

struct
{
    void A::<T344> (struct A *) * __pfn;
    long int __delta;
}

and the type of "0" is "void A::<T344> (struct A *) *".  These types are
structurally equivalent but have different canonical types.  (What's up
with that, anyway?  It seems OK that the canonical type of the struct is
the struct itself and that the canonical type of the pointer is the pointer
itself.)

That could be handled in cp_fold_convert: add code to convert an integer_zerop 
to
TYPE_PTRMEMFUNC_P.  Unfortunately the 0 is not null_ptr_cst_p because it's got
a pointer type.

Or just don't bother substituting null_member_pointer_value_p and avoid the
above.

Bootstrapped/regtested on x86_64-linux, ok for trunk and 8?

2019-02-08  Marek Polacek  <pola...@redhat.com>

        PR c++/89212 - ICE converting nullptr to pointer-to-member-function.
        * pt.c (tsubst_copy_and_build) <case CONSTRUCTOR>: Return early for
        null member pointer value.

        * g++.dg/cpp0x/nullptr40.C: New test.

diff --git gcc/cp/pt.c gcc/cp/pt.c
index b8fbf4046f0..acc2d8f1feb 100644
--- gcc/cp/pt.c
+++ gcc/cp/pt.c
@@ -19251,6 +19251,9 @@ tsubst_copy_and_build (tree t,
           looked up by digest_init.  */
        process_index_p = !(type && MAYBE_CLASS_TYPE_P (type));
+       if (null_member_pointer_value_p (t))
+         RETURN (t);

I would expect this to do the wrong thing if type is different from
TREE_TYPE (t).  Can we get here for a dependent PMF type like T (A::*)()?
If not, let's assert that they're the same.  Otherwise, maybe cp_convert
(type, nullptr_node)?

Yup, that's a concern.  But I'm not seeing any ICEs with the assert added and a
dependent PMF as in the new testcase.  And it seems we get a conversion error
if the types of the PMFs don't match.  If I'm wrong, this would be easy to
fix anyway.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

OK.

Jason

Reply via email to