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>());
+

Reply via email to