#endif
varpool_reset_queue ();
for (node = cgraph_nodes; node; node = node->next)
- if (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
+ if ((!cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
+ /* Keep around virtual functions for possible devirtualization. */
+ || (!before_inlining_p
+ && !node->global.inlined_to
+ && DECL_VIRTUAL_P (node->decl)
+ && (DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl))))
&& ((!DECL_EXTERNAL (node->decl))
|| before_inlining_p))
{
if (!clone)
{
cgraph_release_function_body (node);
- node->analyzed = false;
node->local.inlinable = false;
+ if (node->prev_sibling_clone)
+ node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
+ else if (node->clone_of)
+ node->clone_of->clones = node->next_sibling_clone;
+ if (node->next_sibling_clone)
+ node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone;
+#ifdef ENABLE_CHECKING
+ if (node->clone_of)
+ node->former_clone_of = node->clone_of->decl;
+#endif
+ node->clone_of = NULL;
+ node->next_sibling_clone = NULL;
+ node->prev_sibling_clone = NULL;
}
else
gcc_assert (!clone->in_other_partition);
+ node->analyzed = false;
cgraph_node_remove_callees (node);
ipa_remove_all_references (&node->ref_list);
- if (node->prev_sibling_clone)
- node->prev_sibling_clone->next_sibling_clone = node->next_sibling_clone;
- else if (node->clone_of)
- node->clone_of->clones = node->next_sibling_clone;
- if (node->next_sibling_clone)
- node->next_sibling_clone->prev_sibling_clone = node->prev_sibling_clone;
- node->clone_of = NULL;
- node->next_sibling_clone = NULL;
- node->prev_sibling_clone = NULL;
}
else
cgraph_remove_node (node);
if (dump_file)
fprintf (dump_file, " %s (read-only)", varpool_node_name (vnode));
TREE_READONLY (vnode->decl) = 1;
- vnode->const_value_known |= varpool_decide_const_value_known (vnode);
}
}
if (dump_file)
return true;
}
}
- if (node->local.used_from_object_file)
+ if (cgraph_used_from_object_file_p (node))
return true;
if (DECL_PRESERVE_P (node->decl))
return true;
struct cgraph_node *alias;
gcc_assert (whole_program || in_lto_p || !TREE_PUBLIC (node->decl));
cgraph_make_decl_local (node->decl);
+ node->resolution = LDPR_PREVAILING_DEF_IRONLY;
for (alias = node->same_body; alias; alias = alias->next)
cgraph_make_decl_local (alias->decl);
if (node->same_comdat_group)
|| ! (ADDR_SPACE_GENERIC_P
(TYPE_ADDR_SPACE (TREE_TYPE (vnode->decl))))))
DECL_COMMON (vnode->decl) = 0;
- /* Even extern variables might have initializers known.
- See, for example testsuite/g++.dg/opt/static3.C */
- vnode->const_value_known |= varpool_decide_const_value_known (vnode);
}
for (vnode = varpool_nodes_queue; vnode; vnode = vnode->next_needed)
{
In this case we do not sed used_from_object_file. */
|| !vnode->finalized))
|| DECL_PRESERVE_P (vnode->decl)
- || vnode->used_from_object_file
+ || varpool_used_from_object_file_p (vnode)
|| pointer_set_contains (aliased_vnodes, vnode)
|| lookup_attribute ("externally_visible",
DECL_ATTRIBUTES (vnode->decl))))
{
gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl));
cgraph_make_decl_local (vnode->decl);
+ vnode->resolution = LDPR_PREVAILING_DEF_IRONLY;
}
- vnode->const_value_known |= varpool_decide_const_value_known (vnode);
gcc_assert (TREE_STATIC (vnode->decl));
}
pointer_set_destroy (aliased_nodes);
they are destructors. */
static void
-build_cdtor (bool ctor_p, tree *cdtors, size_t len)
+build_cdtor (bool ctor_p, VEC (tree, heap) *cdtors)
{
size_t i,j;
+ size_t len = VEC_length (tree, cdtors);
i = 0;
while (i < len)
do
{
priority_type p;
- fn = cdtors[i];
+ fn = VEC_index (tree, cdtors, j);
p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn);
if (j == i)
priority = p;
}
while (j < len);
- /* When there is only once constructor and target supports them, do nothing. */
+ /* When there is only one cdtor and target supports them, do nothing. */
if (j == i + 1
&& targetm.have_ctors_dtors)
{
}
/* Find the next batch of constructors/destructors with the same
initialization priority. */
- do
+ for (;i < j; i++)
{
- priority_type p;
tree call;
- fn = cdtors[i];
- p = ctor_p ? DECL_INIT_PRIORITY (fn) : DECL_FINI_PRIORITY (fn);
- if (p != priority)
- break;
+ fn = VEC_index (tree, cdtors, i);
call = build_call_expr (fn, 0);
if (ctor_p)
DECL_STATIC_CONSTRUCTOR (fn) = 0;
optimizing, we want user to be able to breakpoint in them. */
TREE_SIDE_EFFECTS (call) = 1;
append_to_statement_list (call, &body);
- ++i;
}
while (i < len);
gcc_assert (body != NULL_TREE);
VEC_length (tree, static_ctors),
sizeof (tree),
compare_ctor);
- build_cdtor (/*ctor_p=*/true,
- VEC_address (tree, static_ctors),
- VEC_length (tree, static_ctors));
- VEC_truncate (tree, static_ctors, 0);
+ build_cdtor (/*ctor_p=*/true, static_ctors);
}
if (!VEC_empty (tree, static_dtors))
VEC_length (tree, static_dtors),
sizeof (tree),
compare_dtor);
- build_cdtor (/*ctor_p=*/false,
- VEC_address (tree, static_dtors),
- VEC_length (tree, static_dtors));
- VEC_truncate (tree, static_dtors, 0);
+ build_cdtor (/*ctor_p=*/false, static_dtors);
}
}