From: Jason Merrill Date: Sat, 9 Jul 2011 03:33:44 +0000 (-0400) Subject: cgraph.c (cgraph_add_to_same_comdat_group): New. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2fda8e144a7db5ba6025cfe643da0c6111cc2b0f;p=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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 34ebb0aa9ab..c2d866da6a2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2011-07-08 Jason Merrill + + * 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 PR bootstrap/49680 diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 86e72072eab..09aad60c4d2 100644 --- a/gcc/cgraph.c +++ b/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 diff --git a/gcc/cgraph.h b/gcc/cgraph.h index 91339230a16..5d6ff7caf61 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -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); diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 41157a1de83..3f776b097ad 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2011-07-08 Jason Merrill + * 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. diff --git a/gcc/cp/method.c b/gcc/cp/method.c index d41a4dd4238..3d272a33f61 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -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, diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c index b9e3551b40c..6a069880398 100644 --- a/gcc/cp/optimize.c +++ b/gcc/cp/optimize.c @@ -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; } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 5c53a18511c..84b0dd8559f 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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); diff --git a/gcc/ipa.c b/gcc/ipa.c index 5b09250d661..9d54811e5c9 100644 --- a/gcc/ipa.c +++ b/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;