@@ -2342,6 +2342,7 @@ cgraph_create_virtual_clone (struct cgraph_node *old_node,
TREE_PUBLIC (new_node->decl) = 0;
DECL_COMDAT (new_node->decl) = 0;
DECL_WEAK (new_node->decl) = 0;
+ DECL_VIRTUAL_P (new_node->decl) = 0;
new_node->clone.tree_map = tree_map;
new_node->clone.args_to_skip = args_to_skip;
FOR_EACH_VEC_ELT (ipa_replace_map_p, tree_map, i, map)
@@ -912,6 +912,7 @@ cgraph_only_called_directly_p (struct cgraph_node *node)
gcc_assert (!node->global.inlined_to);
return (!node->needed && !node->address_taken
&& !node->reachable_from_other_partition
+ && !DECL_VIRTUAL_P (node->decl)
&& !DECL_STATIC_CONSTRUCTOR (node->decl)
&& !DECL_STATIC_DESTRUCTOR (node->decl)
&& !node->local.externally_visible);
@@ -243,8 +243,7 @@ cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
those only after all devirtualizable virtual calls are processed.
Lacking may edges in callgraph we just preserve them post
inlining. */
- && (!DECL_VIRTUAL_P (e->callee->decl)
- || (!DECL_COMDAT (e->callee->decl) && !DECL_EXTERNAL (e->callee->decl)))
+ && !DECL_VIRTUAL_P (e->callee->decl)
/* Don't reuse if more than one function shares a comdat group.
If the other function(s) are needed, we need to emit even
this function out of line. */
@@ -235,9 +235,7 @@ cgraph_remove_unreachable_nodes (bool before_inlining_p, FILE *file)
if (node->analyzed && !node->global.inlined_to
&& (!cgraph_can_remove_if_no_direct_calls_and_refs_p (node)
/* Keep around virtual functions for possible devirtualization. */
- || (before_inlining_p
- && DECL_VIRTUAL_P (node->decl)
- && (DECL_COMDAT (node->decl) || DECL_EXTERNAL (node->decl)))
+ || (before_inlining_p && DECL_VIRTUAL_P (node->decl))
/* Also external functions with address taken are better to stay
for indirect inlining. */
|| (before_inlining_p
new file mode 100644
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-early-inlining -fno-weak" } */
+
+struct S
+{
+ S();
+ virtual inline void foo ()
+ {
+ foo();
+ }
+};
+
+void
+B ()
+{
+ S().foo ();
+}