From: Jason Merrill Date: Wed, 24 Jun 2020 05:49:06 +0000 (-0400) Subject: c++: Simplify build_over_call a bit. X-Git-Tag: basepoints/gcc-12~6619 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3faa0dde31720a59082b038a9f50f5703711bb53;p=thirdparty%2Fgcc.git 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 fe68fda1364f..d8923be1d68b 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);