aboutsummaryrefslogtreecommitdiff
path: root/gcc/cgraphunit.c
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2020-08-24 13:21:10 +0200
committerMartin Liska <mliska@suse.cz>2020-08-26 10:03:19 +0200
commit363080bb8bd2cca81dd9e2e774910a8c8226f430 (patch)
treedbd812c1ccd60680bc8aaaa61140d251e64efc4b /gcc/cgraphunit.c
parentd58e7173ef964ddac3ab3ad8cc97de8f9f3b32ee (diff)
downloadgcc-363080bb8bd2cca81dd9e2e774910a8c8226f430.zip
gcc-363080bb8bd2cca81dd9e2e774910a8c8226f430.tar.gz
gcc-363080bb8bd2cca81dd9e2e774910a8c8226f430.tar.bz2
IPA symver: allow multiple symvers for a definition
gcc/ChangeLog: * cgraphunit.c (process_symver_attribute): Allow multiple symver attributes for one symbol. * doc/extend.texi: Document the change. gcc/testsuite/ChangeLog: * lib/target-supports-dg.exp: Add dg-require-symver. * lib/target-supports.exp: Likewise. * gcc.dg/ipa/symver1.c: New test.
Diffstat (limited to 'gcc/cgraphunit.c')
-rw-r--r--gcc/cgraphunit.c143
1 files changed, 72 insertions, 71 deletions
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 0b1009d..fa3aec7 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -720,80 +720,81 @@ process_symver_attribute (symtab_node *n)
{
tree value = lookup_attribute ("symver", DECL_ATTRIBUTES (n->decl));
- if (!value)
- return;
- if (lookup_attribute ("symver", TREE_CHAIN (value)))
+ for (; value != NULL; value = TREE_CHAIN (value))
{
- error_at (DECL_SOURCE_LOCATION (n->decl),
- "multiple versions for one symbol");
- return;
- }
- tree symver = get_identifier_with_length
- (TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (value))),
- TREE_STRING_LENGTH (TREE_VALUE (TREE_VALUE (value))));
- symtab_node *def = symtab_node::get_for_asmname (symver);
+ /* Starting from bintuils 2.35 gas supports:
+ # Assign foo to bar@V1 and baz@V2.
+ .symver foo, bar@V1
+ .symver foo, baz@V2
+ */
+
+ tree symver = get_identifier_with_length
+ (TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (value))),
+ TREE_STRING_LENGTH (TREE_VALUE (TREE_VALUE (value))));
+ symtab_node *def = symtab_node::get_for_asmname (symver);
+
+ if (def)
+ {
+ error_at (DECL_SOURCE_LOCATION (n->decl),
+ "duplicate definition of a symbol version");
+ inform (DECL_SOURCE_LOCATION (def->decl),
+ "same version was previously defined here");
+ return;
+ }
+ if (!n->definition)
+ {
+ error_at (DECL_SOURCE_LOCATION (n->decl),
+ "symbol needs to be defined to have a version");
+ return;
+ }
+ if (DECL_COMMON (n->decl))
+ {
+ error_at (DECL_SOURCE_LOCATION (n->decl),
+ "common symbol cannot be versioned");
+ return;
+ }
+ if (DECL_COMDAT (n->decl))
+ {
+ error_at (DECL_SOURCE_LOCATION (n->decl),
+ "comdat symbol cannot be versioned");
+ return;
+ }
+ if (n->weakref)
+ {
+ error_at (DECL_SOURCE_LOCATION (n->decl),
+ "%<weakref%> cannot be versioned");
+ return;
+ }
+ if (!TREE_PUBLIC (n->decl))
+ {
+ error_at (DECL_SOURCE_LOCATION (n->decl),
+ "versioned symbol must be public");
+ return;
+ }
+ if (DECL_VISIBILITY (n->decl) != VISIBILITY_DEFAULT)
+ {
+ error_at (DECL_SOURCE_LOCATION (n->decl),
+ "versioned symbol must have default visibility");
+ return;
+ }
- if (def)
- {
- error_at (DECL_SOURCE_LOCATION (n->decl),
- "duplicate definition of a symbol version");
- inform (DECL_SOURCE_LOCATION (def->decl),
- "same version was previously defined here");
- return;
- }
- if (!n->definition)
- {
- error_at (DECL_SOURCE_LOCATION (n->decl),
- "symbol needs to be defined to have a version");
- return;
- }
- if (DECL_COMMON (n->decl))
- {
- error_at (DECL_SOURCE_LOCATION (n->decl),
- "common symbol cannot be versioned");
- return;
- }
- if (DECL_COMDAT (n->decl))
- {
- error_at (DECL_SOURCE_LOCATION (n->decl),
- "comdat symbol cannot be versioned");
- return;
- }
- if (n->weakref)
- {
- error_at (DECL_SOURCE_LOCATION (n->decl),
- "%<weakref%> cannot be versioned");
- return;
+ /* Create new symbol table entry representing the version. */
+ tree new_decl = copy_node (n->decl);
+
+ DECL_INITIAL (new_decl) = NULL_TREE;
+ if (TREE_CODE (new_decl) == FUNCTION_DECL)
+ DECL_STRUCT_FUNCTION (new_decl) = NULL;
+ SET_DECL_ASSEMBLER_NAME (new_decl, symver);
+ TREE_PUBLIC (new_decl) = 1;
+ DECL_ATTRIBUTES (new_decl) = NULL;
+
+ symtab_node *symver_node = symtab_node::get_create (new_decl);
+ symver_node->alias = true;
+ symver_node->definition = true;
+ symver_node->symver = true;
+ symver_node->create_reference (n, IPA_REF_ALIAS, NULL);
+ symver_node->analyzed = true;
}
- if (!TREE_PUBLIC (n->decl))
- {
- error_at (DECL_SOURCE_LOCATION (n->decl),
- "versioned symbol must be public");
- return;
- }
- if (DECL_VISIBILITY (n->decl) != VISIBILITY_DEFAULT)
- {
- error_at (DECL_SOURCE_LOCATION (n->decl),
- "versioned symbol must have default visibility");
- return;
- }
-
- /* Create new symbol table entry representing the version. */
- tree new_decl = copy_node (n->decl);
-
- DECL_INITIAL (new_decl) = NULL_TREE;
- if (TREE_CODE (new_decl) == FUNCTION_DECL)
- DECL_STRUCT_FUNCTION (new_decl) = NULL;
- SET_DECL_ASSEMBLER_NAME (new_decl, symver);
- TREE_PUBLIC (new_decl) = 1;
- DECL_ATTRIBUTES (new_decl) = NULL;
-
- symtab_node *symver_node = symtab_node::get_create (new_decl);
- symver_node->alias = true;
- symver_node->definition = true;
- symver_node->symver = true;
- symver_node->create_reference (n, IPA_REF_ALIAS, NULL);
- symver_node->analyzed = true;
}
/* Process attributes common for vars and functions. */