value_type infer_binary_type(object_converter factory, node_type &left, node_type &right) { value_type rt = right->infer_type(factory); value_type lt = left->infer_type(factory); if (lt == type_multi || rt == type_multi) { if (lt == rt) return type_tbd; if (lt == type_multi) lt = left->infer_type(factory, rt); else rt = right->infer_type(factory, lt); } if (lt == rt) return lt; if (type_is_float(lt) && type_is_int(rt)) rt = right->infer_type(factory, lt); if (type_is_float(rt) && type_is_int(lt)) lt = left->infer_type(factory, rt); if (lt == rt) return lt; if (rt == type_invalid || lt == type_invalid) return type_invalid; if (rt == type_tbd && lt == type_tbd) return type_tbd; if (factory->can_convert(rt, lt)) { right = add_convert_node(right, lt); return lt; } if (factory->can_convert(lt, rt)) { left = add_convert_node(left, rt); return rt; } if (can_convert(rt, lt)) { right = add_convert_node(right, lt); return lt; } if (can_convert(lt, rt)) { left = add_convert_node(left, rt); return rt; } factory->error("Cannot compare " + left->to_string() + " to " + right->to_string() + " (" + type_to_string(lt) + " to " + type_to_string(rt) + ")"); return type_invalid; }
tree convert_to_reference (tree reftype, tree expr, int convtype, int flags, tree decl) { tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype)); tree intype; tree rval = NULL_TREE; tree rval_as_conversion = NULL_TREE; bool can_convert_intype_to_type; if (TREE_CODE (type) == FUNCTION_TYPE && TREE_TYPE (expr) == unknown_type_node) expr = instantiate_type (type, expr, (flags & LOOKUP_COMPLAIN) ? tf_warning_or_error : tf_none); if (expr == error_mark_node) return error_mark_node; intype = TREE_TYPE (expr); gcc_assert (TREE_CODE (intype) != REFERENCE_TYPE); gcc_assert (TREE_CODE (reftype) == REFERENCE_TYPE); intype = TYPE_MAIN_VARIANT (intype); can_convert_intype_to_type = can_convert (type, intype); if (!can_convert_intype_to_type && (convtype & CONV_IMPLICIT) && MAYBE_CLASS_TYPE_P (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); 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; can_convert_intype_to_type = 1; } } if (((convtype & CONV_STATIC) && can_convert (intype, type)) || ((convtype & CONV_IMPLICIT) && can_convert_intype_to_type)) { if (flags & LOOKUP_COMPLAIN) { tree ttl = TREE_TYPE (reftype); tree ttr = lvalue_type (expr); if (! real_lvalue_p (expr)) warn_ref_binding (reftype, intype, decl); if (! (convtype & CONV_CONST) && !at_least_as_qualified_p (ttl, ttr)) permerror (input_location, "conversion from %qT to %qT discards qualifiers", ttr, reftype); } return build_up_reference (reftype, expr, flags, decl); } 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_DERIVED))) warning (0, "casting %qT to %qT does not dereference pointer", intype, reftype); rval = cp_build_unary_op (ADDR_EXPR, expr, 0, tf_warning_or_error); 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, tf_warning_or_error); if (rval == NULL_TREE || rval == error_mark_node) return rval; warn_ref_binding (reftype, intype, decl); rval = build_up_reference (reftype, rval, flags, decl); } if (rval) { /* If we found a way to convert earlier, then use it. */ return rval; } if (flags & LOOKUP_COMPLAIN) error ("cannot convert type %qT to type %qT", intype, reftype); return error_mark_node; }