📄 cp-call.c
字号:
} i = 0; do { int exact_conversions = 0; i -= 1; tta = parms; if (DECL_STATIC_FUNCTION_P (cp[i].function)) tta = TREE_CHAIN (tta); /* special note, we don't go through len parameters, because we may only need len-1 parameters because of a call to a static member. */ for (ttf = TYPE_ARG_TYPES (TREE_TYPE (cp[i].function)), index = 0; tta; tta = TREE_CHAIN (tta), ttf = TREE_CHAIN (ttf), index++) { if (USER_HARSHNESS (cp[i].harshness[index])) { tree this_parm = build_type_conversion (CALL_EXPR, TREE_VALUE (ttf), TREE_PURPOSE (tta), 2); if (basetype != NULL_TREE) TREE_VALUE (tta) = this_parm; if (this_parm) { if (TREE_CODE (this_parm) != CONVERT_EXPR && (TREE_CODE (this_parm) != NOP_EXPR || comp_target_types (TREE_TYPE (this_parm), TREE_TYPE (TREE_OPERAND (this_parm, 0)), 1))) exact_conversions += 1; } else if (PROMOTES_TO_AGGR_TYPE (TREE_VALUE (ttf), REFERENCE_TYPE)) { /* To get here we had to have succeeded via a constructor. */ TREE_VALUE (tta) = TREE_PURPOSE (tta); exact_conversions += 1; } } } if (exact_conversions == cp[i].user) { if (best == 0) { best = i; f1 = cp[best].function; p1 = TYPE_ARG_TYPES (TREE_TYPE (f1)); } else { /* Don't complain if next best is from base class. */ tree f2 = cp[i].function; if (TREE_CODE (TREE_TYPE (f1)) == METHOD_TYPE && TREE_CODE (TREE_TYPE (f2)) == METHOD_TYPE && BASE_DERIVED_HARSHNESS (cp[i].harshness[0]) && cp[best].harshness[0] < cp[i].harshness[0]) {#if 0 tree p2 = TYPE_ARG_TYPES (TREE_TYPE (f2)); /* For LUCID. */ if (! compparms (TREE_CHAIN (p1), TREE_CHAIN (p2), 1)) goto ret0; else#endif continue; } else { /* Ensure that there's nothing ambiguous about these two fns. */ int identical = 1; for (index = 0; index < len; index++) { /* Type conversions must be piecewise equivalent. */ if (USER_HARSHNESS (cp[best].harshness[index]) != USER_HARSHNESS (cp[i].harshness[index])) goto ret0; /* If there's anything we like better about the other function, consider it ambiguous. */ if (cp[i].harshness[index] < cp[best].harshness[index]) goto ret0; /* If any single one it diffent, then the whole is not identical. */ if (cp[i].harshness[index] != cp[best].harshness[index]) identical = 0; } /* If we can't tell the difference between the two, it is ambiguous. */ if (identical) goto ret0; /* If we made it to here, it means we're satisfied that BEST is still best. */ continue; } } } } while (cp + i != candidates); if (best) { int exact_conversions = cp[best].user; tta = parms; if (DECL_STATIC_FUNCTION_P (cp[best].function)) tta = TREE_CHAIN (parms); for (ttf = TYPE_ARG_TYPES (TREE_TYPE (cp[best].function)), index = 0; exact_conversions > 0; tta = TREE_CHAIN (tta), ttf = TREE_CHAIN (ttf), index++) { if (USER_HARSHNESS (cp[best].harshness[index])) { /* We must now fill in the slot we left behind. @@ This could be optimized to use the value previously @@ computed by build_type_conversion in some cases. */ if (basetype != NULL_TREE) TREE_VALUE (tta) = convert (TREE_VALUE (ttf), TREE_PURPOSE (tta)); exact_conversions -= 1; } else TREE_VALUE (tta) = TREE_PURPOSE (tta); } return cp + best; } goto ret0; } /* If the best two candidates we find both use default parameters, we may need to report and error. Don't need to worry if next-best candidate is forced to use user-defined conversion when best is not. */ if (cp[-2].user == 0 && cp[-1].harshness[len] != 0 && cp[-2].harshness[len] != 0) { tree tt1 = TYPE_ARG_TYPES (TREE_TYPE (cp[-1].function)); tree tt2 = TYPE_ARG_TYPES (TREE_TYPE (cp[-2].function)); unsigned i = cp[-1].harshness[len]; if (cp[-2].harshness[len] < i) i = cp[-2].harshness[len]; while (--i > 0) { if (TYPE_MAIN_VARIANT (TREE_VALUE (tt1)) != TYPE_MAIN_VARIANT (TREE_VALUE (tt2))) /* These lists are not identical, so we can choose our best candidate. */ return cp - 1; tt1 = TREE_CHAIN (tt1); tt2 = TREE_CHAIN (tt2); } /* To get here, both lists had the same parameters up to the defaults which were used. This is an ambiguous request. */ goto ret0; } /* Otherwise, return our best candidate. Note that if we get candidates from independent base classes, we have an ambiguity, even if one argument list look a little better than another one. */ if (cp[-1].b_or_d && basetype && TYPE_USES_MULTIPLE_INHERITANCE (basetype)) { int i = n_candidates - 1, best = i; tree base1 = NULL_TREE; if (TREE_CODE (TREE_TYPE (candidates[i].function)) == FUNCTION_TYPE) return cp - 1; for (; i >= 0 && candidates[i].user == 0 && candidates[i].evil == 0; i--) { if (TREE_CODE (TREE_TYPE (candidates[i].function)) == METHOD_TYPE) { tree newbase = DECL_CLASS_CONTEXT (candidates[i].function); if (base1 != NULL_TREE) { /* newbase could be a base or a parent of base1 */ if (newbase != base1 && ! UNIQUELY_DERIVED_FROM_P (newbase, base1) && ! UNIQUELY_DERIVED_FROM_P (base1, newbase)) { error_with_aggr_type (basetype, "ambiguous request for function from distinct base classes of type `%s'"); error ("first candidate is `%s'", fndecl_as_string (0, candidates[best].function, 1)); error ("second candidate is `%s'", fndecl_as_string (0, candidates[i].function, 1)); cp[-1].evil = 1; return cp - 1; } } else { best = i; base1 = newbase; } } else return cp - 1; } } /* Don't accept a candidate as being ideal if it's indistinguishable from another candidate. */ if (rank_for_overload (cp-1, cp-2) == 0) { /* If the types are distinguishably different (like `long' vs. `unsigned long'), that's ok. But if they are arbitrarily different, such as `int (*)(void)' vs. `void (*)(int)', that's not ok. */ tree p1 = TYPE_ARG_TYPES (TREE_TYPE (cp[-1].function)); tree p2 = TYPE_ARG_TYPES (TREE_TYPE (cp[-2].function)); while (p1 && p2) { if (TREE_CODE (TREE_VALUE (p1)) == POINTER_TYPE && TREE_CODE (TREE_TYPE (TREE_VALUE (p1))) == FUNCTION_TYPE && TREE_VALUE (p1) != TREE_VALUE (p2)) return 0; p1 = TREE_CHAIN (p1); p2 = TREE_CHAIN (p2); } if (p1 || p2) return 0; } return cp - 1; ret0: /* In the case where there is no ideal candidate, restore TREE_VALUE slots of PARMS from TREE_PURPOSE slots. */ while (parms) { TREE_VALUE (parms) = TREE_PURPOSE (parms); parms = TREE_CHAIN (parms); } return 0;}/* Assume that if the class referred to is not in the current class hierarchy, that it may be remote. PARENT is assumed to be of aggregate type here. */static intmay_be_remote (parent) tree parent;{ if (TYPE_OVERLOADS_METHOD_CALL_EXPR (parent) == 0) return 0; if (current_class_type == NULL_TREE) return 0; if (parent == current_class_type) return 0; if (UNIQUELY_DERIVED_FROM_P (parent, current_class_type)) return 0; return 1;}#ifdef ESKIT/* Return the number of bytes that the arglist in PARMS would occupy on the stack. */intget_arglist_len_in_bytes (parms) tree parms;{ register tree parm; register int bytecount = 0; for (parm = parms; parm; parm = TREE_CHAIN (parm)) { register tree pval = TREE_VALUE (parm); register int used, size; if (TREE_CODE (pval) == ERROR_MARK) continue; else if (TYPE_MODE (TREE_TYPE (pval)) != BLKmode) { used = size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (pval)));#ifdef PUSH_ROUNDING size = PUSH_ROUNDING (size);#endif used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1) / (PARM_BOUNDARY / BITS_PER_UNIT)) * (PARM_BOUNDARY / BITS_PER_UNIT)); } else { register tree size = size_in_bytes (TREE_TYPE (pval)); register tree used_t = round_up (size, PARM_BOUNDARY / BITS_PER_UNIT); used = TREE_INT_CST_LOW (used_t); } bytecount += used; } return bytecount;}#endiftreebuild_vfield_ref (datum, type) tree datum, type;{ tree rval; int old_assume_nonnull_objects = flag_assume_nonnull_objects; /* Vtable references are always made from non-null objects. */ flag_assume_nonnull_objects = 1; if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE) datum = convert_from_reference (datum); if (! TYPE_USES_COMPLEX_INHERITANCE (type)) rval = build (COMPONENT_REF, TREE_TYPE (CLASSTYPE_VFIELD (type)), datum, CLASSTYPE_VFIELD (type)); else rval = build_component_ref (datum, DECL_NAME (CLASSTYPE_VFIELD (type)), 0, 0); flag_assume_nonnull_objects = old_assume_nonnull_objects; return rval;}/* Build a call to a member of an object. I.e., one that overloads operator ()(), or is a pointer-to-function or pointer-to-method. */static treebuild_field_call (basetype_path, instance_ptr, name, parms, err_name) tree basetype_path; tree instance_ptr, name, parms; char *err_name;{ tree field, instance; if (instance_ptr == current_class_decl) { /* Check to see if we really have a reference to an instance variable with `operator()()' overloaded. */ field = IDENTIFIER_CLASS_VALUE (name); if (field == NULL_TREE) { error ("`this' has no member named `%s'", err_name); return error_mark_node; } if (TREE_CODE (field) == FIELD_DECL) { /* If it's a field, try overloading operator (), or calling if the field is a pointer-to-function. */ instance = build_component_ref_1 (C_C_D, field, 0); if (instance == error_mark_node) return error_mark_node; if (TYPE_LANG_SPECIFIC (TREE_TYPE (instance)) && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (instance))) return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, instance, parms); if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE) if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE) return build_function_call (instance, parms); else if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == METHOD_TYPE) return build_function_call (instance, tree_cons (NULL_TREE, current_class_decl, parms)); } return NULL_TREE; } /* Check to see if this is not really a reference to an instance variable with `operator()()' overloaded. */ field = lookup_field (basetype_path, name, 1, 0); /* This can happen if the reference was ambiguous or for visibility violations. */ if (field == error_mark_node) return error_mark_node; if (field) { tree basetype; tree ftype = TREE_TYPE (field); if (TYPE_LANG_SPECIFIC (ftype) && TYPE_OVERLOADS_CALL_EXPR (ftype)) { /* Make the next search for this field very short. */ basetype = DECL_FIELD_CONTEXT (field); instance_ptr = convert_pointer_to (basetype, instance_ptr); instance = build_indirect_ref (instance_ptr, 0); return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, build_component_ref_1 (instance, field, 0), parms); } if (TREE_CODE (ftype) == POINTER_TYPE) { if (TREE_CODE (TREE_TYPE (ftype)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (ftype)) == METHOD_TYPE) { /* This is a member which is a pointer to function. */ tree ref = build_component_ref_1 (build_indirect_ref (instance_ptr, 0), field, LOOKUP_COMPLAIN); if (ref == error_mark_node) return error_mark_node; return build_function_call (ref, parms); } } else if (TREE_CODE (ftype) == METHOD_TYPE) { error ("invalid call via pointer-to-member function"); return error_mark_node; } else return NULL_TREE; } return NULL_TREE;}treefind_scoped_type (type, inner_name, inner_types) tree type, inner_name, inner_types;{ tree tags = CLASSTYPE_TAGS (type); while (tags) { /* The TREE_PURPOSE of an enum tag (which becomes a member of the enclosing class) is set to the name for the enum type. So, if inner_name is `bar', and we strike `baz' for `enum bar { baz }', then this test will be true. */ if (TREE_PURPOSE (tags) == inner_name) { if (inner_types == NULL_TREE) return DECL_NESTED_TYPENAME (TYPE_NAME (TREE_VALUE (tags))); return resolve_scope_to_name (TREE_VALUE (tags), inner_types); } tags = TREE_CHAIN (tags); } /* Look for a TYPE_DECL. */ for (tags = TYPE_FIELDS (type); tags; tags = TREE_CHAIN (tags)) if (TREE_CODE (tags) == TYPE_DECL && DECL_NAME (tags) == inner_name) { /* Code by raeburn. */ if (inner_types == NULL_TREE) return DECL_NESTED_TYPENAME (tags); return resolve_scope_to_name (TREE_TYPE (tags), inner_types); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -