📄 call.c
字号:
purposes of reference binding. For lvalue binding, either pass a reference type to FROM or an lvalue expression to EXPR. Currently does not distinguish in the generated trees between binding to an lvalue and a temporary. Should it? */static treereference_binding (rto, rfrom, expr, flags) tree rto, rfrom, expr; int flags;{ tree conv; int lvalue = 1; tree to = TREE_TYPE (rto); tree from = rfrom; int related; if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr)) { expr = instantiate_type (to, expr, 0); if (expr == error_mark_node) return NULL_TREE; from = TREE_TYPE (expr); } if (TREE_CODE (from) == REFERENCE_TYPE) from = TREE_TYPE (from); else if (! expr || ! real_lvalue_p (expr)) lvalue = 0; related = (same_type_p (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from)) || (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from) && DERIVED_FROM_P (to, from))); if (lvalue && related && at_least_as_qualified_p (to, from)) { conv = build1 (IDENTITY_CONV, from, expr); if (same_type_p (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from))) conv = build_conv (REF_BIND, rto, conv); else { conv = build_conv (REF_BIND, rto, conv); ICS_STD_RANK (conv) = STD_RANK; } } else conv = NULL_TREE; if (! conv) { conv = standard_conversion (to, rfrom, expr); if (conv) { conv = build_conv (REF_BIND, rto, conv); /* Bind directly to a base subobject of a class rvalue. Do it after building the conversion for proper handling of ICS_RANK. */ if (TREE_CODE (TREE_OPERAND (conv, 0)) == BASE_CONV) TREE_OPERAND (conv, 0) = TREE_OPERAND (TREE_OPERAND (conv, 0), 0); } if (conv && ((! (CP_TYPE_CONST_NON_VOLATILE_P (to) && (flags & LOOKUP_NO_TEMP_BIND) == 0)) /* If T1 is reference-related to T2, cv1 must be the same cv-qualification as, or greater cv-qualification than, cv2; otherwise, the program is ill-formed. */ || (related && !at_least_as_qualified_p (to, from)))) ICS_BAD_FLAG (conv) = 1; } return conv;}/* Returns the implicit conversion sequence (see [over.ics]) from type FROM to type TO. The optional expression EXPR may affect the conversion. FLAGS are the usual overloading flags. Only LOOKUP_NO_CONVERSION is significant. */static treeimplicit_conversion (to, from, expr, flags) tree to, from, expr; int flags;{ tree conv; struct z_candidate *cand; if (TREE_CODE (to) == REFERENCE_TYPE) conv = reference_binding (to, from, expr, flags); else conv = standard_conversion (to, from, expr); if (conv) ; else if (expr != NULL_TREE && (IS_AGGR_TYPE (non_reference (from)) || IS_AGGR_TYPE (non_reference (to))) && (flags & LOOKUP_NO_CONVERSION) == 0) { cand = build_user_type_conversion_1 (to, expr, LOOKUP_ONLYCONVERTING); if (cand) conv = cand->second_conv; if ((! conv || ICS_BAD_FLAG (conv)) && TREE_CODE (to) == REFERENCE_TYPE && (flags & LOOKUP_NO_TEMP_BIND) == 0) { cand = build_user_type_conversion_1 (TYPE_MAIN_VARIANT (TREE_TYPE (to)), expr, LOOKUP_ONLYCONVERTING); if (cand) { if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (to))) ICS_BAD_FLAG (cand->second_conv) = 1; if (!conv || (ICS_BAD_FLAG (conv) > ICS_BAD_FLAG (cand->second_conv))) conv = build_conv (REF_BIND, to, cand->second_conv); } } } return conv;}/* Add a new entry to the list of candidates. Used by the add_*_candidate functions. */static struct z_candidate *add_candidate (candidates, fn, convs, viable) struct z_candidate *candidates; tree fn, convs; int viable;{ struct z_candidate *cand = (struct z_candidate *) scratchalloc (sizeof (struct z_candidate)); cand->fn = fn; cand->convs = convs; cand->second_conv = NULL_TREE; cand->viable = viable; cand->basetype_path = NULL_TREE; cand->template = NULL_TREE; cand->warnings = NULL_TREE; cand->next = candidates; return cand;}/* Create an overload candidate for the function or method FN called with the argument list ARGLIST and add it to CANDIDATES. FLAGS is passed on to implicit_conversion. */static struct z_candidate *add_function_candidate (candidates, fn, arglist, flags) struct z_candidate *candidates; tree fn, arglist; int flags;{ tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn)); int i, len; tree convs; tree parmnode, argnode; int viable = 1; /* The `this', `in_chrg', and `vlist' arguments to constructors are not considered in overload resolution. */ if (DECL_CONSTRUCTOR_P (fn)) { parmlist = TREE_CHAIN (parmlist); arglist = TREE_CHAIN (arglist); if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn))) { parmlist = TREE_CHAIN (parmlist); arglist = TREE_CHAIN (arglist); } if ((flags & LOOKUP_HAS_VLIST) && DECL_CONSTRUCTOR_FOR_PVBASE_P (fn)) { parmlist = TREE_CHAIN (parmlist); arglist = TREE_CHAIN (arglist); } else if (!(flags & LOOKUP_HAS_VLIST) && !DECL_CONSTRUCTOR_FOR_PVBASE_P (fn)) /* Ok */; else { /* The ctor expects a vlist and the arguments don't have one, or vice versa, so fn is not even a candidate, since the corresponding ctor would be the candidate. */ return candidates; } } len = list_length (arglist); convs = make_scratch_vec (len); /* 13.3.2 - Viable functions [over.match.viable] First, to be a viable function, a candidate function shall have enough parameters to agree in number with the arguments in the list. We need to check this first; otherwise, checking the ICSes might cause us to produce an ill-formed template instantiation. */ parmnode = parmlist; for (i = 0; i < len; ++i) { if (parmnode == NULL_TREE || parmnode == void_list_node) break; parmnode = TREE_CHAIN (parmnode); } if (i < len && parmnode) viable = 0; /* Make sure there are default args for the rest of the parms. */ else for (; parmnode && parmnode != void_list_node; parmnode = TREE_CHAIN (parmnode)) if (! TREE_PURPOSE (parmnode)) { viable = 0; break; } if (! viable) goto out; /* Second, for F to be a viable function, there shall exist for each argument an implicit conversion sequence that converts that argument to the corresponding parameter of F. */ parmnode = parmlist; argnode = arglist; for (i = 0; i < len; ++i) { tree arg = TREE_VALUE (argnode); tree argtype = lvalue_type (arg); tree t; if (parmnode == void_list_node) break; if (parmnode) { tree parmtype = TREE_VALUE (parmnode); /* [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. Since build_over_call ignores the ICS for the `this' parameter, we can just change the parm type. */ if (DECL_CONV_FN_P (fn) && i == 0) { parmtype = build_qualified_type (TREE_TYPE (argtype), TYPE_QUALS (TREE_TYPE (parmtype))); parmtype = build_pointer_type (parmtype); } t = implicit_conversion (parmtype, argtype, arg, flags); } else { t = build1 (IDENTITY_CONV, argtype, arg); ICS_ELLIPSIS_FLAG (t) = 1; } if (i == 0 && t && TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE && ! DECL_CONSTRUCTOR_P (fn)) ICS_THIS_FLAG (t) = 1; TREE_VEC_ELT (convs, i) = t; if (! t) { viable = 0; break; } if (ICS_BAD_FLAG (t)) viable = -1; if (parmnode) parmnode = TREE_CHAIN (parmnode); argnode = TREE_CHAIN (argnode); } out: return add_candidate (candidates, fn, convs, viable);}/* Create an overload candidate for the conversion function FN which will be invoked for expression OBJ, producing a pointer-to-function which will in turn be called with the argument list ARGLIST, and add it to CANDIDATES. FLAGS is passed on to implicit_conversion. Actually, we don't really care about FN; we care about the type it converts to. There may be multiple conversion functions that will convert to that type, and we rely on build_user_type_conversion_1 to choose the best one; so when we create our candidate, we record the type instead of the function. */static struct z_candidate *add_conv_candidate (candidates, fn, obj, arglist) struct z_candidate *candidates; tree fn, obj, arglist;{ tree totype = TREE_TYPE (TREE_TYPE (fn)); tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (totype)); int i, len = list_length (arglist) + 1; tree convs = make_scratch_vec (len); tree parmnode = parmlist; tree argnode = arglist; int viable = 1; int flags = LOOKUP_NORMAL; /* Don't bother looking up the same type twice. */ if (candidates && candidates->fn == totype) return candidates; for (i = 0; i < len; ++i) { tree arg = i == 0 ? obj : TREE_VALUE (argnode); tree argtype = lvalue_type (arg); tree t; if (i == 0) t = implicit_conversion (totype, argtype, arg, flags); else if (parmnode == void_list_node) break; else if (parmnode) t = implicit_conversion (TREE_VALUE (parmnode), argtype, arg, flags); else { t = build1 (IDENTITY_CONV, argtype, arg); ICS_ELLIPSIS_FLAG (t) = 1; } TREE_VEC_ELT (convs, i) = t; if (! t) break; if (ICS_BAD_FLAG (t)) viable = -1; if (i == 0) continue; if (parmnode) parmnode = TREE_CHAIN (parmnode); argnode = TREE_CHAIN (argnode); } if (i < len) viable = 0; for (; parmnode && parmnode != void_list_node; parmnode = TREE_CHAIN (parmnode)) if (! TREE_PURPOSE (parmnode)) { viable = 0; break; } return add_candidate (candidates, totype, convs, viable);}static struct z_candidate *build_builtin_candidate (candidates, fnname, type1, type2, args, argtypes, flags) struct z_candidate *candidates; tree fnname, type1, type2, *args, *argtypes; int flags;{ tree t, convs; int viable = 1, i; tree types[2]; types[0] = type1; types[1] = type2; convs = make_scratch_vec (args[2] ? 3 : (args[1] ? 2 : 1)); for (i = 0; i < 2; ++i) { if (! args[i]) break; t = implicit_conversion (types[i], argtypes[i], args[i], flags); if (! t) { viable = 0; /* We need something for printing the candidate. */ t = build1 (IDENTITY_CONV, types[i], NULL_TREE); } else if (ICS_BAD_FLAG (t)) viable = 0; TREE_VEC_ELT (convs, i) = t; } /* For COND_EXPR we rearranged the arguments; undo that now. */ if (args[2]) { TREE_VEC_ELT (convs, 2) = TREE_VEC_ELT (convs, 1); TREE_VEC_ELT (convs, 1) = TREE_VEC_ELT (convs, 0); t = implicit_conversion (boolean_type_node, argtypes[2], args[2], flags); if (t) TREE_VEC_ELT (convs, 0) = t; else viable = 0; } return add_candidate (candidates, fnname, convs, viable);}static intis_complete (t) tree t;{ return TYPE_SIZE (complete_type (t)) != NULL_TREE;}/* Create any builtin operator overload candidates for the operator in question given the converted operand types TYPE1 and TYPE2. The other args are passed through from add_builtin_candidates to build_builtin_candidate. */static struct z_candidate *add_builtin_candidate (candidates, code, code2, fnname, type1, type2, args, argtypes, flags) struct z_candidate *candidates; enum tree_code code, code2; tree fnname, type1, type2, *args, *argtypes; int flags;{ switch (code) { case POSTINCREMENT_EXPR: case POSTDECREMENT_EXPR: args[1] = integer_zero_node; type2 = integer_type_node; break; default: break; } switch (code) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -