From 5c824000a5b855d454483bee7d32850f161ecdab Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 12 May 2010 13:34:15 -0400 Subject: [PATCH] call.c (add_candidates): Add first_arg and return_type parms. * call.c (add_candidates): Add first_arg and return_type parms. Add special constructor/conversion op handling. (convert_class_to_reference): Use it. (build_user_type_conversion_1): Likewise. (build_op_call): Likewise. (build_new_method_call): Likewise. (build_new_op): Adjust. (perform_overload_resolution): Adjust. From-SVN: r159332 --- gcc/cp/ChangeLog | 11 + gcc/cp/call.c | 358 +++++++----------- gcc/testsuite/ChangeLog | 4 + gcc/testsuite/g++.old-deja/g++.robertl/eb43.C | 2 + 4 files changed, 160 insertions(+), 215 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 58a57e05e51..5c8ff3a739a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,14 @@ +2010-05-12 Jason Merrill + + * call.c (add_candidates): Add first_arg and return_type parms. + Add special constructor/conversion op handling. + (convert_class_to_reference): Use it. + (build_user_type_conversion_1): Likewise. + (build_op_call): Likewise. + (build_new_method_call): Likewise. + (build_new_op): Adjust. + (perform_overload_resolution): Adjust. + 2010-05-11 Paolo Carlini PR c++/34272 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index d74eb19580f..17ad99e8426 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -197,8 +197,8 @@ static bool promoted_arithmetic_type_p (tree); static conversion *conditional_conversion (tree, tree); static char *name_as_c_string (tree, tree, bool *); static tree prep_operand (tree); -static void add_candidates (tree, const VEC(tree,gc) *, tree, bool, tree, tree, - int, struct z_candidate **); +static void add_candidates (tree, tree, const VEC(tree,gc) *, tree, tree, bool, + tree, tree, int, struct z_candidate **); static conversion *merge_conversion_sequences (conversion *, conversion *); static bool magic_varargs_p (tree); static tree build_temp (tree, tree, int, diagnostic_t *); @@ -1056,57 +1056,28 @@ convert_class_to_reference (tree reference_type, tree s, tree expr, int flags) for (; conversions; conversions = TREE_CHAIN (conversions)) { tree fns = TREE_VALUE (conversions); + tree binfo = TREE_PURPOSE (conversions); + struct z_candidate *old_candidates = candidates;; - for (; fns; fns = OVL_NEXT (fns)) + add_candidates (fns, first_arg, NULL, reference_type, + NULL_TREE, false, + binfo, TYPE_BINFO (s), + flags, &candidates); + + for (cand = candidates; cand != old_candidates; cand = cand->next) { - tree f = OVL_CURRENT (fns); + /* Now, see if the conversion function really returns + an lvalue of the appropriate type. From the + point of view of unification, simply returning an + rvalue of the right type is good enough. */ + tree f = cand->fn; tree t2 = TREE_TYPE (TREE_TYPE (f)); - - if (DECL_NONCONVERTING_P (f) - && (flags & LOOKUP_ONLYCONVERTING)) - continue; - - cand = NULL; - - /* If this is a template function, try to get an exact - match. */ - if (TREE_CODE (f) == TEMPLATE_DECL) + if (TREE_CODE (t2) != REFERENCE_TYPE + || !reference_compatible_p (t, TREE_TYPE (t2))) { - cand = add_template_candidate (&candidates, - f, s, - NULL_TREE, - first_arg, - NULL, - reference_type, - TYPE_BINFO (s), - TREE_PURPOSE (conversions), - LOOKUP_NORMAL, - DEDUCE_CONV); - - if (cand) - { - /* Now, see if the conversion function really returns - an lvalue of the appropriate type. From the - point of view of unification, simply returning an - rvalue of the right type is good enough. */ - f = cand->fn; - t2 = TREE_TYPE (TREE_TYPE (f)); - if (TREE_CODE (t2) != REFERENCE_TYPE - || !reference_compatible_p (t, TREE_TYPE (t2))) - { - candidates = candidates->next; - cand = NULL; - } - } + cand->viable = 0; } - else if (TREE_CODE (t2) == REFERENCE_TYPE - && reference_compatible_p (t, TREE_TYPE (t2))) - cand = add_function_candidate (&candidates, f, s, first_arg, - NULL, TYPE_BINFO (s), - TREE_PURPOSE (conversions), - LOOKUP_NORMAL); - - if (cand) + else { conversion *identity_conv; /* Build a standard conversion sequence indicating the @@ -2874,6 +2845,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) candidates = 0; flags |= LOOKUP_NO_CONVERSION; + if (BRACE_ENCLOSED_INITIALIZER_P (expr)) + flags |= LOOKUP_NO_NARROWING; /* It's OK to bind a temporary for converting constructor arguments, but not in converting the return value of a conversion operator. */ @@ -2882,18 +2855,25 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) if (ctors) { + int ctorflags = flags; ctors = BASELINK_FUNCTIONS (ctors); first_arg = build_int_cst (build_pointer_type (totype), 0); - if (BRACE_ENCLOSED_INITIALIZER_P (expr) - && !TYPE_HAS_LIST_CTOR (totype)) + if (BRACE_ENCLOSED_INITIALIZER_P (expr)) { - args = ctor_to_vec (expr); - /* We still allow more conversions within an init-list. */ - flags = ((flags & ~LOOKUP_NO_CONVERSION) - /* But not for the copy ctor. */ - |LOOKUP_NO_COPY_CTOR_CONVERSION - |LOOKUP_NO_NARROWING); + /* For list-initialization we consider explicit constructors, but + give an error if one is selected. */ + ctorflags &= ~LOOKUP_ONLYCONVERTING; + if (TYPE_HAS_LIST_CTOR (totype)) + args = make_tree_vector_single (expr); + else + { + args = ctor_to_vec (expr); + /* We still allow more conversions within an init-list. */ + ctorflags &= ~LOOKUP_NO_CONVERSION; + /* But not for the copy ctor. */ + ctorflags |= LOOKUP_NO_COPY_CTOR_CONVERSION; + } } else args = make_tree_vector_single (expr); @@ -2902,28 +2882,12 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) from here. */ gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors)) && !DECL_HAS_VTT_PARM_P (OVL_CURRENT (ctors))); - } - for (; ctors; ctors = OVL_NEXT (ctors)) - { - tree ctor = OVL_CURRENT (ctors); - if (DECL_NONCONVERTING_P (ctor) - && !BRACE_ENCLOSED_INITIALIZER_P (expr)) - continue; - if (TREE_CODE (ctor) == TEMPLATE_DECL) - cand = add_template_candidate (&candidates, ctor, totype, - NULL_TREE, first_arg, args, NULL_TREE, - TYPE_BINFO (totype), - TYPE_BINFO (totype), - flags, - DEDUCE_CALL); - else - cand = add_function_candidate (&candidates, ctor, totype, - first_arg, args, TYPE_BINFO (totype), - TYPE_BINFO (totype), - flags); + add_candidates (ctors, first_arg, args, NULL_TREE, NULL_TREE, false, + TYPE_BINFO (totype), TYPE_BINFO (totype), + ctorflags, &candidates); - if (cand) + for (cand = candidates; cand; cand = cand->next) { cand->second_conv = build_identity_conv (totype, NULL_TREE); @@ -2947,8 +2911,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) for (; conv_fns; conv_fns = TREE_CHAIN (conv_fns)) { - tree fns; tree conversion_path = TREE_PURPOSE (conv_fns); + struct z_candidate *old_candidates; /* If we are called to convert to a reference type, we are trying to find an lvalue binding, so don't even consider temporaries. If @@ -2957,65 +2921,40 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) if (TREE_CODE (totype) == REFERENCE_TYPE) convflags |= LOOKUP_NO_TEMP_BIND; - for (fns = TREE_VALUE (conv_fns); fns; fns = OVL_NEXT (fns)) + old_candidates = candidates; + add_candidates (TREE_VALUE (conv_fns), first_arg, NULL, totype, + NULL_TREE, false, + conversion_path, TYPE_BINFO (fromtype), + flags, &candidates); + + for (cand = candidates; cand != old_candidates; cand = cand->next) { - tree fn = OVL_CURRENT (fns); - - if (DECL_NONCONVERTING_P (fn) - && (flags & LOOKUP_ONLYCONVERTING)) - continue; - - /* [over.match.funcs] For conversion functions, the function - is considered to be a member of the class of the implicit - object argument for the purpose of defining the type of - the implicit object parameter. - - So we pass fromtype as CTYPE to add_*_candidate. */ - - if (TREE_CODE (fn) == TEMPLATE_DECL) - cand = add_template_candidate (&candidates, fn, fromtype, - NULL_TREE, - first_arg, NULL, totype, - TYPE_BINFO (fromtype), - conversion_path, - flags, - DEDUCE_CONV); - else - cand = add_function_candidate (&candidates, fn, fromtype, - first_arg, NULL, - TYPE_BINFO (fromtype), - conversion_path, - flags); + conversion *ics + = implicit_conversion (totype, + TREE_TYPE (TREE_TYPE (cand->fn)), + 0, + /*c_cast_p=*/false, convflags); - if (cand) - { - conversion *ics - = implicit_conversion (totype, - TREE_TYPE (TREE_TYPE (cand->fn)), - 0, - /*c_cast_p=*/false, convflags); - - /* If LOOKUP_NO_TEMP_BIND isn't set, then this is - copy-initialization. In that case, "The result of the - call is then used to direct-initialize the object that is - the destination of the copy-initialization." [dcl.init] - - We represent this in the conversion sequence with an - rvalue conversion, which means a constructor call. But - don't add a second rvalue conversion if there's already - one there. Which there really shouldn't be, but it's - harmless since we'd add it here anyway. */ - if (ics && MAYBE_CLASS_TYPE_P (totype) && ics->kind != ck_rvalue - && !(convflags & LOOKUP_NO_TEMP_BIND)) - ics = build_conv (ck_rvalue, totype, ics); - - cand->second_conv = ics; - - if (!ics) - cand->viable = 0; - else if (candidates->viable == 1 && ics->bad_p) - cand->viable = -1; - } + /* If LOOKUP_NO_TEMP_BIND isn't set, then this is + copy-initialization. In that case, "The result of the + call is then used to direct-initialize the object that is + the destination of the copy-initialization." [dcl.init] + + We represent this in the conversion sequence with an + rvalue conversion, which means a constructor call. But + don't add a second rvalue conversion if there's already + one there. Which there really shouldn't be, but it's + harmless since we'd add it here anyway. */ + if (ics && MAYBE_CLASS_TYPE_P (totype) && ics->kind != ck_rvalue + && !(convflags & LOOKUP_NO_TEMP_BIND)) + ics = build_conv (ck_rvalue, totype, ics); + + cand->second_conv = ics; + + if (!ics) + cand->viable = 0; + else if (cand->viable == 1 && ics->bad_p) + cand->viable = -1; } } @@ -3145,7 +3084,8 @@ perform_overload_resolution (tree fn, } /* Add the various candidate functions. */ - add_candidates (fn, args, explicit_targs, template_only, + add_candidates (fn, NULL_TREE, args, NULL_TREE, + explicit_targs, template_only, /*conversion_path=*/NULL_TREE, /*access_path=*/NULL_TREE, LOOKUP_NORMAL, @@ -3383,24 +3323,13 @@ build_op_call (tree obj, VEC(tree,gc) **args, tsubst_flags_t complain) if (fns) { - tree base = BINFO_TYPE (BASELINK_BINFO (fns)); first_mem_arg = build_this (obj); - for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns)) - { - tree fn = OVL_CURRENT (fns); - - if (TREE_CODE (fn) == TEMPLATE_DECL) - add_template_candidate (&candidates, fn, base, NULL_TREE, - first_mem_arg, *args, NULL_TREE, - TYPE_BINFO (type), - TYPE_BINFO (type), - LOOKUP_NORMAL, DEDUCE_CALL); - else - add_function_candidate - (&candidates, fn, base, first_mem_arg, *args, TYPE_BINFO (type), - TYPE_BINFO (type), LOOKUP_NORMAL); - } + add_candidates (BASELINK_FUNCTIONS (fns), + first_mem_arg, *args, NULL_TREE, + NULL_TREE, false, + BASELINK_BINFO (fns), BASELINK_ACCESS_BINFO (fns), + LOOKUP_NORMAL, &candidates); } convs = lookup_conversions (type, /*lookup_template_convs_p=*/true); @@ -4058,53 +3987,86 @@ prep_operand (tree operand) /* Add each of the viable functions in FNS (a FUNCTION_DECL or OVERLOAD) to the CANDIDATES, returning an updated list of - CANDIDATES. The ARGS are the arguments provided to the call, - without any implicit object parameter. This may change ARGS. The + CANDIDATES. The ARGS are the arguments provided to the call; + if FIRST_ARG is non-null it is the implicit object argument, + otherwise the first element of ARGS is used if needed. The EXPLICIT_TARGS are explicit template arguments provided. TEMPLATE_ONLY is true if only template functions should be considered. CONVERSION_PATH, ACCESS_PATH, and FLAGS are as for add_function_candidate. */ static void -add_candidates (tree fns, const VEC(tree,gc) *args, +add_candidates (tree fns, tree first_arg, const VEC(tree,gc) *args, + tree return_type, tree explicit_targs, bool template_only, tree conversion_path, tree access_path, int flags, struct z_candidate **candidates) { tree ctype; - VEC(tree,gc) *non_static_args; - tree first_arg; + const VEC(tree,gc) *non_static_args; + bool check_converting; + unification_kind_t strict; + tree fn; + + if (!fns) + return; + + /* Precalculate special handling of constructors and conversion ops. */ + fn = OVL_CURRENT (fns); + if (DECL_CONV_FN_P (fn)) + { + check_converting = !!(flags & LOOKUP_ONLYCONVERTING); + strict = DEDUCE_CONV; + /* [over.match.funcs] For conversion functions, the function + is considered to be a member of the class of the implicit + object argument for the purpose of defining the type of + the implicit object parameter. */ + ctype = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (first_arg))); + } + else + { + if (DECL_CONSTRUCTOR_P (fn)) + check_converting = !!(flags & LOOKUP_ONLYCONVERTING); + else + check_converting = false; + strict = DEDUCE_CALL; + ctype = conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE; + } - ctype = conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE; - /* Delay creating the implicit this parameter until it is needed. */ - non_static_args = NULL; - first_arg = NULL_TREE; + if (first_arg) + non_static_args = args; + else + /* Delay creating the implicit this parameter until it is needed. */ + non_static_args = NULL; - while (fns) + for (; fns; fns = OVL_NEXT (fns)) { - tree fn; tree fn_first_arg; const VEC(tree,gc) *fn_args; fn = OVL_CURRENT (fns); + + if (check_converting && DECL_NONCONVERTING_P (fn)) + continue; + /* Figure out which set of arguments to use. */ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)) { - /* If this function is a non-static member, prepend the implicit - object parameter. */ - if (non_static_args == NULL) + /* If this function is a non-static member and we didn't get an + implicit object argument, move it out of args. */ + if (first_arg == NULL_TREE) { unsigned int ix; tree arg; - - non_static_args = VEC_alloc (tree, gc, - VEC_length (tree, args) - 1); + VEC(tree,gc) *tempvec + = VEC_alloc (tree, gc, VEC_length (tree, args) - 1); for (ix = 1; VEC_iterate (tree, args, ix, arg); ++ix) - VEC_quick_push (tree, non_static_args, arg); + VEC_quick_push (tree, tempvec, arg); + non_static_args = tempvec; + first_arg = build_this (VEC_index (tree, args, 0)); } - if (first_arg == NULL_TREE) - first_arg = build_this (VEC_index (tree, args, 0)); + fn_first_arg = first_arg; fn_args = non_static_args; } @@ -4122,11 +4084,11 @@ add_candidates (tree fns, const VEC(tree,gc) *args, explicit_targs, fn_first_arg, fn_args, - NULL_TREE, + return_type, access_path, conversion_path, flags, - DEDUCE_CALL); + strict); else if (!template_only) add_function_candidate (candidates, fn, @@ -4136,7 +4098,6 @@ add_candidates (tree fns, const VEC(tree,gc) *args, access_path, conversion_path, flags); - fns = OVL_NEXT (fns); } } @@ -4247,7 +4208,8 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, /* Add namespace-scope operators to the list of functions to consider. */ add_candidates (lookup_function_nonclass (fnname, arglist, /*block_p=*/true), - arglist, NULL_TREE, false, NULL_TREE, NULL_TREE, + NULL_TREE, arglist, NULL_TREE, + NULL_TREE, false, NULL_TREE, NULL_TREE, flags, &candidates); /* Add class-member operators to the candidate set. */ if (CLASS_TYPE_P (TREE_TYPE (arg1))) @@ -4261,10 +4223,11 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3, goto user_defined_result_ready; } if (fns) - add_candidates (BASELINK_FUNCTIONS (fns), arglist, + add_candidates (BASELINK_FUNCTIONS (fns), + NULL_TREE, arglist, NULL_TREE, NULL_TREE, false, BASELINK_BINFO (fns), - TYPE_BINFO (TREE_TYPE (arg1)), + BASELINK_ACCESS_BINFO (fns), flags, &candidates); } @@ -6210,7 +6173,6 @@ build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args, VEC(tree,gc) *user_args; tree call; tree fn; - tree class_type; int template_only = 0; bool any_viable_p; tree orig_instance; @@ -6340,48 +6302,14 @@ build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args, *args = ctor_to_vec (VEC_index (tree, *args, 0)); } - class_type = (conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE); first_mem_arg = instance_ptr; /* Get the high-water mark for the CONVERSION_OBSTACK. */ p = conversion_obstack_alloc (0); - for (fn = fns; fn; fn = OVL_NEXT (fn)) - { - tree t = OVL_CURRENT (fn); - tree this_first_arg; - - /* We can end up here for copy-init of same or base class. */ - if ((flags & LOOKUP_ONLYCONVERTING) - && DECL_NONCONVERTING_P (t)) - continue; - - if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t)) - this_first_arg = first_mem_arg; - else - this_first_arg = NULL_TREE; - - if (TREE_CODE (t) == TEMPLATE_DECL) - /* A member template. */ - add_template_candidate (&candidates, t, - class_type, - explicit_targs, - this_first_arg, - args == NULL ? NULL : *args, - optype, - access_binfo, - conversion_path, - flags, - DEDUCE_CALL); - else if (! template_only) - add_function_candidate (&candidates, t, - class_type, - this_first_arg, - args == NULL ? NULL : *args, - access_binfo, - conversion_path, - flags); - } + add_candidates (fns, first_mem_arg, args ? *args : NULL, optype, + explicit_targs, template_only, conversion_path, + access_binfo, flags, &candidates); candidates = splice_viable (candidates, pedantic, &any_viable_p); if (!any_viable_p) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e5f3a50f2ad..6425c9ecdbf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2010-05-12 Jason Merrill + + * g++.old-deja/g++.robertl/eb43.C: Prune "candidates" messages. + 2010-05-12 H.J. Lu PR target/44088 diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb43.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb43.C index 5355afe4e56..1dc43284c43 100644 --- a/gcc/testsuite/g++.old-deja/g++.robertl/eb43.C +++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb43.C @@ -4,6 +4,8 @@ // The first one should still fail because it requires an implicit conversion // to pointer_to_binary_function, which has an `explicit' constructor. +// { dg-prune-output "note" } + #include #include #include -- 2.30.2