re PR c/6343 (attribute((weak)) not working on second declaration)
authorFranz Sirl <Franz.Sirl-kernel@lauterbach.com>
Sun, 28 Apr 2002 18:31:34 +0000 (18:31 +0000)
committerFranz Sirl <sirl@gcc.gnu.org>
Sun, 28 Apr 2002 18:31:34 +0000 (18:31 +0000)
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.

From-SVN: r52844

14 files changed:
gcc/ChangeLog
gcc/c-decl.c
gcc/c-pragma.c
gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/output.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/weak-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/weak-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/weak-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/weak-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/weak-6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/weak-7.c [new file with mode: 0644]
gcc/varasm.c

index 60324ffa73dfdc4be145611f712752efadfd2b4e..4b62c60f3af380d9746f8134a6a6b20bc00e043e 100644 (file)
@@ -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
index 9cef1874dc68e22b48f41fe0572a96e0b4e5262d..0898613ed9a2b12324fae9e74dc142b44266af84 100644 (file)
@@ -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)
     {
index 4bf7ce205ac21214a8ad9916201bba80473191b9..d5df35595975e07d7b593e5f25710825c2f35c9d 100644 (file)
@@ -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);
 }
 
index 237d66964cde4c142426c0325f62a90e9e6a70b5..61673813fd7052b53a36a35e083095b2543af62b 100644 (file)
@@ -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.
index a260e11acc7b451f5193196e2a1428025fc9d96b..642fcf019d05077585ac08dbbd36ce0e6402c3ba 100644 (file)
@@ -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);
index b3426ce3263619156cdf509660d3b15d2f0ab7c6..67c635b3f177145ca80087cf4ca9534c3c150973 100644 (file)
@@ -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.  */
index c7a4bed57fb90686f136476543125a530a08ac52..ab1c3422ecf15d478b699f0d0e86e793c1750b53 100644 (file)
@@ -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 (file)
index 0000000..217220e
--- /dev/null
@@ -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 (file)
index 0000000..bd7d827
--- /dev/null
@@ -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 (file)
index 0000000..c6bde1e
--- /dev/null
@@ -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 (file)
index 0000000..694eb61
--- /dev/null
@@ -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 (file)
index 0000000..8f88a67
--- /dev/null
@@ -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 (file)
index 0000000..64d6155
--- /dev/null
@@ -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));
index fc45cd8b0d0092c7366107836dc096a57c55ee7a..4dbd09c6d9ea56abbf8463f90ea2e31f34cf2949 100644 (file)
@@ -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.  */