diff mbox series

[pushed] c++: Fix ICE with using and virtual function [PR95719]

Message ID b2ecfe10-09bc-f368-9f82-fd731230707c@redhat.com
State New
Headers show
Series [pushed] c++: Fix ICE with using and virtual function [PR95719] | expand

Commit Message

Jason Merrill June 24, 2020, 7:59 p.m. UTC
Looking in the vtable for cand->conversion_path doesn't work because 
it's the base where we found the function, not the base where the 
function is defined.  If those are different, look farther.  Applying to 
trunk and 10.

The second patch uses that same base lookup for the actual conversion as 
well as finding the final overrider.  Applying only to trunk.

Tested x86_64-pc-linux-gnu.
diff mbox series

Patch

commit 3d9fe61f07abb2653412259a974811917149b3b8
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Jun 24 01:49:06 2020 -0400

    c++: Simplify build_over_call a bit.
    
    It occurred to me that if we're looking up the defining base within the
    conversion_path binfo, we could use the result for the conversion as well
    instead of doing two separate conversions.
    
    gcc/cp/ChangeLog:
    
            * call.c (build_over_call): Only call build_base_path once.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index fe68fda1364..d8923be1d68 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -8658,13 +8658,10 @@  build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
   /* Bypass access control for 'this' parameter.  */
   else if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
     {
-      tree parmtype = TREE_VALUE (parm);
       tree arg = build_this (first_arg != NULL_TREE
 			     ? first_arg
 			     : (*args)[arg_index]);
       tree argtype = TREE_TYPE (arg);
-      tree converted_arg;
-      tree base_binfo;
 
       if (arg == error_mark_node)
 	return error_mark_node;
@@ -8683,38 +8680,20 @@  build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 	    return error_mark_node;
 	}
 
+      /* The class where FN is defined.  */
+      tree ctx = DECL_CONTEXT (fn);
+
       /* See if the function member or the whole class type is declared
 	 final and the call can be devirtualized.  */
-      if (DECL_FINAL_P (fn)
-	  || CLASSTYPE_FINAL (TYPE_METHOD_BASETYPE (TREE_TYPE (fn))))
+      if (DECL_FINAL_P (fn) || CLASSTYPE_FINAL (ctx))
 	flags |= LOOKUP_NONVIRTUAL;
 
-      /* If we know the dynamic type of the object, look up the final overrider
-	 in the BINFO.  */
-      if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0
-	  && resolves_to_fixed_type_p (arg))
-	{
-	  tree binfo = cand->conversion_path;
-	  if (BINFO_TYPE (binfo) != DECL_CONTEXT (fn))
-	    binfo = lookup_base (binfo, DECL_CONTEXT (fn), ba_unique,
-				 NULL, complain);
-	  fn = lookup_vfn_in_binfo (DECL_VINDEX (fn), binfo);
-	  flags |= LOOKUP_NONVIRTUAL;
-	}
-
       /* [class.mfct.non-static]: If a non-static member function of a class
 	 X is called for an object that is not of type X, or of a type
 	 derived from X, the behavior is undefined.
 
 	 So we can assume that anything passed as 'this' is non-null, and
 	 optimize accordingly.  */
-      gcc_assert (TYPE_PTR_P (parmtype));
-      /* Convert to the base in which the function was declared.  */
-      gcc_assert (cand->conversion_path != NULL_TREE);
-      converted_arg = build_base_path (PLUS_EXPR,
-				       arg,
-				       cand->conversion_path,
-				       1, complain);
       /* Check that the base class is accessible.  */
       if (!accessible_base_p (TREE_TYPE (argtype),
 			      BINFO_TYPE (cand->conversion_path), true))
@@ -8728,12 +8707,25 @@  build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
 	}
       /* If fn was found by a using declaration, the conversion path
 	 will be to the derived class, not the base declaring fn. We
-	 must convert from derived to base.  */
-      base_binfo = lookup_base (TREE_TYPE (TREE_TYPE (converted_arg)),
-				TREE_TYPE (parmtype), ba_unique,
-				NULL, complain);
-      converted_arg = build_base_path (PLUS_EXPR, converted_arg,
-				       base_binfo, 1, complain);
+	 must convert to the base.  */
+      tree base_binfo = cand->conversion_path;
+      if (BINFO_TYPE (base_binfo) != ctx)
+	{
+	  base_binfo = lookup_base (base_binfo, ctx, ba_unique, NULL, complain);
+	  if (base_binfo == error_mark_node)
+	    return error_mark_node;
+	}
+      tree converted_arg = build_base_path (PLUS_EXPR, arg,
+					    base_binfo, 1, complain);
+
+      /* If we know the dynamic type of the object, look up the final overrider
+	 in the BINFO.  */
+      if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0
+	  && resolves_to_fixed_type_p (arg))
+	{
+	  fn = lookup_vfn_in_binfo (DECL_VINDEX (fn), base_binfo);
+	  flags |= LOOKUP_NONVIRTUAL;
+	}
 
       argarray[j++] = converted_arg;
       parm = TREE_CHAIN (parm);