📄 cvt.c
字号:
rval = build_type_conversion (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; 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. */ ctor = e; if (IS_AGGR_TYPE (type) && CLASSTYPE_ABSTRACT_VIRTUALS (type)) { abstract_virtuals_error (NULL_TREE, type); return error_mark_node; } if ((flags & LOOKUP_ONLYCONVERTING) && ! (IS_AGGR_TYPE (dtype) && DERIVED_FROM_P (type, dtype))) /* For copy-initialization, first we create a temp of the proper type with a user-defined conversion sequence, then we direct-initialize the target with the temp (see [dcl.init]). */ ctor = build_user_type_conversion (type, ctor, flags); 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); } /* If TYPE or TREE_TYPE (E) is not on the permanent_obstack, then 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) || integer_zerop (e) || TYPE_PTRMEMFUNC_P (TREE_TYPE (e))) && TYPE_PTRMEMFUNC_P (type)) { /* compatible pointer to member functions. */ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1); } return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL);}/* Convert an aggregate EXPR to type XTYPE. If a conversion exists, return the attempted conversion. This may return ERROR_MARK_NODE if the conversion is not allowed (references private members, etc). If no conversion exists, NULL_TREE is returned. If (FOR_SURE & 1) is non-zero, then we allow this type conversion to take place immediately. Otherwise, we build a SAVE_EXPR which can be evaluated if the results are ever needed. Changes to this functions should be mirrored in user_harshness. FIXME: Ambiguity checking is wrong. Should choose one by the implicit object parameter, or by the second standard conversion sequence if that doesn't do it. This will probably wait for an overloading rewrite. (jason 8/9/95) */treebuild_type_conversion (xtype, expr, for_sure) tree xtype, expr; int for_sure;{ /* C++: check to see if we can convert this aggregate type into the required type. */ return build_user_type_conversion (xtype, expr, for_sure ? LOOKUP_NORMAL : 0);}/* Convert the given EXPR to one of a group of types suitable for use in an expression. DESIRES is a combination of various WANT_* flags (q.v.) which indicates which types are suitable. If COMPLAIN is 1, complain about ambiguity; otherwise, the caller will deal with it. */treebuild_expr_type_conversion (desires, expr, complain) int desires; tree expr; int complain;{ tree basetype = TREE_TYPE (expr); tree conv = NULL_TREE; tree winner = NULL_TREE; if (expr == null_node && (desires & WANT_INT) && !(desires & WANT_NULL)) cp_warning ("converting NULL to non-pointer type"); if (TREE_CODE (expr) == OFFSET_REF) expr = resolve_offset_ref (expr); expr = convert_from_reference (expr); basetype = TREE_TYPE (expr); if (! IS_AGGR_TYPE (basetype)) switch (TREE_CODE (basetype)) { case INTEGER_TYPE: if ((desires & WANT_NULL) && null_ptr_cst_p (expr)) return expr; /* else fall through... */ case BOOLEAN_TYPE: return (desires & WANT_INT) ? expr : NULL_TREE; case ENUMERAL_TYPE: return (desires & WANT_ENUM) ? expr : NULL_TREE; case REAL_TYPE: return (desires & WANT_FLOAT) ? expr : NULL_TREE; case POINTER_TYPE: return (desires & WANT_POINTER) ? expr : NULL_TREE; case FUNCTION_TYPE: case ARRAY_TYPE: return (desires & WANT_POINTER) ? default_conversion (expr) : NULL_TREE; default: return NULL_TREE; } /* The code for conversions from class type is currently only used for delete expressions. Other expressions are handled by build_new_op. */ if (! TYPE_HAS_CONVERSION (basetype)) return NULL_TREE; for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv)) { int win = 0; tree candidate; tree cand = TREE_VALUE (conv); if (winner && winner == cand) continue; candidate = TREE_TYPE (TREE_TYPE (cand)); if (TREE_CODE (candidate) == REFERENCE_TYPE) candidate = TREE_TYPE (candidate); switch (TREE_CODE (candidate)) { case BOOLEAN_TYPE: case INTEGER_TYPE: win = (desires & WANT_INT); break; case ENUMERAL_TYPE: win = (desires & WANT_ENUM); break; case REAL_TYPE: win = (desires & WANT_FLOAT); break; case POINTER_TYPE: win = (desires & WANT_POINTER); break; default: break; } if (win) { if (winner) { if (complain) { cp_error ("ambiguous default type conversion from `%T'", basetype); cp_error (" candidate conversions include `%D' and `%D'", winner, cand); } return error_mark_node; } else winner = cand; } } if (winner) { tree type = TREE_TYPE (TREE_TYPE (winner)); if (TREE_CODE (type) == REFERENCE_TYPE) type = TREE_TYPE (type); return build_user_type_conversion (type, expr, LOOKUP_NORMAL); } return NULL_TREE;}/* Implements integral promotion (4.1) and float->double promotion. */treetype_promotes_to (type) tree type;{ int type_quals; if (type == error_mark_node) return error_mark_node; type_quals = CP_TYPE_QUALS (type); type = TYPE_MAIN_VARIANT (type); /* bool always promotes to int (not unsigned), even if it's the same size. */ if (type == boolean_type_node) type = integer_type_node; /* Normally convert enums to int, but convert wide enums to something wider. */ else if (TREE_CODE (type) == ENUMERAL_TYPE || type == wchar_type_node) { int precision = MAX (TYPE_PRECISION (type), TYPE_PRECISION (integer_type_node)); tree totype = type_for_size (precision, 0); if (TREE_UNSIGNED (type) && ! int_fits_type_p (TYPE_MAX_VALUE (type), totype)) type = type_for_size (precision, 1); else type = totype; } else if (C_PROMOTING_INTEGER_TYPE_P (type)) { /* Retain unsignedness if really not getting bigger. */ if (TREE_UNSIGNED (type) && TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)) type = unsigned_type_node; else type = integer_type_node; } else if (type == float_type_node) type = double_type_node; return cp_build_qualified_type (type, type_quals);}/* The routines below this point are carefully written to conform to the standard. They use the same terminology, and follow the rules closely. Although they are used only in pt.c at the moment, they should presumably be used everywhere in the future. *//* Attempt to perform qualification conversions on EXPR to convert it to TYPE. Return the resulting expression, or error_mark_node if the conversion was impossible. */tree perform_qualification_conversions (type, expr) tree type; tree expr;{ if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE && comp_ptr_ttypes (TREE_TYPE (type), TREE_TYPE (TREE_TYPE (expr)))) return build1 (NOP_EXPR, type, expr); else return error_mark_node;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -