bool vfy_is_assignable_from (vfy_jclass target, vfy_jclass source) { /* Any class is always assignable to itself, or java.lang.Object. */ if (source == target || target == object_type_node) return true; /* For the C++ ABI, perform this test statically. */ if (! flag_indirect_dispatch) return can_widen_reference_to (source, target); /* For the BC-ABI, we assume at compile time that reference types are always compatible. However, a type assertion table entry is emitted so that the runtime can detect binary-incompatible changes. */ add_type_assertion (current_class, JV_ASSERT_TYPES_COMPATIBLE, source, target); return true; }
static tree merge_types (tree type1, tree type2) { if (type1 == type2) return type1; if (type1 == TYPE_UNKNOWN || type2 == TYPE_UNKNOWN || type1 == TYPE_RETURN_ADDR || type2 == TYPE_RETURN_ADDR) return TYPE_UNKNOWN; if (TREE_CODE (type1) == POINTER_TYPE && TREE_CODE (type2) == POINTER_TYPE) { int depth1, depth2; tree tt1, tt2; /* ptr_type_node is only used for a null reference, which is compatible with any reference type. */ if (type1 == ptr_type_node || type2 == object_ptr_type_node) return type2; if (type2 == ptr_type_node || type1 == object_ptr_type_node) return type1; tt1 = TREE_TYPE (type1); tt2 = TREE_TYPE (type2); /* If tt{1,2} haven't been properly loaded, now is a good time to do it. */ if (!TYPE_SIZE (tt1)) { load_class (tt1, 1); safe_layout_class (tt1); } if (!TYPE_SIZE (tt2)) { load_class (tt2, 1); safe_layout_class (tt2); } if (TYPE_ARRAY_P (tt1) || TYPE_ARRAY_P (tt2)) { if (TYPE_ARRAY_P (tt1) == TYPE_ARRAY_P (tt2)) { tree el_type1 = TYPE_ARRAY_ELEMENT (tt1); tree el_type2 = TYPE_ARRAY_ELEMENT (tt2); tree el_type = NULL_TREE; if (el_type1 == el_type2) el_type = el_type1; else if (TREE_CODE (el_type1) == POINTER_TYPE && TREE_CODE (el_type2) == POINTER_TYPE) el_type = merge_types (el_type1, el_type2); if (el_type != NULL_TREE) { HOST_WIDE_INT len1 = java_array_type_length (tt1); HOST_WIDE_INT len2 = java_array_type_length (tt2); if (len1 != len2) len1 = -1; else if (el_type1 == el_type2) return type1; return promote_type (build_java_array_type (el_type, len1)); } } return object_ptr_type_node; } if (CLASS_INTERFACE (TYPE_NAME (tt1))) { /* FIXME: should see if two interfaces have a common superinterface. */ if (CLASS_INTERFACE (TYPE_NAME (tt2))) { /* This is a kludge, but matches what Sun's verifier does. It can be tricked, but is safe as long as type errors (i.e. interface method calls) are caught at run-time. */ return object_ptr_type_node; } else { if (can_widen_reference_to (tt2, tt1)) return type1; else return object_ptr_type_node; } } else if (CLASS_INTERFACE (TYPE_NAME (tt2))) { if (can_widen_reference_to (tt1, tt2)) return type2; else return object_ptr_type_node; } type1 = tt1; type2 = tt2; depth1 = class_depth (type1); depth2 = class_depth (type2); for ( ; depth1 > depth2; depth1--) type1 = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (type1), 0)); for ( ; depth2 > depth1; depth2--) type2 = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (type2), 0)); while (type1 != type2) { type1 = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (type1), 0)); type2 = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (type2), 0)); } return promote_type (type1); } if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2) && TYPE_PRECISION (type1) <= 32 && TYPE_PRECISION (type2) <= 32) return int_type_node; return TYPE_UNKNOWN; }