We were ending up with two versions of B<&l::k> internally, one with a NOP_EXPR around the PTRMEM_CST, and the other with the conversion folded away. Let's fold it consistently.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit c2b6fedaffe587242a7af3ffaf99298845c1243c Author: Jason Merrill <ja...@redhat.com> Date: Sat Jun 2 20:56:22 2018 -0400 PR c++/85739 - ICE with pointer to member template parm. * cvt.c (perform_qualification_conversions): Use cp_fold_convert. diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index f29dacd685e..bca9d05af66 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -1945,7 +1945,8 @@ can_convert_qual (tree type, tree expr) /* Attempt to perform qualification conversions on EXPR to convert it to TYPE. Return the resulting expression, or error_mark_node if - the conversion was impossible. */ + the conversion was impossible. Since this is only used by + convert_nontype_argument, we fold the conversion. */ tree perform_qualification_conversions (tree type, tree expr) @@ -1957,7 +1958,7 @@ perform_qualification_conversions (tree type, tree expr) if (same_type_p (type, expr_type)) return expr; else if (can_convert_qual (type, expr)) - return build_nop (type, expr); + return cp_fold_convert (type, expr); else return error_mark_node; } diff --git a/gcc/testsuite/g++.dg/template/ptrmem32.C b/gcc/testsuite/g++.dg/template/ptrmem32.C new file mode 100644 index 00000000000..edf200313ea --- /dev/null +++ b/gcc/testsuite/g++.dg/template/ptrmem32.C @@ -0,0 +1,10 @@ +// PR c++/85739 + +struct l { int k; }; +template <int l::*> class b { }; +template <const int l::*> class B { typedef int e; }; +template <int l::*i, const int l::*n> +bool operator!=(B<n>, b<i>); + +bool bb = (B<&l::k>() != b<&l::k>()); +