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); }