[gcc(refs/users/aoliva/heads/testme)] incremental sym_alias changes
Alexandre Oliva
aoliva@gcc.gnu.org
Sun Dec 3 01:46:43 GMT 2023
https://gcc.gnu.org/g:dcab56afdefe7b43bdf9a90a86300a675d5d7193
commit dcab56afdefe7b43bdf9a90a86300a675d5d7193
Author: Alexandre Oliva <oliva@gnu.org>
Date: Fri Dec 1 15:48:44 2023 -0300
incremental sym_alias changes
Diff:
---
gcc/attribs.cc | 16 +++++++---
gcc/c/c-decl.cc | 5 +++
gcc/cp/decl2.cc | 3 ++
gcc/doc/extend.texi | 8 ++++-
gcc/symtab.cc | 26 +++++++++++++++-
.../c-c++-common/torture/attr-sym-alias-1.c | 36 ++++++++++++++++++++++
.../c-c++-common/torture/attr-sym-alias-2.c | 21 +++++++++----
.../c-c++-common/torture/attr-sym-alias-3.c | 7 -----
gcc/testsuite/g++.dg/torture/attr-sym-alias-1.C | 17 ++++++++++
9 files changed, 120 insertions(+), 19 deletions(-)
diff --git a/gcc/attribs.cc b/gcc/attribs.cc
index 7294ff27277..5f811c937f0 100644
--- a/gcc/attribs.cc
+++ b/gcc/attribs.cc
@@ -2696,6 +2696,11 @@ create_sym_alias_decl (tree decl, tree id)
tree clone = copy_node (decl);
DECL_ATTRIBUTES (clone) = remove_attribute (attr_str,
DECL_ATTRIBUTES (decl));
+ /* Mark it as a "sym alias" for decl, an internal attribute that
+ enables symbol_table::insert_to_assembler_name_hash can recognize
+ sym_alias decls. */
+ DECL_ATTRIBUTES (clone) = tree_cons (get_identifier ("sym alias"),
+ decl, DECL_ATTRIBUTES (clone));
SET_DECL_ASSEMBLER_NAME (clone, id);
TREE_USED (id) = 1;
TREE_USED (clone) = 1;
@@ -2703,13 +2708,16 @@ create_sym_alias_decl (tree decl, tree id)
DECL_EXTERNAL (clone) = 0;
TREE_STATIC (clone) = 1;
+ symtab_node *node;
if (VAR_P (clone))
// DECL_READ_P (clone) = 1;
- // varpool_node::create_extra_name_alias (clone, decl);
- varpool_node::create_alias (clone, decl);
+ // node = varpool_node::create_extra_name_alias (clone, decl);
+ node = varpool_node::create_alias (clone, decl);
else
- cgraph_node::create_same_body_alias (clone, decl);
- // cgraph_node::create_alias (clone, decl);
+ node = cgraph_node::create_same_body_alias (clone, decl);
+ // node = cgraph_node::create_alias (clone, decl);
+ if (symtab_node *dnode = symtab_node::get_create (decl))
+ node->copy_visibility_from (dnode);
return clone;
}
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index e5a1ee54cb3..1ed281dfa76 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -5904,6 +5904,11 @@ finish_decl (tree decl, location_t init_loc, tree init,
set_user_assembler_name (decl, asmspec);
}
+ /* Give attribute sym_alias a chance to make the symbol name
+ available for aliasing, even for a static local variable. */
+ if (VAR_P (decl) && !DECL_EXTERNAL (decl) && is_global_var (decl))
+ varpool_node::get_create (decl);
+
if (DECL_FILE_SCOPE_P (decl))
{
if (DECL_INITIAL (decl) == NULL_TREE
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index c7f009beaf0..9b4afb3d889 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -2219,6 +2219,9 @@ copy_interface (tree dest, tree decl)
DECL_INTERFACE_KNOWN (dest) = DECL_INTERFACE_KNOWN (decl);
DECL_VISIBILITY (dest) = DECL_VISIBILITY (decl);
DECL_VISIBILITY_SPECIFIED (dest) = DECL_VISIBILITY_SPECIFIED (decl);
+ if (symtab_node *dest_node = symtab_node::get (dest))
+ if (symtab_node *decl_node = symtab_node::get (decl))
+ decl_node->copy_visibility_from (dest_node);
}
/* Propagate linkage changes to sym aliases. */
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 4aca96de04e..77ea5c9e022 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -4174,7 +4174,13 @@ declarations.
Aliases introduced with this attribute, such as @samp{f_u64} in the
example above, are assembly symbol names: they do not undergo C++ name
mangling, and are not made visible in any scope in the source language.
-They can, however, can be named as alias targets.
+They can, however, be named as alias targets, as long as their
+definition is output. Naming a @samp{sym_alias} as an alias target will
+@emph{not} cause a definition to be output if it otherwise wouldn't.
+This may affect inline functions, C++ template instantiations, and other
+synthesized definitions that would have to be (synthesized and) compiled
+in order for the @samp{sym_alias} to be considered as a potential alias
+target.
This attribute requires assembler and object file support for aliases,
and may not be available on all targets.
diff --git a/gcc/symtab.cc b/gcc/symtab.cc
index 43ba88d7939..44df52095c1 100644
--- a/gcc/symtab.cc
+++ b/gcc/symtab.cc
@@ -187,6 +187,22 @@ symbol_table::insert_to_assembler_name_hash (symtab_node *node,
(*aslot)->previous_sharing_asm_name = node;
*aslot = node;
+ /* Check for sym_alias name clashes. In create_sym_alias_decl,
+ we check for a preexisting definition using the same
+ assembler_name, so here we check for a previously-defined
+ sym_name, marked with a "sym name" pseudo-attribute that
+ points back at the declaration for which it was created. */
+ if (symtab_node *sym_node = node->next_sharing_asm_name)
+ if (lookup_attribute ("sym alias",
+ DECL_ATTRIBUTES (sym_node->decl)))
+ {
+ error_at (DECL_SOURCE_LOCATION (node->decl),
+ "duplicate symbol name %qE", decl);
+ inform (DECL_SOURCE_LOCATION (sym_node->decl),
+ "already used by %qD in a %qE attribute",
+ sym_node->decl, get_identifier ("sym_alias"));
+ }
+
/* Update also possible inline clones sharing a decl. */
cnode = dyn_cast <cgraph_node *> (node);
if (cnode && cnode->clones && with_clones)
@@ -1949,8 +1965,9 @@ symtab_node::noninterposable_alias (symtab_node *node, void *data)
void
symtab_node::remap_sym_alias_target (tree replaced, tree replacement)
{
+ symtab_node *repl_node = NULL;
if (!decl_in_symtab_p (replacement)
- || !symtab_node::get (replacement))
+ || !(repl_node = symtab_node::get (replacement)))
return;
FOR_EACH_SYM_ALIAS (sym, DECL_ATTRIBUTES (replaced))
@@ -1978,6 +1995,7 @@ symtab_node::remap_sym_alias_target (tree replaced, tree replacement)
else
cgraph_node::create_same_body_alias (sym_node->decl, replacement);
// cgraph_node::create_alias (sym_node->decl, replacement);
+ sym_node->copy_visibility_from (repl_node);
}
}
@@ -2008,6 +2026,12 @@ symtab_node::noninterposable_alias (void)
/* Otherwise create a new one. */
new_decl = copy_node (node->decl);
+ DECL_ATTRIBUTES (new_decl) = remove_attribute ("sym_alias",
+ DECL_ATTRIBUTES
+ (new_decl));
+ DECL_ATTRIBUTES (new_decl) = remove_attribute ("sym alias",
+ DECL_ATTRIBUTES
+ (new_decl));
DECL_DLLIMPORT_P (new_decl) = 0;
tree name = clone_function_name (node->decl, "localalias");
if (!flag_wpa)
diff --git a/gcc/testsuite/c-c++-common/torture/attr-sym-alias-1.c b/gcc/testsuite/c-c++-common/torture/attr-sym-alias-1.c
index 61af50cb552..2fe1948aed9 100644
--- a/gcc/testsuite/c-c++-common/torture/attr-sym-alias-1.c
+++ b/gcc/testsuite/c-c++-common/torture/attr-sym-alias-1.c
@@ -2,10 +2,13 @@
/* { dg-require-alias "" } */
extern int var_a __attribute__ ((__sym_alias__ ("FOOVAR_A")));
+extern int var_alias __attribute__ ((__alias__ ("FOOVAR_A")));
int var_a = 1;
void foo_a () __attribute__ ((__sym_alias__ ("FOOBAR_A")));
+void foo_alias () __attribute__ ((__alias__ ("FOOBAR_A")));
+
void
foo_a ()
{
@@ -31,9 +34,42 @@ foo_c ()
}
+void baf () {}
+
+void foo_x () {
+ extern void baf () __attribute__ ((__sym_alias__ ("FOO_BAF")));
+ extern void bad () /* ok, but not defined, so no alias issued. */
+ __attribute__ ((__sym_alias__ ("FOO_BAD")));
+ extern void bar () __attribute__ ((__sym_alias__ ("FOO_BAR")));
+
+ static int x __attribute__ ((sym_alias ("FOO_x")));
+}
+
+void bar () {}
+
+extern int xr __attribute__ ((alias ("FOO_x")));
+
+
+ /* The *u* symbols are not defined, so the sym_aliases do not clash. ??? Is
+ this just an implementation artifact, or a feature someone might actually
+ rely on? */
+extern int var_u1 __attribute__ ((__sym_alias__ ("VAR_U")));
+extern int var_u2 __attribute__ ((__sym_alias__ ("VAR_U")));
+
+void foo_u1 () __attribute__ ((__sym_alias__ ("FOOBAR_U")));
+void foo_u2 () __attribute__ ((__sym_alias__ ("FOOBAR_U")));
+
+
/* { dg-final { scan-assembler "FOOBAR_A" } } */
+/* { dg-final { scan-assembler "foo_alias" } } */
/* { dg-final { scan-assembler "FOOVAR_A" } } */
+/* { dg-final { scan-assembler "var_alias" } } */
/* { dg-final { scan-assembler "FOOBAR_B" } } */
/* { dg-final { scan-assembler "FOOVAR_B" } } */
/* { dg-final { scan-assembler "FOOBAR_C" } } */
/* { dg-final { scan-assembler "FOOVAR_C" } } */
+/* { dg-final { scan-assembler "FOO_BAF" } } */
+/* { dg-final { scan-assembler "FOO_BAR" } } */
+/* { dg-final { scan-assembler-not "FOO_BAD" } } */
+/* { dg-final { scan-assembler-not "VAR_U" } } */
+/* { dg-final { scan-assembler-not "FOOBAR_U" } } */
diff --git a/gcc/testsuite/c-c++-common/torture/attr-sym-alias-2.c b/gcc/testsuite/c-c++-common/torture/attr-sym-alias-2.c
index 67dcd4fd7e1..f692a552606 100644
--- a/gcc/testsuite/c-c++-common/torture/attr-sym-alias-2.c
+++ b/gcc/testsuite/c-c++-common/torture/attr-sym-alias-2.c
@@ -7,16 +7,14 @@ struct s
};
void foo () {
- extern void bar () __attribute__ ((__sym_alias__ ("FOO_BAR"))); /* ok */
+ extern void bar () __attribute__ ((__sym_alias__ ("FOO_BAR"))); /* Ok. */
int i __attribute__ ((sym_alias ("FOO_i"))); /* { dg-warning "ignored" } */
- /* ??? X cannot be an alias target; should this be flagged? ... */
static int x __attribute__ ((sym_alias ("FOO_x")));
static int sx __attribute__ ((alias ("FOO_x"))); /* { dg-warning "ignored" } */
extern int xx __attribute__ ((alias ("FOO_x"))); /* { dg-warning "ignored" } */
+ extern int y __attribute__ ((sym_alias ("FOO_y"))); /* Ok. */
}
-/* ??? ... or should XR be accepted? */
-extern int xr __attribute__ ((alias ("FOO_x"))); /* { dg-error "undefined" "" { xfail c++ } } */
int dr __attribute__ ((alias ("FOO_x"))); /* { dg-error "defined both" } */
@@ -40,7 +38,7 @@ int l __attribute__ ((sym_alias ("L_fn")));
extern "C"
#endif
void
-L_fn () /* { dg-error "duplicate" "" { xfail *-*-* } } */
+L_fn () /* { dg-error "duplicate" "" } */
{
}
@@ -53,7 +51,7 @@ m ()
{
}
-int M_var; /* { dg-error "duplicate" "" { xfail *-*-* } } */
+int M_var; /* { dg-error "duplicate" "" } */
void __attribute__ ((sym_alias ("N_sym")))
@@ -88,3 +86,14 @@ void __attribute__ ((sym_alias ("Q_sym")))
q_fn2 () /* { dg-error "duplicate" } */
{
}
+
+int __attribute__ ((sym_alias ("R_var")))
+R_var; /* { dg-error "duplicate" } */
+
+#ifdef __cplusplus
+extern "C"
+#endif
+void __attribute__ ((sym_alias ("S_fn")))
+S_fn () /* { dg-error "duplicate" } */
+{
+}
diff --git a/gcc/testsuite/c-c++-common/torture/attr-sym-alias-3.c b/gcc/testsuite/c-c++-common/torture/attr-sym-alias-3.c
index 0052485a30a..52f8fb76496 100644
--- a/gcc/testsuite/c-c++-common/torture/attr-sym-alias-3.c
+++ b/gcc/testsuite/c-c++-common/torture/attr-sym-alias-3.c
@@ -10,13 +10,6 @@ foo_a ()
void foo_a () __attribute__ ((__sym_alias__ ("FOOBAR_A")));
}
-#if 0 // __cplusplus
-/* Without this declaration before the local declaration below, the
- attributes of the local declaration do not get propagated to the
- (global) namespace scope. */
-extern int var_b;
-#endif
-
void
foo_b ()
{
diff --git a/gcc/testsuite/g++.dg/torture/attr-sym-alias-1.C b/gcc/testsuite/g++.dg/torture/attr-sym-alias-1.C
index 579eda1a473..51729994913 100644
--- a/gcc/testsuite/g++.dg/torture/attr-sym-alias-1.C
+++ b/gcc/testsuite/g++.dg/torture/attr-sym-alias-1.C
@@ -45,6 +45,20 @@ namespace c {
}
}
+#include <typeinfo>
+
+namespace d {
+ namespace {
+ class __attribute__ ((__sym_alias__ ("FOOCLS_D"))) foo {
+ virtual ~foo() {} // typeid(foo) is not defined otherwise.
+ };
+ }
+
+ extern std::type_info __attribute__ ((__alias__ ("FOOCLS_D"))) foo_d_typeinfo;
+}
+
+extern std::type_info __attribute__ ((__alias__ ("FOOCLS_C"))) foo_c_typeinfo;
+
/* { dg-final { scan-assembler "FOOCLS_A" } } */
/* { dg-final { scan-assembler "FOOCLS_A_Dupe" } } */
/* { dg-final { scan-assembler "FOOBAR_A" } } */
@@ -70,3 +84,6 @@ namespace c {
/* { dg-final { scan-assembler "FOODTR_C_Base" } } */
/* { dg-final { scan-assembler "FOODTR_C_Del" } } */
/* { dg-final { scan-assembler "FOOVAR_C" } } */
+/* { dg-final { scan-assembler "FOOCLS_D" } } */
+/* { dg-final { scan-assembler "foo_d_typeinfo" } } */
+/* { dg-final { scan-assembler "foo_c_typeinfo" } } */
More information about the Gcc-cvs
mailing list