fix c/19031

Richard Henderson rth@redhat.com
Sun Jan 2 07:54:00 GMT 2005


The solution here is to let cgraph know (kinda) about the dependency
between the alias and its referant.  C and ObjC needed a tweak so that
this would happen early enough; C++ already did this in the right place.

Tested on i686-linux.


r~


        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.

Index: gcc/c-decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-decl.c,v
retrieving revision 1.621
diff -c -p -d -r1.621 c-decl.c
*** gcc/c-decl.c	1 Jan 2005 16:15:10 -0000	1.621
--- gcc/c-decl.c	2 Jan 2005 07:47:28 -0000
*************** pop_file_scope (void)
*** 897,902 ****
--- 897,904 ----
    /* Pop off the file scope and close this translation unit.  */
    pop_scope ();
    file_scope = 0;
+ 
+   maybe_apply_pending_pragma_weaks ();
    cgraph_finalize_compilation_unit ();
  }
  
Index: gcc/c-lang.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/c-lang.c,v
retrieving revision 1.137
diff -c -p -d -r1.137 c-lang.c
*** gcc/c-lang.c	29 Nov 2004 18:53:53 -0000	1.137
--- gcc/c-lang.c	2 Jan 2005 07:47:28 -0000
*************** const char *const tree_code_name[] = {
*** 89,95 ****
  void
  finish_file (void)
  {
-   maybe_apply_pending_pragma_weaks ();
  }
  
  #include "gtype-c.h"
--- 89,94 ----
Index: gcc/cgraph.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.c,v
retrieving revision 1.61
diff -c -p -d -r1.61 cgraph.c
*** gcc/cgraph.c	13 Nov 2004 21:11:04 -0000	1.61
--- gcc/cgraph.c	2 Jan 2005 07:47:28 -0000
*************** cgraph_node (tree decl)
*** 194,199 ****
--- 194,249 ----
    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)
*************** cgraph_varpool_node (tree decl)
*** 533,544 ****
--- 583,607 ----
      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)
Index: gcc/cgraph.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraph.h,v
retrieving revision 1.41
diff -c -p -d -r1.41 cgraph.h
*** gcc/cgraph.h	18 Nov 2004 00:09:16 -0000	1.41
--- gcc/cgraph.h	2 Jan 2005 07:47:28 -0000
*************** struct cgraph_edge GTY((chain_next ("%h.
*** 138,143 ****
--- 138,145 ----
  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;
  
*************** struct cgraph_edge *cgraph_create_edge (
*** 168,173 ****
--- 170,176 ----
  					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);
*************** struct cgraph_edge * cgraph_clone_edge (
*** 177,182 ****
--- 180,186 ----
  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);
Index: gcc/varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.471
diff -c -p -d -r1.471 varasm.c
*** gcc/varasm.c	23 Dec 2004 07:13:05 -0000	1.471
--- gcc/varasm.c	2 Jan 2005 07:47:29 -0000
*************** globalize_decl (tree decl)
*** 4344,4350 ****
     the symbol for TARGET.  */
  
  void
! assemble_alias (tree decl, tree target ATTRIBUTE_UNUSED)
  {
    const char *name;
  
--- 4344,4350 ----
     the symbol for TARGET.  */
  
  void
! assemble_alias (tree decl, tree target)
  {
    const char *name;
  
*************** assemble_alias (tree decl, tree target A
*** 4395,4400 ****
--- 4395,4438 ----
  #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;
Index: gcc/objc/objc-act.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/objc/objc-act.c,v
retrieving revision 1.259
diff -c -p -d -r1.259 objc-act.c
*** gcc/objc/objc-act.c	30 Dec 2004 10:18:09 -0000	1.259
--- gcc/objc/objc-act.c	2 Jan 2005 07:47:30 -0000
*************** objc_finish_file (void)
*** 603,610 ****
  
  #ifdef OBJCPLUS
    cp_finish_file ();
- #else
-   maybe_apply_pending_pragma_weaks ();
  #endif
  }
  
--- 603,608 ----
Index: gcc/testsuite/gcc.dg/attr-alias-2.c
===================================================================
RCS file: gcc/testsuite/gcc.dg/attr-alias-2.c
diff -N gcc/testsuite/gcc.dg/attr-alias-2.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/gcc.dg/attr-alias-2.c	2 Jan 2005 07:47:30 -0000
***************
*** 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();
+ }
Index: gcc/testsuite/gcc.dg/weak/weak-11.c
===================================================================
RCS file: gcc/testsuite/gcc.dg/weak/weak-11.c
diff -N gcc/testsuite/gcc.dg/weak/weak-11.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/gcc.dg/weak/weak-11.c	2 Jan 2005 07:47:30 -0000
***************
*** 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



More information about the Gcc-patches mailing list