With Nathan's patch for 85437, constexpr evaluation now breaks open a
PTRMEM_CST that has a non-qualification conversion.  Then actually
performing the conversion means messing with the contents of the
CONSTRUCTOR.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 487666e08d885b64235a72c4e9a941acc2cd1512
Author: Jason Merrill <ja...@redhat.com>
Date:   Fri Apr 27 07:45:02 2018 -0400

            PR c++/85545 - ICE with noexcept PMF conversion.
    
            * cvt.c (cp_fold_convert): Pass PMF CONSTRUCTORs to
            build_ptrmemfunc.
            * typeck.c (build_ptrmemfunc): Don't build a NOP_EXPR for zero
            adjustment.
            (build_ptrmemfunc_access_expr): Special-case CONSTRUCTORs.

diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index a3735a1cffe..0f045e2ab12 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -601,14 +601,16 @@ cp_fold_convert (tree type, tree expr)
   tree conv;
   if (TREE_TYPE (expr) == type)
     conv = expr;
-  else if (TREE_CODE (expr) == PTRMEM_CST
-	   || (TREE_CODE (expr) == CONSTRUCTOR
-	       && TYPE_PTRMEMFUNC_P (type)))
+  else if (TREE_CODE (expr) == PTRMEM_CST)
     {
       /* Avoid wrapping a PTRMEM_CST in NOP_EXPR.  */
       conv = copy_node (expr);
       TREE_TYPE (conv) = type;
     }
+  else if (TREE_CODE (expr) == CONSTRUCTOR
+	   && TYPE_PTRMEMFUNC_P (type))
+    conv = build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr,
+			     true, false, tf_warning_or_error);
   else
     {
       conv = fold_convert (type, expr);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 907d31d9786..d881a95322c 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3042,6 +3042,17 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name)
   tree ptrmem_type;
   tree member;
 
+  if (TREE_CODE (ptrmem) == CONSTRUCTOR)
+    {
+      unsigned int ix;
+      tree index, value;
+      FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ptrmem),
+				ix, index, value)
+	if (index && DECL_P (index) && DECL_NAME (index) == member_name)
+	  return value;
+      gcc_unreachable ();
+    }
+
   /* This code is a stripped down version of
      build_class_member_access_expr.  It does not work to use that
      routine directly because it expects the object to be of class
@@ -8517,7 +8528,7 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p,
 	{
 	  if (same_type_p (to_type, pfn_type))
 	    return pfn;
-	  else if (integer_zerop (n))
+	  else if (integer_zerop (n) && TREE_CODE (pfn) != CONSTRUCTOR)
 	    return build_reinterpret_cast (to_type, pfn, 
                                            complain);
 	}
@@ -8537,12 +8548,15 @@ build_ptrmemfunc (tree type, tree pfn, int force, bool c_cast_p,
       /* Just adjust the DELTA field.  */
       gcc_assert  (same_type_ignoring_top_level_qualifiers_p
 		   (TREE_TYPE (delta), ptrdiff_type_node));
-      if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta)
-	n = cp_build_binary_op (input_location,
-				LSHIFT_EXPR, n, integer_one_node,
-				complain);
-      delta = cp_build_binary_op (input_location,
-				  PLUS_EXPR, delta, n, complain);
+      if (!integer_zerop (n))
+	{
+	  if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta)
+	    n = cp_build_binary_op (input_location,
+				    LSHIFT_EXPR, n, integer_one_node,
+				    complain);
+	  delta = cp_build_binary_op (input_location,
+				      PLUS_EXPR, delta, n, complain);
+	}
       return build_ptrmemfunc1 (to_type, delta, npfn);
     }
 

Reply via email to