This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

fix target/15700


The following fixes the symbol alias definition problem wherein we fail 
to emit symbols that are in fact needed.

It is now an error to define an alias to a symbol that isn't defined in
the current translation unit.  It should have been an error before, but
we didn't have code at the right places to detect the erroneous condition.

Tested on i686-linux, and against a patched version of glibc head.
Still testing the application of this patch to the 4.0 branch.


r~


        * varasm.c (struct alias_pair): Rename from struct output_def_pair.
        (alias_pairs): Rename from output_defs.
        (find_decl_and_mark_needed): Split out from assemble_alias.
        (do_assemble_alias): New.
        (assemble_output_def): Remove.
        (finish_aliases_1, finish_aliases_2): New.
        (process_pending_assemble_output_defs): Remove.
        (assemble_alias): Defer aliases for which we don't yet have a
        non-external decl for the target symbol.
        * passes.c (rest_of_decl_compilation): Register variables with cgraph.
        * cgraphunit.c (cgraph_finalize_compilation_unit): Use finish_aliases_1.        * toplev.c (compile_file): Use finish_aliases_2 instead of
        process_pending_assemble_output_defs.
        * tree.h (finish_aliases_1, finish_aliases_2): Declare.
        (process_pending_assemble_output_defs): Remove.

        * gcc.c-torture/compile/20040323-1.c: Don't xfail for solaris.
        (_rtld_global): New.
        * gcc.dg/weak/weak-3.c (ffoox1f, ffoox1g): Define.
        * gcc.dg/weak/weak-9.c (notf1, notf2, notf3, notf4): Define.

        * gcc.dg/alias-3.c: New.
        * gcc.dg/alias-4.c: New.
        * gcc.dg/alias-5.c: New.
        * gcc.dg/alias-6.c: New.

Index: gcc/cgraphunit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cgraphunit.c,v
retrieving revision 1.94
diff -u -p -d -r1.94 cgraphunit.c
--- gcc/cgraphunit.c	2 Mar 2005 11:09:48 -0000	1.94
+++ gcc/cgraphunit.c	16 Mar 2005 17:04:26 -0000
@@ -680,6 +680,8 @@ cgraph_finalize_compilation_unit (void)
 {
   struct cgraph_node *node;
 
+  finish_aliases_1 ();
+
   if (!flag_unit_at_a_time)
     {
       cgraph_assemble_pending_functions ();
Index: gcc/passes.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/passes.c,v
retrieving revision 2.73
diff -u -p -d -r2.73 passes.c
--- gcc/passes.c	1 Mar 2005 13:44:45 -0000	2.73
+++ gcc/passes.c	16 Mar 2005 17:04:27 -0000
@@ -251,6 +251,10 @@ rest_of_decl_compilation (tree decl,
       debug_hooks->type_decl (decl, !top_level);
       timevar_pop (TV_SYMOUT);
     }
+
+  /* Let cgraph know about the existance of variables.  */
+  if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
+    cgraph_varpool_node (decl);
 }
 
 /* Called after finishing a record, union or enumeral type.  */
Index: gcc/toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.946
diff -u -p -d -r1.946 toplev.c
--- gcc/toplev.c	15 Mar 2005 23:02:29 -0000	1.946
+++ gcc/toplev.c	16 Mar 2005 17:04:27 -0000
@@ -1009,8 +1009,8 @@ compile_file (void)
     return;
 
   lang_hooks.decls.final_write_globals ();
-
   cgraph_varpool_assemble_pending_decls ();
+  finish_aliases_2 ();
 
   /* This must occur after the loop to output deferred functions.
      Else the coverage initializer would not be emitted if all the
@@ -1045,9 +1045,6 @@ compile_file (void)
      expander can also generate them.  */
   process_pending_assemble_externals ();
 
-  /* Flush any pending equate directives.  */
-  process_pending_assemble_output_defs ();
-
   /* Attach a special .ident directive to the end of the file to identify
      the version of GCC which compiled this code.  The format of the .ident
      string is patterned after the ones produced by native SVR4 compilers.  */
Index: gcc/tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.702
diff -u -p -d -r1.702 tree.h
--- gcc/tree.h	16 Mar 2005 14:45:15 -0000	1.702
+++ gcc/tree.h	16 Mar 2005 17:04:28 -0000
@@ -3739,7 +3739,8 @@ extern void mark_decl_referenced (tree);
 extern void notice_global_symbol (tree);
 extern void set_user_assembler_name (tree, const char *);
 extern void process_pending_assemble_externals (void);
-extern void process_pending_assemble_output_defs (void);
+extern void finish_aliases_1 (void);
+extern void finish_aliases_2 (void);
 
 /* In stmt.c */
 extern void expand_computed_goto (tree);
Index: gcc/varasm.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/varasm.c,v
retrieving revision 1.481
diff -u -p -d -r1.481 varasm.c
--- gcc/varasm.c	13 Mar 2005 17:56:14 -0000	1.481
+++ gcc/varasm.c	16 Mar 2005 17:04:29 -0000
@@ -4335,55 +4335,139 @@ globalize_decl (tree decl)
   targetm.asm_out.globalize_label (asm_out_file, name);
 }
 
-/* Some targets do not allow a forward or undefined reference in a
-   ASM_OUTPUT_DEF.  Thus, a mechanism is needed to defer the output of
-   this assembler code.  The following struct holds the declaration
-   and target for a deferred output define.  */
-struct output_def_pair GTY(())
+/* We have to be able to tell cgraph about the needed-ness of the target
+   of an alias.  This requires that the decl have been defined.  Aliases
+   that preceed their definition have to be queued for later processing.  */
+
+struct alias_pair GTY(())
 {
   tree decl;
   tree target;
 };
-typedef struct output_def_pair *output_def_pair;
+typedef struct alias_pair *alias_pair;
 
 /* Define gc'd vector type.  */
-DEF_VEC_GC_P(output_def_pair);
+DEF_VEC_GC_P(alias_pair);
 
-/* Vector of output_def_pair pointers.  */
-static GTY(()) VEC(output_def_pair) *output_defs;
+static GTY(()) VEC(alias_pair) *alias_pairs;
 
-#ifdef ASM_OUTPUT_DEF
-/* Output the assembler code for a define (equate) using ASM_OUTPUT_DEF
-   or ASM_OUTPUT_DEF_FROM_DECLS.  The function defines the symbol whose
-   tree node is DECL to have the value of the tree node TARGET.  */
+/* Given an assembly name, find the decl it is associated with.  At the
+   same time, mark it needed for cgraph.  */
+
+static tree
+find_decl_and_mark_needed (tree decl, tree target)
+{
+  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)
+	vnode = cgraph_varpool_node_for_asm (target);
+    }
+  else
+    {
+      vnode = cgraph_varpool_node_for_asm (target);
+      if (vnode == NULL)
+	fnode = cgraph_node_for_asm (target);
+    }
+
+  if (fnode)
+    {
+      cgraph_mark_needed_node (fnode);
+      return fnode->decl;
+    }
+  else if (vnode)
+    {
+      cgraph_varpool_mark_needed_node (vnode);
+      return vnode->decl;
+    }
+  else 
+    return NULL_TREE;
+}
 
 static void
-assemble_output_def (tree decl ATTRIBUTE_UNUSED, tree target ATTRIBUTE_UNUSED)
+do_assemble_alias (tree decl, tree target)
 {
-#ifdef ASM_OUTPUT_DEF_FROM_DECLS
+  TREE_ASM_WRITTEN (decl) = 1;
+  TREE_ASM_WRITTEN (DECL_ASSEMBLER_NAME (decl)) = 1;
+
+#ifdef ASM_OUTPUT_DEF
+  /* Make name accessible from other files, if appropriate.  */
+
+  if (TREE_PUBLIC (decl))
+    {
+      globalize_decl (decl);
+      maybe_assemble_visibility (decl);
+    }
+
+# ifdef ASM_OUTPUT_DEF_FROM_DECLS
   ASM_OUTPUT_DEF_FROM_DECLS (asm_out_file, decl, target);
-#else
+# else
   ASM_OUTPUT_DEF (asm_out_file,
 		  IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
 		  IDENTIFIER_POINTER (target));
+# endif
+#elif defined (ASM_OUTPUT_WEAK_ALIAS) || defined (ASM_WEAKEN_DECL)
+  {
+    const char *name;
+    tree *p, t;
+
+    name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+# ifdef ASM_WEAKEN_DECL
+    ASM_WEAKEN_DECL (asm_out_file, decl, name, IDENTIFIER_POINTER (target));
+# else
+    ASM_OUTPUT_WEAK_ALIAS (asm_out_file, name, IDENTIFIER_POINTER (target));
+# endif
+    /* Remove this function from the pending weak list so that
+       we do not emit multiple .weak directives for it.  */
+    for (p = &weak_decls; (t = *p) ; )
+      if (DECL_ASSEMBLER_NAME (decl) == DECL_ASSEMBLER_NAME (TREE_VALUE (t)))
+	*p = TREE_CHAIN (t);
+      else
+	p = &TREE_CHAIN (t);
+  }
 #endif
 }
-#endif
 
-/* Process the vector of pending assembler defines.  */
+/* First pass of completing pending aliases.  Make sure that cgraph knows
+   which symbols will be required.  */
 
 void
-process_pending_assemble_output_defs (void)
+finish_aliases_1 (void)
 {
-#ifdef ASM_OUTPUT_DEF
   unsigned i;
-  output_def_pair p;
+  alias_pair p;
 
-  for (i = 0; VEC_iterate (output_def_pair, output_defs, i, p); i++)
-    assemble_output_def (p->decl, p->target);
+  for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); i++)
+    {
+      tree target_decl;
 
-  output_defs = NULL;
-#endif
+      target_decl = find_decl_and_mark_needed (p->decl, p->target);
+      if (target_decl == NULL)
+	error ("%J%qD aliased to undefined symbol %qE",
+	       p->decl, p->decl, p->target);
+      else if (DECL_EXTERNAL (target_decl))
+	error ("%J%qD aliased to external symbol %qE",
+	       p->decl, p->decl, p->target);
+    }
+}
+
+/* Second pass of completing pending aliases.  Emit the actual assembly.
+   This happens at the end of compilation and thus it is assured that the
+   target symbol has been emitted.  */
+
+void
+finish_aliases_2 (void)
+{
+  unsigned i;
+  alias_pair p;
+
+  for (i = 0; VEC_iterate (alias_pair, alias_pairs, i, p); i++)
+    do_assemble_alias (p->decl, p->target);
+
+  alias_pairs = NULL;
 }
 
 /* Emit an assembler directive to make the symbol for DECL an alias to
@@ -4392,101 +4476,51 @@ process_pending_assemble_output_defs (vo
 void
 assemble_alias (tree decl, tree target)
 {
-  /* We must force creation of DECL_RTL for debug info generation, even though
-     we don't use it here.  */
-  make_decl_rtl (decl);
-
-#ifdef ASM_OUTPUT_DEF
-  /* Make name accessible from other files, if appropriate.  */
+  tree target_decl;
 
-  if (TREE_PUBLIC (decl))
+#if !defined (ASM_OUTPUT_DEF)
+# if !defined(ASM_OUTPUT_WEAK_ALIAS) && !defined (ASM_WEAKEN_DECL)
+  error ("%Jalias definitions not supported in this configuration", decl);
+  return;
+# else
+  if (!DECL_WEAK (decl))
     {
-      globalize_decl (decl);
-      maybe_assemble_visibility (decl);
+      error ("%Jonly weak aliases are supported in this configuration", decl);
+      return;
     }
+# endif
+#endif
 
-  if (TARGET_DEFERRED_OUTPUT_DEFS (decl, target))
-    {
-      output_def_pair p;
+  /* We must force creation of DECL_RTL for debug info generation, even though
+     we don't use it here.  */
+  make_decl_rtl (decl);
+  TREE_USED (decl) = 1;
 
-      p = ggc_alloc (sizeof (struct output_def_pair));
-      p->decl = decl;
-      p->target = target;
-      VEC_safe_push (output_def_pair, output_defs, p);
-    }
-  else
-    assemble_output_def (decl, target);
-#else /* !ASM_OUTPUT_DEF */
-#if defined (ASM_OUTPUT_WEAK_ALIAS) || defined (ASM_WEAKEN_DECL)
-  if (DECL_WEAK (decl))
-    {
-      const char *name;
-      tree *p, t;
+  /* A quirk of the initial implementation of aliases required that the user
+     add "extern" to all of them.  Which is silly, but now historical.  Do
+     note that the symbol is in fact locally defined.  */
+  DECL_EXTERNAL (decl) = 0;
 
-      name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-#ifdef ASM_WEAKEN_DECL
-      ASM_WEAKEN_DECL (asm_out_file, decl, name, IDENTIFIER_POINTER (target));
-#else
-      ASM_OUTPUT_WEAK_ALIAS (asm_out_file, name, IDENTIFIER_POINTER (target));
-#endif
-      /* Remove this function from the pending weak list so that
-	 we do not emit multiple .weak directives for it.  */
-      for (p = &weak_decls; (t = *p) ; )
-	if (DECL_ASSEMBLER_NAME (decl)
-	    == DECL_ASSEMBLER_NAME (TREE_VALUE (t)))
-	  *p = TREE_CHAIN (t);
-	else
-	  p = &TREE_CHAIN (t);
-    }
+  /* Allow aliases to aliases.  */
+  if (TREE_CODE (decl) == FUNCTION_DECL)
+    cgraph_node (decl);
   else
-    warning ("only weak aliases are supported in this configuration");
-
-#else
-  warning ("alias definitions not supported in this configuration; ignored");
-#endif
-#endif
+    cgraph_varpool_node (decl);
 
-  /* 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)
+  /* If the target has already been emitted, we don't have to queue the
+     alias.  This saves a tad o memory.  */
+  target_decl = find_decl_and_mark_needed (decl, target);
+  if (target_decl && TREE_ASM_WRITTEN (target_decl))
+    do_assemble_alias (decl, target);
+  else
     {
-      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);
-	    }
-	}
+      alias_pair p;
 
-      if (fnode == NULL && vnode == NULL)
-	warning ("%qD aliased to undefined symbol %qE", decl, target);
+      p = ggc_alloc (sizeof (struct alias_pair));
+      p->decl = decl;
+      p->target = target;
+      VEC_safe_push (alias_pair, alias_pairs, p);
     }
-
-  TREE_USED (decl) = 1;
-  TREE_ASM_WRITTEN (decl) = 1;
-  TREE_ASM_WRITTEN (DECL_ASSEMBLER_NAME (decl)) = 1;
 }
 
 /* Emit an assembler directive to set symbol for DECL visibility to
Index: gcc/testsuite/gcc.c-torture/compile/20040323-1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.c-torture/compile/20040323-1.c,v
retrieving revision 1.3
diff -u -p -d -r1.3 20040323-1.c
--- gcc/testsuite/gcc.c-torture/compile/20040323-1.c	1 Jul 2004 08:33:36 -0000	1.3
+++ gcc/testsuite/gcc.c-torture/compile/20040323-1.c	16 Mar 2005 17:04:29 -0000
@@ -1,7 +1,7 @@
 /* PR middle-end/14694 */
 /* { dg-require-alias "" } */
-/* { dg-xfail-if "undefined alias" { "*-*-solaris2.*" } { "*" } { "" } } */
 
+unsigned int _rtld_global;
 extern unsigned int _rtld_local __attribute__ ((alias ("_rtld_global")));
 
 unsigned int
Index: gcc/testsuite/gcc.dg/alias-3.c
===================================================================
RCS file: gcc/testsuite/gcc.dg/alias-3.c
diff -N gcc/testsuite/gcc.dg/alias-3.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/gcc.dg/alias-3.c	16 Mar 2005 17:04:29 -0000
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-alias "" } */
+/* { dg-options "" } */
+
+extern int foo();
+
+int baz () { return foo(); }
+
+static inline int bar () __attribute__ ((alias ("foo"))); /* { dg-error "aliased to" } */
+
+int main () { return bar (); }
Index: gcc/testsuite/gcc.dg/alias-4.c
===================================================================
RCS file: gcc/testsuite/gcc.dg/alias-4.c
diff -N gcc/testsuite/gcc.dg/alias-4.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/gcc.dg/alias-4.c	16 Mar 2005 17:04:29 -0000
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-require-alias "" } */
+/* { dg-options "-O2 -funit-at-a-time" } */
+
+extern int foo();
+
+int baz () { return foo(); }
+
+static inline int bar () __attribute__ ((alias ("foo"))); /* { dg-error "aliased to" } */
+
+int main () { return bar (); }
Index: gcc/testsuite/gcc.dg/alias-5.c
===================================================================
RCS file: gcc/testsuite/gcc.dg/alias-5.c
diff -N gcc/testsuite/gcc.dg/alias-5.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/gcc.dg/alias-5.c	16 Mar 2005 17:04:29 -0000
@@ -0,0 +1,7 @@
+/* { dg-do link } */
+/* { dg-require-alias "" } */
+/* { dg-options "" } */
+
+static inline int foo () { return 0; }
+static int bar () __attribute__ ((alias ("foo")));
+int main () { return bar (); }
Index: gcc/testsuite/gcc.dg/alias-6.c
===================================================================
RCS file: gcc/testsuite/gcc.dg/alias-6.c
diff -N gcc/testsuite/gcc.dg/alias-6.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gcc/testsuite/gcc.dg/alias-6.c	16 Mar 2005 17:04:29 -0000
@@ -0,0 +1,7 @@
+/* { dg-do link } */
+/* { dg-require-alias "" } */
+/* { dg-options "-O2 -funit-at-a-time" } */
+
+static inline int foo () { return 0; }
+static int bar () __attribute__ ((alias ("foo")));
+int main () { return bar (); }
Index: gcc/testsuite/gcc.dg/weak/weak-3.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/weak/weak-3.c,v
retrieving revision 1.5
diff -u -p -d -r1.5 weak-3.c
--- gcc/testsuite/gcc.dg/weak/weak-3.c	28 Oct 2004 00:16:57 -0000	1.5
+++ gcc/testsuite/gcc.dg/weak/weak-3.c	16 Mar 2005 17:04:29 -0000
@@ -52,18 +52,18 @@ void * foo1e (void)
 
 
 extern void * ffoo1f (void);    
-extern void * ffoox1f (void);
 void * foo1f (void)
 {
   if (ffoo1f) /* { dg-warning "" } */
     ffoo1f ();
   return 0;
 }
+void * ffoox1f (void) { return (void *)0; }
 extern void * ffoo1f (void)  __attribute__((weak, alias ("ffoox1f"))); /* { dg-warning "weak declaration" "weak declaration" } */
 
 
 extern void * ffoo1g (void);
-extern void * ffoox1g (void);
+void * ffoox1g (void) { return (void *)0; }
 extern void * ffoo1g (void)  __attribute__((weak, alias ("ffoox1g")));
 void * foo1g (void)
 {
Index: gcc/testsuite/gcc.dg/weak/weak-9.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/weak/weak-9.c,v
retrieving revision 1.3
diff -u -p -d -r1.3 weak-9.c
--- gcc/testsuite/gcc.dg/weak/weak-9.c	28 Oct 2004 00:16:57 -0000	1.3
+++ gcc/testsuite/gcc.dg/weak/weak-9.c	16 Mar 2005 17:04:29 -0000
@@ -7,10 +7,11 @@
 /* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?f2" } } */
 /* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?f3" } } */
 /* { dg-final { scan-assembler "weak\[^ \t\]*\[ \t\]_?f4" } } */
-/* { dg-final { scan-assembler "notf1" } } */
-/* { dg-final { scan-assembler "notf2" } } */
-/* { dg-final { scan-assembler "notf3" } } */
-/* { dg-final { scan-assembler "notf4" } } */
+
+void notf1() { }
+void notf2() { }
+void notf3() { }
+void notf4() { }
 
 void f1() __attribute__((weak, alias("notf1")));
 void f2() __attribute__((alias("notf2"), weak));


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]