re PR lto/53808 (Undefined symbol when building a library with lto)

PR lto/53808
	PR c++/61659
	* pt.c (push_template_decl_real): Set DECL_COMDAT on templates.
	(check_explicit_specialization): Clear it on specializations.
	* decl.c (duplicate_decls, start_decl): Likewise.
	(grokmethod, grokfndecl): Set DECL_COMDAT on inlines.
	* method.c (implicitly_declare_fn): Set DECL_COMDAT.  Determine
	linkage after setting the appropriate flags.
	* tree.c (decl_linkage): Don't check DECL_COMDAT.
	* decl2.c (mark_needed): Mark clones.
	(import_export_decl): Not here.

From-SVN: r213307
This commit is contained in:
Jason Merrill 2014-07-30 13:27:14 -04:00 committed by Jason Merrill
parent ea3e455ac7
commit d5d0ed2d89
7 changed files with 50 additions and 29 deletions

View File

@ -1,3 +1,17 @@
2014-07-30 Jason Merrill <jason@redhat.com>
PR lto/53808
PR c++/61659
* pt.c (push_template_decl_real): Set DECL_COMDAT on templates.
(check_explicit_specialization): Clear it on specializations.
* decl.c (duplicate_decls, start_decl): Likewise.
(grokmethod, grokfndecl): Set DECL_COMDAT on inlines.
* method.c (implicitly_declare_fn): Set DECL_COMDAT. Determine
linkage after setting the appropriate flags.
* tree.c (decl_linkage): Don't check DECL_COMDAT.
* decl2.c (mark_needed): Mark clones.
(import_export_decl): Not here.
2014-07-25 Edward Smith-Rowland <3dw4rd@verizon.net>
Implement N4051 - Allow typename in a template template parameter

View File

@ -2197,6 +2197,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
olddecl);
SET_DECL_TEMPLATE_SPECIALIZATION (olddecl);
DECL_COMDAT (newdecl) = DECL_DECLARED_INLINE_P (olddecl);
/* Don't propagate visibility from the template to the
specialization here. We'll do that in determine_visibility if
@ -4683,6 +4684,10 @@ start_decl (const cp_declarator *declarator,
if (DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
{
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
if (TREE_CODE (decl) == FUNCTION_DECL)
DECL_COMDAT (decl) = DECL_DECLARED_INLINE_P (decl);
else
DECL_COMDAT (decl) = false;
/* [temp.expl.spec] An explicit specialization of a static data
member of a template is a definition if the declaration
@ -7663,7 +7668,10 @@ grokfndecl (tree ctype,
/* If the declaration was declared inline, mark it as such. */
if (inlinep)
DECL_DECLARED_INLINE_P (decl) = 1;
{
DECL_DECLARED_INLINE_P (decl) = 1;
DECL_COMDAT (decl) = 1;
}
if (inlinep & 2)
DECL_DECLARED_CONSTEXPR_P (decl) = true;
@ -14223,6 +14231,7 @@ grokmethod (cp_decl_specifier_seq *declspecs,
check_template_shadow (fndecl);
DECL_COMDAT (fndecl) = 1;
DECL_DECLARED_INLINE_P (fndecl) = 1;
DECL_NO_INLINE_WARNING_P (fndecl) = 1;

View File

@ -1930,6 +1930,12 @@ mark_needed (tree decl)
definition. */
struct cgraph_node *node = cgraph_node::get_create (decl);
node->forced_by_abi = true;
/* #pragma interface and -frepo code can call mark_needed for
maybe-in-charge 'tors; mark the clones as well. */
tree clone;
FOR_EACH_CLONE (clone, decl)
mark_needed (clone);
}
else if (TREE_CODE (decl) == VAR_DECL)
{
@ -2728,17 +2734,7 @@ import_export_decl (tree decl)
{
/* The repository indicates that this entity should be defined
here. Make sure the back end honors that request. */
if (VAR_P (decl))
mark_needed (decl);
else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl)
|| DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
{
tree clone;
FOR_EACH_CLONE (clone, decl)
mark_needed (clone);
}
else
mark_needed (decl);
mark_needed (decl);
/* Output the definition as an ordinary strong definition. */
DECL_EXTERNAL (decl) = 0;
DECL_INTERFACE_KNOWN (decl) = 1;

View File

@ -1798,8 +1798,6 @@ implicitly_declare_fn (special_function_kind kind, tree type,
DECL_ARGUMENTS (fn) = this_parm;
grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL);
set_linkage_according_to_type (type, fn);
rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof);
DECL_IN_AGGR_P (fn) = 1;
DECL_ARTIFICIAL (fn) = 1;
DECL_DEFAULTED_FN (fn) = 1;
@ -1811,6 +1809,9 @@ implicitly_declare_fn (special_function_kind kind, tree type,
DECL_EXTERNAL (fn) = true;
DECL_NOT_REALLY_EXTERN (fn) = 1;
DECL_DECLARED_INLINE_P (fn) = 1;
DECL_COMDAT (fn) = 1;
set_linkage_according_to_type (type, fn);
rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof);
gcc_assert (!TREE_USED (fn));
/* Restore PROCESSING_TEMPLATE_DECL. */

View File

@ -2787,6 +2787,9 @@ check_explicit_specialization (tree declarator,
It's just the name of an instantiation. But, it's not
a request for an instantiation, either. */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
else
/* A specialization is not necessarily COMDAT. */
DECL_COMDAT (decl) = DECL_DECLARED_INLINE_P (decl);
/* Register this specialization so that we can find it
again. */
@ -5017,6 +5020,13 @@ template arguments to %qD do not match original template %qD",
DECL_TEMPLATE_INFO (decl) = info;
}
if (flag_implicit_templates
&& VAR_OR_FUNCTION_DECL_P (decl))
/* Set DECL_COMDAT on template instantiations; if we force
them to be emitted by explicit instantiation or -frepo,
mark_needed will tell cgraph to do the right thing. */
DECL_COMDAT (decl) = true;
return DECL_TEMPLATE_RESULT (tmpl);
}

View File

@ -3722,23 +3722,15 @@ decl_linkage (tree decl)
if (TREE_CODE (decl) == CONST_DECL)
return decl_linkage (TYPE_NAME (DECL_CONTEXT (decl)));
/* Some things that are not TREE_PUBLIC have external linkage, too.
For example, on targets that don't have weak symbols, we make all
template instantiations have internal linkage (in the object
file), but the symbols should still be treated as having external
linkage from the point of view of the language. */
if (VAR_OR_FUNCTION_DECL_P (decl)
&& DECL_COMDAT (decl))
return lk_external;
/* Things in local scope do not have linkage, if they don't have
TREE_PUBLIC set. */
if (decl_function_context (decl))
return lk_none;
/* Members of the anonymous namespace also have TREE_PUBLIC unset, but
are considered to have external linkage for language purposes. DECLs
really meant to have internal linkage have DECL_THIS_STATIC set. */
are considered to have external linkage for language purposes, as do
template instantiations on targets without weak symbols. DECLs really
meant to have internal linkage have DECL_THIS_STATIC set. */
if (TREE_CODE (decl) == TYPE_DECL)
return lk_external;
if (VAR_OR_FUNCTION_DECL_P (decl))

View File

@ -1,8 +1,7 @@
// PR lto/53808
// Devirtualization + inlining should produce a non-virtual
// call to ~foo.
// { dg-options "-O -fdevirtualize" }
// { dg-final { scan-assembler "_ZN3fooD2Ev" } }
// Devirtualization should not produce an external ref to ~bar.
// { dg-options "-O2" }
// { dg-final { scan-assembler-not "_ZN3barD0Ev" } }
struct foo {
virtual ~foo();