📄 call.c
字号:
} types[0] = types[1] = NULL_TREE; for (i = 0; i < 2; ++i) { if (! args[i]) ; else if (IS_AGGR_TYPE (argtypes[i])) { tree convs; if (i == 0 && code == MODIFY_EXPR && code2 == NOP_EXPR) return candidates; convs = lookup_conversions (argtypes[i]); if (code == COND_EXPR) { if (real_lvalue_p (args[i])) types[i] = scratch_tree_cons (NULL_TREE, build_reference_type (argtypes[i]), types[i]); types[i] = scratch_tree_cons (NULL_TREE, TYPE_MAIN_VARIANT (argtypes[i]), types[i]); } else if (! convs) return candidates; for (; convs; convs = TREE_CHAIN (convs)) { type = TREE_TYPE (TREE_TYPE (OVL_CURRENT (TREE_VALUE (convs)))); if (i == 0 && ref1 && (TREE_CODE (type) != REFERENCE_TYPE || CP_TYPE_CONST_P (TREE_TYPE (type)))) continue; if (code == COND_EXPR && TREE_CODE (type) == REFERENCE_TYPE) types[i] = scratch_tree_cons (NULL_TREE, type, types[i]); type = non_reference (type); if (i != 0 || ! ref1) { type = TYPE_MAIN_VARIANT (type_decays_to (type)); if (code == COND_EXPR && TREE_CODE (type) == ENUMERAL_TYPE) types[i] = scratch_tree_cons (NULL_TREE, type, types[i]); if (INTEGRAL_TYPE_P (type)) type = type_promotes_to (type); } if (! value_member (type, types[i])) types[i] = scratch_tree_cons (NULL_TREE, type, types[i]); } } else { if (code == COND_EXPR && real_lvalue_p (args[i])) types[i] = scratch_tree_cons (NULL_TREE, build_reference_type (argtypes[i]), types[i]); type = non_reference (argtypes[i]); if (i != 0 || ! ref1) { type = TYPE_MAIN_VARIANT (type_decays_to (type)); if (code == COND_EXPR && TREE_CODE (type) == ENUMERAL_TYPE) types[i] = scratch_tree_cons (NULL_TREE, type, types[i]); if (INTEGRAL_TYPE_P (type)) type = type_promotes_to (type); } types[i] = scratch_tree_cons (NULL_TREE, type, types[i]); } } for (; types[0]; types[0] = TREE_CHAIN (types[0])) { if (types[1]) for (type = types[1]; type; type = TREE_CHAIN (type)) candidates = add_builtin_candidate (candidates, code, code2, fnname, TREE_VALUE (types[0]), TREE_VALUE (type), args, argtypes, flags); else candidates = add_builtin_candidate (candidates, code, code2, fnname, TREE_VALUE (types[0]), NULL_TREE, args, argtypes, flags); } return candidates;}/* If TMPL can be successfully instantiated as indicated by EXPLICIT_TARGS and ARGLIST, adds the instantiation to CANDIDATES. TMPL is the template. EXPLICIT_TARGS are any explicit template arguments. ARGLIST is the arguments provided at the call-site. The RETURN_TYPE is the desired type for conversion operators. If OBJ is NULL_TREE, FLAGS are as for add_function_candidate. If an OBJ is supplied, FLAGS are ignored, and OBJ is as for add_conv_candidate. */static struct z_candidate*add_template_candidate_real (candidates, tmpl, explicit_targs, arglist, return_type, flags, obj, strict) struct z_candidate *candidates; tree tmpl, explicit_targs, arglist, return_type; int flags; tree obj; unification_kind_t strict;{ int ntparms = DECL_NTPARMS (tmpl); tree targs = make_scratch_vec (ntparms); struct z_candidate *cand; int i; tree fn; i = fn_type_unification (tmpl, explicit_targs, targs, arglist, return_type, strict); if (i != 0) return candidates; fn = instantiate_template (tmpl, targs); if (fn == error_mark_node) return candidates; if (obj != NULL_TREE) /* Aha, this is a conversion function. */ cand = add_conv_candidate (candidates, fn, obj, arglist); else cand = add_function_candidate (candidates, fn, arglist, flags); if (DECL_TI_TEMPLATE (fn) != tmpl) /* This situation can occur if a member template of a template class is specialized. Then, instantiate_template might return an instantiation of the specialization, in which case the DECL_TI_TEMPLATE field will point at the original specialization. For example: template <class T> struct S { template <class U> void f(U); template <> void f(int) {}; }; S<double> sd; sd.f(3); Here, TMPL will be template <class U> S<double>::f(U). And, instantiate template will give us the specialization template <> S<double>::f(int). But, the DECL_TI_TEMPLATE field for this will point at template <class T> template <> S<T>::f(int), so that we can find the definition. For the purposes of overload resolution, however, we want the original TMPL. */ cand->template = tree_cons (tmpl, targs, NULL_TREE); else cand->template = DECL_TEMPLATE_INFO (fn); return cand;}static struct z_candidate *add_template_candidate (candidates, tmpl, explicit_targs, arglist, return_type, flags, strict) struct z_candidate *candidates; tree tmpl, explicit_targs, arglist, return_type; int flags; unification_kind_t strict;{ return add_template_candidate_real (candidates, tmpl, explicit_targs, arglist, return_type, flags, NULL_TREE, strict);}static struct z_candidate *add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type) struct z_candidate *candidates; tree tmpl, obj, arglist, return_type;{ return add_template_candidate_real (candidates, tmpl, NULL_TREE, arglist, return_type, 0, obj, DEDUCE_CONV);}static intany_viable (cands) struct z_candidate *cands;{ for (; cands; cands = cands->next) if (pedantic ? cands->viable == 1 : cands->viable) return 1; return 0;}static struct z_candidate *splice_viable (cands) struct z_candidate *cands;{ struct z_candidate **p = &cands; for (; *p; ) { if (pedantic ? (*p)->viable == 1 : (*p)->viable) p = &((*p)->next); else *p = (*p)->next; } return cands;}static treebuild_this (obj) tree obj;{ /* Fix this to work on non-lvalues. */ if (IS_SIGNATURE_POINTER (TREE_TYPE (obj)) || IS_SIGNATURE_REFERENCE (TREE_TYPE (obj))) return obj; else return build_unary_op (ADDR_EXPR, obj, 0);}static voidprint_z_candidates (candidates) struct z_candidate *candidates;{ const char *str = "candidates are:"; for (; candidates; candidates = candidates->next) { if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE) { if (candidates->fn == ansi_opname [COND_EXPR]) cp_error ("%s %D(%T, %T, %T) <builtin>", str, candidates->fn, TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)), TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)), TREE_TYPE (TREE_VEC_ELT (candidates->convs, 2))); else if (TREE_VEC_LENGTH (candidates->convs) == 2) cp_error ("%s %D(%T, %T) <builtin>", str, candidates->fn, TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)), TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1))); else cp_error ("%s %D(%T) <builtin>", str, candidates->fn, TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0))); } else if (TYPE_P (candidates->fn)) cp_error ("%s %T <conversion>", str, candidates->fn); else cp_error_at ("%s %+#D%s", str, candidates->fn, candidates->viable == -1 ? " <near match>" : ""); str = " "; }}/* Returns the best overload candidate to perform the requested conversion. This function is used for three the overloading situations described in [over.match.copy], [over.match.conv], and [over.match.ref]. If TOTYPE is a REFERENCE_TYPE, we're trying to find an lvalue binding as per [dcl.init.ref], so we ignore temporary bindings. */static struct z_candidate *build_user_type_conversion_1 (totype, expr, flags) tree totype, expr; int flags;{ struct z_candidate *candidates, *cand; tree fromtype = TREE_TYPE (expr); tree ctors = NULL_TREE, convs = NULL_TREE, *p; tree args = NULL_TREE; tree templates = NULL_TREE; if (IS_AGGR_TYPE (totype)) ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0); if (IS_AGGR_TYPE (fromtype) && (! IS_AGGR_TYPE (totype) || ! DERIVED_FROM_P (totype, fromtype))) convs = lookup_conversions (fromtype); candidates = 0; flags |= LOOKUP_NO_CONVERSION; if (ctors) { tree t = build_int_2 (0, 0); TREE_TYPE (t) = build_pointer_type (totype); args = build_scratch_list (NULL_TREE, expr); if (TYPE_USES_PVBASES (totype) && !flag_vtable_thunks_compat) { args = scratch_tree_cons (NULL_TREE, vlist_zero_node, args); flags |= LOOKUP_HAS_VLIST; } if (TYPE_USES_VIRTUAL_BASECLASSES (totype)) args = scratch_tree_cons (NULL_TREE, integer_one_node, args); args = scratch_tree_cons (NULL_TREE, t, args); ctors = TREE_VALUE (ctors); } for (; ctors; ctors = OVL_NEXT (ctors)) { tree ctor = OVL_CURRENT (ctors); if (DECL_NONCONVERTING_P (ctor)) continue; if (TREE_CODE (ctor) == TEMPLATE_DECL) { templates = scratch_tree_cons (NULL_TREE, ctor, templates); candidates = add_template_candidate (candidates, ctor, NULL_TREE, args, NULL_TREE, flags, DEDUCE_CALL); } else candidates = add_function_candidate (candidates, ctor, args, flags); if (candidates) { candidates->second_conv = build1 (IDENTITY_CONV, totype, NULL_TREE); candidates->basetype_path = TYPE_BINFO (totype); } } if (convs) args = build_scratch_list (NULL_TREE, build_this (expr)); for (; convs; convs = TREE_CHAIN (convs)) { tree fns = TREE_VALUE (convs); int convflags = LOOKUP_NO_CONVERSION; tree ics; /* 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 we don't find an lvalue binding, the caller will try again to look for a temporary binding. */ if (TREE_CODE (totype) == REFERENCE_TYPE) convflags |= LOOKUP_NO_TEMP_BIND; if (TREE_CODE (OVL_CURRENT (fns)) != TEMPLATE_DECL) ics = implicit_conversion (totype, TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns))), 0, convflags); else /* We can't compute this yet. */ ics = error_mark_node; if (TREE_CODE (totype) == REFERENCE_TYPE && ics && ICS_BAD_FLAG (ics)) /* ignore the near match. */; else if (ics) for (; fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); struct z_candidate *old_candidates = candidates; if (TREE_CODE (fn) == TEMPLATE_DECL) { templates = scratch_tree_cons (NULL_TREE, fn, templates); candidates = add_template_candidate (candidates, fn, NULL_TREE, args, totype, flags, DEDUCE_CONV); } else candidates = add_function_candidate (candidates, fn, args, flags); if (candidates != old_candidates) { if (TREE_CODE (fn) == TEMPLATE_DECL) ics = implicit_conversion (totype, TREE_TYPE (TREE_TYPE (candidates->fn)), 0, convflags); candidates->second_conv = ics; candidates->basetype_path = TREE_PURPOSE (convs); if (ics == NULL_TREE) candidates->viable = 0; else if (candidates->viable == 1 && ICS_BAD_FLAG (ics)) candidates->viable = -1; } } } if (! any_viable (candidates)) {#if 0 if (flags & LOOKUP_COMPLAIN) { if (candidates && ! candidates->next) /* say why this one won't work or try to be loose */; else cp_error ("no viable candidates"); }#endif return 0; } candidates = splice_viable (candidates); cand = tourney (candidates); if (cand == 0) { if (flags & LOOKUP_COMPLAIN) { cp_error ("conversion from `%T' to `%T' is ambiguous", fromtype, totype); print_z_candidates (candidates); } cand = candidates; /* any one will do */ cand->second_conv = build1 (AMBIG_CONV, totype, expr); ICS_USER_FLAG (cand->second_conv) = 1; ICS_BAD_FLAG (cand->second_conv) = 1; return cand; } for (p = &(cand->second_conv); TREE_CODE (*p) != IDENTITY_CONV; ) p = &(TREE_OPERAND (*p, 0)); /* Pedantically, normal function declarations are never considered to refer to template instantiations, so we only do this with -fguiding-decls. */ if (flag_guiding_decls && templates && ! cand->template && !DECL_INITIAL (cand->fn) && TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE) add_maybe_template (cand->fn, templates); *p = build (USER_CONV, (DECL_CONSTRUCTOR_P (cand->fn) ? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))), expr, build_expr_ptr_wrapper (cand)); ICS_USER_FLAG (cand->second_conv) = 1; if (cand->viable == -1) ICS_BAD_FLAG (cand->second_conv) = 1; return cand;}treebuild_user_type_conversion (totype, expr, flags) tree totype, expr; int flags;{ struct z_candidate *cand = build_user_type_conversion_1 (totype, expr, flags); if (c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -