===================================================================
@@ -968,3 +975,33 @@ lto_symtab_merge_symbols (void)
}
}
}
+
+/* Virtual tables may matter for code generation even if they are not
+ directly refernced by the code because they may be used for devirtualizaiton.
+ For this reason it is important to merge even virtual tables that have no
+ associated symbol table entries. Without doing so we lose optimization
+ oppurtunities by losing track of the vtable constructor.
+ FIXME: we probably ought to introduce explicit symbol table entries for
+ those before streaming. */
+
+tree
+lto_symtab_prevailing_virtual_decl (tree decl)
+{
+ gcc_checking_assert (!type_in_anonymous_namespace_p (DECL_CONTEXT (decl))
+ && DECL_ASSEMBLER_NAME_SET_P (decl));
+
+ symtab_node *n = symtab_node::get_for_asmname
+ (DECL_ASSEMBLER_NAME (decl));
+ while (n && ((!DECL_EXTERNAL (n->decl) && !TREE_PUBLIC (n->decl))
+ || !DECL_VIRTUAL_P (n->decl)))
+ n = n->next_sharing_asm_name;
+ if (n)
+ {
+ lto_symtab_prevail_decl (n->decl, decl);
+ decl = n->decl;
+ }
+ else
+ symtab_node::get_create (decl);
+
+ return decl;
+}
===================================================================
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3.
extern void lto_symtab_merge_decls (void);
extern void lto_symtab_merge_symbols (void);
extern tree lto_symtab_prevailing_decl (tree decl);
+extern tree lto_symtab_prevailing_virtual_decl (tree decl);
/* Mark DECL to be previailed by PREVAILING.
Use DECL_ABSTRACT_ORIGIN and DECL_CHAIN as special markers; those do not
@@ -31,6 +32,7 @@ inline void
lto_symtab_prevail_decl (tree prevailing, tree decl)
{
gcc_checking_assert (DECL_ABSTRACT_ORIGIN (decl) != error_mark_node);
+ gcc_assert (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl));
DECL_CHAIN (decl) = prevailing;
DECL_ABSTRACT_ORIGIN (decl) = error_mark_node;
}
@@ -43,5 +45,12 @@ lto_symtab_prevailing_decl (tree decl)
if (DECL_ABSTRACT_ORIGIN (decl) == error_mark_node)
return DECL_CHAIN (decl);
else
- return decl;
+ {
+ if ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
+ && DECL_VIRTUAL_P (decl)
+ && (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl))
+ && !symtab_node::get (decl))
+ return lto_symtab_prevailing_virtual_decl (decl);
+ return decl;
+ }
}