re PR lto/61886 (LTO breaks fread with _FORTIFY_SOURCE=2)

PR ipa/61886
	* symtab.c (ultimate_transparent_alias_target): New inline function.
	(symbol_table::assembler_names_equal_p): New method; break out from ...
	(symbol_table::decl_assembler_name_equal): ... here.
	(symbol_table::change_decl_assembler_name): Also update names and
	translation links of transparent aliases.
	(symtab_node::dump_base): Dump transparent_alias.
	(symtab_node::verify_base): Implement basic transparent alias
	verification.
	(symtab_node::make_decl_local): Support localization of weakrefs;
	recurse to transparent aliases; set TREE_STATIC.
	(symtab_node::ultimate_alias_target_1): Handle visibility of
	transparent aliases.
	(symtab_node::resolve_alias): New parmaeter transparent; handle
	transparent aliases; recurse to aliases of aliases to fix comdat
	groups.
	(symtab_node::get_partitioning_class): Handle transparent aliases.
	* ipa-visibility.c (cgraph_externally_visible_p,
	varpool_node::externally_visible_p): Visibility of transparent alias
	depends on its target.
	(function_and_variable_visibility): Do not tweak visibility of
	transparent laiases.
	(function_and_variable_visibility): Likewise.
	* ipa.c (symbol_table::remove_unreachable_nodes): Clear
	transparent_alias flag.
	* alias.c (cgraph_node::create_alias, cgraph_node::get_availability):
	Support transparent aliases.
	* cgraph.h (symtab_node): Update prototype of resolve_alias;
	add transparent_alias flag.
	(symbol_table: Add assembler_names_equal_p.
	(symtab_node::real_symbol_p): Skip transparent aliases.
	* cgraphunit.c (cgraph_node::reset): Reset transparent_alias flag.
	(handle_alias_pairs): Set transparent_alias for weakref.
	(cgraph_node::assemble_thunks_and_aliases): Do not asemble transparent
	aliases.
	* lto-cgraph.c (lto_output_node): When outputting same_comdat_group
	skip symbols not put into boundary; stream transparent_alias.
	(lto_output_varpool_node): Likewise.
	(input_overwrite_node, input_varpool_node): Stream transparent alias.
	* varpool.c (ctor_for_folding, varpool_node::get_availability,
	varpool_node::assemble_aliases,
	symbol_table::remove_unreferenced_decls): Handle transparent aliase.
	(varpool_node::create_alias): Set transparent_alias.

	* lto-partition.c (add_symbol_to_partition_1, contained_in_symbol,
	rename_statics, rename_statics): Handle transparent aliases.

From-SVN: r231373
This commit is contained in:
Jan Hubicka 2015-12-07 18:36:54 +01:00 committed by Jan Hubicka
parent 058c6384fe
commit 71e546870c
12 changed files with 387 additions and 135 deletions

View File

@ -1,3 +1,49 @@
2015-12-07 Jan Hubicka <hubicka@ucw.cz>
PR ipa/61886
* symtab.c (ultimate_transparent_alias_target): New inline function.
(symbol_table::assembler_names_equal_p): New method; break out from ...
(symbol_table::decl_assembler_name_equal): ... here.
(symbol_table::change_decl_assembler_name): Also update names and
translation links of transparent aliases.
(symtab_node::dump_base): Dump transparent_alias.
(symtab_node::verify_base): Implement basic transparent alias
verification.
(symtab_node::make_decl_local): Support localization of weakrefs;
recurse to transparent aliases; set TREE_STATIC.
(symtab_node::ultimate_alias_target_1): Handle visibility of
transparent aliases.
(symtab_node::resolve_alias): New parmaeter transparent; handle
transparent aliases; recurse to aliases of aliases to fix comdat
groups.
(symtab_node::get_partitioning_class): Handle transparent aliases.
* ipa-visibility.c (cgraph_externally_visible_p,
varpool_node::externally_visible_p): Visibility of transparent alias
depends on its target.
(function_and_variable_visibility): Do not tweak visibility of
transparent laiases.
(function_and_variable_visibility): Likewise.
* ipa.c (symbol_table::remove_unreachable_nodes): Clear
transparent_alias flag.
* alias.c (cgraph_node::create_alias, cgraph_node::get_availability):
Support transparent aliases.
* cgraph.h (symtab_node): Update prototype of resolve_alias;
add transparent_alias flag.
(symbol_table: Add assembler_names_equal_p.
(symtab_node::real_symbol_p): Skip transparent aliases.
* cgraphunit.c (cgraph_node::reset): Reset transparent_alias flag.
(handle_alias_pairs): Set transparent_alias for weakref.
(cgraph_node::assemble_thunks_and_aliases): Do not asemble transparent
aliases.
* lto-cgraph.c (lto_output_node): When outputting same_comdat_group
skip symbols not put into boundary; stream transparent_alias.
(lto_output_varpool_node): Likewise.
(input_overwrite_node, input_varpool_node): Stream transparent alias.
* varpool.c (ctor_for_folding, varpool_node::get_availability,
varpool_node::assemble_aliases,
symbol_table::remove_unreferenced_decls): Handle transparent aliase.
(varpool_node::create_alias): Set transparent_alias.
2015-12-07 Eric Botcazou <ebotcazou@adacore.com>
PR middle-end/68291

View File

@ -560,7 +560,7 @@ cgraph_node::create_alias (tree alias, tree target)
alias_node->definition = true;
alias_node->alias = true;
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
alias_node->weakref = true;
alias_node->transparent_alias = alias_node->weakref = true;
return alias_node;
}
@ -2147,7 +2147,7 @@ cgraph_node::get_availability (void)
avail = AVAIL_NOT_AVAILABLE;
else if (local.local)
avail = AVAIL_LOCAL;
else if (alias && weakref)
else if (transparent_alias)
ultimate_alias_target (&avail);
else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
avail = AVAIL_INTERPOSABLE;

View File

@ -249,9 +249,10 @@ public:
inline symtab_node *next_defined_symbol (void);
/* Add reference recording that symtab node is alias of TARGET.
If TRANSPARENT is true make the alias to be transparent alias.
The function can fail in the case of aliasing cycles; in this case
it returns false. */
bool resolve_alias (symtab_node *target);
bool resolve_alias (symtab_node *target, bool transparent = false);
/* C++ FE sometimes change linkage flags after producing same
body aliases. */
@ -421,6 +422,28 @@ public:
/* True when symbol is an alias.
Set by ssemble_alias. */
unsigned alias : 1;
/* When true the alias is translated into its target symbol either by GCC
or assembler (it also may just be a duplicate declaration of the same
linker name).
Currently transparent aliases come in three different flavors
- aliases having the same assembler name as their target (aka duplicated
declarations). In this case the assembler names compare via
assembler_names_equal_p and weakref is false
- aliases that are renamed at a time being output to final file
by varasm.c. For those DECL_ASSEMBLER_NAME have
IDENTIFIER_TRANSPARENT_ALIAS set and thus also their assembler
name must be unique.
Weakrefs belong to this cateogry when we target assembler without
.weakref directive.
- weakrefs that are renamed by assembler via .weakref directive.
In this case the alias may or may not be definition (depending if
target declaration was seen by the compiler), weakref is set.
Unless we are before renaming statics, assembler names are different.
Given that we now support duplicate declarations, the second option is
redundant and will be removed. */
unsigned transparent_alias : 1;
/* True when alias is a weakref. */
unsigned weakref : 1;
/* C++ frontend produce same body aliases and extra name aliases for
@ -2098,6 +2121,10 @@ public:
/* Set the DECL_ASSEMBLER_NAME and update symtab hashtables. */
void change_decl_assembler_name (tree decl, tree name);
/* Return true if assembler names NAME1 and NAME2 leads to the same symbol
name. */
static bool assembler_names_equal_p (const char *name1, const char *name2);
int cgraph_count;
int cgraph_max_uid;
int cgraph_max_summary_uid;
@ -2251,6 +2278,8 @@ symtab_node::real_symbol_p (void)
if (DECL_ABSTRACT_P (decl))
return false;
if (transparent_alias && definition)
return false;
if (!is_a <cgraph_node *> (this))
return true;
cnode = dyn_cast <cgraph_node *> (this);

View File

@ -369,6 +369,7 @@ cgraph_node::reset (void)
analyzed = false;
definition = false;
alias = false;
transparent_alias = false;
weakref = false;
cpp_implicit_alias = false;
@ -594,7 +595,7 @@ cgraph_node::analyze (void)
thunk.alias = NULL;
}
if (alias)
resolve_alias (cgraph_node::get (alias_target));
resolve_alias (cgraph_node::get (alias_target), transparent_alias);
else if (dispatcher_function)
{
/* Generate the dispatcher body of multi-versioned functions. */
@ -1254,6 +1255,7 @@ handle_alias_pairs (void)
node->alias_target = p->target;
node->weakref = true;
node->alias = true;
node->transparent_alias = true;
}
alias_pairs->unordered_remove (i);
continue;
@ -1908,15 +1910,18 @@ cgraph_node::assemble_thunks_and_aliases (void)
FOR_EACH_ALIAS (this, ref)
{
cgraph_node *alias = dyn_cast <cgraph_node *> (ref->referring);
bool saved_written = TREE_ASM_WRITTEN (decl);
if (!alias->transparent_alias)
{
bool saved_written = TREE_ASM_WRITTEN (decl);
/* Force assemble_alias to really output the alias this time instead
of buffering it in same alias pairs. */
TREE_ASM_WRITTEN (decl) = 1;
do_assemble_alias (alias->decl,
DECL_ASSEMBLER_NAME (decl));
alias->assemble_thunks_and_aliases ();
TREE_ASM_WRITTEN (decl) = saved_written;
/* Force assemble_alias to really output the alias this time instead
of buffering it in same alias pairs. */
TREE_ASM_WRITTEN (decl) = 1;
do_assemble_alias (alias->decl,
DECL_ASSEMBLER_NAME (decl));
alias->assemble_thunks_and_aliases ();
TREE_ASM_WRITTEN (decl) = saved_written;
}
}
}

View File

@ -185,6 +185,8 @@ static bool
cgraph_externally_visible_p (struct cgraph_node *node,
bool whole_program)
{
while (node->transparent_alias && node->definition)
node = node->get_alias_target ();
if (!node->definition)
return false;
if (!TREE_PUBLIC (node->decl)
@ -248,6 +250,8 @@ cgraph_externally_visible_p (struct cgraph_node *node,
bool
varpool_node::externally_visible_p (void)
{
while (transparent_alias && definition)
return get_alias_target ()->externally_visible_p ();
if (DECL_EXTERNAL (decl))
return true;
@ -531,7 +535,8 @@ function_and_variable_visibility (bool whole_program)
next->set_comdat_group (NULL);
if (!next->alias)
next->set_section (NULL);
next->make_decl_local ();
if (!next->transparent_alias)
next->make_decl_local ();
next->unique_name |= ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
|| next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
&& TREE_PUBLIC (next->decl)
@ -547,7 +552,8 @@ function_and_variable_visibility (bool whole_program)
node->set_comdat_group (NULL);
if (DECL_COMDAT (node->decl) && !node->alias)
node->set_section (NULL);
node->make_decl_local ();
if (!node->transparent_alias)
node->make_decl_local ();
}
if (node->thunk.thunk_p
@ -654,7 +660,7 @@ function_and_variable_visibility (bool whole_program)
DECL_ATTRIBUTES (vnode->decl)))
vnode->no_reorder = 1;
if (!vnode->externally_visible
&& !vnode->weakref)
&& !vnode->transparent_alias)
{
gcc_assert (in_lto_p || whole_program || !TREE_PUBLIC (vnode->decl));
vnode->unique_name |= ((vnode->resolution == LDPR_PREVAILING_DEF_IRONLY
@ -675,11 +681,14 @@ function_and_variable_visibility (bool whole_program)
next->set_comdat_group (NULL);
if (!next->alias)
next->set_section (NULL);
next->make_decl_local ();
next->unique_name |= ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
|| next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
&& TREE_PUBLIC (next->decl)
&& !flag_incremental_link);
if (!next->transparent_alias)
{
next->make_decl_local ();
next->unique_name |= ((next->resolution == LDPR_PREVAILING_DEF_IRONLY
|| next->resolution == LDPR_PREVAILING_DEF_IRONLY_EXP)
&& TREE_PUBLIC (next->decl)
&& !flag_incremental_link);
}
}
vnode->dissolve_same_comdat_group_list ();
}
@ -687,8 +696,11 @@ function_and_variable_visibility (bool whole_program)
vnode->set_comdat_group (NULL);
if (DECL_COMDAT (vnode->decl) && !vnode->alias)
vnode->set_section (NULL);
vnode->make_decl_local ();
vnode->resolution = LDPR_PREVAILING_DEF_IRONLY;
if (!vnode->transparent_alias)
{
vnode->make_decl_local ();
vnode->resolution = LDPR_PREVAILING_DEF_IRONLY;
}
}
update_visibility_by_resolution_info (vnode);

View File

@ -543,6 +543,7 @@ symbol_table::remove_unreachable_nodes (FILE *file)
node->definition = false;
node->cpp_implicit_alias = false;
node->alias = false;
node->transparent_alias = false;
node->thunk.thunk_p = false;
node->weakref = false;
/* After early inlining we drop always_inline attributes on

View File

@ -485,11 +485,12 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
if (group)
{
if (node->same_comdat_group && !boundary_p)
if (node->same_comdat_group)
{
ref = lto_symtab_encoder_lookup (encoder,
node->same_comdat_group);
gcc_assert (ref != LCC_NOT_FOUND);
ref = LCC_NOT_FOUND;
for (struct symtab_node *n = node->same_comdat_group;
ref == LCC_NOT_FOUND && n != node; n = n->same_comdat_group)
ref = lto_symtab_encoder_lookup (encoder, n);
}
else
ref = LCC_NOT_FOUND;
@ -523,6 +524,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
bp_pack_value (&bp, node->lowered, 1);
bp_pack_value (&bp, in_other_partition, 1);
bp_pack_value (&bp, node->alias, 1);
bp_pack_value (&bp, node->transparent_alias, 1);
bp_pack_value (&bp, node->weakref, 1);
bp_pack_value (&bp, node->frequency, 2);
bp_pack_value (&bp, node->only_called_at_startup, 1);
@ -599,8 +601,9 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
bp_pack_value (&bp, node->definition && (encode_initializer_p || node->alias),
1);
bp_pack_value (&bp, node->alias, 1);
bp_pack_value (&bp, node->transparent_alias, 1);
bp_pack_value (&bp, node->weakref, 1);
bp_pack_value (&bp, node->analyzed && !boundary_p, 1);
bp_pack_value (&bp, node->analyzed && (!boundary_p || node->alias), 1);
gcc_assert (node->definition || !node->analyzed);
/* Constant pool initializers can be de-unified into individual ltrans units.
FIXME: Alternatively at -Os we may want to avoid generating for them the local
@ -632,11 +635,12 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
if (group)
{
if (node->same_comdat_group && !boundary_p)
if (node->same_comdat_group)
{
ref = lto_symtab_encoder_lookup (encoder,
node->same_comdat_group);
gcc_assert (ref != LCC_NOT_FOUND);
ref = LCC_NOT_FOUND;
for (struct symtab_node *n = node->same_comdat_group;
ref == LCC_NOT_FOUND && n != node; n = n->same_comdat_group)
ref = lto_symtab_encoder_lookup (encoder, n);
}
else
ref = LCC_NOT_FOUND;
@ -1170,6 +1174,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
TREE_STATIC (node->decl) = 0;
}
node->alias = bp_unpack_value (bp, 1);
node->transparent_alias = bp_unpack_value (bp, 1);
node->weakref = bp_unpack_value (bp, 1);
node->frequency = (enum node_frequency)bp_unpack_value (bp, 2);
node->only_called_at_startup = bp_unpack_value (bp, 1);
@ -1369,6 +1374,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
node->writeonly = bp_unpack_value (&bp, 1);
node->definition = bp_unpack_value (&bp, 1);
node->alias = bp_unpack_value (&bp, 1);
node->transparent_alias = bp_unpack_value (&bp, 1);
node->weakref = bp_unpack_value (&bp, 1);
node->analyzed = bp_unpack_value (&bp, 1);
node->used_from_other_partition = bp_unpack_value (&bp, 1);

View File

@ -1,3 +1,9 @@
2015-12-07 Jan Hubicka <hubicka@ucw.cz>
PR ipa/61886
* lto-partition.c (add_symbol_to_partition_1, contained_in_symbol,
rename_statics, rename_statics): Handle transparent aliases.
2015-12-04 Jan Hubicka <hubicka@ucw.cz>
* lto-symtab.c (lto_cgraph_replace_node): Update code computing

View File

@ -1035,7 +1035,15 @@ rename_statics (lto_symtab_encoder_t encoder, symtab_node *node)
/* Assign every symbol in the set that shares the same ASM name an unique
mangled name. */
for (s = symtab_node::get_for_asmname (name); s;)
if (!s->externally_visible
if ((!s->externally_visible || s->weakref)
/* Transparent aliases having same name as target are renamed at a
time their target gets new name. Transparent aliases that use
separate assembler name require the name to be unique. */
&& (!s->transparent_alias || !s->definition || s->weakref
|| !symbol_table::assembler_names_equal_p
(IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (s->decl)),
IDENTIFIER_POINTER
(DECL_ASSEMBLER_NAME (s->get_alias_target()->decl))))
&& ((s->real_symbol_p ()
&& !DECL_EXTERNAL (node->decl)
&& !TREE_PUBLIC (node->decl))

View File

@ -52,6 +52,26 @@ const char * const ld_plugin_symbol_resolution_names[]=
"prevailing_def_ironly_exp"
};
/* Follow the IDENTIFIER_TRANSPARENT_ALIAS chain starting at ALIAS
until we find an identifier that is not itself a transparent alias. */
static inline tree
ultimate_transparent_alias_target (tree alias)
{
tree target = alias;
while (IDENTIFIER_TRANSPARENT_ALIAS (target))
{
gcc_checking_assert (TREE_CHAIN (target));
target = TREE_CHAIN (target);
}
gcc_checking_assert (! IDENTIFIER_TRANSPARENT_ALIAS (target)
&& ! TREE_CHAIN (target));
return target;
}
/* Hash asmnames ignoring the user specified marks. */
hashval_t
@ -73,6 +93,44 @@ symbol_table::decl_assembler_name_hash (const_tree asmname)
return htab_hash_string (IDENTIFIER_POINTER (asmname));
}
/* Return true if assembler names NAME1 and NAME2 leads to the same symbol
name. */
bool
symbol_table::assembler_names_equal_p (const char *name1, const char *name2)
{
if (name1 != name2)
{
if (name1[0] == '*')
{
size_t ulp_len = strlen (user_label_prefix);
name1 ++;
if (ulp_len == 0)
;
else if (strncmp (name1, user_label_prefix, ulp_len) == 0)
name1 += ulp_len;
else
return false;
}
if (name2[0] == '*')
{
size_t ulp_len = strlen (user_label_prefix);
name2 ++;
if (ulp_len == 0)
;
else if (strncmp (name2, user_label_prefix, ulp_len) == 0)
name2 += ulp_len;
else
return false;
}
return !strcmp (name1, name2);
}
return true;
}
/* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL. */
@ -82,51 +140,13 @@ symbol_table::decl_assembler_name_equal (tree decl, const_tree asmname)
tree decl_asmname = DECL_ASSEMBLER_NAME (decl);
const char *decl_str;
const char *asmname_str;
bool test = false;
if (decl_asmname == asmname)
return true;
decl_str = IDENTIFIER_POINTER (decl_asmname);
asmname_str = IDENTIFIER_POINTER (asmname);
/* If the target assembler name was set by the user, things are trickier.
We have a leading '*' to begin with. After that, it's arguable what
is the correct thing to do with -fleading-underscore. Arguably, we've
historically been doing the wrong thing in assemble_alias by always
printing the leading underscore. Since we're not changing that, make
sure user_label_prefix follows the '*' before matching. */
if (decl_str[0] == '*')
{
size_t ulp_len = strlen (user_label_prefix);
decl_str ++;
if (ulp_len == 0)
test = true;
else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
decl_str += ulp_len, test=true;
else
decl_str --;
}
if (asmname_str[0] == '*')
{
size_t ulp_len = strlen (user_label_prefix);
asmname_str ++;
if (ulp_len == 0)
test = true;
else if (strncmp (asmname_str, user_label_prefix, ulp_len) == 0)
asmname_str += ulp_len, test=true;
else
asmname_str --;
}
if (!test)
return false;
return strcmp (decl_str, asmname_str) == 0;
return assembler_names_equal_p (decl_str, asmname_str);
}
@ -273,6 +293,8 @@ symbol_table::change_decl_assembler_name (tree decl, tree name)
: NULL);
if (node)
unlink_from_assembler_name_hash (node, true);
const char *old_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
&& DECL_RTL_SET_P (decl))
warning (0, "%D renamed after being referenced in assembly", decl);
@ -283,8 +305,48 @@ symbol_table::change_decl_assembler_name (tree decl, tree name)
IDENTIFIER_TRANSPARENT_ALIAS (name) = 1;
TREE_CHAIN (name) = alias;
}
/* If we change assembler name, also all transparent aliases must
be updated. There are three kinds - those having same assembler name,
those being renamed in varasm.c and weakref being renamed by the
assembler. */
if (node)
insert_to_assembler_name_hash (node, true);
{
insert_to_assembler_name_hash (node, true);
ipa_ref *ref;
for (unsigned i = 0; node->iterate_direct_aliases (i, ref); i++)
{
struct symtab_node *alias = ref->referring;
if (alias->transparent_alias && !alias->weakref
&& symbol_table::assembler_names_equal_p
(old_name, IDENTIFIER_POINTER (
DECL_ASSEMBLER_NAME (alias->decl))))
change_decl_assembler_name (alias->decl, name);
else if (alias->transparent_alias
&& IDENTIFIER_TRANSPARENT_ALIAS (alias->decl))
{
gcc_assert (TREE_CHAIN (DECL_ASSEMBLER_NAME (alias->decl))
&& IDENTIFIER_TRANSPARENT_ALIAS
(DECL_ASSEMBLER_NAME (alias->decl)));
TREE_CHAIN (DECL_ASSEMBLER_NAME (alias->decl)) =
ultimate_transparent_alias_target
(DECL_ASSEMBLER_NAME (node->decl));
}
#ifdef ASM_OUTPUT_WEAKREF
else gcc_assert (!alias->transparent_alias || alias->weakref);
#else
else gcc_assert (!alias->transparent_alias);
#endif
}
gcc_assert (!node->transparent_alias || !node->definition
|| node->weakref
|| TREE_CHAIN (DECL_ASSEMBLER_NAME (decl))
|| symbol_table::assembler_names_equal_p
(IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
IDENTIFIER_POINTER
(DECL_ASSEMBLER_NAME
(node->get_alias_target ()->decl))));
}
}
}
@ -727,6 +789,8 @@ symtab_node::dump_base (FILE *f)
fprintf (f, " analyzed");
if (alias)
fprintf (f, " alias");
if (transparent_alias)
fprintf (f, " transparent_alias");
if (weakref)
fprintf (f, " weakref");
if (cpp_implicit_alias)
@ -973,9 +1037,14 @@ symtab_node::verify_base (void)
error ("node is alias but not definition");
error_found = true;
}
if (weakref && !alias)
if (weakref && !transparent_alias)
{
error ("node is weakref but not an alias");
error ("node is weakref but not an transparent_alias");
error_found = true;
}
if (transparent_alias && !alias)
{
error ("node is transparent_alias but not an alias");
error_found = true;
}
if (same_comdat_group)
@ -1061,6 +1130,29 @@ symtab_node::verify_base (void)
get_alias_target ()->dump (stderr);
error_found = true;
}
if (transparent_alias && definition && !weakref)
{
symtab_node *to = get_alias_target ();
const char *name1
= IDENTIFIER_POINTER (
ultimate_transparent_alias_target (DECL_ASSEMBLER_NAME (decl)));
const char *name2
= IDENTIFIER_POINTER (
ultimate_transparent_alias_target (DECL_ASSEMBLER_NAME (to->decl)));
if (!symbol_table::assembler_names_equal_p (name1, name2))
{
error ("Transparent alias and target's assembler names differs");
get_alias_target ()->dump (stderr);
error_found = true;
}
}
if (transparent_alias && definition
&& get_alias_target()->transparent_alias && get_alias_target()->analyzed)
{
error ("Chained transparent aliases");
get_alias_target ()->dump (stderr);
error_found = true;
}
return error_found;
}
@ -1132,15 +1224,35 @@ symtab_node::make_decl_local (void)
{
rtx rtl, symbol;
if (weakref)
{
weakref = false;
IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME (decl)) = 0;
TREE_CHAIN (DECL_ASSEMBLER_NAME (decl)) = NULL_TREE;
symtab->change_decl_assembler_name
(decl, DECL_ASSEMBLER_NAME (get_alias_target ()->decl));
DECL_ATTRIBUTES (decl) = remove_attribute ("weakref",
DECL_ATTRIBUTES (decl));
}
/* Avoid clearing comdat_groups on comdat-local decls. */
if (TREE_PUBLIC (decl) == 0)
else if (TREE_PUBLIC (decl) == 0)
return;
/* Localizing a symbol also make all its transparent aliases local. */
ipa_ref *ref;
for (unsigned i = 0; iterate_direct_aliases (i, ref); i++)
{
struct symtab_node *alias = ref->referring;
if (alias->transparent_alias)
alias->make_decl_local ();
}
if (TREE_CODE (decl) == VAR_DECL)
{
DECL_COMMON (decl) = 0;
/* ADDRESSABLE flag is not defined for public symbols. */
TREE_ADDRESSABLE (decl) = 1;
TREE_STATIC (decl) = 1;
}
else gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
@ -1175,29 +1287,28 @@ symtab_node::make_decl_local (void)
symtab_node *
symtab_node::ultimate_alias_target_1 (enum availability *availability)
{
bool weakref_p = false;
bool transparent_p = false;
/* To determine visibility of the target, we follow ELF semantic of aliases.
Here alias is an alternative assembler name of a given definition. Its
availability prevails the availability of its target (i.e. static alias of
weak definition is available.
Weakref is a different animal (and not part of ELF per se). It is just
alternative name of a given symbol used within one complation unit
and is translated prior hitting the object file. It inherits the
visibility of its target (i.e. weakref of non-overwritable definition
is non-overwritable, while weakref of weak definition is weak).
Transaparent alias is just alternative anme of a given symbol used within
one compilation unit and is translated prior hitting the object file. It
inherits the visibility of its target.
Weakref is a different animal (and noweak definition is weak).
If we ever get into supporting targets with different semantics, a target
hook will be needed here. */
if (availability)
{
weakref_p = weakref;
if (!weakref_p)
transparent_p = transparent_alias;
if (!transparent_p)
*availability = get_availability ();
else
*availability = AVAIL_LOCAL;
*availability = AVAIL_NOT_AVAILABLE;
}
symtab_node *node = this;
@ -1207,27 +1318,19 @@ symtab_node::ultimate_alias_target_1 (enum availability *availability)
node = node->get_alias_target ();
else
{
if (!availability)
if (!availability || (!transparent_p && node->analyzed))
;
else if (node->analyzed)
{
if (weakref_p)
{
enum availability a = node->get_availability ();
if (a < *availability)
*availability = a;
}
}
else if (node->analyzed && !node->transparent_alias)
*availability = node->get_availability ();
else
*availability = AVAIL_NOT_AVAILABLE;
return node;
}
if (node && availability && weakref_p)
if (node && availability && transparent_p
&& node->transparent_alias)
{
enum availability a = node->get_availability ();
if (a < *availability)
*availability = a;
weakref_p = node->weakref;
*availability = node->get_availability ();
transparent_p = false;
}
}
if (availability)
@ -1442,7 +1545,7 @@ symtab_node::set_implicit_section (symtab_node *n,
it returns false. */
bool
symtab_node::resolve_alias (symtab_node *target)
symtab_node::resolve_alias (symtab_node *target, bool transparent)
{
symtab_node *n;
@ -1468,6 +1571,11 @@ symtab_node::resolve_alias (symtab_node *target)
definition = true;
alias = true;
analyzed = true;
transparent |= transparent_alias;
transparent_alias = transparent;
if (transparent)
while (target->transparent_alias && target->analyzed)
target = target->get_alias_target ();
create_reference (target, IPA_REF_ALIAS, NULL);
/* Add alias into the comdat group of its target unless it is already there. */
@ -1492,19 +1600,29 @@ symtab_node::resolve_alias (symtab_node *target)
when renaming symbols. */
alias_target = NULL;
if (cpp_implicit_alias && symtab->state >= CONSTRUCTION)
if (!transparent && cpp_implicit_alias && symtab->state >= CONSTRUCTION)
fixup_same_cpp_alias_visibility (target);
/* If alias has address taken, so does the target. */
if (address_taken)
target->ultimate_alias_target ()->address_taken = true;
/* All non-weakref aliases of THIS are now in fact aliases of TARGET. */
/* All non-transparent aliases of THIS are now in fact aliases of TARGET.
If alias is transparent, also all transparent aliases of THIS are now
aliases of TARGET.
Also merge same comdat group lists. */
ipa_ref *ref;
for (unsigned i = 0; iterate_direct_aliases (i, ref);)
{
struct symtab_node *alias_alias = ref->referring;
if (!alias_alias->weakref)
if (alias_alias->get_comdat_group ())
{
alias_alias->remove_from_same_comdat_group ();
alias_alias->set_comdat_group (NULL);
if (target->get_comdat_group ())
alias_alias->add_to_same_comdat_group (target);
}
if (!alias_alias->transparent_alias || transparent)
{
alias_alias->remove_all_references ();
alias_alias->create_reference (target, IPA_REF_ALIAS, NULL);
@ -1648,9 +1766,9 @@ symtab_node::get_partitioning_class (void)
if (cnode && cnode->global.inlined_to)
return SYMBOL_DUPLICATE;
/* Weakref aliases are always duplicated. */
if (weakref)
return SYMBOL_DUPLICATE;
/* Transparent aliases are always duplicated. */
if (transparent_alias)
return definition ? SYMBOL_DUPLICATE : SYMBOL_EXTERNAL;
/* External declarations are external. */
if (DECL_EXTERNAL (decl))

View File

@ -13423,6 +13423,12 @@ gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
{
tree f1, f2;
/* Don't try to compare variants of an incomplete type, before
TYPE_FIELDS has been copied around. */
if (!COMPLETE_TYPE_P (t1) && !COMPLETE_TYPE_P (t2))
return true;
if (TYPE_REVERSE_STORAGE_ORDER (t1) != TYPE_REVERSE_STORAGE_ORDER (t2))
return false;
@ -13709,28 +13715,35 @@ verify_type (const_tree t)
}
}
else if (RECORD_OR_UNION_TYPE_P (t))
for (tree fld = TYPE_FIELDS (t); fld; fld = TREE_CHAIN (fld))
{
/* TODO: verify properties of decls. */
if (TREE_CODE (fld) == FIELD_DECL)
;
else if (TREE_CODE (fld) == TYPE_DECL)
;
else if (TREE_CODE (fld) == CONST_DECL)
;
else if (TREE_CODE (fld) == VAR_DECL)
;
else if (TREE_CODE (fld) == TEMPLATE_DECL)
;
else if (TREE_CODE (fld) == USING_DECL)
;
else
{
error ("Wrong tree in TYPE_FIELDS list");
debug_tree (fld);
error_found = true;
}
}
{
if (TYPE_FIELDS (t) && !COMPLETE_TYPE_P (t) && in_lto_p)
{
error ("TYPE_FIELDS defined in incomplete type");
error_found = true;
}
for (tree fld = TYPE_FIELDS (t); fld; fld = TREE_CHAIN (fld))
{
/* TODO: verify properties of decls. */
if (TREE_CODE (fld) == FIELD_DECL)
;
else if (TREE_CODE (fld) == TYPE_DECL)
;
else if (TREE_CODE (fld) == CONST_DECL)
;
else if (TREE_CODE (fld) == VAR_DECL)
;
else if (TREE_CODE (fld) == TEMPLATE_DECL)
;
else if (TREE_CODE (fld) == USING_DECL)
;
else
{
error ("Wrong tree in TYPE_FIELDS list");
debug_tree (fld);
error_found = true;
}
}
}
else if (TREE_CODE (t) == INTEGER_TYPE
|| TREE_CODE (t) == BOOLEAN_TYPE
|| TREE_CODE (t) == OFFSET_TYPE

View File

@ -440,7 +440,7 @@ ctor_for_folding (tree decl)
gcc_assert (!DECL_INITIAL (decl)
|| (node->alias && node->get_alias_target () == real_node)
|| DECL_INITIAL (decl) == error_mark_node);
if (node->weakref)
while (node->transparent_alias && node->analyzed)
{
node = node->get_alias_target ();
decl = node->decl;
@ -490,11 +490,11 @@ varpool_node::get_availability (void)
if (DECL_IN_CONSTANT_POOL (decl)
|| DECL_VIRTUAL_P (decl))
return AVAIL_AVAILABLE;
if (alias && weakref)
if (transparent_alias)
{
enum availability avail;
ultimate_alias_target (&avail)->get_availability ();
ultimate_alias_target (&avail);
return avail;
}
/* If the variable can be overwritten, return OVERWRITABLE. Takes
@ -536,8 +536,9 @@ varpool_node::assemble_aliases (void)
FOR_EACH_ALIAS (this, ref)
{
varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
do_assemble_alias (alias->decl,
DECL_ASSEMBLER_NAME (decl));
if (!alias->transparent_alias)
do_assemble_alias (alias->decl,
DECL_ASSEMBLER_NAME (decl));
alias->assemble_aliases ();
}
}
@ -665,7 +666,14 @@ symbol_table::remove_unreferenced_decls (void)
&& vnode->analyzed)
enqueue_node (vnode, &first);
else
referenced.add (node);
{
referenced.add (node);
while (node->alias && node->definition)
{
node = node->get_alias_target ();
referenced.add (node);
}
}
}
}
if (dump_file)
@ -760,7 +768,7 @@ varpool_node::create_alias (tree alias, tree decl)
alias_node->definition = true;
alias_node->alias_target = decl;
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
alias_node->weakref = true;
alias_node->weakref = alias_node->transparent_alias = true;
return alias_node;
}