diff options
author | Jan Hubicka <jh@suse.cz> | 2016-04-16 18:30:48 +0200 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2016-04-16 16:30:48 +0000 |
commit | f13fe18b5b4881a457c2176214349d322b61e187 (patch) | |
tree | 4cef7161787b418b3d579ca1e2fc6cd70a647584 /gcc/cgraph.c | |
parent | 06c3ddc04956997f9a45769cf44cc85f013e0245 (diff) | |
download | gcc-f13fe18b5b4881a457c2176214349d322b61e187.zip gcc-f13fe18b5b4881a457c2176214349d322b61e187.tar.gz gcc-f13fe18b5b4881a457c2176214349d322b61e187.tar.bz2 |
re PR c++/70018 (Possible issue around IPO and C++ comdats discovered as pure/const)
PR ipa/70018
* cgraph.c (cgraph_node::get_availability): Add REF parameter.
(cgraph_node::function_symbol): Likewise.
(cgraph_node::function_or_virtual_thunk_symbol): Likewise.
* cgraph.h (symtab_node::get_availabbility): Add REF parameter.
(symtab_node::ultimate_alias_target): Add REF parameter.
(symtab_node::binds_to_current_def_p): Declare.
(symtab_node;:ultimate_alias_target_1): Add REF parameter.
(cgraph_node::function_symbol): Likewise.
(cgraph_node::function_or_virtual_thunk_symbol): Likewise.
(cgraph_node::get_availability): Likewise.
(cgraph_edge::binds_to_current_def_p): New inline function.
(varpool_node::get_availability): Add REF parameter.
(varpool_node::ultimate_alias_target): Likewise.
* symtab.c (symtab_node::ultimate_alias_target_1): Likewise.
(symtab_node::binds_to_current_def_p): Likewise.
* varpool.c (varpool_node::get_availability): Likewise.
From-SVN: r235063
Diffstat (limited to 'gcc/cgraph.c')
-rw-r--r-- | gcc/cgraph.c | 55 |
1 files changed, 38 insertions, 17 deletions
diff --git a/gcc/cgraph.c b/gcc/cgraph.c index 4804081..0ced2db 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -2209,19 +2209,36 @@ cgraph_node::unnest (void) /* Return function availability. See cgraph.h for description of individual return values. */ enum availability -cgraph_node::get_availability (void) +cgraph_node::get_availability (symtab_node *ref) { + if (ref) + { + cgraph_node *cref = dyn_cast <cgraph_node *> (ref); + if (cref) + ref = cref->global.inlined_to; + } enum availability avail; if (!analyzed) avail = AVAIL_NOT_AVAILABLE; else if (local.local) avail = AVAIL_LOCAL; + else if (global.inlined_to) + avail = AVAIL_AVAILABLE; else if (transparent_alias) - ultimate_alias_target (&avail); + ultimate_alias_target (&avail, ref); else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl))) avail = AVAIL_INTERPOSABLE; else if (!externally_visible) avail = AVAIL_AVAILABLE; + /* If this is a reference from symbol itself and there are no aliases, we + may be sure that the symbol was not interposed by soemthing else because + the symbol itself would be unreachable otherwise. + + Also comdat groups are always resolved in groups. */ + else if ((this == ref && !has_aliases_p ()) + || (ref && get_comdat_group () + && get_comdat_group () == ref->get_comdat_group ())) + avail = AVAIL_AVAILABLE; /* Inline functions are safe to be analyzed even if their symbol can be overwritten at runtime. It is not meaningful to enforce any sane behavior on replacing inline function by different body. */ @@ -2232,11 +2249,7 @@ cgraph_node::get_availability (void) care at least of two notable extensions - the COMDAT functions used to share template instantiations in C++ (this is symmetric to code cp_cannot_inline_tree_fn and probably shall be shared and - the inlinability hooks completely eliminated). - - ??? Does the C++ one definition rule allow us to always return - AVAIL_AVAILABLE here? That would be good reason to preserve this - bit. */ + the inlinability hooks completely eliminated). */ else if (decl_replaceable_p (decl) && !DECL_EXTERNAL (decl)) avail = AVAIL_INTERPOSABLE; @@ -3250,24 +3263,28 @@ cgraph_node::verify_cgraph_nodes (void) /* Walk the alias chain to return the function cgraph_node is alias of. Walk through thunks, too. - When AVAILABILITY is non-NULL, get minimal availability in the chain. */ + When AVAILABILITY is non-NULL, get minimal availability in the chain. + When REF is non-NULL, assume that reference happens in symbol REF + when determining the availability. */ cgraph_node * -cgraph_node::function_symbol (enum availability *availability) +cgraph_node::function_symbol (enum availability *availability, + struct symtab_node *ref) { - cgraph_node *node = ultimate_alias_target (availability); + cgraph_node *node = ultimate_alias_target (availability, ref); while (node->thunk.thunk_p) { + ref = node; node = node->callees->callee; if (availability) { enum availability a; - a = node->get_availability (); + a = node->get_availability (ref); if (a < *availability) *availability = a; } - node = node->ultimate_alias_target (availability); + node = node->ultimate_alias_target (availability, ref); } return node; } @@ -3275,25 +3292,29 @@ cgraph_node::function_symbol (enum availability *availability) /* Walk the alias chain to return the function cgraph_node is alias of. Walk through non virtual thunks, too. Thus we return either a function or a virtual thunk node. - When AVAILABILITY is non-NULL, get minimal availability in the chain. */ + When AVAILABILITY is non-NULL, get minimal availability in the chain. + When REF is non-NULL, assume that reference happens in symbol REF + when determining the availability. */ cgraph_node * cgraph_node::function_or_virtual_thunk_symbol - (enum availability *availability) + (enum availability *availability, + struct symtab_node *ref) { - cgraph_node *node = ultimate_alias_target (availability); + cgraph_node *node = ultimate_alias_target (availability, ref); while (node->thunk.thunk_p && !node->thunk.virtual_offset_p) { + ref = node; node = node->callees->callee; if (availability) { enum availability a; - a = node->get_availability (); + a = node->get_availability (ref); if (a < *availability) *availability = a; } - node = node->ultimate_alias_target (availability); + node = node->ultimate_alias_target (availability, ref); } return node; } |