mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-22 15:11:15 +08:00
re PR c/19031 (#pragma weak handling changes in 4.0.0)
PR c/19031 * c-decl.c (pop_file_scope): Call maybe_apply_pending_pragma_weaks. * c-lang.c (finish_file): Don't do it here. * objc/objc-act.c (objc_finish_file): Likewise. * cgraph.c (decl_assembler_name_equal): New. (cgraph_node_for_asm, cgraph_varpool_node_for_asm): New. (cgraph_varpool_node): Actually link up cgraph_varpool_nodes. * cgraph.h (struct cgraph_varpool_node): Add next. (cgraph_node_for_asm, cgraph_varpool_node_for_asm): Declare. * varasm.c (assemble_alias): Mark the target as needed. From-SVN: r92803
This commit is contained in:
parent
1cb2fc7b18
commit
bedb9fc04b
@ -1,3 +1,17 @@
|
||||
2005-01-01 Richard Henderson <rth@redhat.com>
|
||||
|
||||
PR c/19031
|
||||
* c-decl.c (pop_file_scope): Call maybe_apply_pending_pragma_weaks.
|
||||
* c-lang.c (finish_file): Don't do it here.
|
||||
* objc/objc-act.c (objc_finish_file): Likewise.
|
||||
|
||||
* cgraph.c (decl_assembler_name_equal): New.
|
||||
(cgraph_node_for_asm, cgraph_varpool_node_for_asm): New.
|
||||
(cgraph_varpool_node): Actually link up cgraph_varpool_nodes.
|
||||
* cgraph.h (struct cgraph_varpool_node): Add next.
|
||||
(cgraph_node_for_asm, cgraph_varpool_node_for_asm): Declare.
|
||||
* varasm.c (assemble_alias): Mark the target as needed.
|
||||
|
||||
2005-01-01 Andrew Pinski <pinskia@physics.uc.edu>
|
||||
|
||||
PR middle-end/19221
|
||||
|
@ -897,6 +897,8 @@ pop_file_scope (void)
|
||||
/* Pop off the file scope and close this translation unit. */
|
||||
pop_scope ();
|
||||
file_scope = 0;
|
||||
|
||||
maybe_apply_pending_pragma_weaks ();
|
||||
cgraph_finalize_compilation_unit ();
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,6 @@ const char *const tree_code_name[] = {
|
||||
void
|
||||
finish_file (void)
|
||||
{
|
||||
maybe_apply_pending_pragma_weaks ();
|
||||
}
|
||||
|
||||
#include "gtype-c.h"
|
||||
|
63
gcc/cgraph.c
63
gcc/cgraph.c
@ -194,6 +194,56 @@ cgraph_node (tree decl)
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Compare ASMNAME with the DECL_ASSEMBLER_NAME of DECL. */
|
||||
|
||||
static bool
|
||||
decl_assembler_name_equal (tree decl, tree asmname)
|
||||
{
|
||||
tree decl_asmname = DECL_ASSEMBLER_NAME (decl);
|
||||
|
||||
if (decl_asmname == asmname)
|
||||
return true;
|
||||
|
||||
/* If the target assembler name was set by the user, things are trickier.
|
||||
We have a leading '*' to begin with. After that, it's arguable what
|
||||
is the correct thing to do with -fleading-underscore. Arguably, we've
|
||||
historically been doing the wrong thing in assemble_alias by always
|
||||
printing the leading underscore. Since we're not changing that, make
|
||||
sure user_label_prefix follows the '*' before matching. */
|
||||
if (IDENTIFIER_POINTER (decl_asmname)[0] == '*')
|
||||
{
|
||||
const char *decl_str = IDENTIFIER_POINTER (decl_asmname) + 1;
|
||||
size_t ulp_len = strlen (user_label_prefix);
|
||||
|
||||
if (ulp_len == 0)
|
||||
;
|
||||
else if (strncmp (decl_str, user_label_prefix, ulp_len) == 0)
|
||||
decl_str += ulp_len;
|
||||
else
|
||||
return false;
|
||||
|
||||
return strcmp (decl_str, IDENTIFIER_POINTER (asmname)) == 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/* Return the cgraph node that has ASMNAME for its DECL_ASSEMBLER_NAME.
|
||||
Return NULL if there's no such node. */
|
||||
|
||||
struct cgraph_node *
|
||||
cgraph_node_for_asm (tree asmname)
|
||||
{
|
||||
struct cgraph_node *node;
|
||||
|
||||
for (node = cgraph_nodes; node ; node = node->next)
|
||||
if (decl_assembler_name_equal (node->decl, asmname))
|
||||
return node;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Return callgraph edge representing CALL_EXPR. */
|
||||
struct cgraph_edge *
|
||||
cgraph_edge (struct cgraph_node *node, tree call_expr)
|
||||
@ -533,12 +583,25 @@ cgraph_varpool_node (tree decl)
|
||||
return *slot;
|
||||
node = ggc_alloc_cleared (sizeof (*node));
|
||||
node->decl = decl;
|
||||
node->next = cgraph_varpool_nodes;
|
||||
cgraph_varpool_n_nodes++;
|
||||
cgraph_varpool_nodes = node;
|
||||
*slot = node;
|
||||
return node;
|
||||
}
|
||||
|
||||
struct cgraph_varpool_node *
|
||||
cgraph_varpool_node_for_asm (tree asmname)
|
||||
{
|
||||
struct cgraph_varpool_node *node;
|
||||
|
||||
for (node = cgraph_varpool_nodes; node ; node = node->next)
|
||||
if (decl_assembler_name_equal (node->decl, asmname))
|
||||
return node;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set the DECL_ASSEMBLER_NAME and update cgraph hashtables. */
|
||||
void
|
||||
change_decl_assembler_name (tree decl, tree name)
|
||||
|
@ -138,6 +138,8 @@ struct cgraph_edge GTY((chain_next ("%h.next_caller")))
|
||||
struct cgraph_varpool_node GTY(())
|
||||
{
|
||||
tree decl;
|
||||
/* Pointer to the next function in cgraph_varpool_nodes. */
|
||||
struct cgraph_varpool_node *next;
|
||||
/* Pointer to the next function in cgraph_varpool_nodes_queue. */
|
||||
struct cgraph_varpool_node *next_needed;
|
||||
|
||||
@ -168,6 +170,7 @@ struct cgraph_edge *cgraph_create_edge (struct cgraph_node *,
|
||||
struct cgraph_node *,
|
||||
tree);
|
||||
struct cgraph_node *cgraph_node (tree decl);
|
||||
struct cgraph_node *cgraph_node_for_asm (tree asmname);
|
||||
struct cgraph_edge *cgraph_edge (struct cgraph_node *, tree call_expr);
|
||||
struct cgraph_local_info *cgraph_local_info (tree);
|
||||
struct cgraph_global_info *cgraph_global_info (tree);
|
||||
@ -177,6 +180,7 @@ struct cgraph_edge * cgraph_clone_edge (struct cgraph_edge *, struct cgraph_node
|
||||
struct cgraph_node * cgraph_clone_node (struct cgraph_node *);
|
||||
|
||||
struct cgraph_varpool_node *cgraph_varpool_node (tree decl);
|
||||
struct cgraph_varpool_node *cgraph_varpool_node_for_asm (tree asmname);
|
||||
void cgraph_varpool_mark_needed_node (struct cgraph_varpool_node *);
|
||||
void cgraph_varpool_finalize_decl (tree);
|
||||
bool cgraph_varpool_assemble_pending_decls (void);
|
||||
|
@ -603,8 +603,6 @@ objc_finish_file (void)
|
||||
|
||||
#ifdef OBJCPLUS
|
||||
cp_finish_file ();
|
||||
#else
|
||||
maybe_apply_pending_pragma_weaks ();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
20
gcc/testsuite/gcc.dg/attr-alias-2.c
Normal file
20
gcc/testsuite/gcc.dg/attr-alias-2.c
Normal file
@ -0,0 +1,20 @@
|
||||
/* PR 19031 */
|
||||
/* { dg-do link } */
|
||||
/* { dg-require-alias } */
|
||||
/* { dg-options "-funit-at-a-time" } */
|
||||
|
||||
static int f1 (void) { return 0; }
|
||||
extern int g1 (void) __attribute__((__alias__("f1")));
|
||||
|
||||
#define STR(x) STR1(__USER_LABEL_PREFIX__, x)
|
||||
#define STR1(x,y) STR2(x, y)
|
||||
#define STR2(x,y) #x #y
|
||||
|
||||
static int f2 (void) __asm__(STR(a2));
|
||||
static int f2 (void) { return 0; }
|
||||
extern int g2 (void) __attribute__((__alias__("a2")));
|
||||
|
||||
int main ()
|
||||
{
|
||||
return g1() + g2();
|
||||
}
|
10
gcc/testsuite/gcc.dg/weak/weak-11.c
Normal file
10
gcc/testsuite/gcc.dg/weak/weak-11.c
Normal file
@ -0,0 +1,10 @@
|
||||
/* PR 19031 */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-require-weak "" } */
|
||||
/* { dg-require-alias "" } */
|
||||
/* { dg-options "-funit-at-a-time" } */
|
||||
|
||||
/* { dg-final { scan-assembler "xyzzy" } } */
|
||||
|
||||
static const int local = 1;
|
||||
#pragma weak xyzzy = local
|
40
gcc/varasm.c
40
gcc/varasm.c
@ -4344,7 +4344,7 @@ globalize_decl (tree decl)
|
||||
the symbol for TARGET. */
|
||||
|
||||
void
|
||||
assemble_alias (tree decl, tree target ATTRIBUTE_UNUSED)
|
||||
assemble_alias (tree decl, tree target)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
@ -4395,6 +4395,44 @@ assemble_alias (tree decl, tree target ATTRIBUTE_UNUSED)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Tell cgraph that the aliased symbol is needed. We *could* be more
|
||||
specific and tell cgraph about the relationship between the two
|
||||
symbols, but given that aliases virtually always exist for a reason,
|
||||
it doesn't seem worthwhile. */
|
||||
if (flag_unit_at_a_time)
|
||||
{
|
||||
struct cgraph_node *fnode = NULL;
|
||||
struct cgraph_varpool_node *vnode = NULL;
|
||||
|
||||
if (TREE_CODE (decl) == FUNCTION_DECL)
|
||||
{
|
||||
fnode = cgraph_node_for_asm (target);
|
||||
if (fnode != NULL)
|
||||
cgraph_mark_needed_node (fnode);
|
||||
else
|
||||
{
|
||||
vnode = cgraph_varpool_node_for_asm (target);
|
||||
if (vnode != NULL)
|
||||
cgraph_varpool_mark_needed_node (vnode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vnode = cgraph_varpool_node_for_asm (target);
|
||||
if (vnode != NULL)
|
||||
cgraph_varpool_mark_needed_node (vnode);
|
||||
else
|
||||
{
|
||||
fnode = cgraph_node_for_asm (target);
|
||||
if (fnode != NULL)
|
||||
cgraph_mark_needed_node (fnode);
|
||||
}
|
||||
}
|
||||
|
||||
if (fnode == NULL && vnode == NULL)
|
||||
warning ("%qD aliased to undefined symbol %qE", decl, target);
|
||||
}
|
||||
|
||||
TREE_USED (decl) = 1;
|
||||
TREE_ASM_WRITTEN (decl) = 1;
|
||||
TREE_ASM_WRITTEN (DECL_ASSEMBLER_NAME (decl)) = 1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user