mirror of git://gcc.gnu.org/git/gcc.git
cgraph.c (cgraph_add_to_same_comdat_group): New.
gcc/ * cgraph.c (cgraph_add_to_same_comdat_group): New. * cgraph.h: Declare it. * ipa.c (function_and_variable_visibility): Make sure thunks have the right visibility. gcc/cp/ * method.c (use_thunk): Use cgraph_add_to_same_comdat_group. * optimize.c (maybe_clone_body): Likewise. * semantics.c (maybe_add_lambda_conv_op): Likewise. From-SVN: r176071
This commit is contained in:
parent
e8f8774a90
commit
2fda8e144a
|
|
@ -1,3 +1,10 @@
|
|||
2011-07-08 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* cgraph.c (cgraph_add_to_same_comdat_group): New.
|
||||
* cgraph.h: Declare it.
|
||||
* ipa.c (function_and_variable_visibility): Make sure thunks
|
||||
have the right visibility.
|
||||
|
||||
2011-07-08 Richard Henderson <rth@redhat.com>
|
||||
|
||||
PR bootstrap/49680
|
||||
|
|
|
|||
25
gcc/cgraph.c
25
gcc/cgraph.c
|
|
@ -1630,6 +1630,31 @@ cgraph_remove_node (struct cgraph_node *node)
|
|||
free_nodes = node;
|
||||
}
|
||||
|
||||
/* Add NEW_ to the same comdat group that OLD is in. */
|
||||
|
||||
void
|
||||
cgraph_add_to_same_comdat_group (struct cgraph_node *new_,
|
||||
struct cgraph_node *old)
|
||||
{
|
||||
gcc_assert (DECL_ONE_ONLY (old->decl));
|
||||
gcc_assert (!new_->same_comdat_group);
|
||||
gcc_assert (new_ != old);
|
||||
|
||||
DECL_COMDAT_GROUP (new_->decl) = DECL_COMDAT_GROUP (old->decl);
|
||||
new_->same_comdat_group = old;
|
||||
if (!old->same_comdat_group)
|
||||
old->same_comdat_group = new_;
|
||||
else
|
||||
{
|
||||
struct cgraph_node *n;
|
||||
for (n = old->same_comdat_group;
|
||||
n->same_comdat_group != old;
|
||||
n = n->same_comdat_group)
|
||||
;
|
||||
n->same_comdat_group = new_;
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove the node from cgraph. */
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -469,6 +469,7 @@ void debug_cgraph_node (struct cgraph_node *);
|
|||
void cgraph_insert_node_to_hashtable (struct cgraph_node *node);
|
||||
void cgraph_remove_edge (struct cgraph_edge *);
|
||||
void cgraph_remove_node (struct cgraph_node *);
|
||||
void cgraph_add_to_same_comdat_group (struct cgraph_node *, struct cgraph_node *);
|
||||
void cgraph_remove_node_and_inline_clones (struct cgraph_node *);
|
||||
void cgraph_release_function_body (struct cgraph_node *);
|
||||
void cgraph_node_remove_callees (struct cgraph_node *node);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
2011-07-08 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* method.c (use_thunk): Use cgraph_add_to_same_comdat_group.
|
||||
* optimize.c (maybe_clone_body): Likewise.
|
||||
* semantics.c (maybe_add_lambda_conv_op): Likewise.
|
||||
|
||||
PR c++/45603
|
||||
* decl.c (expand_static_init): Don't get confused by user
|
||||
declaration of __cxa_guard_acquire.
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
|
|||
tree virtual_offset;
|
||||
HOST_WIDE_INT fixed_offset, virtual_value;
|
||||
bool this_adjusting = DECL_THIS_THUNK_P (thunk_fndecl);
|
||||
struct cgraph_node *funcn;
|
||||
struct cgraph_node *funcn, *thunk_node;
|
||||
|
||||
/* We should have called finish_thunk to give it a name. */
|
||||
gcc_assert (DECL_NAME (thunk_fndecl));
|
||||
|
|
@ -344,8 +344,7 @@ use_thunk (tree thunk_fndecl, bool emit_p)
|
|||
DECL_VISIBILITY_SPECIFIED (thunk_fndecl)
|
||||
= DECL_VISIBILITY_SPECIFIED (function);
|
||||
DECL_COMDAT (thunk_fndecl) = DECL_COMDAT (function);
|
||||
if (DECL_ONE_ONLY (function) || DECL_WEAK (function))
|
||||
make_decl_one_only (thunk_fndecl, cxx_comdat_group (thunk_fndecl));
|
||||
DECL_WEAK (thunk_fndecl) = DECL_WEAK (function);
|
||||
|
||||
if (flag_syntax_only)
|
||||
{
|
||||
|
|
@ -386,9 +385,11 @@ use_thunk (tree thunk_fndecl, bool emit_p)
|
|||
TREE_ASM_WRITTEN (thunk_fndecl) = 1;
|
||||
funcn = cgraph_get_node (function);
|
||||
gcc_checking_assert (funcn);
|
||||
cgraph_add_thunk (funcn, thunk_fndecl, function,
|
||||
this_adjusting, fixed_offset, virtual_value,
|
||||
virtual_offset, alias);
|
||||
thunk_node = cgraph_add_thunk (funcn, thunk_fndecl, function,
|
||||
this_adjusting, fixed_offset, virtual_value,
|
||||
virtual_offset, alias);
|
||||
if (DECL_ONE_ONLY (function))
|
||||
cgraph_add_to_same_comdat_group (thunk_node, funcn);
|
||||
|
||||
if (!this_adjusting
|
||||
|| !targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset,
|
||||
|
|
|
|||
|
|
@ -309,12 +309,12 @@ maybe_clone_body (tree fn)
|
|||
&& (!DECL_ONE_ONLY (fns[0])
|
||||
|| (HAVE_COMDAT_GROUP
|
||||
&& DECL_WEAK (fns[0])))
|
||||
&& (flag_syntax_only
|
||||
/* Set linkage flags appropriately before
|
||||
cgraph_create_function_alias looks at them. */
|
||||
|| (expand_or_defer_fn_1 (clone)
|
||||
&& cgraph_same_body_alias (cgraph_get_node (fns[0]),
|
||||
clone, fns[0]))))
|
||||
&& !flag_syntax_only
|
||||
/* Set linkage flags appropriately before
|
||||
cgraph_create_function_alias looks at them. */
|
||||
&& expand_or_defer_fn_1 (clone)
|
||||
&& cgraph_same_body_alias (cgraph_get_node (fns[0]),
|
||||
clone, fns[0]))
|
||||
{
|
||||
alias = true;
|
||||
if (DECL_ONE_ONLY (fns[0]))
|
||||
|
|
@ -324,13 +324,22 @@ maybe_clone_body (tree fn)
|
|||
*[CD][12]*. */
|
||||
comdat_group = cdtor_comdat_group (fns[1], fns[0]);
|
||||
DECL_COMDAT_GROUP (fns[0]) = comdat_group;
|
||||
cgraph_add_to_same_comdat_group (cgraph_get_node (clone),
|
||||
cgraph_get_node (fns[0]));
|
||||
}
|
||||
}
|
||||
|
||||
/* Build the delete destructor by calling complete destructor
|
||||
and delete function. */
|
||||
if (idx == 2)
|
||||
build_delete_destructor_body (clone, fns[1]);
|
||||
{
|
||||
build_delete_destructor_body (clone, fns[1]);
|
||||
/* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
|
||||
virtual, it goes into the same comdat group as well. */
|
||||
if (comdat_group)
|
||||
cgraph_add_to_same_comdat_group (cgraph_get_create_node (clone),
|
||||
cgraph_get_node (fns[0]));
|
||||
}
|
||||
else if (alias)
|
||||
/* No need to populate body. */ ;
|
||||
else
|
||||
|
|
@ -419,24 +428,6 @@ maybe_clone_body (tree fn)
|
|||
}
|
||||
pop_from_top_level ();
|
||||
|
||||
if (comdat_group)
|
||||
{
|
||||
DECL_COMDAT_GROUP (fns[1]) = comdat_group;
|
||||
if (fns[2])
|
||||
{
|
||||
struct cgraph_node *base_dtor_node, *deleting_dtor_node;
|
||||
/* If *[CD][12]* dtors go into the *[CD]5* comdat group and dtor is
|
||||
virtual, it goes into the same comdat group as well. */
|
||||
DECL_COMDAT_GROUP (fns[2]) = comdat_group;
|
||||
base_dtor_node = cgraph_get_node (fns[0]);
|
||||
deleting_dtor_node = cgraph_get_node (fns[2]);
|
||||
gcc_assert (base_dtor_node->same_comdat_group == NULL);
|
||||
gcc_assert (deleting_dtor_node->same_comdat_group == NULL);
|
||||
base_dtor_node->same_comdat_group = deleting_dtor_node;
|
||||
deleting_dtor_node->same_comdat_group = base_dtor_node;
|
||||
}
|
||||
}
|
||||
|
||||
/* We don't need to process the original function any further. */
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8880,14 +8880,8 @@ maybe_add_lambda_conv_op (tree type)
|
|||
if (DECL_ONE_ONLY (statfn))
|
||||
{
|
||||
/* Put the thunk in the same comdat group as the call op. */
|
||||
struct cgraph_node *callop_node, *thunk_node;
|
||||
DECL_COMDAT_GROUP (statfn) = cxx_comdat_group (callop);
|
||||
callop_node = cgraph_get_create_node (callop);
|
||||
thunk_node = cgraph_get_create_node (statfn);
|
||||
gcc_assert (callop_node->same_comdat_group == NULL);
|
||||
gcc_assert (thunk_node->same_comdat_group == NULL);
|
||||
callop_node->same_comdat_group = thunk_node;
|
||||
thunk_node->same_comdat_group = callop_node;
|
||||
cgraph_add_to_same_comdat_group (cgraph_get_create_node (statfn),
|
||||
cgraph_get_create_node (callop));
|
||||
}
|
||||
body = begin_function_body ();
|
||||
compound_stmt = begin_compound_stmt (0);
|
||||
|
|
|
|||
29
gcc/ipa.c
29
gcc/ipa.c
|
|
@ -865,31 +865,14 @@ function_and_variable_visibility (bool whole_program)
|
|||
decl_node = cgraph_function_node (decl_node->callees->callee, NULL);
|
||||
|
||||
/* Thunks have the same visibility as function they are attached to.
|
||||
For some reason C++ frontend don't seem to care. I.e. in
|
||||
g++.dg/torture/pr41257-2.C the thunk is not comdat while function
|
||||
it is attached to is.
|
||||
|
||||
We also need to arrange the thunk into the same comdat group as
|
||||
the function it reffers to. */
|
||||
Make sure the C++ front end set this up properly. */
|
||||
if (DECL_ONE_ONLY (decl_node->decl))
|
||||
{
|
||||
DECL_COMDAT (node->decl) = DECL_COMDAT (decl_node->decl);
|
||||
DECL_COMDAT_GROUP (node->decl) = DECL_COMDAT_GROUP (decl_node->decl);
|
||||
if (DECL_ONE_ONLY (decl_node->decl) && !node->same_comdat_group)
|
||||
{
|
||||
node->same_comdat_group = decl_node;
|
||||
if (!decl_node->same_comdat_group)
|
||||
decl_node->same_comdat_group = node;
|
||||
else
|
||||
{
|
||||
struct cgraph_node *n;
|
||||
for (n = decl_node->same_comdat_group;
|
||||
n->same_comdat_group != decl_node;
|
||||
n = n->same_comdat_group)
|
||||
;
|
||||
n->same_comdat_group = node;
|
||||
}
|
||||
}
|
||||
gcc_checking_assert (DECL_COMDAT (node->decl)
|
||||
== DECL_COMDAT (decl_node->decl));
|
||||
gcc_checking_assert (DECL_COMDAT_GROUP (node->decl)
|
||||
== DECL_COMDAT_GROUP (decl_node->decl));
|
||||
gcc_checking_assert (node->same_comdat_group);
|
||||
}
|
||||
if (DECL_EXTERNAL (decl_node->decl))
|
||||
DECL_EXTERNAL (node->decl) = 1;
|
||||
|
|
|
|||
Loading…
Reference in New Issue