This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: output unreferenced static variable if an alias to it isreferenced
On Oct 20, 2005, Richard Henderson <rth@redhat.com> wrote:
> On Thu, Oct 20, 2005 at 04:47:53AM -0200, Alexandre Oliva wrote:
>> * cgraphunit.c (cgraph_varpool_remove_unreferenced_decls): Mark
>> alias targets.
>> * varasm.c (find_decl_and_mark_needed): After cgraph global info
>> is ready, stop marking functions, but still mark variables.
> Ok, except,
>> * gcc.dg/attr-alias-3.c: New test.
> Don't we have some test keyword that disables the test when
> (strong) aliases aren't available on the platform? It seems
> like there should be something here...
Indeed. Oops. Thanks,
Here's yet another revised version of the patch that supersedes the
one I just posted. It tweaks the new weak-14.c test such that it
actually tests what it should, namely, that we do emit the static
variable with the correct value, as opposed to simply emitting the
weak aliases, which we did before the fix as well. I found out that
when we emitted the alias but not the target, gas and ld would succeed
in linking, as long as the weak alias was not actually used in the
same translation unit. Using it in a separate translation unit would
make it seem like it actually aliased something, as opposed to being
an undefweak. Seems like a separate bug in binutils...
Anyhow, here's the patch I'm checking in.
Index: gcc/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
PR middle-end/24295
* cgraphunit.c (cgraph_varpool_remove_unreferenced_decls): Mark
alias targets.
* varasm.c (find_decl_and_mark_needed): After cgraph global info
is ready, stop marking functions, but still mark variables.
Index: gcc/testsuite/ChangeLog
from Alexandre Oliva <aoliva@redhat.com>
PR middle-end/24295
* g++.old-deja/g++.abi/vtable2.C: Do not introduce external
declarations with the same names as thunks' alias targets, use
aliases instead.
* gcc.dg/attr-alias-3.c: New test.
* gcc.dg/weak/weak-14.c, gcc.dg/weak/weak-14a.c: New test.
Index: gcc/cgraphunit.c
===================================================================
--- gcc/cgraphunit.c.orig 2005-10-20 16:58:36.000000000 -0200
+++ gcc/cgraphunit.c 2005-10-20 16:59:24.000000000 -0200
@@ -322,6 +322,8 @@
node = next;
}
+ /* Make sure we mark alias targets as used targets. */
+ finish_aliases_1 ();
cgraph_varpool_analyze_pending_decls ();
}
Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c.orig 2005-10-20 16:58:36.000000000 -0200
+++ gcc/varasm.c 2005-10-20 17:01:48.000000000 -0200
@@ -4560,27 +4560,28 @@
struct cgraph_node *fnode = NULL;
struct cgraph_varpool_node *vnode = NULL;
- /* C++ thunk emitting code produces aliases late in the game.
- Avoid confusing cgraph code in that case. */
- if (!cgraph_global_info_ready)
+ if (TREE_CODE (decl) == FUNCTION_DECL)
{
- if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- fnode = cgraph_node_for_asm (target);
- if (fnode == NULL)
- vnode = cgraph_varpool_node_for_asm (target);
- }
- else
- {
- vnode = cgraph_varpool_node_for_asm (target);
- if (vnode == NULL)
- fnode = cgraph_node_for_asm (target);
- }
+ fnode = cgraph_node_for_asm (target);
+ if (fnode == NULL)
+ vnode = cgraph_varpool_node_for_asm (target);
+ }
+ else
+ {
+ vnode = cgraph_varpool_node_for_asm (target);
+ if (vnode == NULL)
+ fnode = cgraph_node_for_asm (target);
}
if (fnode)
{
- cgraph_mark_needed_node (fnode);
+ /* We can't mark function nodes as used after cgraph global info
+ is finished. This wouldn't generally be necessary, but C++
+ virtual table thunks are introduced late in the game and
+ might seem like they need marking, although in fact they
+ don't. */
+ if (! cgraph_global_info_ready)
+ cgraph_mark_needed_node (fnode);
return fnode->decl;
}
else if (vnode)
Index: gcc/testsuite/g++.old-deja/g++.abi/vtable2.C
===================================================================
--- gcc/testsuite/g++.old-deja/g++.abi/vtable2.C.orig 2005-10-20 16:58:36.000000000 -0200
+++ gcc/testsuite/g++.old-deja/g++.abi/vtable2.C 2005-10-20 16:59:24.000000000 -0200
@@ -124,8 +124,8 @@
// These are tricks to allow us to get raw function pointers for
// member functions.
extern "C" {
-void _ZN2S32s3Ev ();
-void _ZN2S42s1Ev ();
+ void S3_s3 () __attribute__((__alias__ ("_ZN2S32s3Ev")));
+ void S4_s1 () __attribute__((__alias__ ("_ZN2S42s1Ev")));
}
// IA-64 uses function descriptors not function pointers in its vtables.
@@ -169,10 +169,10 @@
INC_VDATA (vtbl, 1);
// Skip the RTTI entry.
INC_VDATA (vtbl, 1);
- if (! CMP_VPTR (vtbl, &_ZN2S32s3Ev))
+ if (! CMP_VPTR (vtbl, &S3_s3))
return 5;
INC_VPTR (vtbl);
- if (! CMP_VPTR (vtbl, &_ZN2S42s1Ev))
+ if (! CMP_VPTR (vtbl, &S4_s1))
return 6;
INC_VPTR (vtbl);
// The S1 vbase offset.
Index: gcc/testsuite/gcc.dg/attr-alias-3.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/attr-alias-3.c 2005-10-20 16:59:24.000000000 -0200
@@ -0,0 +1,55 @@
+// { dg-do link }
+// { dg-require-alias "" }
+// { dg-options "-O2 -fno-common" }
+
+// Copyright 2005 Free Software Foundation, Inc.
+// Contributed by Alexandre Oliva <aoliva@redhat.com>
+
+// PR middle-end/24295
+
+// The unit-at-a-time call graph code used to fail to emit variables
+// without external linkage that were only used indirectly, through
+// aliases. Although the PR above is about #pragma weak-introduced
+// aliases, the underlying machinery is the same.
+
+#ifndef ATTRIBUTE_USED
+# define ATTRIBUTE_USED __attribute__((used))
+#endif
+
+static int lv1;
+extern int Av1a __attribute__((alias ("lv1")));
+int *pv1a = &Av1a;
+
+static int lv2;
+extern int Av2a __attribute__((alias ("lv2")));
+int *pv2a = &lv2;
+
+static int lv3;
+extern int Av3a __attribute__((alias ("lv3")));
+static int *pv3a ATTRIBUTE_USED = &Av3a;
+
+static int lv4;
+extern int Av4a __attribute__((alias ("lv4")));
+static int *pv4a = &Av4a;
+
+typedef void ftype(void);
+
+static void lf1(void) {}
+extern ftype Af1a __attribute__((alias ("lf1")));
+ftype *pf1a = &Af1a;
+
+static void lf2(void) {}
+extern ftype Af2a __attribute__((alias ("lf2")));
+ftype *pf2a = &Af2a;
+
+static void lf3(void) {}
+extern ftype Af3a __attribute__((alias ("lf3")));
+static ftype *pf3a ATTRIBUTE_USED = &Af3a;
+
+static void lf4(void) {}
+extern ftype Af4a __attribute__((alias ("lf4")));
+static ftype *pf4a = &Af4a;
+
+main() {
+ asm volatile ("" : : "m" (pv4a), "m" (pf4a));
+}
Index: gcc/testsuite/gcc.dg/weak/weak-14.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/weak/weak-14.c 2005-10-20 17:21:20.000000000 -0200
@@ -0,0 +1,33 @@
+// { dg-do run }
+// { dg-require-weak "" }
+// { dg-options "-O2 -fno-common" }
+
+// Copyright 2005 Free Software Foundation, Inc.
+// Contributed by Alexandre Oliva <aoliva@redhat.com>
+
+// PR middle-end/24295
+
+// The unit-at-a-time call graph code used to fail to emit variables
+// without external linkage that were only used indirectly, through
+// aliases. We might then get linker failures because the static
+// variable was not defined, or run-time errors because the weak alias
+// ended up pointing somewhere random.
+
+#include <stdlib.h>
+
+static unsigned long lv1 = 0xdeadbeefUL;
+#pragma weak Av1a = lv1
+extern unsigned long Av1a;
+
+static unsigned long lf1(void) { return 0x510bea7UL; }
+#pragma weak Af1a = lf1
+extern unsigned long Af1a(void);
+
+int main (void) {
+ if (! &Av1a
+ || ! &Af1a
+ || Av1a != 0xdeadbeefUL
+ || Af1a() != 0x510bea7UL)
+ abort ();
+ exit (0);
+}
--
Alexandre Oliva http://www.lsd.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist oliva@{lsd.ic.unicamp.br, gnu.org}