📄 cvt.c
字号:
/* The type of the first argument will be filled in inside the loop. */ parmlist = tree_cons (NULL_TREE, integer_zero_node, parmlist); parmtypes = tree_cons (NULL_TREE, build_pointer_type (basetype), parmtypes);#if 0 method_name = build_decl_overload (name, parmtypes, 1); /* constructors are up front. */ fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0); if (TYPE_HAS_DESTRUCTOR (basetype)) fndecl = DECL_CHAIN (fndecl); while (fndecl) { if (DECL_ASSEMBLER_NAME (fndecl) == method_name) { function = fndecl; if (protect) { if (TREE_PRIVATE (fndecl)) { can_be_private = (basetype == current_class_type || is_friend (basetype, current_function_decl) || purpose_member (basetype, DECL_ACCESS (fndecl))); if (! can_be_private) goto found; } else if (TREE_PROTECTED (fndecl)) { if (! can_be_protected) goto found; } } goto found_and_ok; } fndecl = DECL_CHAIN (fndecl); }#endif /* No exact conversion was found. See if an approximate one will do. */ fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0); if (TYPE_HAS_DESTRUCTOR (basetype)) fndecl = DECL_CHAIN (fndecl); { int saw_private = 0; int saw_protected = 0; struct candidate *candidates = (struct candidate *) alloca ((decl_list_length (fndecl)+1) * sizeof (struct candidate)); struct candidate *cp = candidates; while (fndecl) { function = fndecl; cp->h_len = 2; cp->harshness = (struct harshness_code *) alloca (3 * sizeof (struct harshness_code)); compute_conversion_costs (fndecl, parmlist, cp, 2); if ((cp->h.code & EVIL_CODE) == 0) { cp->u.field = fndecl; if (protect) { if (TREE_PRIVATE (fndecl)) access = access_private; else if (TREE_PROTECTED (fndecl)) access = access_protected; else access = access_public; } else access = access_public; if (access == access_private ? (basetype == current_class_type || is_friend (basetype, cp->function) || purpose_member (basetype, DECL_ACCESS (fndecl))) : access == access_protected ? (can_be_protected || purpose_member (basetype, DECL_ACCESS (fndecl))) : 1) { if (cp->h.code <= TRIVIAL_CODE) goto found_and_ok; cp++; } else { if (access == access_private) saw_private = 1; else saw_protected = 1; } } fndecl = DECL_CHAIN (fndecl); } if (cp - candidates) { /* Rank from worst to best. Then cp will point to best one. Private fields have their bits flipped. For unsigned numbers, this should make them look very large. If the best alternate has a (signed) negative value, then all we ever saw were private members. */ if (cp - candidates > 1) qsort (candidates, /* char *base */ cp - candidates, /* int nel */ sizeof (struct candidate), /* int width */ rank_for_overload); /* int (*compar)() */ --cp; if (cp->h.code & EVIL_CODE) { if (msgp) *msgp = "ambiguous type conversion possible for `%s'"; return error_mark_node; } function = cp->function; fndecl = cp->u.field; goto found_and_ok; } else if (msgp) { if (saw_private) if (saw_protected) *msgp = "only private and protected conversions apply"; else *msgp = "only private conversions apply"; else if (saw_protected) *msgp = "only protected conversions apply"; else *msgp = "no appropriate conversion to type `%s'"; } return error_mark_node; } /* NOTREACHED */ found: if (access == access_private) if (! can_be_private) { if (msgp) *msgp = TREE_PRIVATE (fndecl) ? "conversion to type `%s' is private" : "conversion to type `%s' is from private base class"; return error_mark_node; } if (access == access_protected) if (! can_be_protected) { if (msgp) *msgp = TREE_PRIVATE (fndecl) ? "conversion to type `%s' is protected" : "conversion to type `%s' is from protected base class"; return error_mark_node; } function = fndecl; found_and_ok: /* It will convert, but we don't do anything about it yet. */ if (msgp == 0) return NULL_TREE; fntype = TREE_TYPE (function); function = default_conversion (function); result = build_nt (CALL_EXPR, function, convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype), parmlist, NULL_TREE, LOOKUP_NORMAL), NULL_TREE); TREE_TYPE (result) = TREE_TYPE (fntype); TREE_SIDE_EFFECTS (result) = 1; return result;}/* Call this when we know (for any reason) that expr is not, in fact, zero. This routine is like convert_pointer_to, but it pays attention to which specific instance of what type we want to convert to. This routine should eventually become convert_to_pointer after all references to convert_to_pointer are removed. */treeconvert_pointer_to_real (binfo, expr) tree binfo, expr;{ register tree intype = TREE_TYPE (expr); tree ptr_type; tree type, rval; if (TREE_CODE (binfo) == TREE_VEC) type = BINFO_TYPE (binfo); else if (IS_AGGR_TYPE (binfo)) { type = binfo; } else { type = binfo; binfo = NULL_TREE; } ptr_type = build_pointer_type (type); if (ptr_type == TYPE_MAIN_VARIANT (intype)) return expr; if (intype == error_mark_node) return error_mark_node; my_friendly_assert (!integer_zerop (expr), 191); if (TREE_CODE (type) == RECORD_TYPE && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE && type != TYPE_MAIN_VARIANT (TREE_TYPE (intype))) { tree path; int distance = get_base_distance (binfo, TYPE_MAIN_VARIANT (TREE_TYPE (intype)), 0, &path); /* This function shouldn't be called with unqualified arguments but if it is, give them an error message that they can read. */ if (distance < 0) { cp_error ("cannot convert a pointer of type `%T' to a pointer of type `%T'", TREE_TYPE (intype), type); if (distance == -2) cp_error ("because `%T' is an ambiguous base class", type); return error_mark_node; } return build_vbase_path (PLUS_EXPR, ptr_type, expr, path, 1); } rval = build1 (NOP_EXPR, ptr_type, TREE_CODE (expr) == NOP_EXPR ? TREE_OPERAND (expr, 0) : expr); TREE_CONSTANT (rval) = TREE_CONSTANT (expr); return rval;}/* Call this when we know (for any reason) that expr is not, in fact, zero. This routine gets a type out of the first argument and uses it to search for the type to convert to. If there is more than one instance of that type in the expr, the conversion is ambiguous. This routine should eventually go away, and all callers should use convert_to_pointer_real. */treeconvert_pointer_to (binfo, expr) tree binfo, expr;{ tree type; if (TREE_CODE (binfo) == TREE_VEC) type = BINFO_TYPE (binfo); else if (IS_AGGR_TYPE (binfo)) type = binfo; else type = binfo; return convert_pointer_to_real (type, expr);}/* Conversion... FLAGS indicates how we should behave. */treecp_convert (type, expr, convtype, flags) tree type, expr; int convtype, flags;{ register tree e = expr; register enum tree_code code = TREE_CODE (type); if (TREE_CODE (e) == ERROR_MARK || TREE_CODE (TREE_TYPE (e)) == ERROR_MARK) return error_mark_node; if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP)) /* We need a new temporary; don't take this shortcut. */; else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e))) /* Trivial conversion: cv-qualifiers do not matter on rvalues. */ return fold (build1 (NOP_EXPR, type, e)); if (code == VOID_TYPE && (convtype & CONV_STATIC)) return build1 (CONVERT_EXPR, type, e);#if 0 /* This is incorrect. A truncation can't be stripped this way. Extensions will be stripped by the use of get_unwidened. */ if (TREE_CODE (e) == NOP_EXPR) return convert (type, TREE_OPERAND (e, 0));#endif /* Just convert to the type of the member. */ if (code == OFFSET_TYPE) { type = TREE_TYPE (type); code = TREE_CODE (type); }#if 0 if (code == REFERENCE_TYPE) return fold (convert_to_reference (type, e, convtype, flags, NULL_TREE)); else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE) e = convert_from_reference (e);#endif if (TREE_CODE (e) == OFFSET_REF) e = resolve_offset_ref (e); if (TREE_READONLY_DECL_P (e)) e = decl_constant_value (e); if (INTEGRAL_CODE_P (code)) { tree intype = TREE_TYPE (e); enum tree_code form = TREE_CODE (intype); /* enum = enum, enum = int, enum = float are all errors. */ if (flag_int_enum_equivalence == 0 && TREE_CODE (type) == ENUMERAL_TYPE && ARITHMETIC_TYPE_P (intype) && ! (convtype & CONV_STATIC)) { cp_pedwarn ("conversion from `%#T' to `%#T'", intype, type); if (flag_pedantic_errors) return error_mark_node; } if (IS_AGGR_TYPE (intype)) { tree rval; rval = build_type_conversion (CONVERT_EXPR, type, e, 1); if (rval) return rval; if (flags & LOOKUP_COMPLAIN) cp_error ("`%#T' used where a `%T' was expected", intype, type); if (flags & LOOKUP_SPECULATIVELY) return NULL_TREE; return error_mark_node; } if (code == BOOLEAN_TYPE) return truthvalue_conversion (e); return fold (convert_to_integer (type, e)); } if (code == POINTER_TYPE || code == REFERENCE_TYPE || TYPE_PTRMEMFUNC_P (type)) return fold (cp_convert_to_pointer (type, e)); if (code == REAL_TYPE) { if (IS_AGGR_TYPE (TREE_TYPE (e))) { tree rval; rval = build_type_conversion (CONVERT_EXPR, type, e, 1); if (rval) return rval; else if (flags & LOOKUP_COMPLAIN) cp_error ("`%#T' used where a floating point value was expected", TREE_TYPE (e)); } return fold (convert_to_real (type, e)); } /* New C++ semantics: since assignment is now based on memberwise copying, if the rhs type is derived from the lhs type, then we may still do a conversion. */ if (IS_AGGR_TYPE_CODE (code)) { tree dtype = TREE_TYPE (e); tree ctor = NULL_TREE; tree conversion = NULL_TREE; dtype = TYPE_MAIN_VARIANT (dtype); /* Conversion of object pointers or signature pointers/references to signature pointers/references. */ if (TYPE_LANG_SPECIFIC (type) && (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type))) { tree constructor = build_signature_pointer_constructor (type, expr); tree sig_ty = SIGNATURE_TYPE (type); tree sig_ptr; if (constructor == error_mark_node) return error_mark_node; sig_ptr = get_temp_name (type, 1); DECL_INITIAL (sig_ptr) = constructor; CLEAR_SIGNATURE (sig_ty); cp_finish_decl (sig_ptr, constructor, NULL_TREE, 0, 0); SET_SIGNATURE (sig_ty); TREE_READONLY (sig_ptr) = 1; return sig_ptr; } /* Conversion between aggregate types. New C++ semantics allow objects of derived type to be cast to objects of base type. Old semantics only allowed this between pointers. There may be some ambiguity between using a constructor vs. using a type conversion operator when both apply. */ if (IS_AGGR_TYPE (dtype) && ! DERIVED_FROM_P (type, dtype) && TYPE_HAS_CONVERSION (dtype)) conversion = build_type_conversion (CONVERT_EXPR, type, e, 1); if (conversion == error_mark_node) { if (flags & LOOKUP_COMPLAIN) error ("ambiguous pointer conversion"); return conversion; } if (TYPE_HAS_CONSTRUCTOR (type)) ctor = build_method_call (NULL_TREE, constructor_name_full (type), build_tree_list (NULL_TREE, e), TYPE_BINFO (type), (flags & LOOKUP_NORMAL) | LOOKUP_SPECULATIVELY | (convtype&CONV_NONCONVERTING ? 0 : LOOKUP_ONLYCONVERTING) | (conversion ? LOOKUP_NO_CONVERSION : 0)); if (ctor == error_mark_node) { if (flags & LOOKUP_COMPLAIN) cp_error ("in conversion to type `%T'", type); if (flags & LOOKUP_SPECULATIVELY) return NULL_TREE; return error_mark_node; } if (conversion && ctor) { if (flags & LOOKUP_COMPLAIN) error ("both constructor and type conversion operator apply"); if (flags & LOOKUP_SPECULATIVELY) return NULL_TREE; return error_mark_node; } else if (conversion) return conversion; else if (ctor) { ctor = build_cplus_new (type, ctor, 0); return ctor; } } /* If TYPE or TREE_TYPE (E) is not on the permanent_obstack, then the it won't be hashed and hence compare as not equal, even when it is. */ if (code == ARRAY_TYPE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -