+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
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
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
/* 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;
check_template_shadow (fndecl);
+ DECL_COMDAT (fndecl) = 1;
DECL_DECLARED_INLINE_P (fndecl) = 1;
DECL_NO_INLINE_WARNING_P (fndecl) = 1;
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)
{
{
/* 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;
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;
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. */
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. */
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);
}
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))
// 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();