static void record_target_from_binfo (vec <cgraph_node *> &nodes, tree binfo, tree otr_type, tree type_binfo, HOST_WIDE_INT otr_token, tree outer_type, HOST_WIDE_INT offset, pointer_set_t *inserted, pointer_set_t *matched_vtables, bool anonymous) { tree type = BINFO_TYPE (binfo); int i; tree base_binfo; gcc_checking_assert (BINFO_VTABLE (type_binfo)); if (types_same_for_odr (type, outer_type)) { tree inner_binfo = get_binfo_at_offset (type_binfo, offset, otr_type); /* For types in anonymous namespace first check if the respective vtable is alive. If not, we know the type can't be called. */ if (!flag_ltrans && anonymous) { tree vtable = BINFO_VTABLE (inner_binfo); struct varpool_node *vnode; if (TREE_CODE (vtable) == POINTER_PLUS_EXPR) vtable = TREE_OPERAND (TREE_OPERAND (vtable, 0), 0); vnode = varpool_get_node (vtable); if (!vnode || !vnode->definition) return; } gcc_assert (inner_binfo); if (!pointer_set_insert (matched_vtables, BINFO_VTABLE (inner_binfo))) { tree target = gimple_get_virt_method_for_binfo (otr_token, inner_binfo); if (target) maybe_record_node (nodes, target, inserted, NULL); } return; } /* Walk bases. */ for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) /* Walking bases that have no virtual method is pointless excercise. */ if (polymorphic_type_binfo_p (base_binfo)) record_target_from_binfo (nodes, base_binfo, otr_type, /* In the case of single inheritance, the virtual table is shared with the outer type. */ BINFO_VTABLE (base_binfo) ? base_binfo : type_binfo, otr_token, outer_type, offset, inserted, matched_vtables, anonymous); }
static bool ipcp_copy_types (struct ipa_node_params *caller_info, struct ipa_node_params *callee_info, int callee_idx, struct ipa_jump_func *jf) { int caller_idx, j, count; bool res; if (ipa_param_cannot_devirtualize_p (callee_info, callee_idx)) return false; if (jf->type == IPA_JF_PASS_THROUGH) { if (jf->value.pass_through.operation != NOP_EXPR) { ipa_set_param_cannot_devirtualize (callee_info, callee_idx); return true; } caller_idx = jf->value.pass_through.formal_id; } else caller_idx = jf->value.ancestor.formal_id; if (ipa_param_cannot_devirtualize_p (caller_info, caller_idx)) { ipa_set_param_cannot_devirtualize (callee_info, callee_idx); return true; } if (!caller_info->params[caller_idx].types) return false; res = false; count = VEC_length (tree, caller_info->params[caller_idx].types); for (j = 0; j < count; j++) { tree binfo = VEC_index (tree, caller_info->params[caller_idx].types, j); if (jf->type == IPA_JF_ANCESTOR) { binfo = get_binfo_at_offset (binfo, jf->value.ancestor.offset, jf->value.ancestor.type); if (!binfo) { ipa_set_param_cannot_devirtualize (callee_info, callee_idx); return true; } } res |= ipcp_add_param_type (callee_info, callee_idx, binfo); } return res; }