aboutsummaryrefslogtreecommitdiff
path: root/gcc/varasm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r--gcc/varasm.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/gcc/varasm.c b/gcc/varasm.c
index fc45cd8..4dbd09c 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. */