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 20, 2005, Richard Henderson <rth@redhat.com> wrote:

> On Thu, Oct 20, 2005 at 04:55:44AM -0200, Alexandre Oliva wrote:
>> 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?

> Yes, I think so.  Although if you've already done the survey, I'd
> like to see a summary before I send you off on a wild goose chase.

I haven't really done a survey, just noticed some
potentially-suspicious uses of DECL_ASSEMBLER_NAME and decided to not
pursue that earlier.

I've now chosen to try another possibility I had in mind that actually
appears to work.  The idea is to flag weakref identifiers such that
their TREE_CHAIN is the identifier they target, and have assemble_name
output the target instead of the alias.  This was quite
straightforward to implement, but I'm sure there are going to be some
corner cases that will have to handle this flag as well.

I also tried to narrow TREE_DEPRECATED (because that's the flag I
chose to use to flag transparent-alias identifiers) such that it would
only apply to decls, which appears to match some comments but not all,
and then run into trouble.  I intend to investigate that further, but
I'd be happy to go with another flag if someone tells me
TREE_DEPRECATED is still used in identifiers, which some
apparently-outdated comments stated.

>> +	  && TREE_SYMBOL_REFERENCED (get_identifier
>> +				     (targetm.strip_name_encoding
>> +				      (IDENTIFIER_POINTER
>> +				       (DECL_ASSEMBLER_NAME (alias_decl))))))

> In theory there's *never* a name encoding on a DECL_ASSEMBLER_NAME;
> that should be a property of the rtl SYMBOL_REF alone.  I see that
> a few backends are confused though, including cygwin.

I've used DECL_ASSEMBLER_NAME directly in this revision of the patch.
How does this one look?

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

	* tree.h (IDENTIFIER_TRANSPARENT_ALIAS): New.
	(TREE_DEPRECATED): Adjust comment.  Check for a DECL.
	* 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-20 17:31:09.000000000 -0200
+++ gcc/c-common.c	2005-10-20 17:32:45.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-20 17:31:09.000000000 -0200
+++ gcc/config.in	2005-10-20 17:32:45.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-20 17:31:09.000000000 -0200
+++ gcc/configure	2005-10-20 17:32:45.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-20 17:31:09.000000000 -0200
+++ gcc/configure.ac	2005-10-20 17:32:45.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-20 17:31:09.000000000 -0200
+++ gcc/defaults.h	2005-10-20 17:32:45.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-20 17:31:09.000000000 -0200
+++ gcc/doc/extend.texi	2005-10-20 17:32:45.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-20 17:32:09.000000000 -0200
+++ gcc/varasm.c	2005-10-20 23:29:05.000000000 -0200
@@ -2026,7 +2026,18 @@
 
   id = maybe_get_identifier (real_name);
   if (id)
-    mark_referenced (id);
+    {
+      mark_referenced (id);
+      gcc_assert ((TREE_CHAIN (id) != NULL_TREE)
+		  == (IDENTIFIER_TRANSPARENT_ALIAS (id) != 0));
+      if (IDENTIFIER_TRANSPARENT_ALIAS (id))
+	{
+	  id = TREE_CHAIN (id);
+	  name = IDENTIFIER_POINTER (id);
+	  gcc_assert (! TREE_CHAIN (id)
+		      && ! IDENTIFIER_TRANSPARENT_ALIAS (id));
+	}
+    }
 
   assemble_name_raw (file, name);
 }
@@ -4466,35 +4477,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
+      gcc_assert (IDENTIFIER_TRANSPARENT_ALIAS (DECL_ASSEMBLER_NAME
+						(alias_decl))
+		  && TREE_CHAIN (DECL_ASSEMBLER_NAME (alias_decl)) == target);
+      if (!TREE_SYMBOL_REFERENCED (target)
+	  && (! decl || (TREE_USED (decl) && TREE_PUBLIC (decl)))
+	  && TREE_SYMBOL_REFERENCED (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 +4665,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 +4749,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 +4757,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 +4810,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 +4839,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 +4875,33 @@
 {
   tree target_decl;
 
+  if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
+    {
+      tree alias = DECL_ASSEMBLER_NAME (decl);
+
+      if (alias == target)
+	error ("%Jweakref %qD targets itself", decl);
+
+#ifndef ASM_OUTPUT_WEAKREF
+      IDENTIFIER_TRANSPARENT_ALIAS (alias) = 1;
+      TREE_CHAIN (alias) = 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-20 17:32:45.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-20 17:32:45.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) {}
Index: gcc/tree.h
===================================================================
--- gcc/tree.h.orig	2005-10-18 14:03:07.000000000 -0200
+++ gcc/tree.h	2005-10-20 18:43:08.000000000 -0200
@@ -428,6 +428,9 @@
 	TREE_DEPRECATED in
 	   ..._DECL
 
+	IDENTIFIER_TRANSPARENT_ALIAS in
+	   IDENTIFIER_NODE
+
    visited:
 
    	Used in tree traversals to mark visited nodes.
@@ -1042,9 +1045,15 @@
    In a BLOCK node, this is BLOCK_HANDLER_BLOCK.  */
 #define TREE_PROTECTED(NODE) ((NODE)->common.protected_flag)
 
-/* Nonzero in an IDENTIFIER_NODE if the use of the name is defined as a
+/* Nonzero in a _DECL if the use of the name is defined as a
    deprecated feature by __attribute__((deprecated)).  */
-#define TREE_DEPRECATED(NODE) ((NODE)->common.deprecated_flag)
+#define TREE_DEPRECATED(NODE) \
+  ((NODE)->common.deprecated_flag)
+
+/* Nonzero in an IDENTIFIER_NODE if the name is a local alias, whose
+   uses are to be substituted for uses of the TREE_CHAINed identifier.  */
+#define IDENTIFIER_TRANSPARENT_ALIAS(NODE) \
+  (IDENTIFIER_NODE_CHECK (NODE)->common.deprecated_flag)
 
 /* Value of expression is function invariant.  A strict subset of
    TREE_CONSTANT, such an expression is constant over any one function
-- 
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]