I was playing around with this a few months ago but set it aside because
we weren't in stage 1 at the time. The way we currently set up comdat
groups early means that we need to mangle decls early, significantly
negating the earlier work to lazily set DECL_ASSEMBLER_NAME. This patch
improves this situation by allowing a DECL to be used as
DECL_COMDAT_GROUP in cases where the group name is the same as the
mangled name of the declaration.
Tested x86_64-pc-linux-gnu. OK for trunk?
commit 6f9182ed91a88bb993fe137f6decc15b25f466fd
Author: Jason Merrill <ja...@redhat.com>
Date: Mon May 19 15:41:24 2014 -0400
PR c++/47202
gcc/cp/
* decl.c (cxx_comdat_group): Return a decl.
* optimize.c (cdtor_comdat_group): Get its DECL_ASSEMBLER_NAME.
gcc/
* cgraphunit.c (analyze_functions): Convert all DECL_COMDAT_GROUPs
to IDENTIFIER_NODEs.
* tree.h (DECL_COMDAT_GROUP_ID): New.
* lto-streamer-out.c (write_symbol): Use it.
* symtab.c (dump_symtab_node): Likewise.
* trans-mem.c (ipa_tm_create_version_alias): Likewise.
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index f5d9594..044af45 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -943,6 +943,14 @@ analyze_functions (void)
cgraph_state = CGRAPH_STATE_CONSTRUCTION;
input_location = UNKNOWN_LOCATION;
+ /* Convert all COMDAT group designators to IDENTIFIER_NODEs while we still
+ have front end information. */
+ FOR_EACH_SYMBOL (node)
+ if (DECL_COMDAT_GROUP (node->decl)
+ && DECL_P (DECL_COMDAT_GROUP (node->decl)))
+ DECL_COMDAT_GROUP (node->decl)
+ = DECL_ASSEMBLER_NAME (DECL_COMDAT_GROUP (node->decl));
+
/* Ugly, but the fixup can not happen at a time same body alias is created;
C++ FE is confused about the COMDAT groups being right. */
if (cpp_implicit_aliases_done)
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index a29e3e3..2d6b6cf 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -14443,18 +14443,17 @@ cp_missing_noreturn_ok_p (tree decl)
return DECL_MAIN_P (decl);
}
-/* Return the COMDAT group into which DECL should be placed. */
+/* Return the decl used to identify the COMDAT group into which DECL should
+ be placed. */
tree
cxx_comdat_group (tree decl)
{
- tree name;
-
/* Virtual tables, construction virtual tables, and virtual table
tables all go in a single COMDAT group, named after the primary
virtual table. */
if (VAR_P (decl) && DECL_VTABLE_OR_VTT_P (decl))
- name = DECL_ASSEMBLER_NAME (CLASSTYPE_VTABLES (DECL_CONTEXT (decl)));
+ decl = CLASSTYPE_VTABLES (DECL_CONTEXT (decl));
/* For all other DECLs, the COMDAT group is the mangled name of the
declaration itself. */
else
@@ -14472,10 +14471,9 @@ cxx_comdat_group (tree decl)
else
break;
}
- name = DECL_ASSEMBLER_NAME (decl);
}
- return name;
+ return decl;
}
/* Returns the return type for FN as written by the user, which may include
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index b089432..0d9a68a 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -170,6 +170,8 @@ cdtor_comdat_group (tree complete, tree base)
complete_name = cxx_comdat_group (complete);
if (base_name == NULL)
base_name = cxx_comdat_group (base);
+ complete_name = DECL_ASSEMBLER_NAME (complete_name);
+ base_name = DECL_ASSEMBLER_NAME (base_name);
gcc_assert (IDENTIFIER_LENGTH (complete_name)
== IDENTIFIER_LENGTH (base_name));
grp_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (complete_name) + 1);
diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c
index 6f2bf9c..9da79fa 100644
--- a/gcc/lto-streamer-out.c
+++ b/gcc/lto-streamer-out.c
@@ -2331,7 +2331,7 @@ write_symbol (struct streamer_tree_cache_d *cache,
size = 0;
if (DECL_ONE_ONLY (t))
- comdat = IDENTIFIER_POINTER (DECL_COMDAT_GROUP (t));
+ comdat = IDENTIFIER_POINTER (DECL_COMDAT_GROUP_ID (t));
else
comdat = "";
diff --git a/gcc/symtab.c b/gcc/symtab.c
index 6b9b77a..bc13667 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -641,7 +641,7 @@ dump_symtab_base (FILE *f, symtab_node *node)
fprintf (f, " comdat");
if (DECL_COMDAT_GROUP (node->decl))
fprintf (f, " comdat_group:%s",
- IDENTIFIER_POINTER (DECL_COMDAT_GROUP (node->decl)));
+ IDENTIFIER_POINTER (DECL_COMDAT_GROUP_ID (node->decl)));
if (DECL_ONE_ONLY (node->decl))
fprintf (f, " one_only");
if (DECL_SECTION_NAME (node->decl))
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index f73f454..1da02ab 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -4852,7 +4852,7 @@ ipa_tm_create_version_alias (struct cgraph_node *node, void *data)
/* Perform the same remapping to the comdat group. */
if (DECL_ONE_ONLY (new_decl))
- DECL_COMDAT_GROUP (new_decl) = tm_mangle (DECL_COMDAT_GROUP (old_decl));
+ DECL_COMDAT_GROUP (new_decl) = tm_mangle (DECL_COMDAT_GROUP_ID (old_decl));
new_node = cgraph_same_body_alias (NULL, new_decl, info->new_decl);
new_node->tm_clone = true;
diff --git a/gcc/tree.h b/gcc/tree.h
index f9c2ca9..6c34153 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2322,9 +2322,18 @@ extern void decl_value_expr_insert (tree, tree);
#define DECL_COMDAT(NODE) \
(DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.comdat_flag)
+/* When the target supports COMDAT groups, this indicates which group the
+ DECL is associated with. This can be either an IDENTIFIER_NODE or a
+ decl, in which case its DECL_ASSEMBLER_NAME identifies the group. */
#define DECL_COMDAT_GROUP(NODE) \
(DECL_WITH_VIS_CHECK (NODE)->decl_with_vis.comdat_group)
+/* The identifier for the COMDAT group. */
+#define DECL_COMDAT_GROUP_ID(NODE) \
+ (DECL_COMDAT_GROUP (NODE) && DECL_P (DECL_COMDAT_GROUP (NODE)) \
+ ? DECL_ASSEMBLER_NAME (DECL_COMDAT_GROUP (NODE)) \
+ : DECL_COMDAT_GROUP (NODE))
+
/* Used in TREE_PUBLIC decls to indicate that copies of this DECL in
multiple translation units should be merged. */
#define DECL_ONE_ONLY(NODE) (DECL_COMDAT_GROUP (NODE) != NULL_TREE)