PR c++/85545 - ICE with noexcept PMF conversion.
authorJason Merrill <jason@redhat.com>
Fri, 27 Apr 2018 15:00:53 +0000 (11:00 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 27 Apr 2018 15:00:53 +0000 (11:00 -0400)
* 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.

From-SVN: r259712

gcc/cp/ChangeLog
gcc/cp/cvt.c
gcc/cp/typeck.c

index 149262c..9fd5266 100644 (file)
@@ -1,3 +1,12 @@
+2018-04-27  Jason Merrill  <jason@redhat.com>
+
+       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.
+
 2018-04-27  Nathan Sidwell  <nathan@acm.org>
 
        * typeck.c (convert_ptrmem): Move local var decls to initialization.
index a3735a1..0f045e2 100644 (file)
@@ -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);
index 24a206a..19db315 100644 (file)
@@ -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
@@ -8511,7 +8522,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);
        }
@@ -8531,12 +8542,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);
     }