diff options
author | sirl <sirl@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-04-28 18:31:34 +0000 |
---|---|---|
committer | sirl <sirl@138bc75d-0d04-0410-961f-82ee72b054a4> | 2002-04-28 18:31:34 +0000 |
commit | 296c463e520419ac1adf0f5a90fd4c7470130451 (patch) | |
tree | bf07a3136b537dc0844e7c227d87d6ade6e858ef /gcc | |
parent | 2493f5d5862475a536a05867536687c5cdacd8b2 (diff) | |
download | gcc-296c463e520419ac1adf0f5a90fd4c7470130451.tar.gz |
2002-04-28 Franz Sirl <Franz.Sirl-kernel@lauterbach.com>
PR c/6343
* c-decl.c (duplicate_decls): Call merge_weak.
* c-pragma.c (apply_pragma_weak): Warn about misuse.
* output.h (merge_weak): Prototype merge_weak.
* varasm.c (merge_weak): New function.
(declare_weak): Make sure we don't give an error on VAR_DECLs.
Mark RTL with SYMBOL_REF_WEAK.
cp:
* decl.c (duplicate_decls): Call merge_weak.
testsuite:
* gcc.dg/weak-[2-7].c: New tests.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@52844 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/c-decl.c | 3 | ||||
-rw-r--r-- | gcc/c-pragma.c | 4 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/decl.c | 3 | ||||
-rw-r--r-- | gcc/output.h | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/weak-2.c | 53 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/weak-3.c | 78 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/weak-4.c | 111 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/weak-5.c | 116 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/weak-6.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/weak-7.c | 6 | ||||
-rw-r--r-- | gcc/varasm.c | 33 |
14 files changed, 432 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 60324ffa73d..4b62c60f3af 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2002-04-28 Franz Sirl <Franz.Sirl-kernel@lauterbach.com> + + PR c/6343 + * c-decl.c (duplicate_decls): Call merge_weak. + * c-pragma.c (apply_pragma_weak): Warn about misuse. + * output.h (merge_weak): Prototype merge_weak. + * varasm.c (merge_weak): New function. + (declare_weak): Make sure we don't give an error on VAR_DECLs. + Mark RTL with SYMBOL_REF_WEAK. + 2002-04-27 Kurt Garloff <garloff@suse.de> * tree-inline.c (inlinable_function_p): Improve heuristics diff --git a/gcc/c-decl.c b/gcc/c-decl.c index 9cef1874dc6..0898613ed9a 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -1843,7 +1843,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level) } /* Merge the storage class information. */ - DECL_WEAK (newdecl) |= DECL_WEAK (olddecl); + merge_weak (newdecl, olddecl); + /* For functions, static overrides non-static. */ if (TREE_CODE (newdecl) == FUNCTION_DECL) { diff --git a/gcc/c-pragma.c b/gcc/c-pragma.c index 4bf7ce205ac..d5df3559597 100644 --- a/gcc/c-pragma.c +++ b/gcc/c-pragma.c @@ -287,6 +287,10 @@ apply_pragma_weak (decl, value) decl_attributes (&decl, build_tree_list (get_identifier ("alias"), build_tree_list (NULL, value)), 0); + if (SUPPORTS_WEAK && DECL_EXTERNAL (decl) && TREE_USED (decl) + && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) + warning_with_decl (decl, "applying #pragma weak `%s' after first use results in unspecified behavior"); + declare_weak (decl); } diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 237d66964cd..61673813fd7 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2002-04-28 Franz Sirl <Franz.Sirl-kernel@lauterbach.com> + + PR c/6343 + * decl.c (duplicate_decls): Call merge_weak. + 2002-04-26 Richard Henderson <rth@redhat.com> * parse.y (malloced_yyss, malloced_yyvs): New. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index a260e11acc7..642fcf019d0 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3640,7 +3640,8 @@ duplicate_decls (newdecl, olddecl) } /* Merge the storage class information. */ - DECL_WEAK (newdecl) |= DECL_WEAK (olddecl); + merge_weak (newdecl, olddecl); + DECL_ONE_ONLY (newdecl) |= DECL_ONE_ONLY (olddecl); DECL_DEFER_OUTPUT (newdecl) |= DECL_DEFER_OUTPUT (olddecl); TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl); diff --git a/gcc/output.h b/gcc/output.h index b3426ce3263..67c635b3f17 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -231,6 +231,8 @@ extern void mergeable_constant_section PARAMS ((enum machine_mode, /* Declare DECL to be a weak symbol. */ extern void declare_weak PARAMS ((tree)); +/* Merge weak status. */ +extern void merge_weak PARAMS ((tree, tree)); #endif /* TREE_CODE */ /* Emit any pending weak declarations. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c7a4bed57fb..ab1c3422ecf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2002-04-28 Franz Sirl <Franz.Sirl-kernel@lauterbach.com> + + PR c/6343 + * gcc.dg/weak-[2-7].c: New tests. + 2002-04-26 Alexandre Oliva <aoliva@redhat.com> * gcc.dg/enum1.c: New test. diff --git a/gcc/testsuite/gcc.dg/weak-2.c b/gcc/testsuite/gcc.dg/weak-2.c new file mode 100644 index 00000000000..217220e359e --- /dev/null +++ b/gcc/testsuite/gcc.dg/weak-2.c @@ -0,0 +1,53 @@ +/* { dg-do compile } */ +/* { dg-options "-fno-common" } */ + +/* COFF does not support weak, and dg doesn't support UNSUPPORTED. */ +/* { dg-do compile { xfail *-*-coff i?86-pc-cygwin h8300-*-hms } } */ + +/* { dg-final { global target_triplet } } */ +/* { dg-final { if [string match h8300-*-hms $target_triplet ] {return} } } */ +/* { dg-final { if [string match i?86-pc-cygwin $target_triplet ] {return} } } */ +/* { dg-final { if [string match *-*-coff $target_triplet ] {return} } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]ffoo1a" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]ffoo1b" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]ffoo1c" } } */ +/* { dg-final { scan-assembler-not "weak\[^ \t\]*\[ \t\]ffoo1d" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]ffoo1e" } } */ + +/* test function addresses with #pragma weak */ + +#pragma weak ffoo1a +extern void * ffoo1a (void); +void * foo1a (void) +{ + return (void *)ffoo1a; +} + +extern void * ffoo1b (void); +#pragma weak ffoo1b +void * foo1b (void) +{ + return (void *)ffoo1b; +} + +extern void * ffoo1c (void); /* { dg-warning "applying #pragma weak" "applying #pragma weak" } */ +void * foo1c (void) +{ + return (void *)ffoo1c; +} +#pragma weak ffoo1c + + +int ffoo1d (void); +#pragma weak ffoo1d + + +extern void * ffoo1e (void); +#pragma weak ffoo1e +void * foo1e (void) +{ + if (ffoo1e) + ffoo1e (); + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/weak-3.c b/gcc/testsuite/gcc.dg/weak-3.c new file mode 100644 index 00000000000..bd7d827ee97 --- /dev/null +++ b/gcc/testsuite/gcc.dg/weak-3.c @@ -0,0 +1,78 @@ +/* { dg-do compile } */ +/* { dg-options "-fno-common" } */ + +/* COFF does not support weak, and dg doesn't support UNSUPPORTED. */ +/* { dg-do compile { xfail *-*-coff i?86-pc-cygwin h8300-*-hms } } */ + +/* { dg-final { global target_triplet } } */ +/* { dg-final { if [string match h8300-*-hms $target_triplet ] {return} } } */ +/* { dg-final { if [string match i?86-pc-cygwin $target_triplet ] {return} } } */ +/* { dg-final { if [string match *-*-coff $target_triplet ] {return} } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]ffoo1a" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]ffoo1b" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]ffoo1c" } } */ +/* { dg-final { scan-assembler-not "weak\[^ \t\]*\[ \t\]ffoo1d" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]ffoo1e" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]ffoo1f" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]ffoo1g" } } */ + +/* test function addresses with __attribute__((weak)) */ + +extern void * ffoo1a (void) __attribute__((weak)); +extern void * ffoo1a (void); +void * foo1a (void) +{ + return (void *)ffoo1a; +} + + +extern void * ffoo1b (void); +extern void * ffoo1b (void) __attribute__((weak)); +void * foo1b (void) +{ + return (void *)ffoo1b; +} + + +extern void * ffoo1c (void); /* { dg-warning "weak declaration" "weak declaration" } */ +void * foo1c (void) +{ + return (void *)ffoo1c; +} +extern void * ffoo1c (void) __attribute__((weak)); + + +int ffoo1d (void); +int ffoo1d (void) __attribute__((weak)); + + +extern void * ffoo1e (void); +extern void * ffoo1e (void) __attribute__((weak)); +void * foo1e (void) +{ + if (ffoo1e) + ffoo1e (); + return 0; +} + + +extern void * ffoo1f (void); /* { dg-warning "weak declaration" "weak declaration" } */ +extern void * ffoox1f (void); +void * foo1f (void) +{ + if (ffoo1f) + ffoo1f (); + return 0; +} +extern void * ffoo1f (void) __attribute__((weak, alias ("ffoox1f"))); + + +extern void * ffoo1g (void); +extern void * ffoox1g (void); +extern void * ffoo1g (void) __attribute__((weak, alias ("ffoox1g"))); +void * foo1g (void) +{ + if (ffoo1g) + ffoo1g (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/weak-4.c b/gcc/testsuite/gcc.dg/weak-4.c new file mode 100644 index 00000000000..c6bde1ea3fd --- /dev/null +++ b/gcc/testsuite/gcc.dg/weak-4.c @@ -0,0 +1,111 @@ +/* { dg-do compile } */ +/* { dg-options "-fno-common" } */ + +/* COFF does not support weak, and dg doesn't support UNSUPPORTED. */ +/* { dg-do compile { xfail *-*-coff i?86-pc-cygwin h8300-*-hms } } */ + +/* { dg-final { global target_triplet } } */ +/* { dg-final { if [string match h8300-*-hms $target_triplet ] {return} } } */ +/* { dg-final { if [string match i?86-pc-cygwin $target_triplet ] {return} } } */ +/* { dg-final { if [string match *-*-coff $target_triplet ] {return} } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1a" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1b" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1c" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1d" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1e" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1f" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1g" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1h" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1i" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1j" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1k" } } */ + +/* test variable addresses with #pragma weak */ + +#pragma weak vfoo1a +extern int vfoo1a; +void * foo1a (void) +{ + return (void *)&vfoo1a; +} + + +extern int vfoo1b; +#pragma weak vfoo1b +void * foo1b (void) +{ + return (void *)&vfoo1b; +} + + +extern int vfoo1c; /* { dg-warning "applying #pragma weak" "applying #pragma weak" } */ +void * foo1c (void) +{ + return (void *)&vfoo1c; +} +#pragma weak vfoo1c + + +#pragma weak vfoo1d +int vfoo1d; +void * foo1d (void) +{ + return (void *)&vfoo1d; +} + + +int vfoo1e; +#pragma weak vfoo1e +void * foo1e (void) +{ + return (void *)&vfoo1e; +} + + +int vfoo1f; +void * foo1f (void) +{ + return (void *)&vfoo1f; +} +#pragma weak vfoo1f + + +extern int vfoo1g; /* { dg-warning "applying #pragma weak" "applying #pragma weak" } */ +void * foo1g (void) +{ + return (void *)&vfoo1g; +} +#pragma weak vfoo1g +int vfoo1g; + + +extern int vfoo1h; +void * foo1h (void) +{ + return (void *)&vfoo1h; +} +int vfoo1h; +#pragma weak vfoo1h + + +int vfoo1i; +extern int vfoo1i; +void * foo1i (void) +{ + return (void *)&vfoo1i; +} +#pragma weak vfoo1i + + +extern int vfoo1j; +int vfoo1j; +void * foo1j (void) +{ + return (void *)&vfoo1j; +} +#pragma weak vfoo1j + + +#pragma weak vfoo1k +int vfoo1k = 1; + diff --git a/gcc/testsuite/gcc.dg/weak-5.c b/gcc/testsuite/gcc.dg/weak-5.c new file mode 100644 index 00000000000..694eb61ac1c --- /dev/null +++ b/gcc/testsuite/gcc.dg/weak-5.c @@ -0,0 +1,116 @@ +/* { dg-do compile } */ +/* { dg-options "-fno-common" } */ + +/* COFF does not support weak, and dg doesn't support UNSUPPORTED. */ +/* { dg-do compile { xfail *-*-coff i?86-pc-cygwin h8300-*-hms } } */ + +/* { dg-final { global target_triplet } } */ +/* { dg-final { if [string match h8300-*-hms $target_triplet ] {return} } } */ +/* { dg-final { if [string match i?86-pc-cygwin $target_triplet ] {return} } } */ +/* { dg-final { if [string match *-*-coff $target_triplet ] {return} } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1a" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1b" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1c" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1d" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1e" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1f" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1g" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1h" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1i" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1j" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1k" } } */ +/* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]vfoo1l" } } */ + +/* test variable addresses with __attribute__ ((weak)) */ + +extern int vfoo1a __attribute__((weak)); +extern int vfoo1a; +void * foo1a (void) +{ + return (void *)&vfoo1a; +} + + +extern int vfoo1b; +extern int vfoo1b __attribute__((weak)); +void * foo1b (void) +{ + return (void *)&vfoo1b; +} + + +extern int vfoo1c; /* { dg-warning "weak declaration" "weak declaration" } */ +void * foo1c (void) +{ + return (void *)&vfoo1c; +} +extern int vfoo1c __attribute__((weak)); + + +extern int vfoo1d __attribute__((weak)); +int vfoo1d; +void * foo1d (void) +{ + return (void *)&vfoo1d; +} + + +int vfoo1e; +extern int vfoo1e __attribute__((weak)); +void * foo1e (void) +{ + return (void *)&vfoo1e; +} + + +int vfoo1f; +void * foo1f (void) +{ + return (void *)&vfoo1f; +} +extern int vfoo1f __attribute__((weak)); + + +extern int vfoo1g; +void * foo1g (void) +{ + return (void *)&vfoo1g; +} +int vfoo1g __attribute__((weak)); + + +extern int vfoo1h __attribute__((weak)); +void * foo1h (void) +{ + return (void *)&vfoo1h; +} +extern int vfoo1h __attribute__((weak)); +int vfoo1h; + + +extern int vfoo1i __attribute__((weak)); +void * foo1i (void) +{ + return (void *)&vfoo1i; +} +extern int vfoo1i __attribute__((weak)); +extern int vfoo1i; + + +extern int vfoo1j __attribute__((weak)); +void * foo1j (void) +{ + return (void *)&vfoo1j; +} +extern int vfoo1j; +extern int vfoo1j __attribute__((weak)); + + +extern int vfoo1k __attribute__((weak)); +int vfoo1k = 1; + + +int vfoox1l = 1; +extern int vfoo1l __attribute__((alias ("vfoox1l"))); +extern int vfoo1l __attribute__((weak, alias ("vfoox1l"))); + diff --git a/gcc/testsuite/gcc.dg/weak-6.c b/gcc/testsuite/gcc.dg/weak-6.c new file mode 100644 index 00000000000..8f88a675d31 --- /dev/null +++ b/gcc/testsuite/gcc.dg/weak-6.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ + +extern void * foo (void); +void * foo (void) { return (void *)foo; } /* { dg-error "precede" } */ + +#pragma weak foo diff --git a/gcc/testsuite/gcc.dg/weak-7.c b/gcc/testsuite/gcc.dg/weak-7.c new file mode 100644 index 00000000000..64d6155a890 --- /dev/null +++ b/gcc/testsuite/gcc.dg/weak-7.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ + +extern void * foo (void); +void * foo (void) { return (void *)foo; } /* { dg-error "precede" } */ + +extern void * foo (void) __attribute__((weak)); diff --git a/gcc/varasm.c b/gcc/varasm.c index fc45cd8b0d0..4dbd09c6d9e 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -4989,6 +4989,31 @@ output_constructor (exp, size, align) to be emitted. */ static tree weak_decls; +/* Merge weak status between NEWDECL and OLDDECL. */ + +void +merge_weak (newdecl, olddecl) + tree newdecl; + tree olddecl; +{ + tree decl; + + if (DECL_WEAK (newdecl) == DECL_WEAK (olddecl)) + return; + + decl = DECL_WEAK (olddecl) ? newdecl : olddecl; + + if (SUPPORTS_WEAK + && DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl) + && (TREE_CODE (decl) != VAR_DECL + || ! TREE_STATIC (decl)) + && TREE_USED (decl) + && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) + warning_with_decl (decl, "weak declaration of `%s' after first use results in unspecified behavior"); + + declare_weak (decl); +} + /* Declare DECL to be a weak symbol. */ void @@ -4997,7 +5022,7 @@ declare_weak (decl) { if (! TREE_PUBLIC (decl)) error_with_decl (decl, "weak declaration of `%s' must be public"); - else if (TREE_ASM_WRITTEN (decl)) + else if (TREE_CODE (decl) == FUNCTION_DECL && TREE_ASM_WRITTEN (decl)) error_with_decl (decl, "weak declaration of `%s' must precede definition"); else if (SUPPORTS_WEAK) { @@ -5008,6 +5033,12 @@ declare_weak (decl) warning_with_decl (decl, "weak declaration of `%s' not supported"); DECL_WEAK (decl) = 1; + + if (DECL_RTL_SET_P (decl) + && GET_CODE (DECL_RTL (decl)) == MEM + && XEXP (DECL_RTL (decl), 0) + && GET_CODE (XEXP (DECL_RTL (decl), 0)) == SYMBOL_REF) + SYMBOL_REF_WEAK (XEXP (DECL_RTL (decl), 0)) = 1; } /* Emit any pending weak declarations. */ |