This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: f build dies with: undefined reference to `lookup_name'
On Thu, Mar 07, 2002 at 09:48:29AM +1030, Alan Modra wrote:
> How about looking through the weak_decls list from pushdecl?
This seems to work. Tested by building c,c++,f powerpc64-linux, and
using the following testcase.
cat >weakf.c <<EOF
extern int foo (void) __attribute__ ((weak));
#pragma weak bar
extern int bar (void);
extern int var1 __attribute__ ((weak));
#pragma weak var2
extern int var2;
extern int def (void) __attribute__ ((weak));
int def (void) { return var1; }
#pragma weak zzz = def
#pragma weak xxx = def2
#pragma weak def2
int def2 (void) { return var2; }
#pragma weak oops
static int oops (void) { return zzz () + xxx (); }
int main (void)
{
if (foo)
return (*foo) ();
if (bar)
return (*bar) ();
if (&var1)
return var1;
if (&var2)
return var2;
return def ();
}
EOF
powerpc-linux and i686-linux bootstrap in progress.
BTW, how should we treat "#pragma weak foo = foo" ? My c-pragma.c patch
makes it the same as "#pragma weak foo", but maybe an error is more
appropriate. This change (or doing something slightly different in
decl_pending_weak) is necessary as decl_pending_weak needs to look
through the weak list twice to handle:
#pragma weak fun
#pragma weak fun2 = fun
int fun (void);
gcc/ChangeLog
* c-decl.c (pushdecl): Call decl_pending_weak.
* output.h (decl_pending_weak): Declare.
* varasm.c (weak_decls_tail): New.
(add_weak): Manipulate weak_decls_tail.
(decl_pending_weak): New.
(weak_finish): Don't lookup_name here.
(remove_from_pending_weak_list): Fix up weak_decls_tail. Don't
strcmp identifiers.
* c-pragma.c (handle_pragma_weak): Try to find a decl for value.
Check value != name.
gcc/cp/ChangeLog
* decl.c (pushdecl): Call decl_pending_weak.
Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.305
diff -u -p -r1.305 c-decl.c
--- c-decl.c 2002/03/05 02:34:05 1.305
+++ c-decl.c 2002/03/07 02:44:37
@@ -2242,6 +2242,14 @@ pushdecl (x)
IDENTIFIER_GLOBAL_VALUE (name) = x;
+ /* Check for a function or var decl weakened by "#pragma weak". */
+ if ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
+ && decl_pending_weak (x))
+ {
+ TREE_PUBLIC (name) = 1;
+ DECL_WEAK (x) = 1;
+ }
+
/* We no longer care about any previous block level declarations. */
IDENTIFIER_LIMBO_VALUE (name) = 0;
Index: c-pragma.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-pragma.c,v
retrieving revision 1.47
diff -u -p -r1.47 c-pragma.c
--- c-pragma.c 2002/03/01 06:00:32 1.47
+++ c-pragma.c 2002/03/07 02:44:37
@@ -26,6 +26,7 @@ Software Foundation, 59 Temple Place - S
#include "function.h"
#include "cpplib.h"
#include "c-pragma.h"
+#include "c-tree.h"
#include "flags.h"
#include "toplev.h"
#include "ggc.h"
@@ -281,8 +282,9 @@ static void
handle_pragma_weak (dummy)
cpp_reader *dummy ATTRIBUTE_UNUSED;
{
- tree name, value, x;
+ tree name, value, x, decl;
enum cpp_ttype t;
+ const char *valstr;
value = 0;
@@ -298,8 +300,14 @@ handle_pragma_weak (dummy)
if (t != CPP_EOF)
warning ("junk at end of #pragma weak");
- add_weak (NULL_TREE, IDENTIFIER_POINTER (name),
- value ? IDENTIFIER_POINTER (value) : NULL);
+ decl = NULL_TREE;
+ valstr = NULL;
+ if (value && value != name)
+ {
+ decl = lookup_name (value);
+ valstr = IDENTIFIER_POINTER (value);
+ }
+ add_weak (decl, IDENTIFIER_POINTER (name), valstr);
}
#endif
Index: output.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/output.h,v
retrieving revision 1.96
diff -u -p -r1.96 output.h
--- output.h 2002/03/01 06:00:33 1.96
+++ output.h 2002/03/07 02:44:37
@@ -231,6 +231,10 @@ extern void mergeable_constant_section P
/* Declare DECL to be a weak symbol. */
extern void declare_weak PARAMS ((tree));
+
+/* Look for DECL on "#pragma weak" list. If found return 1 and tie
+ decl to list, otherwise return 0. */
+extern int decl_pending_weak PARAMS ((tree));
#endif /* TREE_CODE */
/* Emit any pending weak declarations. */
Index: varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.255
diff -u -p -r1.255 varasm.c
--- varasm.c 2002/03/03 04:50:53 1.255
+++ varasm.c 2002/03/07 02:44:43
@@ -42,7 +42,6 @@ Software Foundation, 59 Temple Place - S
#include "obstack.h"
#include "hashtab.h"
#include "c-pragma.h"
-#include "c-tree.h"
#include "ggc.h"
#include "langhooks.h"
#include "tm_p.h"
@@ -5036,6 +5035,7 @@ struct weak_syms
};
static struct weak_syms * weak_decls;
+static struct weak_syms ** weak_decls_tail = &weak_decls;
/* Mark weak_decls for garbage collection. */
@@ -5050,7 +5050,8 @@ mark_weak_decls (arg)
}
/* Add function NAME to the weak symbols list. VALUE is a weak alias
- associated with NAME. */
+ associated with NAME. IF DECL is 0, we are being called from
+ #pragma weak handler. *WEAK_DECLS_TAIL points to such entries. */
int
add_weak (decl, name, value)
@@ -5065,15 +5066,53 @@ add_weak (decl, name, value)
if (weak == NULL)
return 0;
- weak->next = weak_decls;
weak->decl = decl;
weak->name = name;
weak->value = value;
- weak_decls = weak;
+ weak->next = *weak_decls_tail;
+ *weak_decls_tail = weak;
+ if (decl)
+ weak_decls_tail = &weak->next;
return 1;
}
+/* Look for DECL on "#pragma weak" list. If found return 1 and tie
+ decl to list, otherwise return 0. */
+
+int
+decl_pending_weak (decl)
+ tree decl;
+{
+ const char *name = IDENTIFIER_POINTER (DECL_NAME (decl));
+ struct weak_syms **p;
+ struct weak_syms *weak;
+
+ for (p = weak_decls_tail; (weak = *p) != NULL; p = &weak->next)
+ if (weak->value == name)
+ {
+ weak->decl = decl;
+ *p = weak->next;
+ weak->next = *weak_decls_tail;
+ *weak_decls_tail = weak;
+ weak_decls_tail = &weak->next;
+ break;
+ }
+
+ for (p = weak_decls_tail; (weak = *p) != NULL; p = &weak->next)
+ if (weak->name == name)
+ {
+ weak->decl = decl;
+ *p = weak->next;
+ weak->next = *weak_decls_tail;
+ *weak_decls_tail = weak;
+ weak_decls_tail = &weak->next;
+ return 1;
+ }
+
+ return 0;
+}
+
/* Declare DECL to be a weak symbol. */
void
@@ -5103,14 +5142,7 @@ weak_finish ()
for (t = weak_decls; t != NULL; t = t->next)
{
#ifdef ASM_WEAKEN_DECL
- tree decl = t->decl;
- if (decl == NULL_TREE)
- {
- tree name = get_identifier (t->name);
- if (name)
- decl = lookup_name (name);
- }
- ASM_WEAKEN_DECL (asm_out_file, decl, t->name, t->value);
+ ASM_WEAKEN_DECL (asm_out_file, t->decl, t->name, t->value);
#else
#ifdef ASM_OUTPUT_WEAK_ALIAS
ASM_OUTPUT_WEAK_ALIAS (asm_out_file, t->name, t->value);
@@ -5140,9 +5172,11 @@ remove_from_pending_weak_list (name)
for (p = &weak_decls; *p; )
{
t = *p;
- if (strcmp (name, t->name) == 0)
+ if (name == t->name)
{
*p = t->next;
+ if (weak_decls_tail == &t->next)
+ weak_decls_tail = p;
free (t);
}
else
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.869
diff -u -p -r1.869 decl.c
--- decl.c 2002/03/03 14:07:29 1.869
+++ decl.c 2002/03/07 02:44:58
@@ -4087,6 +4087,14 @@ pushdecl (x)
|| TREE_CODE (x) == TEMPLATE_DECL))
SET_IDENTIFIER_NAMESPACE_VALUE (name, x);
+ /* Check for a function or var decl weakened by "#pragma weak". */
+ if ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
+ && decl_pending_weak (x))
+ {
+ TREE_PUBLIC (name) = 1;
+ DECL_WEAK (x) = 1;
+ }
+
/* Don't forget if the function was used via an implicit decl. */
if (IDENTIFIER_IMPLICIT_DECL (name)
&& TREE_USED (IDENTIFIER_IMPLICIT_DECL (name)))