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); + n = vec_safe_copy (CONSTRUCTOR_ELTS (t)); newlen = vec_safe_length (n); FOR_EACH_VEC_SAFE_ELT (n, idx, ce) diff --git gcc/testsuite/g++.dg/cpp0x/nullptr40.C gcc/testsuite/g++.dg/cpp0x/nullptr40.C new file mode 100644 index 00000000000..21c188bdb5e --- /dev/null +++ gcc/testsuite/g++.dg/cpp0x/nullptr40.C @@ -0,0 +1,19 @@ +// PR c++/89212 +// { dg-do compile { target c++11 } } + +template <int, typename T> using enable_if_t = int; + +template<class X, void(X::*foo)() = nullptr> +struct p +{ + template<void(X::*fun)() = foo, typename T = enable_if_t<nullptr == fun, int>> + p(T) { } + p() = default; +}; + +struct A +{ + p<A> i = 1; + void bar(); + p<A, &A::bar> j; +};