Commit f13fe18b by Jan Hubicka Committed by Jan Hubicka

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
parent 06c3ddc0
2016-04-15 Jan Hubicka <jh@suse.cz>
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.
2016-04-15 Kirill Yukhin <kirill.yukhin@intel.com> 2016-04-15 Kirill Yukhin <kirill.yukhin@intel.com>
PR target/70662 PR target/70662
......
...@@ -2209,19 +2209,36 @@ cgraph_node::unnest (void) ...@@ -2209,19 +2209,36 @@ cgraph_node::unnest (void)
/* Return function availability. See cgraph.h for description of individual /* Return function availability. See cgraph.h for description of individual
return values. */ return values. */
enum availability 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; enum availability avail;
if (!analyzed) if (!analyzed)
avail = AVAIL_NOT_AVAILABLE; avail = AVAIL_NOT_AVAILABLE;
else if (local.local) else if (local.local)
avail = AVAIL_LOCAL; avail = AVAIL_LOCAL;
else if (global.inlined_to)
avail = AVAIL_AVAILABLE;
else if (transparent_alias) else if (transparent_alias)
ultimate_alias_target (&avail); ultimate_alias_target (&avail, ref);
else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl))) else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
avail = AVAIL_INTERPOSABLE; avail = AVAIL_INTERPOSABLE;
else if (!externally_visible) else if (!externally_visible)
avail = AVAIL_AVAILABLE; 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 /* Inline functions are safe to be analyzed even if their symbol can
be overwritten at runtime. It is not meaningful to enforce any sane be overwritten at runtime. It is not meaningful to enforce any sane
behavior on replacing inline function by different body. */ behavior on replacing inline function by different body. */
...@@ -2232,11 +2249,7 @@ cgraph_node::get_availability (void) ...@@ -2232,11 +2249,7 @@ cgraph_node::get_availability (void)
care at least of two notable extensions - the COMDAT functions care at least of two notable extensions - the COMDAT functions
used to share template instantiations in C++ (this is symmetric used to share template instantiations in C++ (this is symmetric
to code cp_cannot_inline_tree_fn and probably shall be shared and to code cp_cannot_inline_tree_fn and probably shall be shared and
the inlinability hooks completely eliminated). 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. */
else if (decl_replaceable_p (decl) && !DECL_EXTERNAL (decl)) else if (decl_replaceable_p (decl) && !DECL_EXTERNAL (decl))
avail = AVAIL_INTERPOSABLE; avail = AVAIL_INTERPOSABLE;
...@@ -3250,24 +3263,28 @@ cgraph_node::verify_cgraph_nodes (void) ...@@ -3250,24 +3263,28 @@ cgraph_node::verify_cgraph_nodes (void)
/* Walk the alias chain to return the function cgraph_node is alias of. /* Walk the alias chain to return the function cgraph_node is alias of.
Walk through thunks, too. 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 *
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) while (node->thunk.thunk_p)
{ {
ref = node;
node = node->callees->callee; node = node->callees->callee;
if (availability) if (availability)
{ {
enum availability a; enum availability a;
a = node->get_availability (); a = node->get_availability (ref);
if (a < *availability) if (a < *availability)
*availability = a; *availability = a;
} }
node = node->ultimate_alias_target (availability); node = node->ultimate_alias_target (availability, ref);
} }
return node; return node;
} }
...@@ -3275,25 +3292,29 @@ cgraph_node::function_symbol (enum availability *availability) ...@@ -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 the alias chain to return the function cgraph_node is alias of.
Walk through non virtual thunks, too. Thus we return either a function Walk through non virtual thunks, too. Thus we return either a function
or a virtual thunk node. 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 *
cgraph_node::function_or_virtual_thunk_symbol 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) while (node->thunk.thunk_p && !node->thunk.virtual_offset_p)
{ {
ref = node;
node = node->callees->callee; node = node->callees->callee;
if (availability) if (availability)
{ {
enum availability a; enum availability a;
a = node->get_availability (); a = node->get_availability (ref);
if (a < *availability) if (a < *availability)
*availability = a; *availability = a;
} }
node = node->ultimate_alias_target (availability); node = node->ultimate_alias_target (availability, ref);
} }
return node; return node;
} }
......
...@@ -242,8 +242,11 @@ public: ...@@ -242,8 +242,11 @@ public:
/* Walk the alias chain to return the symbol NODE is alias of. /* Walk the alias chain to return the symbol NODE is alias of.
If NODE is not an alias, return NODE. If NODE is not an alias, return NODE.
When AVAILABILITY is non-NULL, get minimal availability in the chain. */ When AVAILABILITY is non-NULL, get minimal availability in the chain.
symtab_node *ultimate_alias_target (enum availability *avail = NULL); When REF is non-NULL, assume that reference happens in symbol REF
when determining the availability. */
symtab_node *ultimate_alias_target (enum availability *avail = NULL,
struct symtab_node *ref = NULL);
/* Return next reachable static symbol with initializer after NODE. */ /* Return next reachable static symbol with initializer after NODE. */
inline symtab_node *next_defined_symbol (void); inline symtab_node *next_defined_symbol (void);
...@@ -287,8 +290,13 @@ public: ...@@ -287,8 +290,13 @@ public:
/* Return the initialization priority. */ /* Return the initialization priority. */
priority_type get_init_priority (); priority_type get_init_priority ();
/* Return availability of NODE. */ /* Return availability of NODE when referenced from REF. */
enum availability get_availability (void); enum availability get_availability (symtab_node *ref = NULL);
/* Return true if NODE binds to current definition in final executable
when referenced from REF. If REF is NULL return conservative value
for any reference. */
bool binds_to_current_def_p (symtab_node *ref = NULL);
/* Make DECL local. */ /* Make DECL local. */
void make_decl_local (void); void make_decl_local (void);
...@@ -595,7 +603,8 @@ private: ...@@ -595,7 +603,8 @@ private:
static bool noninterposable_alias (symtab_node *node, void *data); static bool noninterposable_alias (symtab_node *node, void *data);
/* Worker for ultimate_alias_target. */ /* Worker for ultimate_alias_target. */
symtab_node *ultimate_alias_target_1 (enum availability *avail = NULL); symtab_node *ultimate_alias_target_1 (enum availability *avail = NULL,
symtab_node *ref = NULL);
}; };
inline void inline void
...@@ -867,15 +876,21 @@ public: ...@@ -867,15 +876,21 @@ public:
/* Walk the alias chain to return the function cgraph_node is alias of. /* Walk the alias chain to return the function cgraph_node is alias of.
Walk through thunk, too. Walk through thunk, too.
When AVAILABILITY is non-NULL, get minimal availability in the chain. */ When AVAILABILITY is non-NULL, get minimal availability in the chain.
cgraph_node *function_symbol (enum availability *avail = NULL); When REF is non-NULL, assume that reference happens in symbol REF
when determining the availability. */
cgraph_node *function_symbol (enum availability *avail = NULL,
struct symtab_node *ref = NULL);
/* Walk the alias chain to return the function cgraph_node is alias of. /* 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 Walk through non virtual thunks, too. Thus we return either a function
or a virtual thunk node. 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 *function_or_virtual_thunk_symbol cgraph_node *function_or_virtual_thunk_symbol
(enum availability *avail = NULL); (enum availability *avail = NULL,
struct symtab_node *ref = NULL);
/* Create node representing clone of N executed COUNT times. Decrease /* Create node representing clone of N executed COUNT times. Decrease
the execution counts from original node too. the execution counts from original node too.
...@@ -974,9 +989,12 @@ public: ...@@ -974,9 +989,12 @@ public:
/* Given function symbol, walk the alias chain to return the function node /* Given function symbol, walk the alias chain to return the function node
is alias of. Do not walk through thunks. is alias of. Do not walk through thunks.
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 *ultimate_alias_target (availability *availability = NULL); cgraph_node *ultimate_alias_target (availability *availability = NULL,
symtab_node *ref = NULL);
/* Expand thunk NODE to gimple if possible. /* Expand thunk NODE to gimple if possible.
When FORCE_GIMPLE_THUNK is true, gimple thunk is created and When FORCE_GIMPLE_THUNK is true, gimple thunk is created and
...@@ -1089,7 +1107,7 @@ public: ...@@ -1089,7 +1107,7 @@ public:
/* Return function availability. See cgraph.h for description of individual /* Return function availability. See cgraph.h for description of individual
return values. */ return values. */
enum availability get_availability (void); enum availability get_availability (symtab_node *ref = NULL);
/* Set TREE_NOTHROW on cgraph_node's decl and on aliases of the node /* Set TREE_NOTHROW on cgraph_node's decl and on aliases of the node
if any to NOTHROW. */ if any to NOTHROW. */
...@@ -1689,6 +1707,9 @@ struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"), ...@@ -1689,6 +1707,9 @@ struct GTY((chain_next ("%h.next_caller"), chain_prev ("%h.prev_caller"),
type. */ type. */
unsigned in_polymorphic_cdtor : 1; unsigned in_polymorphic_cdtor : 1;
/* Return true if call must bind to current definition. */
bool binds_to_current_def_p ();
private: private:
/* Remove the edge from the list of the callers of the callee. */ /* Remove the edge from the list of the callers of the callee. */
void remove_caller (void); void remove_caller (void);
...@@ -1731,7 +1752,7 @@ public: ...@@ -1731,7 +1752,7 @@ public:
void analyze (void); void analyze (void);
/* Return variable availability. */ /* Return variable availability. */
availability get_availability (void); availability get_availability (symtab_node *ref = NULL);
/* When doing LTO, read variable's constructor from disk if /* When doing LTO, read variable's constructor from disk if
it is not already present. */ it is not already present. */
...@@ -1742,9 +1763,11 @@ public: ...@@ -1742,9 +1763,11 @@ public:
/* For given variable pool node, walk the alias chain to return the function /* For given variable pool node, walk the alias chain to return the function
the variable is alias of. Do not walk through thunks. the variable is alias of. Do not walk through thunks.
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. */
inline varpool_node *ultimate_alias_target inline varpool_node *ultimate_alias_target
(availability *availability = NULL); (availability *availability = NULL, symtab_node *ref = NULL);
/* Return node that alias is aliasing. */ /* Return node that alias is aliasing. */
inline varpool_node *get_alias_target (void); inline varpool_node *get_alias_target (void);
...@@ -2888,30 +2911,36 @@ varpool_node::get_alias_target (void) ...@@ -2888,30 +2911,36 @@ varpool_node::get_alias_target (void)
/* Walk the alias chain to return the symbol NODE is alias of. /* Walk the alias chain to return the symbol NODE is alias of.
If NODE is not an alias, return NODE. If NODE is not an alias, return 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. */
inline symtab_node * inline symtab_node *
symtab_node::ultimate_alias_target (enum availability *availability) symtab_node::ultimate_alias_target (enum availability *availability,
symtab_node *ref)
{ {
if (!alias) if (!alias)
{ {
if (availability) if (availability)
*availability = get_availability (); *availability = get_availability (ref);
return this; return this;
} }
return ultimate_alias_target_1 (availability); return ultimate_alias_target_1 (availability, ref);
} }
/* Given function symbol, walk the alias chain to return the function node /* Given function symbol, walk the alias chain to return the function node
is alias of. Do not walk through thunks. is alias of. Do not walk through thunks.
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. */
inline cgraph_node * inline cgraph_node *
cgraph_node::ultimate_alias_target (enum availability *availability) cgraph_node::ultimate_alias_target (enum availability *availability,
symtab_node *ref)
{ {
cgraph_node *n = dyn_cast <cgraph_node *> cgraph_node *n = dyn_cast <cgraph_node *>
(symtab_node::ultimate_alias_target (availability)); (symtab_node::ultimate_alias_target (availability, ref));
if (!n && availability) if (!n && availability)
*availability = AVAIL_NOT_AVAILABLE; *availability = AVAIL_NOT_AVAILABLE;
return n; return n;
...@@ -2919,13 +2948,16 @@ cgraph_node::ultimate_alias_target (enum availability *availability) ...@@ -2919,13 +2948,16 @@ cgraph_node::ultimate_alias_target (enum availability *availability)
/* For given variable pool node, walk the alias chain to return the function /* For given variable pool node, walk the alias chain to return the function
the variable is alias of. Do not walk through thunks. the variable is alias of. Do not walk through thunks.
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. */
inline varpool_node * inline varpool_node *
varpool_node::ultimate_alias_target (availability *availability) varpool_node::ultimate_alias_target (availability *availability,
symtab_node *ref)
{ {
varpool_node *n = dyn_cast <varpool_node *> varpool_node *n = dyn_cast <varpool_node *>
(symtab_node::ultimate_alias_target (availability)); (symtab_node::ultimate_alias_target (availability, ref));
if (!n && availability) if (!n && availability)
*availability = AVAIL_NOT_AVAILABLE; *availability = AVAIL_NOT_AVAILABLE;
...@@ -2985,6 +3017,17 @@ cgraph_edge::remove_callee (void) ...@@ -2985,6 +3017,17 @@ cgraph_edge::remove_callee (void)
callee->callers = next_caller; callee->callers = next_caller;
} }
/* Return true if call must bind to current definition. */
inline bool
cgraph_edge::binds_to_current_def_p ()
{
if (callee)
return callee->binds_to_current_def_p (caller);
else
return NULL;
}
/* Return true if the TM_CLONE bit is set for a given FNDECL. */ /* Return true if the TM_CLONE bit is set for a given FNDECL. */
static inline bool static inline bool
decl_is_tm_clone (const_tree fndecl) decl_is_tm_clone (const_tree fndecl)
...@@ -3030,15 +3073,15 @@ symtab_node::get_create (tree node) ...@@ -3030,15 +3073,15 @@ symtab_node::get_create (tree node)
return cgraph_node::get_create (node); return cgraph_node::get_create (node);
} }
/* Return availability of NODE. */ /* Return availability of NODE when referenced from REF. */
inline enum availability inline enum availability
symtab_node::get_availability (void) symtab_node::get_availability (symtab_node *ref)
{ {
if (is_a <cgraph_node *> (this)) if (is_a <cgraph_node *> (this))
return dyn_cast <cgraph_node *> (this)->get_availability (); return dyn_cast <cgraph_node *> (this)->get_availability (ref);
else else
return dyn_cast <varpool_node *> (this)->get_availability (); return dyn_cast <varpool_node *> (this)->get_availability (ref);
} }
/* Call calback on symtab node and aliases associated to this node. /* Call calback on symtab node and aliases associated to this node.
......
...@@ -1347,7 +1347,8 @@ symtab_node::copy_visibility_from (symtab_node *n) ...@@ -1347,7 +1347,8 @@ symtab_node::copy_visibility_from (symtab_node *n)
Assumes NODE is known to be alias. */ Assumes NODE is known to be alias. */
symtab_node * symtab_node *
symtab_node::ultimate_alias_target_1 (enum availability *availability) symtab_node::ultimate_alias_target_1 (enum availability *availability,
symtab_node *ref)
{ {
bool transparent_p = false; bool transparent_p = false;
...@@ -1368,7 +1369,7 @@ symtab_node::ultimate_alias_target_1 (enum availability *availability) ...@@ -1368,7 +1369,7 @@ symtab_node::ultimate_alias_target_1 (enum availability *availability)
{ {
transparent_p = transparent_alias; transparent_p = transparent_alias;
if (!transparent_p) if (!transparent_p)
*availability = get_availability (); *availability = get_availability (ref);
else else
*availability = AVAIL_NOT_AVAILABLE; *availability = AVAIL_NOT_AVAILABLE;
} }
...@@ -1383,7 +1384,7 @@ symtab_node::ultimate_alias_target_1 (enum availability *availability) ...@@ -1383,7 +1384,7 @@ symtab_node::ultimate_alias_target_1 (enum availability *availability)
if (!availability || (!transparent_p && node->analyzed)) if (!availability || (!transparent_p && node->analyzed))
; ;
else if (node->analyzed && !node->transparent_alias) else if (node->analyzed && !node->transparent_alias)
*availability = node->get_availability (); *availability = node->get_availability (ref);
else else
*availability = AVAIL_NOT_AVAILABLE; *availability = AVAIL_NOT_AVAILABLE;
return node; return node;
...@@ -1391,7 +1392,7 @@ symtab_node::ultimate_alias_target_1 (enum availability *availability) ...@@ -1391,7 +1392,7 @@ symtab_node::ultimate_alias_target_1 (enum availability *availability)
if (node && availability && transparent_p if (node && availability && transparent_p
&& node->transparent_alias) && node->transparent_alias)
{ {
*availability = node->get_availability (); *availability = node->get_availability (ref);
transparent_p = false; transparent_p = false;
} }
} }
...@@ -2206,3 +2207,58 @@ symbol_table::symbol_suffix_separator () ...@@ -2206,3 +2207,58 @@ symbol_table::symbol_suffix_separator ()
return '_'; return '_';
#endif #endif
} }
/* Return true when references to this symbol from REF must bind to current
definition in final executable. */
bool
symtab_node::binds_to_current_def_p (symtab_node *ref)
{
if (!definition)
return false;
if (decl_binds_to_current_def_p (decl))
return true;
/* Inline clones always binds locally. */
cgraph_node *cnode = dyn_cast <cgraph_node *> (this);
if (cnode && cnode->global.inlined_to)
return true;
if (DECL_EXTERNAL (decl))
return false;
if (!externally_visible)
debug ();
gcc_assert (externally_visible);
if (ref)
{
cgraph_node *cref = dyn_cast <cgraph_node *> (ref);
if (cref)
ref = cref->global.inlined_to;
}
/* 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. This is important
to optimize recursive functions well.
This assumption may be broken by inlining: if symbol is interposable
but the body is available (i.e. declared inline), inliner may make
the body reachable even with interposition. */
if (this == ref && !has_aliases_p ()
&& (!cnode
|| symtab->state >= IPA_SSA_AFTER_INLINING
|| get_availability () >= AVAIL_INTERPOSABLE))
return true;
/* References within one comdat group are always bound in a group. */
if (ref
&& symtab->state >= IPA_SSA_AFTER_INLINING
&& get_comdat_group ()
&& get_comdat_group () == ref->get_comdat_group ())
return true;
return false;
}
...@@ -482,7 +482,7 @@ varpool_node::add (tree decl) ...@@ -482,7 +482,7 @@ varpool_node::add (tree decl)
/* Return variable availability. See cgraph.h for description of individual /* Return variable availability. See cgraph.h for description of individual
return values. */ return values. */
enum availability enum availability
varpool_node::get_availability (void) varpool_node::get_availability (symtab_node *ref)
{ {
if (!definition) if (!definition)
return AVAIL_NOT_AVAILABLE; return AVAIL_NOT_AVAILABLE;
...@@ -495,9 +495,16 @@ varpool_node::get_availability (void) ...@@ -495,9 +495,16 @@ varpool_node::get_availability (void)
{ {
enum availability avail; enum availability avail;
ultimate_alias_target (&avail); ultimate_alias_target (&avail, ref);
return avail; return avail;
} }
/* 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. */
if ((this == ref && !has_aliases_p ())
|| (ref && get_comdat_group ()
&& get_comdat_group () == ref->get_comdat_group ()))
return AVAIL_AVAILABLE;
/* If the variable can be overwritten, return OVERWRITABLE. Takes /* If the variable can be overwritten, return OVERWRITABLE. Takes
care of at least one notable extension - the COMDAT variables care of at least one notable extension - the COMDAT variables
used to share template instantiations in C++. */ used to share template instantiations in C++. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment