The 'weakref' attribute is defined in terms of aliases. Now, if the user writes
void foo(void) { } void bar(void) __attribute__((alias ("foo"))); then that causes 'bar' to be defined. Other translation units can use 'bar'. If 'weakref' is to define an alias, it should behave the same way. Unfortunately, it can't do that; Mach-O (on Darwin) doesn't support aliases in the object file at all, and even ELF doesn't support aliases to symbols outside the current .o. The easiest solution to this is to require that weakrefs must be 'static', because the name that they define is not visible outside this translation unit. There's an additional wrinkle, which is although this name is 'static', it is also 'weak' because it can be NULL. So we have introduced a new concept, a static weak name. Fortunately it is limited to just this one case. I couldn't fully test this patch because weakrefs still don't seem to be working properly on Darwin. However, the testcases do compile successfully. Sorry I didn't say anything earlier about Alexandre's proposal, I thought that it implied that in fact ELF did have this capability. What do people think? Obviously this should be settled before 4.1 ships... -- - Geoffrey Keating <[EMAIL PROTECTED]> ===File ~/patches/gcc-weakrefstatic-0.patch================= Index: gcc/ChangeLog 2005-12-01 Geoffrey Keating <[EMAIL PROTECTED]> * doc/extend.texi (Function Attributes): Mention that an alias attribute creates a definition for the thing it's attached to. Change the documentation for weakref to say that the thing it's attached to must be static. ... other changes Index: gcc/doc/extend.texi =================================================================== --- gcc/doc/extend.texi (revision 107814) +++ gcc/doc/extend.texi (working copy) @@ -1554,7 +1554,7 @@ void f () __attribute__ ((weak, alias ("__f"))); @end smallexample -declares @samp{f} to be a weak alias for @samp{__f}. In C++, the +defines @samp{f} to be a weak alias for @samp{__f}. In C++, the mangled name for the target must be used. It is an error if @samp{__f} is not defined in the same translation unit. @@ -2376,12 +2376,12 @@ @code{weakref} is equivalent to @code{weak}. @smallexample -extern int x() __attribute__ ((weakref ("y"))); +static int x() __attribute__ ((weakref ("y"))); /* is equivalent to... */ -extern int x() __attribute__ ((weak, weakref, alias ("y"))); +static int x() __attribute__ ((weak, weakref, alias ("y"))); /* and to... */ -extern int x() __attribute__ ((weakref)); -extern int x() __attribute__ ((alias ("y"))); +static int x() __attribute__ ((weakref)); +static int x() __attribute__ ((alias ("y"))); @end smallexample A weak reference is an alias that does not by itself require a @@ -2396,6 +2396,9 @@ declaring it as weak, compiling the two separate translation units and performing a reloadable link on them. +At present, a declaration to which @code{weakref} is attached can +only be @code{static}. + @item externally_visible @cindex @code{externally_visible} attribute. This attribute, attached to a global variable or function nullify Index: gcc/testsuite/gcc.dg/attr-weakref-1.c =================================================================== --- gcc/testsuite/gcc.dg/attr-weakref-1.c (revision 107814) +++ gcc/testsuite/gcc.dg/attr-weakref-1.c (working copy) @@ -26,37 +26,32 @@ typedef int vtype; extern vtype wv1; -extern vtype Wv1a __attribute__((weakref ("wv1"))); +static vtype Wv1a __attribute__((weakref ("wv1"))); static vtype *pv1a USED = &Wv1a; -extern vtype Wv1b __attribute__((weak, weakref, alias ("wv1"))); -static vtype *pv1b USED = &Wv1b; -extern vtype Wv1c __attribute__((weakref)); -extern vtype Wv1c __attribute__((alias ("wv1"))); -static vtype *pv1c USED = &Wv1c; vtype gv2; -extern vtype Wv2a __attribute__((weakref ("gv2"))); +static vtype Wv2a __attribute__((weakref ("gv2"))); static vtype *pv2a USED = &Wv2a; static vtype lv3; -extern vtype Wv3a __attribute__((weakref ("lv3"))); +static vtype Wv3a __attribute__((weakref ("lv3"))); static vtype *pv3a USED = &Wv3a; extern vtype uv4; -extern vtype Wv4a __attribute__((weakref ("uv4"))); +static vtype Wv4a __attribute__((weakref ("uv4"))); static vtype *pv4a USED = &Wv4a; static vtype *pv4 USED = &uv4; -extern vtype Wv5a __attribute__((weakref ("uv5"))); +static vtype Wv5a __attribute__((weakref ("uv5"))); static vtype *pv5a USED = &Wv5a; extern vtype uv5; static vtype *pv5 USED = &uv5; -extern vtype Wv6a __attribute__((weakref ("wv6"))); +static vtype Wv6a __attribute__((weakref ("wv6"))); static vtype *pv6a USED = &Wv6a; extern vtype wv6; -extern vtype Wv7a __attribute__((weakref ("uv7"))); +static vtype Wv7a __attribute__((weakref ("uv7"))); static vtype* USED fv7 (void) { return &Wv7a; } @@ -69,71 +64,69 @@ static vtype* USED fv8a (void) { return &uv8; } -extern vtype Wv8a __attribute__((weakref ("uv8"))); +static vtype Wv8a __attribute__((weakref ("uv8"))); static vtype* USED fv8 (void) { return &Wv8a; } extern vtype wv9 __attribute__((weak)); -extern vtype Wv9a __attribute__((weakref ("wv9"))); +static vtype Wv9a __attribute__((weakref ("wv9"))); static vtype *pv9a USED = &Wv9a; -extern vtype Wv10a __attribute__((weakref ("Wv10b"))); -extern vtype Wv10b __attribute__((weakref ("Wv10c"))); -extern vtype Wv10c __attribute__((weakref ("Wv10d"))); -extern vtype Wv10d __attribute__((weakref ("wv10"))); +static vtype Wv10a __attribute__((weakref ("Wv10b"))); +static vtype Wv10b __attribute__((weakref ("Wv10c"))); +static vtype Wv10c __attribute__((weakref ("Wv10d"))); +static vtype Wv10d __attribute__((weakref ("wv10"))); extern vtype wv10; extern vtype wv11; -extern vtype Wv11d __attribute__((weakref ("wv11"))); -extern vtype Wv11c __attribute__((weakref ("Wv11d"))); -extern vtype Wv11b __attribute__((weakref ("Wv11c"))); -extern vtype Wv11a __attribute__((weakref ("Wv11b"))); +static vtype Wv11d __attribute__((weakref ("wv11"))); +static vtype Wv11c __attribute__((weakref ("Wv11d"))); +static vtype Wv11b __attribute__((weakref ("Wv11c"))); +static vtype Wv11a __attribute__((weakref ("Wv11b"))); -extern vtype Wv12 __attribute__((weakref ("wv12"))); +static vtype Wv12 __attribute__((weakref ("wv12"))); extern vtype wv12 __attribute__((weak)); -extern vtype Wv13 __attribute__((weakref ("wv13"))); +static vtype Wv13 __attribute__((weakref ("wv13"))); extern vtype wv13 __attribute__((weak)); -extern vtype Wv14a __attribute__((weakref ("wv14"))); -extern vtype Wv14b __attribute__((weakref ("wv14"))); +static vtype Wv14a __attribute__((weakref ("wv14"))); +static vtype Wv14b __attribute__((weakref ("wv14"))); extern vtype wv14 __attribute__((weak)); typedef void ftype(void); extern ftype wf1; -extern ftype Wf1a __attribute__((weakref ("wf1"))); +static ftype Wf1a __attribute__((weakref ("wf1"))); static ftype *pf1a USED = &Wf1a; -extern ftype Wf1b __attribute__((weak, weakref, alias ("wf1"))); -static ftype *pf1b USED = &Wf1b; -extern ftype Wf1c __attribute__((weakref)); +static ftype Wf1c __attribute__((weakref)); extern ftype Wf1c __attribute__((alias ("wf1"))); static ftype *pf1c USED = &Wf1c; void gf2(void) {} -extern ftype Wf2a __attribute__((weakref ("gf2"))); +static ftype Wf2a __attribute__((weakref ("gf2"))); static ftype *pf2a USED = &Wf2a; static void lf3(void) {} -extern ftype Wf3a __attribute__((weakref ("lf3"))); +static ftype Wf3a __attribute__((weakref ("lf3"))); static ftype *pf3a USED = &Wf3a; extern ftype uf4; -extern ftype Wf4a __attribute__((weakref ("uf4"))); +static ftype Wf4a __attribute__((weakref ("uf4"))); static ftype *pf4a USED = &Wf4a; static ftype *pf4 USED = &uf4; -extern ftype Wf5a __attribute__((weakref ("uf5"))); +static ftype Wf5a __attribute__((weakref ("uf5"))); static ftype *pf5a USED = &Wf5a; extern ftype uf5; static ftype *pf5 USED = &uf5; -extern ftype Wf6a __attribute__((weakref ("wf6"))); +static ftype Wf6a __attribute__((weakref ("wf6"))); static ftype *pf6a USED = &Wf6a; extern ftype wf6; -extern ftype Wf7a __attribute__((weakref ("uf7"))); +static ftype Wf7a __attribute__((weakref ("uf7"))); static ftype* USED ff7 (void) { return &Wf7a; } @@ -146,43 +139,41 @@ static ftype* USED ff8a (void) { return &uf8; } -extern ftype Wf8a __attribute__((weakref ("uf8"))); +static ftype Wf8a __attribute__((weakref ("uf8"))); static ftype* USED ff8 (void) { return &Wf8a; } extern ftype wf9 __attribute__((weak)); -extern ftype Wf9a __attribute__((weakref ("wf9"))); +static ftype Wf9a __attribute__((weakref ("wf9"))); static ftype *pf9a USED = &Wf9a; -extern ftype Wf10a __attribute__((weakref ("Wf10b"))); -extern ftype Wf10b __attribute__((weakref ("Wf10c"))); -extern ftype Wf10c __attribute__((weakref ("Wf10d"))); -extern ftype Wf10d __attribute__((weakref ("wf10"))); +static ftype Wf10a __attribute__((weakref ("Wf10b"))); +static ftype Wf10b __attribute__((weakref ("Wf10c"))); +static ftype Wf10c __attribute__((weakref ("Wf10d"))); +static ftype Wf10d __attribute__((weakref ("wf10"))); extern ftype wf10; extern ftype wf11; -extern ftype Wf11d __attribute__((weakref ("wf11"))); -extern ftype Wf11c __attribute__((weakref ("Wf11d"))); -extern ftype Wf11b __attribute__((weakref ("Wf11c"))); -extern ftype Wf11a __attribute__((weakref ("Wf11b"))); +static ftype Wf11d __attribute__((weakref ("wf11"))); +static ftype Wf11c __attribute__((weakref ("Wf11d"))); +static ftype Wf11b __attribute__((weakref ("Wf11c"))); +static ftype Wf11a __attribute__((weakref ("Wf11b"))); -extern ftype Wf12 __attribute__((weakref ("wf12"))); +static ftype Wf12 __attribute__((weakref ("wf12"))); extern ftype wf12 __attribute__((weak)); -extern ftype Wf13 __attribute__((weakref ("wf13"))); +static ftype Wf13 __attribute__((weakref ("wf13"))); extern ftype wf13 __attribute__((weak)); -extern ftype Wf14a __attribute__((weakref ("wf14"))); -extern ftype Wf14b __attribute__((weakref ("wf14"))); +static ftype Wf14a __attribute__((weakref ("wf14"))); +static ftype Wf14b __attribute__((weakref ("wf14"))); extern ftype wf14 __attribute__((weak)); #define chk(p) do { if (!p) abort (); } while (0) int main () { chk (!pv1a); - chk (!pv1b); - chk (!pv1c); chk (pv2a); chk (pv3a); chk (pv4a); @@ -203,7 +194,6 @@ chk (!&Wv14a); chk (!pf1a); - chk (!pf1b); chk (!pf1c); chk (pf2a); chk (pf3a); Index: gcc/testsuite/gcc.dg/attr-weakref-2.c =================================================================== --- gcc/testsuite/gcc.dg/attr-weakref-2.c (revision 0) +++ gcc/testsuite/gcc.dg/attr-weakref-2.c (revision 0) @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-require-weak "" } */ + +typedef int vtype; + +extern vtype wv1; +extern vtype Wv1a __attribute__((weakref ("wv1"))); /* { dg-error "weakref 'Wv1a' must have static linkage" } */ Index: gcc/testsuite/g++.old-deja/g++.abi/vtable2.C =================================================================== --- gcc/testsuite/g++.old-deja/g++.abi/vtable2.C (revision 107814) +++ gcc/testsuite/g++.old-deja/g++.abi/vtable2.C (working copy) @@ -127,8 +127,8 @@ /* We can use weakref here without dg-require-weak, because we know the symbols are defined, so we don't actually issue the .weak directives. */ - void S3_s3 () __attribute__((__weakref__ ("_ZN2S32s3Ev"))); - void S4_s1 () __attribute__((__weakref__ ("_ZN2S42s1Ev"))); + static void S3_s3 () __attribute__((__weakref__ ("_ZN2S32s3Ev"))); + static void S4_s1 () __attribute__((__weakref__ ("_ZN2S42s1Ev"))); } // IA-64 uses function descriptors not function pointers in its vtables. Index: gcc/gthr-dce.h =================================================================== --- gcc/gthr-dce.h (revision 107814) +++ gcc/gthr-dce.h (working copy) @@ -64,7 +64,7 @@ #if SUPPORTS_WEAK && GTHREAD_USE_WEAK # define __gthrw(name) \ - extern __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name))) + static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name))) #else # define __gthrw_asmname(cname) __gthrw_asmnamep (__USER_LABEL_PREFIX__, cname) # define __gthrw_asmnamep(prefix, cname) __gthrw_string (prefix) cname Index: gcc/varasm.c =================================================================== --- gcc/varasm.c (revision 107814) +++ gcc/varasm.c (working copy) @@ -4508,10 +4508,6 @@ if (! TREE_USED (decl)) return; - if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)) - && lookup_attribute ("alias", DECL_ATTRIBUTES (decl))) - return; - #ifdef ASM_WEAKEN_DECL ASM_WEAKEN_DECL (asm_out_file, decl, name, NULL); #else @@ -4878,6 +4874,8 @@ TREE_CHAIN (alias) = target; #endif } + if (TREE_PUBLIC (decl)) + error ("weakref %q+D must have static linkage", decl); } else { Index: gcc/c-common.c =================================================================== --- gcc/c-common.c (revision 107814) +++ gcc/c-common.c (working copy) @@ -4757,7 +4757,12 @@ tree decl = *node; if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl)) - || (TREE_CODE (decl) != FUNCTION_DECL && !DECL_EXTERNAL (decl))) + || (TREE_CODE (decl) != FUNCTION_DECL + && TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl)) + /* A static variable declaration is always a tentative definition, + but the alias is a non-tentative definition which overrides. */ + || (TREE_CODE (decl) != FUNCTION_DECL + && ! TREE_PUBLIC (decl) && DECL_INITIAL (decl))) { error ("%q+D defined both normally and as an alias", decl); *no_add_attrs = true; @@ -4822,6 +4827,8 @@ attr = tree_cons (get_identifier ("weakref"), NULL_TREE, attr); *no_add_attrs = true; + + decl_attributes (node, attr, flags); } else { @@ -4829,11 +4836,12 @@ error ("%Jweakref attribute must appear before alias attribute", *node); - attr = tree_cons (get_identifier ("weak"), NULL_TREE, attr); + /* Can't call declare_weak because it wants this to be TREE_PUBLIC, + and that isn't supported; and because it wants to add it to + the list of weak decls, which isn't helpful. */ + DECL_WEAK (*node) = 1; } - decl_attributes (node, attr, flags); - return NULL_TREE; } Index: gcc/gthr-tpf.h =================================================================== --- gcc/gthr-tpf.h (revision 107814) +++ gcc/gthr-tpf.h (working copy) @@ -70,7 +70,7 @@ #if SUPPORTS_WEAK && GTHREAD_USE_WEAK # define __gthrw(name) \ - extern __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name))) + static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name))) #else # define __gthrw_asmname(cname) __gthrw_asmnamep (__USER_LABEL_PREFIX__, cname) # define __gthrw_asmnamep(prefix, cname) __gthrw_string (prefix) cname Index: gcc/gthr-solaris.h =================================================================== --- gcc/gthr-solaris.h (revision 107814) +++ gcc/gthr-solaris.h (working copy) @@ -58,7 +58,7 @@ #if SUPPORTS_WEAK && GTHREAD_USE_WEAK # define __gthrw(name) \ - extern __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name))) + static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name))) #else # define __gthrw_asmname(cname) __gthrw_asmnamep (__USER_LABEL_PREFIX__, cname) # define __gthrw_asmnamep(prefix, cname) __gthrw_string (prefix) cname Index: gcc/gthr-posix.h =================================================================== --- gcc/gthr-posix.h (revision 107814) +++ gcc/gthr-posix.h (working copy) @@ -60,7 +60,7 @@ #if SUPPORTS_WEAK && GTHREAD_USE_WEAK # define __gthrw(name) \ - extern __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name))) + static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name))) #else # define __gthrw_asmname(cname) __gthrw_asmnamep (__USER_LABEL_PREFIX__, cname) # define __gthrw_asmnamep(prefix, cname) __gthrw_string (prefix) cname Index: gcc/config/darwin.c =================================================================== --- gcc/config/darwin.c (revision 107814) +++ gcc/config/darwin.c (working copy) @@ -1026,7 +1026,10 @@ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED) { void (*base_function)(void); - bool weak_p = DECL_P (exp) && DECL_WEAK (exp); + bool weak_p = (DECL_P (exp) && DECL_WEAK (exp) + && (lookup_attribute ("weak", DECL_ATTRIBUTES (exp)) + || ! lookup_attribute ("weak_import", + DECL_ATTRIBUTES (exp)))); static void (* const base_funs[][2])(void) = { { text_section, text_coal_section }, { unlikely_text_section, text_unlikely_coal_section }, Index: gcc/gthr-posix95.h =================================================================== --- gcc/gthr-posix95.h (revision 107814) +++ gcc/gthr-posix95.h (working copy) @@ -58,7 +58,7 @@ #if SUPPORTS_WEAK && GTHREAD_USE_WEAK # define __gthrw(name) \ - extern __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name))) + static __typeof(name) __gthrw_ ## name __attribute__ ((__weakref__(#name))) #else # define __gthrw_asmname(cname) __gthrw_asmnamep (__USER_LABEL_PREFIX__, cname) # define __gthrw_asmnamep(prefix, cname) __gthrw_string (prefix) cname ============================================================