📄 cp-cvt.c
字号:
type = TYPE_MAIN_VARIANT (TREE_TYPE (xtype)); for (n_variants = 0; type; type = TYPE_NEXT_VARIANT (type)) n_variants++; typenames = (tree *)alloca (n_variants * sizeof (tree)); for (n_variants = 0, type = TYPE_MAIN_VARIANT (TREE_TYPE (xtype)); type; n_variants++, type = TYPE_NEXT_VARIANT (type)) { if (type == TREE_TYPE (xtype)) typenames[n_variants] = typename; else if (TREE_CODE (xtype) == POINTER_TYPE) typenames[n_variants] = build_typename_overload (build_pointer_type (type)); else typenames[n_variants] = build_typename_overload (build_reference_type (type)); } } save_basetype = basetype; type = xtype; while (TYPE_HAS_CONVERSION (basetype)) { int i; if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0)) return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure); for (i = 0; i < n_variants; i++) if (typenames[i] != typename && lookup_fnfields (TYPE_BINFO (basetype), typenames[i], 0)) return build_type_conversion_1 (xtype, basetype, expr, typenames[i], for_sure); if (TYPE_BINFO_BASETYPES (basetype)) basetype = TYPE_BINFO_BASETYPE (basetype, 0); else break; } if (TREE_CODE (type) == REFERENCE_TYPE) { tree first_arg = expr; type = TYPE_MAIN_VARIANT (TREE_TYPE (type)); basetype = save_basetype; /* May need to build a temporary for this. */ while (TYPE_HAS_CONVERSION (basetype)) { if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0)) { int flags; if (for_sure == 0) { if (! lvalue_p (expr)) first_arg = build1 (NOP_EXPR, TYPE_POINTER_TO (basetype), integer_zero_node); flags = LOOKUP_PROTECT; } else flags = LOOKUP_NORMAL; rval = build_method_call (first_arg, constructor_name (typename), NULL_TREE, NULL_TREE, flags); if (rval == error_mark_node) { if (for_sure == 0) return NULL_TREE; return error_mark_node; } TREE_VALUE (TREE_OPERAND (rval, 1)) = expr; if (IS_AGGR_TYPE (type)) { tree init = build_method_call (NULL_TREE, constructor_name (type), build_tree_list (NULL_TREE, rval), NULL_TREE, LOOKUP_NORMAL); tree temp = build_cplus_new (type, init, 1); return build_up_reference (TYPE_REFERENCE_TO (type), temp, LOOKUP_COMPLAIN, 1); } return convert (xtype, rval); } if (TYPE_BINFO_BASETYPES (basetype)) basetype = TYPE_BINFO_BASETYPE (basetype, 0); else break; } /* No free conversions for reference types, right?. */ return NULL_TREE; } if (exact_conversion) return NULL_TREE; /* No perfect match found, try default. */ if (code == CONVERT_EXPR && TREE_CODE (type) == POINTER_TYPE) type_default = ptr_type_node; else if (type == void_type_node) return NULL_TREE; else { extern tree default_conversion (); tree tmp = default_conversion (build1 (NOP_EXPR, type, integer_zero_node)); if (tmp == error_mark_node) return NULL_TREE; type_default = TREE_TYPE (tmp); } basetype = save_basetype; if (type_default != type) { type = type_default; typename = build_typename_overload (type); while (TYPE_HAS_CONVERSION (basetype)) { if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0)) return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure); if (TYPE_BINFO_BASETYPES (basetype)) basetype = TYPE_BINFO_BASETYPE (basetype, 0); else break; } } try_pointer: if (type == ptr_type_node) { /* Try converting to some other pointer type with which void* is compatible, or in situations in which void* is appropriate (such as &&,||, and !). */ while (TYPE_HAS_CONVERSION (basetype)) { if (CLASSTYPE_CONVERSION (basetype, ptr_conv) != 0) { if (CLASSTYPE_CONVERSION (basetype, ptr_conv) == error_mark_node) return error_mark_node; typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, ptr_conv)); return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure); } if (TYPE_BINFO_BASETYPES (basetype)) basetype = TYPE_BINFO_BASETYPE (basetype, 0); else break; } } if (TREE_CODE (type) == POINTER_TYPE && TYPE_READONLY (TREE_TYPE (type)) && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node) { /* Try converting to some other pointer type with which const void* is compatible. */ while (TYPE_HAS_CONVERSION (basetype)) { if (CLASSTYPE_CONVERSION (basetype, constptr_conv) != 0) { if (CLASSTYPE_CONVERSION (basetype, constptr_conv) == error_mark_node) return error_mark_node; typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, constptr_conv)); return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure); } if (TYPE_BINFO_BASETYPES (basetype)) basetype = TYPE_BINFO_BASETYPE (basetype, 0); else break; } } /* Use the longer or shorter conversion that is appropriate. Have to check against 0 because the conversion may come from a baseclass. */ if (TREE_CODE (type) == INTEGER_TYPE && TYPE_HAS_INT_CONVERSION (basetype) && CLASSTYPE_CONVERSION (basetype, int_conv) != 0 && CLASSTYPE_CONVERSION (basetype, int_conv) != error_mark_node) { typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, int_conv)); return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure); } if (TREE_CODE (type) == REAL_TYPE && TYPE_HAS_REAL_CONVERSION (basetype) && CLASSTYPE_CONVERSION (basetype, real_conv) != 0 && CLASSTYPE_CONVERSION (basetype, real_conv) != error_mark_node) { typename = DECL_NAME (CLASSTYPE_CONVERSION (basetype, real_conv)); return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure); } /* THIS IS A KLUDGE. */ if (TREE_CODE (type) != POINTER_TYPE && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR || code == TRUTH_NOT_EXPR)) { /* Here's when we can convert to a pointer. */ type = ptr_type_node; goto try_pointer; } /* THESE ARE TOTAL KLUDGES. */ /* Default promotion yields no new alternatives, try conversions which are anti-default, such as double -> float or int -> unsigned or unsigned -> long */ if (type_default == type && (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == REAL_TYPE)) { int not_again = 0; if (type == double_type_node) typename = build_typename_overload (float_type_node); else if (type == integer_type_node) typename = build_typename_overload (unsigned_type_node); else if (type == unsigned_type_node) typename = build_typename_overload (long_integer_type_node); again: basetype = save_basetype; while (TYPE_HAS_CONVERSION (basetype)) { if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0)) return build_type_conversion_1 (xtype, basetype, expr, typename, for_sure); if (TYPE_BINFO_BASETYPES (basetype)) basetype = TYPE_BINFO_BASETYPE (basetype, 0); else break; } if (! not_again) { if (type == integer_type_node) { typename = build_typename_overload (long_integer_type_node); not_again = 1; goto again; } else { typename = build_typename_overload (integer_type_node); not_again = 1; goto again; } } } /* Now, try C promotions... float -> int int -> float, void * void * -> int Truthvalue conversions let us try to convert to pointer if we were going for int, and to int if we were looking for pointer. */ basetype = save_basetype; if (TREE_CODE (type) == REAL_TYPE || (TREE_CODE (type) == POINTER_TYPE && (code == TRUTH_ANDIF_EXPR || code == TRUTH_ORIF_EXPR || code == TRUTH_NOT_EXPR))) type = integer_type_node; else if (TREE_CODE (type) == INTEGER_TYPE) if (TYPE_HAS_REAL_CONVERSION (basetype)) type = double_type_node; else return NULL_TREE; else return NULL_TREE; typename = build_typename_overload (type); while (TYPE_HAS_CONVERSION (basetype)) { if (lookup_fnfields (TYPE_BINFO (basetype), typename, 0)) { rval = build_type_conversion_1 (xtype, basetype, expr, typename, for_sure); return rval; } if (TYPE_BINFO_BASETYPES (basetype)) basetype = TYPE_BINFO_BASETYPE (basetype, 0); else break; } return NULL_TREE;}/* Must convert two aggregate types to non-aggregate type. Attempts to find a non-ambiguous, "best" type conversion. Return 1 on success, 0 on failure. @@ What are the real semantics of this supposed to be??? */intbuild_default_binary_type_conversion (code, arg1, arg2) enum tree_code code; tree *arg1, *arg2;{ tree type1 = TREE_TYPE (*arg1); tree type2 = TREE_TYPE (*arg2); char *name1, *name2; if (TREE_CODE (type1) == REFERENCE_TYPE) type1 = TREE_TYPE (type1); if (TREE_CODE (type2) == REFERENCE_TYPE) type2 = TREE_TYPE (type2); if (TREE_CODE (TYPE_NAME (type1)) != TYPE_DECL) { tree decl = typedecl_for_tag (type1); if (decl) error ("type conversion nonexistent for type `%s'", IDENTIFIER_POINTER (DECL_NAME (decl))); else error ("type conversion nonexistent for non-C++ type"); return 0; } if (TREE_CODE (TYPE_NAME (type2)) != TYPE_DECL) { tree decl = typedecl_for_tag (type2); if (decl) error ("type conversion nonexistent for type `%s'", IDENTIFIER_POINTER (decl)); else error ("type conversion nonexistent for non-C++ type"); return 0; } name1 = TYPE_NAME_STRING (type1); name2 = TYPE_NAME_STRING (type2); if (!IS_AGGR_TYPE (type1) || !TYPE_HAS_CONVERSION (type1)) { if (!IS_AGGR_TYPE (type2) || !TYPE_HAS_CONVERSION (type2)) error ("type conversion required for binary operation on types `%s' and `%s'", name1, name2); else error ("type conversion required for type `%s'", name1); return 0; } else if (!IS_AGGR_TYPE (type2) || !TYPE_HAS_CONVERSION (type2)) { error ("type conversion required for type `%s'", name2); return 0; } if (TYPE_HAS_INT_CONVERSION (type1) && TYPE_HAS_REAL_CONVERSION (type1)) warning ("ambiguous type conversion for type `%s', defaulting to int", name1); if (TYPE_HAS_INT_CONVERSION (type1)) { *arg1 = build_type_conversion (code, integer_type_node, *arg1, 1); *arg2 = build_type_conversion (code, integer_type_node, *arg2, 1); } else if (TYPE_HAS_REAL_CONVERSION (type1)) { *arg1 = build_type_conversion (code, double_type_node, *arg1, 1); *arg2 = build_type_conversion (code, double_type_node, *arg2, 1); } else { *arg1 = build_type_conversion (code, ptr_type_node, *arg1, 1); if (*arg1 == error_mark_node) error ("ambiguous pointer conversion"); *arg2 = build_type_conversion (code, ptr_type_node, *arg2, 1); if (*arg1 != error_mark_node && *arg2 == error_mark_node) error ("ambiguous pointer conversion"); } if (*arg1 == 0) { if (*arg2 == 0 && type1 != type2) error ("default type conversion for types `%s' and `%s' failed", name1, name2); else error ("default type conversion for type `%s' failed", name1); return 0; } else if (*arg2 == 0) { error ("default type conversion for type `%s' failed", name2); return 0; } return 1;}/* Must convert two aggregate types to non-aggregate type. Attempts to find a non-ambiguous, "best" type conversion. Return 1 on success, 0 on failure. The type of the argument is expected to be of aggregate type here. @@ What are the real semantics of this supposed to be??? */intbuild_default_unary_type_conversion (code, arg) enum tree_code code; tree *arg;{ tree type = TREE_TYPE (*arg); tree id = TREE_CODE (TYPE_NAME (type)) == TYPE_DECL ? TYPE_IDENTIFIER (type) : TYPE_NAME (type); char *name = IDENTIFIER_POINTER (id); if (! TYPE_HAS_CONVERSION (type)) { error ("type conversion required for type `%s'", name); return 0; } if (TYPE_HAS_INT_CONVERSION (type) && TYPE_HAS_REAL_CONVERSION (type)) warning ("ambiguous type conversion for type `%s', defaulting to int", name); if (TYPE_HAS_INT_CONVERSION (type)) *arg = build_type_conversion (code, integer_type_node, *arg, 1); else if (TYPE_HAS_REAL_CONVERSION (type)) *arg = build_type_conversion (code, double_type_node, *arg, 1); else { *arg = build_type_conversion (code, ptr_type_node, *arg, 1); if (*arg == error_mark_node) error ("ambiguous pointer conversion"); } if (*arg == 0) { error ("default type conversion for type `%s' failed", name); return 0; } return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -