Hi
According to gnu document of function attributes, neither weakref nor alias
could be attached to a function defined in current translation unit.
Although GCC checks the attributes under some circumstances, it still fails
on some cases and even causes ICE.
This patch checks whether alias/weakref attribute attaches on a function
declaration which has body, and removes the attribute later.
This also avoid the ICE.
Bootstrapped/regtested on x86_64-linux, ok for GCC10?
Regards
JunMa
gcc/ChangeLog
2019-03-26 Jun Ma <ju...@linux.alibaba.com>
PR89341
* cgraphunit.c (handle_alias_pairs): Check whether alias attribute
attaches
on a function declaration which has body.
gcc/testsuite/ChangeLog
2019-03-26 Jun Ma <ju...@linux.alibaba.com>
PR89341
* gcc.dg/attr-alias-6.c: New test.
* gcc.dg/attr-weakref-5.c: Likewise.
---
gcc/cgraphunit.c | 11 ++++++++---
gcc/testsuite/gcc.dg/attr-alias-6.c | 4 ++++
gcc/testsuite/gcc.dg/attr-weakref-5.c | 4 ++++
3 files changed, 16 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/gcc.dg/attr-alias-6.c
create mode 100644 gcc/testsuite/gcc.dg/attr-weakref-5.c
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 8bfbd0b..733e184 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -1405,14 +1405,20 @@ handle_alias_pairs (void)
for (i = 0; alias_pairs && alias_pairs->iterate (i, &p);)
{
symtab_node *target_node = symtab_node::get_for_asmname (p->target);
-
+ symtab_node *node = symtab_node::get (p->decl);
+ if (node && TREE_CODE (p->decl) == FUNCTION_DECL
+ && DECL_SAVED_TREE (p->decl))
+ {
+ node->alias = false;
+ alias_pairs->unordered_remove (i);
+ continue;
+ }
/* Weakrefs with target not defined in current unit are easy to handle:
they behave just as external variables except we need to note the
alias flag to later output the weakref pseudo op into asm file. */
if (!target_node
&& lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)) != NULL)
{
- symtab_node *node = symtab_node::get (p->decl);
if (node)
{
node->alias_target = p->target;
@@ -1426,7 +1432,6 @@ handle_alias_pairs (void)
else if (!target_node)
{
error ("%q+D aliased to undefined symbol %qE", p->decl, p->target);
- symtab_node *node = symtab_node::get (p->decl);
if (node)
node->alias = false;
alias_pairs->unordered_remove (i);
diff --git a/gcc/testsuite/gcc.dg/attr-alias-6.c
b/gcc/testsuite/gcc.dg/attr-alias-6.c
new file mode 100644
index 0000000..a3ec311
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-alias-6.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-require-alias "" } */
+static void __attribute__((alias("bar"))) foo(void) { } /* { dg-warning
"attribute ignored because function is defined" } */
+void bar(void);
diff --git a/gcc/testsuite/gcc.dg/attr-weakref-5.c
b/gcc/testsuite/gcc.dg/attr-weakref-5.c
new file mode 100644
index 0000000..bb21126
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-weakref-5.c
@@ -0,0 +1,4 @@
+/* { dg-do compile } */
+/* { dg-require-weak "" } */
+static void __attribute__((weakref("bar"))) foo(void) { } /* { dg-warning
"attribute ignored because function is defined" } */
+void foo(void);
--
1.8.3.1