📄 cvt.c
字号:
case RESULT_DECL: if (staticp (targ)) literal_flag = 1; TREE_ADDRESSABLE (targ) = 1; put_var_into_stack (targ); break; case PARM_DECL:#if 0 if (targ == current_class_decl) { error ("address of `this' not available");/* #if 0 */ /* This code makes the following core dump the compiler on a sun4, if the code below is used. class e_decl; class a_decl; typedef a_decl* a_ref; class a_s { public: a_s(); void* append(a_ref& item); }; class a_decl { public: a_decl (e_decl *parent); a_s generic_s; a_s decls; e_decl* parent; }; class e_decl { public: e_decl(); a_s implementations; }; void foobar(void *); a_decl::a_decl(e_decl *parent) { parent->implementations.append(this); } */ TREE_ADDRESSABLE (targ) = 1; /* so compiler doesn't die later */ put_var_into_stack (targ); break;/* #else */ return error_mark_node;/* #endif */ }#endif /* Fall through. */ case VAR_DECL: case CONST_DECL: if (DECL_REGISTER (targ) && !TREE_ADDRESSABLE (targ) && !DECL_ARTIFICIAL (targ)) cp_warning ("address needed to build reference for `%D', which is declared `register'", targ); else if (staticp (targ)) literal_flag = 1; TREE_ADDRESSABLE (targ) = 1; put_var_into_stack (targ); break; case COMPOUND_EXPR: { tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 1), LOOKUP_PROTECT, checkconst); rval = build (COMPOUND_EXPR, type, TREE_OPERAND (targ, 0), real_reference); TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 1)); return rval; } case PREINCREMENT_EXPR: case PREDECREMENT_EXPR: case MODIFY_EXPR: case INIT_EXPR: { tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 0), LOOKUP_PROTECT, checkconst); rval = build (COMPOUND_EXPR, type, arg, real_reference); TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 0)); return rval; } case COND_EXPR: return build (COND_EXPR, type, TREE_OPERAND (targ, 0), build_up_reference (type, TREE_OPERAND (targ, 1), LOOKUP_PROTECT, checkconst), build_up_reference (type, TREE_OPERAND (targ, 2), LOOKUP_PROTECT, checkconst)); /* Undo the folding... */ case MIN_EXPR: case MAX_EXPR: return build (COND_EXPR, type, build (TREE_CODE (targ) == MIN_EXPR ? LT_EXPR : GT_EXPR, boolean_type_node, TREE_OPERAND (targ, 0), TREE_OPERAND (targ, 1)), build_up_reference (type, TREE_OPERAND (targ, 0), LOOKUP_PROTECT, checkconst), build_up_reference (type, TREE_OPERAND (targ, 1), LOOKUP_PROTECT, checkconst)); case WITH_CLEANUP_EXPR: return build (WITH_CLEANUP_EXPR, type, build_up_reference (type, TREE_OPERAND (targ, 0), LOOKUP_PROTECT, checkconst), 0, TREE_OPERAND (targ, 2)); case BIND_EXPR: arg = TREE_OPERAND (targ, 1); if (arg == NULL_TREE) { compiler_error ("({ ... }) expression not expanded when needed for reference"); return error_mark_node; } rval = build1 (ADDR_EXPR, type, arg); TREE_REFERENCE_EXPR (rval) = 1; return rval; default: break; } if (TREE_ADDRESSABLE (targ) == 0) { tree temp; if (TREE_CODE (targ) == CALL_EXPR && IS_AGGR_TYPE (argtype)) { temp = build_cplus_new (argtype, targ, 1); if (TREE_CODE (temp) == WITH_CLEANUP_EXPR) rval = build (WITH_CLEANUP_EXPR, type, build1 (ADDR_EXPR, type, TREE_OPERAND (temp, 0)), 0, TREE_OPERAND (temp, 2)); else rval = build1 (ADDR_EXPR, type, temp); goto done; } else { temp = get_temp_name (argtype, 0); if (toplevel_bindings_p ()) { /* Give this new temp some rtl and initialize it. */ DECL_INITIAL (temp) = targ; TREE_STATIC (temp) = 1; cp_finish_decl (temp, targ, NULL_TREE, 0, LOOKUP_ONLYCONVERTING); /* Do this after declaring it static. */ rval = build_unary_op (ADDR_EXPR, temp, 0); TREE_TYPE (rval) = type; literal_flag = TREE_CONSTANT (rval); goto done; } else { rval = build_unary_op (ADDR_EXPR, temp, 0); if (binfo && !BINFO_OFFSET_ZEROP (binfo)) rval = convert_pointer_to (target_type, rval); else TREE_TYPE (rval) = type; temp = build (MODIFY_EXPR, argtype, temp, arg); TREE_SIDE_EFFECTS (temp) = 1; return build (COMPOUND_EXPR, type, temp, rval); } } } else rval = build1 (ADDR_EXPR, type, arg); done: if (TYPE_USES_COMPLEX_INHERITANCE (argtype) || TYPE_USES_COMPLEX_INHERITANCE (target_type)) { TREE_TYPE (rval) = build_pointer_type (argtype); if (flags & LOOKUP_PROTECT) rval = convert_pointer_to (target_type, rval); else rval = convert_to_pointer_force (build_pointer_type (target_type), rval); TREE_TYPE (rval) = type; if (TREE_CODE (rval) == PLUS_EXPR || TREE_CODE (rval) == MINUS_EXPR) TREE_TYPE (TREE_OPERAND (rval, 0)) = TREE_TYPE (TREE_OPERAND (rval, 1)) = type; } TREE_CONSTANT (rval) = literal_flag; 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 (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 (CONVERT_EXPR, type, 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; { int r = TREE_READONLY (expr); int v = TREE_THIS_VOLATILE (expr); ttr = cp_build_type_variant (TREE_TYPE (expr), r, v); } if (! real_lvalue_p (expr) && (decl == NULL_TREE || ! TYPE_READONLY (ttl))) { if (decl) /* Ensure semantics of [dcl.init.ref] */ cp_pedwarn ("initialization of non-const `%T' from rvalue `%T'", reftype, intype); else cp_pedwarn ("conversion to `%T' from rvalue `%T'", reftype, intype); } else if (! (convtype & CONV_CONST)) { if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr)) cp_pedwarn ("conversion from `%T' to `%T' discards const", ttr, reftype); else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr)) cp_pedwarn ("conversion from `%T' to `%T' discards volatile", ttr, reftype); } } return build_up_reference (reftype, expr, flags, ! (convtype & CONV_CONST)); } 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, -1))) 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 if (decl) { tree rval_as_ctor = NULL_TREE; if (rval_as_conversion) { if (rval_as_conversion == error_mark_node) { cp_error ("conversion from `%T' to `%T' is ambiguous", intype, reftype); return error_mark_node; } rval_as_conversion = build_up_reference (reftype, rval_as_conversion, flags, 1); } /* Definitely need to go through a constructor here. */ if (TYPE_HAS_CONSTRUCTOR (type) && ! CLASSTYPE_ABSTRACT_VIRTUALS (type) && (rval = build_method_call (NULL_TREE, constructor_name_full (type), build_tree_list (NULL_TREE, expr), TYPE_BINFO (type), LOOKUP_NO_CONVERSION|LOOKUP_SPECULATIVELY | LOOKUP_ONLYCONVERTING))) { tree init; if (toplevel_bindings_p ()) { extern tree static_aggregates; tree t = get_temp_name (type, toplevel_bindings_p ()); init = build_method_call (t, constructor_name_full (type), build_tree_list (NULL_TREE, expr), TYPE_BINFO (type), LOOKUP_NORMAL|LOOKUP_NO_CONVERSION | LOOKUP_ONLYCONVERTING); if (init == error_mark_node) return error_mark_node; make_decl_rtl (t, NULL_PTR, 1); static_aggregates = perm_tree_cons (expr, t, static_aggregates); rval = build_unary_op (ADDR_EXPR, t, 0); } else { init = build_method_call (NULL_TREE, constructor_name_full (type), build_tree_list (NULL_TREE, expr), TYPE_BINFO (type), LOOKUP_NORMAL|LOOKUP_NO_CONVERSION |LOOKUP_ONLYCONVERTING); if (init == error_mark_node) return error_mark_node; rval = build_cplus_new (type, init, 1); rval = build_up_reference (reftype, rval, flags, 1); } rval_as_ctor = rval; } if (rval_as_ctor && rval_as_conversion) { cp_error ("ambiguous conversion from `%T' to `%T'; both user-defined conversion and constructor apply", intype, reftype); return error_mark_node; } else if (rval_as_ctor) rval = rval_as_ctor; else if (rval_as_conversion) rval = rval_as_conversion; else if (! IS_AGGR_TYPE (type) && ! IS_AGGR_TYPE (intype)) { rval = convert (type, expr); if (rval == error_mark_node) return error_mark_node; rval = build_up_reference (reftype, rval, flags, 1); } if (rval && ! TYPE_READONLY (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;}/* See if there is a constructor of type TYPE which will convert EXPR. The reference manual seems to suggest (8.5.6) that we need not worry about finding constructors for base classes, then converting to the derived class. MSGP is a pointer to a message that would be an appropriate error string. If MSGP is NULL, then we are not interested in reporting errors. */treeconvert_to_aggr (type, expr, msgp, protect) tree type, expr; char **msgp; int protect;{ tree basetype = type; tree name = TYPE_IDENTIFIER (basetype); tree function, fndecl, fntype, parmtypes, parmlist, result; tree method_name; enum access_type access; int can_be_private, can_be_protected; if (! TYPE_HAS_CONSTRUCTOR (basetype)) { if (msgp) *msgp = "type `%s' does not have a constructor"; return error_mark_node; } access = access_public; can_be_private = 0; can_be_protected = IDENTIFIER_CLASS_VALUE (name) || name == current_class_name; parmlist = build_tree_list (NULL_TREE, expr); parmtypes = tree_cons (NULL_TREE, TREE_TYPE (expr), void_list_node); if (TYPE_USES_VIRTUAL_BASECLASSES (basetype)) { parmtypes = tree_cons (NULL_TREE, integer_type_node, parmtypes); parmlist = tree_cons (NULL_TREE, integer_one_node, parmlist); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -