aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2014-07-30 13:27:14 -0400
committerJason Merrill <jason@gcc.gnu.org>2014-07-30 13:27:14 -0400
commitd5d0ed2d89a56273efe30331c3e94651134615e7 (patch)
tree043925ba81282b0a865db1992b86c852a51fdf2f /gcc/cp
parentea3e455ac77a67e96a916c4c64249be8e20124cd (diff)
downloadgcc-d5d0ed2d89a56273efe30331c3e94651134615e7.zip
gcc-d5d0ed2d89a56273efe30331c3e94651134615e7.tar.gz
gcc-d5d0ed2d89a56273efe30331c3e94651134615e7.tar.bz2
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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/decl.c11
-rw-r--r--gcc/cp/decl2.c18
-rw-r--r--gcc/cp/method.c5
-rw-r--r--gcc/cp/pt.c10
-rw-r--r--gcc/cp/tree.c14
6 files changed, 47 insertions, 25 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index cfe0a48..3d8bf6d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index aafb917..fd5e2e5 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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;
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 8fa3145..884be0a 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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;
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index e5fa0c1..f86a214 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -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. */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index b32cf6c..0eac771 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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);
}
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index f6c5693..1bfffb8 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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))