+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
}
/* 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)
{
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);
}
+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.
}
/* 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);
/* 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. */
+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.
--- /dev/null
+/* { 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;
+}
+
--- /dev/null
+/* { 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;
+}
--- /dev/null
+/* { 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;
+
--- /dev/null
+/* { 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")));
+
--- /dev/null
+/* { dg-do compile } */
+
+extern void * foo (void);
+void * foo (void) { return (void *)foo; } /* { dg-error "precede" } */
+
+#pragma weak foo
--- /dev/null
+/* { dg-do compile } */
+
+extern void * foo (void);
+void * foo (void) { return (void *)foo; } /* { dg-error "precede" } */
+
+extern void * foo (void) __attribute__((weak));
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
{
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)
{
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. */