📄 cp-call.c
字号:
matter if we make life easier for the programmer by creating a temporary variable with which to hold the result. */ if (parm && (coder == INTEGER_TYPE || coder == ENUMERAL_TYPE || coder == REAL_TYPE) && ! lvalue_p (parm)) return (convert_harshness (ttl, ttr, 0) | INT_TO_EASY_HARSHNESS (penalty)); if (ttl == ttr) { if (penalty) return INT_TO_EASY_HARSHNESS (penalty); return INT_TO_BD_HARSHNESS (0); } /* Pointers to voids always convert for pointers. But make them less natural than more specific matches. */ if (TREE_CODE (ttl) == POINTER_TYPE && TREE_CODE (ttr) == POINTER_TYPE) if (TREE_TYPE (ttl) == void_type_node || TREE_TYPE (ttr) == void_type_node) return INT_TO_EASY_HARSHNESS (penalty+1); if (parm && codel != REFERENCE_TYPE) return (convert_harshness (ttl, ttr, 0) | INT_TO_EASY_HARSHNESS (penalty)); /* Here it does matter. If this conversion is from derived to base, allow it. Otherwise, types must be compatible in the strong sense. */ if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE) { int b_or_d = get_base_distance (ttl, ttr, 0, 0); if (b_or_d < 0) { b_or_d = get_base_distance (ttr, ttl, 0, 0); if (b_or_d < 0) return 1; return CONTRAVARIANT_HARSHNESS (-1); } /* Say that this conversion is relatively painless. If it turns out that there is a user-defined X(X&) constructor, then that will be invoked, but that's preferable to dealing with other user-defined conversions that may produce surprising results. */ return INT_TO_BD_HARSHNESS (b_or_d); } if (comp_target_types (ttl, intype, 1)) return INT_TO_EASY_HARSHNESS (penalty); } } if (codel == RECORD_TYPE && coder == RECORD_TYPE) { int b_or_d = get_base_distance (type, parmtype, 0, 0); if (b_or_d < 0) { b_or_d = get_base_distance (parmtype, type, 0, 0); if (b_or_d < 0) return 1; return CONTRAVARIANT_HARSHNESS (-1); } return INT_TO_BD_HARSHNESS (b_or_d); } return 1;}/* Algorithm: Start out with no strikes against. For each argument which requires a (subjective) hard conversion (such as between floating point and integer), issue a strike. If there are the same number of formal and actual parameters in the list, there will be at least on strike, otherwise an exact match would have been found. If there are not the same number of arguments in the type lists, we are not dead yet: a `...' means that we can have more parms then were declared, and if we wind up in the default argument section of the list those can be used as well. If an exact match could be found for one of those cases, return it immediately. Otherwise, rank the fields so that fields with fewer strikes are tried first. Conversions between builtin and user-defined types are allowed, but no function involving such a conversion is preferred to one which does not require such a conversion. Furthermore, such conversions must be unique. */voidcompute_conversion_costs (function, tta_in, cp, arglen) tree function; tree tta_in; struct candidate *cp; int arglen;{ tree ttf_in = TYPE_ARG_TYPES (TREE_TYPE (function)); tree ttf = ttf_in; tree tta = tta_in; /* Start out with no strikes against. */ int evil_strikes = 0; int user_strikes = 0; int b_or_d_strikes = 0; int easy_strikes = 0; int strike_index = 0, win, lose;#ifdef GATHER_STATISTICS n_compute_conversion_costs++;#endif cp->function = function; cp->arg = tta ? TREE_VALUE (tta) : NULL_TREE; cp->u.bad_arg = 0; /* optimistic! */ bzero (cp->harshness, (arglen+1) * sizeof (short)); while (ttf && tta) { int harshness; if (ttf == void_list_node) break; if (type_unknown_p (TREE_VALUE (tta))) { /* Must perform some instantiation here. */ tree rhs = TREE_VALUE (tta); tree lhstype = TREE_VALUE (ttf); /* Keep quiet about possible contravariance violations. */ int old_inhibit_warnings = inhibit_warnings; inhibit_warnings = 1; /* @@ This is to undo what `grokdeclarator' does to parameter types. It really should go through something more general. */ TREE_TYPE (tta) = unknown_type_node; rhs = instantiate_type (lhstype, rhs, 0); inhibit_warnings = old_inhibit_warnings; if (TREE_CODE (rhs) == ERROR_MARK) harshness = 1; else { harshness = convert_harshness (lhstype, TREE_TYPE (rhs), rhs); /* harshness |= 2; */ } } else harshness = convert_harshness (TREE_VALUE (ttf), TREE_TYPE (TREE_VALUE (tta)), TREE_VALUE (tta)); cp->harshness[strike_index] = harshness; if (EVIL_HARSHNESS (harshness) || CONTRAVARIANT_HARSHNESS (harshness)) { cp->u.bad_arg = strike_index; evil_strikes = 1; }#if 0 /* This is never set by `convert_harshness'. */ else if (USER_HARSHNESS (harshness)) { user_strikes += 1; }#endif else if (BASE_DERIVED_HARSHNESS (harshness)) { b_or_d_strikes += INT_FROM_BD_HARSHNESS (harshness); } else easy_strikes += INT_FROM_EASY_HARSHNESS (harshness); ttf = TREE_CHAIN (ttf); tta = TREE_CHAIN (tta); strike_index += 1; } if (tta) { /* ran out of formals, and parmlist is fixed size. */ if (ttf /* == void_type_node */) { cp->evil = 1; cp->u.bad_arg = -1; return; } } else if (ttf && ttf != void_list_node) { /* ran out of actuals, and no defaults. */ if (TREE_PURPOSE (ttf) == NULL_TREE) { cp->evil = 1; cp->u.bad_arg = -2; return; } /* Store index of first default. */ cp->harshness[arglen] = strike_index+1; } else cp->harshness[arglen] = 0; /* Argument list lengths work out, so don't need to check them again. */ if (evil_strikes) { /* We do not check for derived->base conversions here, since in no case would they give evil strike counts, unless such conversions are somehow ambiguous. */ /* See if any user-defined conversions apply. But make sure that we do not loop. */ static int dont_convert_types = 0; if (dont_convert_types) { cp->evil = 1; return; } win = 0; /* Only get one chance to win. */ ttf = TYPE_ARG_TYPES (TREE_TYPE (function)); tta = tta_in; strike_index = 0; evil_strikes = 0; while (ttf && tta) { if (ttf == void_list_node) break; lose = cp->harshness[strike_index]; if (EVIL_HARSHNESS (lose) || CONTRAVARIANT_HARSHNESS (lose)) { tree actual_type = TREE_TYPE (TREE_VALUE (tta)); tree formal_type = TREE_VALUE (ttf); dont_convert_types = 1; if (TREE_CODE (formal_type) == REFERENCE_TYPE) formal_type = TREE_TYPE (formal_type); if (TREE_CODE (actual_type) == REFERENCE_TYPE) actual_type = TREE_TYPE (actual_type); if (formal_type != error_mark_node && actual_type != error_mark_node) { formal_type = TYPE_MAIN_VARIANT (formal_type); actual_type = TYPE_MAIN_VARIANT (actual_type); if (TYPE_HAS_CONSTRUCTOR (formal_type)) { /* If it has a constructor for this type, try to use it. */ if (convert_to_aggr (formal_type, TREE_VALUE (tta), 0, 1) != error_mark_node) { /* @@ There is no way to save this result yet. @@ So success is NULL_TREE for now. */ win++; } } if (TYPE_LANG_SPECIFIC (actual_type) && TYPE_HAS_CONVERSION (actual_type)) { if (TREE_CODE (formal_type) == INTEGER_TYPE && TYPE_HAS_INT_CONVERSION (actual_type)) win++; else if (TREE_CODE (formal_type) == REAL_TYPE && TYPE_HAS_REAL_CONVERSION (actual_type)) win++; else { tree conv = build_type_conversion (CALL_EXPR, TREE_VALUE (ttf), TREE_VALUE (tta), 0); if (conv) { if (conv == error_mark_node) win += 2; else win++; } else if (TREE_CODE (TREE_VALUE (ttf)) == REFERENCE_TYPE) { conv = build_type_conversion (CALL_EXPR, formal_type, TREE_VALUE (tta), 0); if (conv) { if (conv == error_mark_node) win += 2; else win++; } } } } } dont_convert_types = 0; if (win == 1) { user_strikes += 1; cp->harshness[strike_index] = USER_HARSHNESS (-1); win = 0; } else { if (cp->u.bad_arg > strike_index) cp->u.bad_arg = strike_index; evil_strikes = win ? 2 : 1; break; } } ttf = TREE_CHAIN (ttf); tta = TREE_CHAIN (tta); strike_index += 1; } } /* Const member functions get a small penalty because defaulting to const is less useful than defaulting to non-const. */ /* This is bogus, it does not correspond to anything in the ARM. This code will be fixed when this entire section is rewritten to conform to the ARM. (mrs) */ if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE) { if (TYPE_READONLY (TREE_TYPE (TREE_VALUE (ttf_in)))) { cp->harshness[0] += INT_TO_EASY_HARSHNESS (1); ++easy_strikes; } else { /* Calling a non-const member function from a const member function is probably invalid, but for now we let it only draw a warning. We indicate that such a mismatch has occurred by setting the harshness to a maximum value. */ if (TREE_CODE (TREE_TYPE (TREE_VALUE (tta_in))) == POINTER_TYPE && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (TREE_VALUE (tta_in)))))) cp->harshness[0] |= CONST_HARSHNESS (-1); } } cp->evil = evil_strikes; cp->user = user_strikes; cp->b_or_d = b_or_d_strikes; cp->easy = easy_strikes;}/* When one of several possible overloaded functions and/or methods can be called, choose the best candidate for overloading. BASETYPE is the context from which we start method resolution or NULL if we are comparing overloaded functions. CANDIDATES is the array of candidates we have to choose from. N_CANDIDATES is the length of CANDIDATES. PARMS is a TREE_LIST of parameters to the function we'll ultimately choose. It is modified in place when resolving methods. It is not modified in place when resolving overloaded functions. LEN is the length of the parameter list. */static struct candidate *ideal_candidate (basetype, candidates, n_candidates, parms, len) tree basetype; struct candidate *candidates; int n_candidates; tree parms; int len;{ struct candidate *cp = candidates + n_candidates; int index, i; tree ttf; qsort (candidates, /* char *base */ n_candidates, /* int nel */ sizeof (struct candidate), /* int width */ rank_for_overload); /* int (*compar)() */ /* If the best candidate requires user-defined conversions, and its user-defined conversions are a strict subset of all other candidates requiring user-defined conversions, then it is, in fact, the best. */ for (i = -1; cp + i != candidates; i--) if (cp[i].user == 0) break; if (i < -1) { tree ttf0; /* Check that every other candidate requires those conversions as a strict subset of their conversions. */ if (cp[i].user == cp[-1].user) goto non_subset; /* Look at subset relationship more closely. */ while (i != -1) { for (ttf = TYPE_ARG_TYPES (TREE_TYPE (cp[i].function)), ttf0 = TYPE_ARG_TYPES (TREE_TYPE (cp[-1].function)), index = 0; index < len; ttf = TREE_CHAIN (ttf), ttf0 = TREE_CHAIN (ttf0), index++) if (USER_HARSHNESS (cp[i].harshness[index])) { /* If our "best" candidate also needs a conversion, it must be the same one. */ if (USER_HARSHNESS (cp[-1].harshness[index]) && TREE_VALUE (ttf) != TREE_VALUE (ttf0)) goto non_subset; } i++; } /* The best was the best. */ return cp - 1; non_subset: /* Use other rules for determining "bestness". */ ; } /* If the best two candidates we find require user-defined conversions, we may need to report and error message. */ if (cp[-1].user && cp[-2].user && (cp[-1].b_or_d || cp[-2].b_or_d == 0)) { /* If the best two methods found involved user-defined type conversions, then we must see whether one of them is exactly what we wanted. If not, then we have an ambiguity. */ int best = 0; tree tta = parms; tree f1, p1; /* Stash all of our parameters in safe places so that we can perform type conversions in place. */ while (tta) { TREE_PURPOSE (tta) = TREE_VALUE (tta); tta = TREE_CHAIN (tta);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -