cvt.c
来自「GCC编译器源代码」· C语言 代码 · 共 1,673 行 · 第 1/4 页
C
1,673 行
*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); parmlist = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype), parmlist, NULL_TREE, LOOKUP_NORMAL); result = build_call (function, TREE_TYPE (fntype), parmlist); 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 = cp_build_type_variant (type, TYPE_READONLY (TREE_TYPE (intype)), TYPE_VOLATILE (TREE_TYPE (intype))); ptr_type = build_pointer_type (ptr_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);}/* C++ conversions, preference to static cast conversions. */treecp_convert (type, expr) tree type, expr;{ return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL);}/* Conversion... FLAGS indicates how we should behave. */treeocp_convert (type, expr, convtype, flags) tree type, expr; int convtype, flags;{ register tree e = expr; register enum tree_code code = TREE_CODE (type); if (e == error_mark_node || TREE_TYPE (e) == error_mark_node) 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 cp_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 = enum, enum = int, enum = float, (enum)pointer are all errors. */ if (flag_int_enum_equivalence == 0 && TREE_CODE (type) == ENUMERAL_TYPE && ((ARITHMETIC_TYPE_P (intype) && ! (convtype & CONV_STATIC)) || (TREE_CODE (intype) == POINTER_TYPE))) { 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) { /* Common Ada/Pascal programmer's mistake. We always warn about this since it is so bad. */ if (TREE_CODE (expr) == FUNCTION_DECL) cp_warning ("the address of `%D', will always be `true'", expr); 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 || code == COMPLEX_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)); } if (code == REAL_TYPE) return fold (convert_to_real (type, e)); else if (code == COMPLEX_TYPE) return fold (convert_to_complex (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 (flag_ansi_overloading) { ctor = e; if ((flags & LOOKUP_ONLYCONVERTING) && ! (IS_AGGR_TYPE (dtype) && DERIVED_FROM_P (type, dtype))) { ctor = build_user_type_conversion (type, ctor, flags); flags |= LOOKUP_NO_CONVERSION; } if (ctor) ctor = build_method_call (NULL_TREE, ctor_identifier, build_expr_list (NULL_TREE, ctor), TYPE_BINFO (type), flags); if (ctor) return build_cplus_new (type, ctor); } else { 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 (complete_type (type))) ctor = build_method_call (NULL_TREE, ctor_identifier, build_expr_list (NULL_TREE, e), TYPE_BINFO (type), (flags & LOOKUP_NORMAL) | LOOKUP_SPECULATIVELY | (flags & LOOKUP_ONLYCONVERTING) | (flags & LOOKUP_NO_CONVERSION) | (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); 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 && TREE_TYPE (TREE_TYPE (e)) == TREE_TYPE (type) && index_type_equal (TYPE_DOMAIN (TREE_TYPE (e)), TYPE_DOMAIN (type))) return e; if (flags & LOOKUP_COMPLAIN) cp_error ("conversion from `%T' to non-scalar type `%T' requested", TREE_TYPE (expr), type); if (flags & LOOKUP_SPECULATIVELY) return NULL_TREE; return error_mark_node;}/* Create an expression whose value is that of EXPR, converted to type TYPE. The TREE_TYPE of the value is always TYPE. This function implements all reasonable conversions; callers should filter out those that are not permitted by the language being compiled. Most of this routine is from build_reinterpret_cast. The backend cannot call cp_convert (what was convert) because conversions to/from basetypes may involve memory references (vbases) and adding or subtracting small values (multiple inheritance), but it calls convert from the constant folding code on subtrees of already build trees after it has ripped them apart. Also, if we ever support range variables, we'll probably also have to do a little bit more work. */treeconvert (type, expr) tree type, expr;{ tree intype; if (type == error_mark_node || expr == error_mark_node) return error_mark_node; intype = TREE_TYPE (expr); if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype)) { if (TREE_READONLY_DECL_P (expr)) expr = decl_constant_value (expr); return fold (build1 (NOP_EXPR, type, expr)); } return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);}/* Like cp_convert, except permit conversions to take place which are not normally allowed due to access restrictions (such as conversion from sub-type to private super-type). */treeconvert_force (type, expr, convtype) tree type; tree expr; int convtype;{ register tree e = expr; register enum tree_code code = TREE_CODE (type); if (code == REFERENCE_TYPE) return fold (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN, NULL_TREE)); else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE) e = convert_from_reference (e); if (code == POINTER_TYPE) return fold (convert_to_pointer_force (type, e)); /* From typeck.c convert_for_assignment */ if (((TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (e) == ADDR_EXPR && TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (TREE_TYPE (TREE_TYPE (e))) == METHOD_TYPE)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?