Commit 45806a3f by Franz Sirl Committed by Franz Sirl

re PR c/6343 (attribute((weak)) not working on second declaration)

	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
parent 32c8d100
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
......
......@@ -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)
{
......
......@@ -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);
}
......
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.
......
......@@ -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);
......
......@@ -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. */
......
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.
......
/* { 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;
}
/* { 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;
}
/* { 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;
/* { 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")));
/* { dg-do compile } */
extern void * foo (void);
void * foo (void) { return (void *)foo; } /* { dg-error "precede" } */
#pragma weak foo
/* { dg-do compile } */
extern void * foo (void);
void * foo (void) { return (void *)foo; } /* { dg-error "precede" } */
extern void * foo (void) __attribute__((weak));
......@@ -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. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment