📄 cvt.c
字号:
} else rval = convert_to_pointer_force (build_pointer_type (target_type), rval); rval = build1 (NOP_EXPR, type, rval); TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0)); return rval;}/* For C++: Only need to do one-level references, but cannot get tripped up on signed/unsigned differences. DECL is either NULL_TREE or the _DECL node for a reference that is being initialized. It can be error_mark_node if we don't know the _DECL but we know it's an initialization. */treeconvert_to_reference (reftype, expr, convtype, flags, decl) tree reftype, expr; int convtype, flags; tree decl;{ register tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype)); register tree intype = TREE_TYPE (expr); tree rval = NULL_TREE; tree rval_as_conversion = NULL_TREE; int i; if (TREE_CODE (type) == FUNCTION_TYPE && intype == unknown_type_node) { expr = instantiate_type (type, expr, (flags & LOOKUP_COMPLAIN) != 0); if (expr == error_mark_node) return error_mark_node; intype = TREE_TYPE (expr); } if (TREE_CODE (intype) == REFERENCE_TYPE) my_friendly_abort (364); intype = TYPE_MAIN_VARIANT (intype); i = comp_target_types (type, intype, 0); if (i <= 0 && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype) && ! (flags & LOOKUP_NO_CONVERSION)) { /* Look for a user-defined conversion to lvalue that we can use. */ rval_as_conversion = build_type_conversion (reftype, expr, 1); if (rval_as_conversion && rval_as_conversion != error_mark_node && real_lvalue_p (rval_as_conversion)) { expr = rval_as_conversion; rval_as_conversion = NULL_TREE; intype = type; i = 1; } } if (((convtype & CONV_STATIC) && i == -1) || ((convtype & CONV_IMPLICIT) && i == 1)) { if (flags & LOOKUP_COMPLAIN) { tree ttl = TREE_TYPE (reftype); tree ttr = lvalue_type (expr); /* [dcl.init.ref] says that if an rvalue is used to initialize a reference, then the reference must be to a non-volatile const type. */ if (! real_lvalue_p (expr) && !CP_TYPE_CONST_NON_VOLATILE_P (ttl)) { const char *msg; if (CP_TYPE_VOLATILE_P (ttl) && decl) msg = "initialization of volatile reference type `%#T'"; else if (CP_TYPE_VOLATILE_P (ttl)) msg = "conversion to volatile reference type `%#T'"; else if (decl) msg = "initialization of non-const reference type `%#T'"; else msg = "conversion to non-const reference type `%#T'"; cp_pedwarn (msg, reftype); cp_pedwarn ("from rvalue of type `%T'", intype); } else if (! (convtype & CONV_CONST) && !at_least_as_qualified_p (ttl, ttr)) cp_pedwarn ("conversion from `%T' to `%T' discards qualifiers", ttr, reftype); } return build_up_reference (reftype, expr, flags); } else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr)) { /* When casting an lvalue to a reference type, just convert into a pointer to the new type and deference it. This is allowed by San Diego WP section 5.2.9 paragraph 12, though perhaps it should be done directly (jason). (int &)ri ---> *(int*)&ri */ /* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they meant. */ if (TREE_CODE (intype) == POINTER_TYPE && (comptypes (TREE_TYPE (intype), type, COMPARE_BASE | COMPARE_RELAXED ))) cp_warning ("casting `%T' to `%T' does not dereference pointer", intype, reftype); rval = build_unary_op (ADDR_EXPR, expr, 0); if (rval != error_mark_node) rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval, 0); if (rval != error_mark_node) rval = build1 (NOP_EXPR, reftype, rval); } else { rval = convert_for_initialization (NULL_TREE, type, expr, flags, "converting", 0, 0); if (rval == NULL_TREE || rval == error_mark_node) return rval; rval = build_up_reference (reftype, rval, flags); if (rval && ! CP_TYPE_CONST_P (TREE_TYPE (reftype))) cp_pedwarn ("initializing non-const `%T' with `%T' will use a temporary", reftype, intype); } if (rval) { /* If we found a way to convert earlier, then use it. */ return rval; } my_friendly_assert (TREE_CODE (intype) != OFFSET_TYPE, 189); if (flags & LOOKUP_COMPLAIN) cp_error ("cannot convert type `%T' to type `%T'", intype, reftype); if (flags & LOOKUP_SPECULATIVELY) return NULL_TREE; return error_mark_node;}/* We are using a reference VAL for its value. Bash that reference all the way down to its lowest form. */treeconvert_from_reference (val) tree val;{ tree type = TREE_TYPE (val); if (TREE_CODE (type) == OFFSET_TYPE) type = TREE_TYPE (type); if (TREE_CODE (type) == REFERENCE_TYPE) return build_indirect_ref (val, NULL_PTR); return val;}/* 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 (intype == error_mark_node) return error_mark_node; 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_qualified_type (type, CP_TYPE_QUALS (TREE_TYPE (intype))); ptr_type = build_pointer_type (ptr_type); if (same_type_p (ptr_type, TYPE_MAIN_VARIANT (intype))) return expr; my_friendly_assert (!integer_zerop (expr), 191); intype = TYPE_MAIN_VARIANT (TREE_TYPE (intype)); if (TREE_CODE (type) == RECORD_TYPE && TREE_CODE (intype) == RECORD_TYPE && type != intype) { tree path; int distance = get_base_distance (binfo, 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'", 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 (TREE_READONLY_DECL_P (e)) e = decl_constant_value (e); if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP) /* Some internal structures (vtable_entry_type, sigtbl_ptr_type) don't go through finish_struct, so they don't have the synthesized constructors. So don't force a temporary. */ && TYPE_HAS_CONSTRUCTOR (type)) /* We need a new temporary; don't take this shortcut. */; else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e))) { if (same_type_p (type, TREE_TYPE (e))) /* The call to fold will not always remove the NOP_EXPR as might be expected, since if one of the types is a typedef; the comparsion in fold is just equality of pointers, not a call to comptypes. We don't call fold in this case because that can result in infinite recursion; fold will call convert, which will call ocp_convert, etc. */ return e; else return fold (build1 (NOP_EXPR, type, e)); } if (code == VOID_TYPE && (convtype & CONV_STATIC)) { e = require_complete_type_in_void (e); if (e != error_mark_node) e = build1 (CONVERT_EXPR, void_type_node, e); return 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 (INTEGRAL_CODE_P (code)) { tree intype = TREE_TYPE (e); /* enum = enum, enum = int, enum = float, (enum)pointer are all errors. */ if (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 (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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -