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]

Re: RFC: weakref GCC attribute and .weakref assembly directive


On Oct 10, 2005, Alexandre Oliva <aoliva@redhat.com> wrote:

> I'll probably post a patch for the assembler, that implements this,
> tonight.  The compiler still needs a bit more work in the testsuite
> (or in the implementation, to make it independent from assembler
> support) so it might take longer.

I went ahead and implemented support for weakrefs in the compiler,
without relying on .weakref support in the assembler.  It uncovered a
bug in the compiler in handling of aliases to local variables, that
I've just posted.

This patch introduces code to emit .weakref directives, if the
assembler supports them, or to emulate that by emitting references to
the target where the alias is used, and deciding at the end whether to
emit a .weak directive for the target or not, depending on whether it
was referenced directly.

Because of the way cgraph maps identifiers to declarations, if I used
the same DECL_ASSEMBLER_NAME for the alias as for the target, I'd be
overriding the target declaration in the hash table, becoming unable
to get information from it.  I'd also be unable to tell whether a
symbol was referenced directly or not.  To work around these
limitations, I've arranged to have a blank prepended to the alias
symbol name, such that the assembly output is nearly identical and
equivalent (or so I hope), but I can still distinguish uses of the
target from uses of the weakref alias.

Yeah, this is ugly, I'm open to alternatives.  I suppose I could leave
DECL_ASSEMBLER_NAME alone and only modify DECL_RTL, but some output
code uses DECL_ASSEMBLER_NAME instead of extracting the symbol name
from DECL_RTL, so I'd have to modify that as well.  Would this be
preferred?

This patch only introduces the weakref attribute, without actually
using it.  I'm about to post a follow-up patch that uses this new
feature to fix the libstdc++ bug that causes pthread functions to
become weak by including libstdc++ headers.

:ADDPATCH weakref:

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* c-common.c (handle_weakref_attribute): New.
	(c_common_attribute_table): Add weakref.
	* configure.ac (HAVE_GAS_WEAKREF): Check for weakref support
	in the assembler.
	* configure, config.in: Rebuilt.
	* defaults.h (ASM_OUTPUT_WEAKREF): Define if HAVE_GAS_WEAKREF.
	* doc/extend.texi: Document weakref attribute.
	* varasm.c (weak_finish_1): Split out of...
	(weak_finish): ... and deal with weakrefs in...
	(weakref_targets): ... new list.
	(find_decl): New.
	(globalize_decl): Clean up weakref_targets.
	(do_assemble_alias): Handle weakrefs.
	(finish_aliases_1): Do not reject weakrefs to external symbols.
	(assemble_alias): Handle weakrefs.

Index: gcc/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* gcc.dg/attr-weakref-1.c, gcc.dg/attr-weakref-1a.c: New test.

Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c.orig	2005-10-19 02:41:17.000000000 -0200
+++ gcc/c-common.c	2005-10-19 02:55:22.000000000 -0200
@@ -520,6 +520,7 @@
 static tree handle_aligned_attribute (tree *, tree, tree, int, bool *);
 static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
 static tree handle_alias_attribute (tree *, tree, tree, int, bool *);
+static tree handle_weakref_attribute (tree *, tree, tree, int, bool *) ;
 static tree handle_visibility_attribute (tree *, tree, tree, int,
 					 bool *);
 static tree handle_tls_model_attribute (tree *, tree, tree, int,
@@ -599,6 +600,8 @@
 			      handle_weak_attribute },
   { "alias",                  1, 1, true,  false, false,
 			      handle_alias_attribute },
+  { "weakref",                0, 1, true,  false, false,
+			      handle_weakref_attribute },
   { "no_instrument_function", 0, 0, true,  false, false,
 			      handle_no_instrument_function_attribute },
   { "malloc",                 0, 0, true,  false, false,
@@ -4755,6 +4758,40 @@
   return NULL_TREE;
 }
 
+/* Handle a "weakref" attribute; arguments as in struct
+   attribute_spec.handler.  */
+
+static tree
+handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args,
+			  int flags, bool *no_add_attrs)
+{
+  tree attr = NULL_TREE;
+
+  /* The idea here is that `weakref("name")' mutates into `weakref,
+     alias("name")', and weakref without arguments, in turn,
+     implicitly adds weak. */
+
+  if (args)
+    {
+      attr = tree_cons (get_identifier ("alias"), args, attr);
+      attr = tree_cons (get_identifier ("weakref"), NULL_TREE, attr);
+
+      *no_add_attrs = true;
+    }
+  else
+    {
+      if (lookup_attribute ("alias", DECL_ATTRIBUTES (*node)))
+	error ("%Jweakref attribute must appear before alias attribute",
+	       *node);
+
+      attr = tree_cons (get_identifier ("weak"), NULL_TREE, attr);
+    }
+
+  decl_attributes (node, attr, flags);
+
+  return NULL_TREE;
+}
+
 /* Handle an "visibility" attribute; arguments as in
    struct attribute_spec.handler.  */
 
Index: gcc/config.in
===================================================================
--- gcc/config.in.orig	2005-10-19 02:41:17.000000000 -0200
+++ gcc/config.in	2005-10-19 02:52:28.000000000 -0200
@@ -744,6 +744,12 @@
 #endif
 
 
+/* Define if your assembler supports .weakref. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_WEAKREF
+#endif
+
+
 /* Define to 1 if you have the `getchar_unlocked' function. */
 #ifndef USED_FOR_TARGET
 #undef HAVE_GETCHAR_UNLOCKED
Index: gcc/configure
===================================================================
--- gcc/configure.orig	2005-10-19 02:41:17.000000000 -0200
+++ gcc/configure	2005-10-19 02:52:08.000000000 -0200
@@ -13988,6 +13988,43 @@
 
 fi
 
+echo "$as_me:$LINENO: checking assembler for .weakref" >&5
+echo $ECHO_N "checking assembler for .weakref... $ECHO_C" >&6
+if test "${gcc_cv_as_weakref+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  gcc_cv_as_weakref=no
+    if test $in_tree_gas = yes; then
+    if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 17 \) \* 1000 + 0`
+  then gcc_cv_as_weakref=yes
+fi
+  elif test x$gcc_cv_as != x; then
+    echo '	.weakref foobar, barfnot' > conftest.s
+    if { ac_try='$gcc_cv_as  -o conftest.o conftest.s >&5'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }
+    then
+	gcc_cv_as_weakref=yes
+    else
+      echo "configure: failed program was" >&5
+      cat conftest.s >&5
+    fi
+    rm -f conftest.o conftest.s
+  fi
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_as_weakref" >&5
+echo "${ECHO_T}$gcc_cv_as_weakref" >&6
+if test $gcc_cv_as_weakref = yes; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_GAS_WEAKREF 1
+_ACEOF
+
+fi
+
 echo "$as_me:$LINENO: checking assembler for .nsubspa comdat" >&5
 echo $ECHO_N "checking assembler for .nsubspa comdat... $ECHO_C" >&6
 if test "${gcc_cv_as_nsubspa_comdat+set}" = set; then
Index: gcc/configure.ac
===================================================================
--- gcc/configure.ac.orig	2005-10-19 02:41:17.000000000 -0200
+++ gcc/configure.ac	2005-10-19 02:52:08.000000000 -0200
@@ -1947,6 +1947,11 @@
  [	.weak foobar],,
 [AC_DEFINE(HAVE_GAS_WEAK, 1, [Define if your assembler supports .weak.])])
 
+gcc_GAS_CHECK_FEATURE([.weakref], gcc_cv_as_weakref,
+ [2,17,0],,
+ [	.weakref foobar, barfnot],,
+[AC_DEFINE(HAVE_GAS_WEAKREF, 1, [Define if your assembler supports .weakref.])])
+
 gcc_GAS_CHECK_FEATURE([.nsubspa comdat], gcc_cv_as_nsubspa_comdat,
  [2,15,91],,
  [	.SPACE $TEXT$
Index: gcc/defaults.h
===================================================================
--- gcc/defaults.h.orig	2005-10-19 02:41:17.000000000 -0200
+++ gcc/defaults.h	2005-10-19 02:52:08.000000000 -0200
@@ -166,6 +166,27 @@
 #endif
 #endif
 
+/* This is how we tell the assembler that a symbol is a weak alias to
+   another symbol that doesn't require the other symbol to be defined.
+   Uses of the former will turn into weak uses of the latter, i.e.,
+   uses that, in case the latter is undefined, will not cause errors,
+   and will add it to the symbol table as weak undefined.  However, if
+   the latter is referenced directly, a strong reference prevails.  */
+#ifndef ASM_OUTPUT_WEAKREF
+#if defined HAVE_GAS_WEAKREF
+#define ASM_OUTPUT_WEAKREF(FILE, NAME, VALUE)				\
+  do									\
+    {									\
+      fprintf ((FILE), ".weakref\t");					\
+      assemble_name ((FILE), (NAME));					\
+      fprintf ((FILE), ",");						\
+      assemble_name ((FILE), (VALUE));					\
+      fprintf ((FILE), "\n");						\
+    }									\
+  while (0)
+#endif
+#endif
+
 /* How to emit a .type directive.  */
 #ifndef ASM_OUTPUT_TYPE_DIRECTIVE
 #if defined TYPE_ASM_OP && defined TYPE_OPERAND_FMT
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi.orig	2005-10-19 02:41:17.000000000 -0200
+++ gcc/doc/extend.texi	2005-10-19 02:52:08.000000000 -0200
@@ -2364,6 +2364,38 @@
 for ELF targets, and also for a.out targets when using the GNU assembler
 and linker.
 
+@item weakref
+@itemx weakref ("@var{target}")
+@cindex @code{weakref} attribute
+The @code{weakref} attribute marks a declaration as a weak reference.
+Without arguments, it should be accompanied by an @code{alias} attribute
+naming the target symbol.  Optionally, the @var{target} may be given as
+an argument to @code{weakref} itself.  In either case, @code{weakref}
+implicitly marks the declaration as @code{weak}.  Without a
+@var{target}, given as an argument to @code{weakref} or to @code{alias},
+@code{weakref} is equivalent to @code{weak}.
+
+@smallexample
+extern int x() __attribute__ ((weakref ("y")));
+/* is equivalent to... */
+extern int x() __attribute__ ((weak, weakref, alias ("y")));
+/* and to... */
+extern int x() __attribute__ ((weakref));
+extern int x() __attribute__ ((alias ("y")));
+@end smallexample
+
+A weak reference is an alias that does not by itself require a
+definition to be given for the target symbol.  If the target symbol is
+only referenced through weak references, then the becomes a @code{weak}
+undefined symbol.  If it is directly referenced, however, then such
+strong references prevail, and a definition will be required for the
+symbol, not necessarily in the same translation unit.
+
+The effect is equivalent to moving all references to the alias to a
+separate translation unit, renaming the alias to the aliased symbol,
+declaring it as weak, compiling the two separate translation units and
+performing a reloadable link on them.
+
 @item externally_visible
 @cindex @code{externally_visible} attribute.
 This attribute, attached to a global variable or function nullify
Index: gcc/varasm.c
===================================================================
--- gcc/varasm.c.orig	2005-10-19 02:52:08.000000000 -0200
+++ gcc/varasm.c	2005-10-19 03:31:00.000000000 -0200
@@ -4466,35 +4466,164 @@
   mark_weak (decl);
 }
 
-/* Emit any pending weak declarations.  */
-
-void
-weak_finish (void)
+static void
+weak_finish_1 (tree decl)
 {
-  tree t;
-
-  for (t = weak_decls; t; t = TREE_CHAIN (t))
-    {
-      tree decl = TREE_VALUE (t);
 #if defined (ASM_WEAKEN_DECL) || defined (ASM_WEAKEN_LABEL)
-      const char *const name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+  const char *const name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
 #endif
 
-      if (! TREE_USED (decl))
-	continue;
+  if (! TREE_USED (decl))
+    return;
+
+  if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
+      && lookup_attribute ("alias", DECL_ATTRIBUTES (decl)))
+    return;
 
 #ifdef ASM_WEAKEN_DECL
-      ASM_WEAKEN_DECL (asm_out_file, decl, name, NULL);
+  ASM_WEAKEN_DECL (asm_out_file, decl, name, NULL);
 #else
 #ifdef ASM_WEAKEN_LABEL
-      ASM_WEAKEN_LABEL (asm_out_file, name);
+  ASM_WEAKEN_LABEL (asm_out_file, name);
 #else
 #ifdef ASM_OUTPUT_WEAK_ALIAS
-      warning (0, "only weak aliases are supported in this configuration");
-      return;
+  {
+    static bool warn_once = 0;
+    if (! warn_once)
+      {
+	warning (0, "only weak aliases are supported in this configuration");
+	warn_once = 1;
+      }
+    return;
+  }
+#endif
 #endif
 #endif
+}
+
+/* This TREE_LIST contains weakref targets.  */
+
+static GTY(()) tree weakref_targets;
+
+/* Given an assembly name, find the decl it is associated with.  */
+
+static tree
+find_decl (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)
+    return fnode->decl;
+  else if (vnode)
+    return vnode->decl;
+  else
+    return NULL_TREE;
+}
+
+/* Emit any pending weak declarations.  */
+
+void
+weak_finish (void)
+{
+  tree t;
+
+  for (t = weakref_targets; t; t = TREE_CHAIN (t))
+    {
+      tree alias_decl = TREE_PURPOSE (t);
+      tree target = TREE_VALUE (t);
+      tree decl = find_decl (alias_decl, target);
+
+      /* FIXME: we should be able to assume decl is non-NULL, except
+	 for errors for undefined (actually, undeclared) symbols that
+	 finish_aliases_1 could have already issued.  Unfortunately,
+	 we'll often find decl to be NULL, so we can't always
+	 distinguish the cases of an undeclared alias target from a
+	 declared external alias target.  We try to compensate for
+	 that below.  */
+
+      if (decl && lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
+	{
+	  error ("%q+D's weakref target %q+D must not be a weakref itself\n",
+		 alias_decl, decl);
+	  continue;
+	}
+
+      /* If we got a decl for the target, use it to avoid issuing
+	 inappropriate weak directives.  */
+#ifndef ASM_OUTPUT_WEAKREF
+      if (!TREE_SYMBOL_REFERENCED (target)
+	  && (! decl || (TREE_USED (decl) && TREE_PUBLIC (decl)))
+	  && TREE_SYMBOL_REFERENCED (get_identifier
+				     (targetm.strip_name_encoding
+				      (IDENTIFIER_POINTER
+				       (DECL_ASSEMBLER_NAME (alias_decl))))))
+	{
+# ifdef ASM_WEAKEN_LABEL
+	  ASM_WEAKEN_LABEL (asm_out_file, IDENTIFIER_POINTER (target));
+# else
+	  if (! decl)
+	    {
+	      decl = build_decl (TREE_CODE (alias_decl), target,
+				 TREE_TYPE (alias_decl));
+
+	      DECL_EXTERNAL (decl) = 1;
+	      TREE_PUBLIC (decl) = 1;
+	      DECL_ARTIFICIAL (decl) = 1;
+	      TREE_NOTHROW (decl) = TREE_NOTHROW (alias_decl);
+	      TREE_USED (decl) = 1;
+	    }
+
+	  weak_finish_1 (decl);
+# endif
+	}
 #endif
+
+      {
+	tree *p;
+	tree t2;
+
+	/* Remove the alias and the target from the pending weak list
+	   so that we do not emit any .weak directives for the former,
+	   nor multiple .weak directives for the latter.  */
+	for (p = &weak_decls; (t2 = *p) ; )
+	  {
+	    if (TREE_VALUE (t2) == alias_decl
+		|| target == DECL_ASSEMBLER_NAME (TREE_VALUE (t2)))
+	      *p = TREE_CHAIN (t2);
+	    else
+	      p = &TREE_CHAIN (t2);
+	  }
+
+	/* Remove other weakrefs to the same target, to speed things up.  */
+	for (p = &TREE_CHAIN (t); (t2 = *p) ; )
+	  {
+	    if (target == TREE_VALUE (t2))
+	      *p = TREE_CHAIN (t2);
+	    else
+	      p = &TREE_CHAIN (t2);
+	  }
+      }
+    }
+
+  for (t = weak_decls; t; t = TREE_CHAIN (t))
+    {
+      tree decl = TREE_VALUE (t);
+
+      weak_finish_1 (decl);
     }
 }
 
@@ -4525,6 +4654,17 @@
 	  else
 	    p = &TREE_CHAIN (t);
 	}
+
+	/* Remove weakrefs to the same target from the pending weakref
+	   list, for the same reason.  */
+	for (p = &weakref_targets; (t = *p) ; )
+	  {
+	    if (DECL_ASSEMBLER_NAME (decl) == TREE_VALUE (t))
+	      *p = TREE_CHAIN (t);
+	    else
+	      p = &TREE_CHAIN (t);
+	  }
+
       return;
     }
 #elif defined(ASM_MAKE_LABEL_LINKONCE)
@@ -4598,7 +4738,7 @@
    tree node is DECL to have the value of the tree node TARGET.  */
 
 static void
-do_assemble_alias (tree decl, tree target ATTRIBUTE_UNUSED)
+do_assemble_alias (tree decl, tree target)
 {
   if (TREE_ASM_WRITTEN (decl))
     return;
@@ -4606,6 +4746,25 @@
   TREE_ASM_WRITTEN (decl) = 1;
   TREE_ASM_WRITTEN (DECL_ASSEMBLER_NAME (decl)) = 1;
 
+  if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
+    {
+      if (!TREE_SYMBOL_REFERENCED (target))
+	weakref_targets = tree_cons (decl, target, weakref_targets);
+
+#ifdef ASM_OUTPUT_WEAKREF
+      ASM_OUTPUT_WEAKREF (asm_out_file,
+			  IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
+			  IDENTIFIER_POINTER (target));
+#else
+      if (!SUPPORTS_WEAK)
+	{
+	  error ("%Jweakref is not supported in this configuration", decl);
+	  return;
+	}
+#endif
+      return;
+    }
+
 #ifdef ASM_OUTPUT_DEF
   /* Make name accessible from other files, if appropriate.  */
 
@@ -4640,6 +4799,16 @@
 	*p = TREE_CHAIN (t);
       else
 	p = &TREE_CHAIN (t);
+
+    /* Remove weakrefs to the same target from the pending weakref
+       list, for the same reason.  */
+    for (p = &weakref_targets; (t = *p) ; )
+      {
+	if (DECL_ASSEMBLER_NAME (decl) == TREE_VALUE (t))
+	  *p = TREE_CHAIN (t);
+	else
+	  p = &TREE_CHAIN (t);
+      }
   }
 #endif
 }
@@ -4659,9 +4828,13 @@
 
       target_decl = find_decl_and_mark_needed (p->decl, p->target);
       if (target_decl == NULL)
-	error ("%q+D aliased to undefined symbol %qs",
-	       p->decl, IDENTIFIER_POINTER (p->target));
-      else if (DECL_EXTERNAL (target_decl))
+	{
+	  if (! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)))
+	    error ("%q+D aliased to undefined symbol %qs",
+		   p->decl, IDENTIFIER_POINTER (p->target));
+	}
+      else if (DECL_EXTERNAL (target_decl)
+	       && ! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl)))
 	error ("%q+D aliased to external symbol %qs",
 	       p->decl, IDENTIFIER_POINTER (p->target));
     }
@@ -4691,18 +4864,60 @@
 {
   tree target_decl;
 
+  if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
+    {
+#ifndef ASM_OUTPUT_WEAKREF
+      /* We have to make the alias's identifier lexicographically
+	 different from that of the actual symbol, but still
+	 equivalent as far as the assembler is concerned, so we
+	 prepend a blank.  Making it equivalent would get us the
+	 incorrect decls from the cgraph hash tables.  */
+      const char *alt_asm_name;
+      tree target_id;
+
+      alt_asm_name = targetm.strip_name_encoding (IDENTIFIER_POINTER (target));
+      if (alt_asm_name[0] == '*')
+	alt_asm_name = ACONCAT (("* ", alt_asm_name + 1, NULL));
+      else
+	alt_asm_name = ACONCAT ((" ", alt_asm_name, NULL));
+
+      target_id = get_identifier (alt_asm_name);
+
+      if (DECL_ASSEMBLER_NAME_SET_P (decl))
+	{
+	  if (DECL_ASSEMBLER_NAME (decl) != target_id)
+	    warning (0, "%Joverriding weakref symbol name with that of target",
+		     decl);
+	}
+      else
+	{
+	  if (DECL_ASSEMBLER_NAME (decl) == target)
+	    error ("%Jweakref %qs targets itself",
+		   IDENTIFIER_POINTER (target));
+	}
+
+      SET_DECL_ASSEMBLER_NAME (decl, target_id);
+
+      gcc_assert (TREE_CHAIN (target_id) == NULL_TREE
+		  || TREE_CHAIN (target_id) == target);
+      TREE_CHAIN (target_id) = target;
+#endif
+    }
+  else
+    {
 #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))
-    {
-      error ("%Jonly weak aliases are supported in this configuration", decl);
+      error ("%Jalias definitions not supported in this configuration", decl);
       return;
-    }
+# else
+      if (!DECL_WEAK (decl))
+	{
+	  error ("%Jonly weak aliases are supported in this configuration", decl);
+	  return;
+	}
 # endif
 #endif
+    }
 
   /* We must force creation of DECL_RTL for debug info generation, even though
      we don't use it here.  */
Index: gcc/testsuite/gcc.dg/attr-weakref-1.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/attr-weakref-1.c	2005-10-19 02:52:08.000000000 -0200
@@ -0,0 +1,134 @@
+// { dg-do link }
+// { dg-additional-sources "attr-weakref-1a.c" }
+// { dg-require-weak "" }
+// { dg-options "-O2 -fno-common" }
+
+// Copyright 2005 Free Software Foundation, Inc.
+// Contributed by Alexandre Oliva <aoliva@redhat.com>
+
+// Torture test for weakrefs.  The first letter of an identifier
+// indicates whether/how it is defined; the second letter indicates
+// whether it is part of a variable or function test; the number that
+// follows is a test counter, and a letter that may follow enables
+// multiple identifiers within the same test (e.g., multiple weakrefs
+// or pointers to the same identifier).
+
+// Identifiers starting with W are weakrefs; those with p are
+// pointers; those with g are global definitions; those with l are
+// local definitions; those with w are expected to be weak undefined
+// in the symbol table; those with u are expected to be marked as
+// non-weak undefined in the symbol table.
+
+#ifndef ATTRIBUTE_USED
+# define ATTRIBUTE_USED __attribute__((used))
+#endif
+
+extern int wv1;
+extern int Wv1a __attribute__((weakref ("wv1")));
+static int *pv1a  ATTRIBUTE_USED = &Wv1a;
+extern int Wv1b __attribute__((weak, weakref, alias ("wv1")));
+static int *pv1b ATTRIBUTE_USED = &Wv1b;
+extern int Wv1c __attribute__((weakref));
+extern int Wv1c __attribute__((alias ("wv1")));
+static int *pv1c ATTRIBUTE_USED = &Wv1c;
+
+int gv2;
+extern int Wv2a __attribute__((weakref ("gv2")));
+static int *pv2a ATTRIBUTE_USED = &Wv2a;
+
+static int lv3;
+extern int Wv3a __attribute__((weakref ("lv3")));
+static int *pv3a ATTRIBUTE_USED = &Wv3a;
+
+extern int uv4;
+extern int Wv4a __attribute__((weakref ("uv4")));
+static int *pv4a ATTRIBUTE_USED = &Wv4a;
+static int *pv4 ATTRIBUTE_USED = &uv4;
+
+extern int Wv5a __attribute__((weakref ("uv5")));
+static int *pv5a ATTRIBUTE_USED = &Wv5a;
+extern int uv5;
+static int *pv5 ATTRIBUTE_USED = &uv5;
+
+extern int Wv6a __attribute__((weakref ("wv6")));
+static int *pv6a ATTRIBUTE_USED = &Wv6a;
+extern int wv6;
+
+extern int Wv7a __attribute__((weakref ("uv7")));
+static int ATTRIBUTE_USED fv7 () {
+  return Wv7a;
+}
+extern int uv7;
+static int ATTRIBUTE_USED fv7a () {
+  return uv7;
+}
+
+extern int uv8;
+static int ATTRIBUTE_USED fv8a () {
+  return uv8;
+}
+extern int Wv8a __attribute__((weakref ("uv8")));
+static int ATTRIBUTE_USED fv8 () {
+  return Wv8a;
+}
+
+extern int wv9 __attribute__((weak));
+extern int Wv9a __attribute__((weakref ("wv9")));
+static int *pv9a ATTRIBUTE_USED = &Wv9a;
+
+typedef void ftype(void);
+
+extern ftype wf1;
+extern ftype Wf1a __attribute__((weakref ("wf1")));
+static ftype *pf1a  ATTRIBUTE_USED = &Wf1a;
+extern ftype Wf1b __attribute__((weak, weakref, alias ("wf1")));
+static ftype *pf1b ATTRIBUTE_USED = &Wf1b;
+extern ftype Wf1c __attribute__((weakref));
+extern ftype Wf1c __attribute__((alias ("wf1")));
+static ftype *pf1c ATTRIBUTE_USED = &Wf1c;
+
+void gf2(void) {}
+extern ftype Wf2a __attribute__((weakref ("gf2")));
+static ftype *pf2a ATTRIBUTE_USED = &Wf2a;
+
+static void lf3(void) {}
+extern ftype Wf3a __attribute__((weakref ("lf3")));
+static ftype *pf3a ATTRIBUTE_USED = &Wf3a;
+
+extern ftype uf4;
+extern ftype Wf4a __attribute__((weakref ("uf4")));
+static ftype *pf4a ATTRIBUTE_USED = &Wf4a;
+static ftype *pf4 ATTRIBUTE_USED = &uf4;
+
+extern ftype Wf5a __attribute__((weakref ("uf5")));
+static ftype *pf5a ATTRIBUTE_USED = &Wf5a;
+extern ftype uf5;
+static ftype *pf5 ATTRIBUTE_USED = &uf5;
+
+extern ftype Wf6a __attribute__((weakref ("wf6")));
+static ftype *pf6a ATTRIBUTE_USED = &Wf6a;
+extern ftype wf6;
+
+extern ftype Wf7a __attribute__((weakref ("uf7")));
+static ftype* ATTRIBUTE_USED ff7 () {
+  return Wf7a;
+}
+extern ftype uf7;
+static ftype* ATTRIBUTE_USED ff7a () {
+  return uf7;
+}
+
+extern ftype uf8;
+static ftype* ATTRIBUTE_USED ff8a () {
+  return uf8;
+}
+extern ftype Wf8a __attribute__((weakref ("uf8")));
+static ftype* ATTRIBUTE_USED ff8 () {
+  return Wf8a;
+}
+
+extern ftype wf9 __attribute__((weak));
+extern ftype Wf9a __attribute__((weakref ("wf9")));
+static ftype *pf9a ATTRIBUTE_USED = &Wf9a;
+
+int main () {}
Index: gcc/testsuite/gcc.dg/attr-weakref-1a.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc/testsuite/gcc.dg/attr-weakref-1a.c	2005-10-19 02:52:08.000000000 -0200
@@ -0,0 +1,8 @@
+int uv4;
+int uv5;
+int uv7;
+int uv8;
+void uf4 (void) {}
+void uf5 (void) {}
+void uf7 (void) {}
+void uf8 (void) {}
-- 
Alexandre Oliva         http://www.lsd.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer   aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist  oliva@{lsd.ic.unicamp.br, gnu.org}

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