pragma redefine_extname, v3

Martin v. Loewis martin@v.loewis.de
Sun Feb 3 18:35:00 GMT 2002


Attached is revision 3 of the redefine_extname patch. The following
changes were implemented:
- correct commentary, and
- enable the feature on Solaris only.

Regards,
Martin

2002-02-03  Martin v. Löwis  <loewis@informatik.hu-berlin.de>

	* c-decl.c (finish_decl): Look for external name.
	(c_handle_pragma_extname): New function.
	* c-lang.c (LANG_HOOKS_HANDLE_PRAGMA_EXTNAME): Redefine.
	* c-pragma.c (langhooks.h): Include.
	(handle_pragma_redefine_extname): New function.
	(init_pragma): Register it.
	* c-pragma.h (HANDLE_PRAGMA_REDEFINE_EXTNAME): Define.
	* c-tree.h (c_handle_pragma_extname): Declare.
	* langhooks-def.h (LANG_HOOKS_HANDLE_PRAGMA_EXTNAME): Define.
	* langhooks.h (struct lang_hooks): Add handle_pragma_extname.
	* tree.c (struct extname, EXTNAME_HASH_INITIAL_SIZE, 
	extname_hash_table): Define.
	(add_external_name, find_external_name, extname_eq,
	extname_hash): New functions.
	(init_obstacks): Create extname_hash_table.
	* tree.h (add_external_name, find_external_name): Declare.
	* config/sparc/sol2.h (HANDLE_PRAGMA_REDEFINE_EXTNAME): Define.
	(CPP_PREDEFINES): Add __PRAGMA_REDEFINE_EXTNAME.
	* config/i386/sol2.h: Likewise.
	* cp/lang.c (LANG_HOOKS_HANDLE_PRAGMA_EXTNAME): Redefine.
	* cp/tree.h (cp_handle_pragma_extname): Declare.
	* cp/decl.c (cp_finish_decl): Look for external name.
	(cp_handle_pragma_extname): New function.
	* doc/extend.texi: Document pragma redefine_extname.

Index: c-decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-decl.c,v
retrieving revision 1.294
diff -u -r1.294 c-decl.c
--- c-decl.c	2002/02/02 00:14:31	1.294
+++ c-decl.c	2002/02/03 12:09:20
@@ -3593,11 +3593,24 @@
   tree type = TREE_TYPE (decl);
   int was_incomplete = (DECL_SIZE (decl) == 0);
   const char *asmspec = 0;
+  tree extname;
 
   /* If a name was specified, get the string.  */
   if (asmspec_tree)
     asmspec = TREE_STRING_POINTER (asmspec_tree);
 
+  if (!DECL_CONTEXT (decl))
+    {
+      extname = find_external_name (DECL_NAME (decl));
+      if (extname) 
+	{
+	  if (asmspec_tree)
+	    error_with_decl (decl, "'%s' has both extname and asm spec.");
+	  else
+	    asmspec = IDENTIFIER_POINTER (extname);
+	}
+    }
+
   /* If `start_decl' didn't like having an initialization, ignore it now.  */
   if (init != 0 && DECL_INITIAL (decl) == 0)
     init = 0;
@@ -7434,4 +7447,24 @@
 {
   tree t = build_tree_list (NULL_TREE, void_type_node);
   return t;
+}
+
+/* Handle #pragma redefine_extname.  */
+void
+c_handle_pragma_extname (old, new)
+     tree old, new;
+{
+  tree decl = IDENTIFIER_GLOBAL_VALUE (old);
+  if (decl)
+    {
+      /* If DECL_ASSEMBLER_NAME has been used already, it will be equal to the
+         decl_name. Unfortunately, we cannot test whether it was used to emit
+         code already.  */
+      if (DECL_ASSEMBLER_NAME_SET_P (decl)
+          && DECL_ASSEMBLER_NAME (decl) != new
+          && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
+	warning ("#pragma redefine_extname conflicts with declaration");
+      SET_DECL_ASSEMBLER_NAME (decl, new);
+    }
+  add_external_name (old, new);
 }
Index: c-lang.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-lang.c,v
retrieving revision 1.74
diff -u -r1.74 c-lang.c
--- c-lang.c	2001/12/17 22:43:40	1.74
+++ c-lang.c	2002/02/03 12:09:20
@@ -65,6 +65,8 @@
 #undef LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P
 #define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P \
   anon_aggr_type_p
+#undef LANG_HOOKS_HANDLE_PRAGMA_EXTNAME
+#define LANG_HOOKS_HANDLE_PRAGMA_EXTNAME c_handle_pragma_extname
 
 /* ### When changing hooks, consider if ObjC needs changing too!! ### */
 
Index: c-pragma.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-pragma.c,v
retrieving revision 1.46
diff -u -r1.46 c-pragma.c
--- c-pragma.c	2001/11/13 03:20:58	1.46
+++ c-pragma.c	2002/02/03 12:09:20
@@ -32,6 +32,7 @@
 #include "c-lex.h"
 #include "output.h"
 #include "tm_p.h"
+#include "langhooks.h"
 
 #define GCC_BAD(msgid) do { warning (msgid); return; } while (0)
 #define GCC_BAD2(msgid, arg) do { warning (msgid, arg); return; } while (0)
@@ -302,6 +303,37 @@
 }
 #endif
 
+#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME
+static void handle_pragma_redefine_extname      PARAMS ((cpp_reader *));
+
+static void
+handle_pragma_redefine_extname (dummy)
+     cpp_reader *dummy ATTRIBUTE_UNUSED;
+{
+  tree oldname, newname, x;
+  enum cpp_ttype t;
+
+  if (c_lex (&oldname) != CPP_NAME)
+    {
+      warning ("malformed #pragma redefine_extname, ignored");
+      return;
+    }
+  if (c_lex (&newname) != CPP_NAME)
+    {
+      warning ("malformed #pragma redefine_extname, ignored");
+      return;
+    }
+  t = c_lex (&x);
+  if (t != CPP_EOF)
+    warning ("junk at end of #pragma redefine_extname");
+
+  if (lang_hooks.handle_pragma_extname)
+    lang_hooks.handle_pragma_extname (oldname, newname);
+  else
+    warning ("pragma redefine_extname not supported");
+}
+#endif
+
 void
 init_pragma ()
 {
@@ -310,6 +342,9 @@
 #endif
 #ifdef HANDLE_PRAGMA_WEAK
   cpp_register_pragma (parse_in, 0, "weak", handle_pragma_weak);
+#endif
+#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME
+  cpp_register_pragma (parse_in, 0, "redefine_extname", handle_pragma_redefine_extname);
 #endif
 #ifdef REGISTER_TARGET_PRAGMAS
   REGISTER_TARGET_PRAGMAS (parse_in);
Index: c-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-tree.h,v
retrieving revision 1.80
diff -u -r1.80 c-tree.h
--- c-tree.h	2002/01/11 11:31:03	1.80
+++ c-tree.h	2002/02/03 12:09:20
@@ -214,6 +214,7 @@
 extern tree c_begin_compound_stmt               PARAMS ((void));
 extern void c_expand_deferred_function          PARAMS ((tree));
 extern void c_expand_decl_stmt                  PARAMS ((tree));
+extern void c_handle_pragma_extname		PARAMS ((tree, tree));
 
 
 /* in c-objc-common.c */
Index: langhooks-def.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/langhooks-def.h,v
retrieving revision 1.8
diff -u -r1.8 langhooks-def.h
--- langhooks-def.h	2001/12/05 23:48:10	1.8
+++ langhooks-def.h	2002/02/03 12:09:21
@@ -82,6 +82,7 @@
 #define LANG_HOOKS_PRINT_TYPE		lhd_print_tree_nothing
 #define LANG_HOOKS_PRINT_IDENTIFIER	lhd_print_tree_nothing
 #define LANG_HOOKS_SET_YYDEBUG		lhd_set_yydebug
+#define LANG_HOOKS_HANDLE_PRAGMA_EXTNAME 0
 
 /* Tree inlining hooks.  */
 #define LANG_HOOKS_TREE_INLINING_WALK_SUBTREES lhd_tree_inlining_walk_subtrees
@@ -151,7 +152,8 @@
   LANG_HOOKS_PRINT_IDENTIFIER, \
   LANG_HOOKS_SET_YYDEBUG, \
   LANG_HOOKS_TREE_INLINING_INITIALIZER, \
-  LANG_HOOKS_TREE_DUMP_INITIALIZER \
+  LANG_HOOKS_TREE_DUMP_INITIALIZER, \
+  LANG_HOOKS_HANDLE_PRAGMA_EXTNAME \
 }
 
 #endif /* GCC_LANG_HOOKS_DEF_H */
Index: langhooks.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/langhooks.h,v
retrieving revision 1.15
diff -u -r1.15 langhooks.h
--- langhooks.h	2001/12/05 23:48:10	1.15
+++ langhooks.h	2002/02/03 12:09:21
@@ -154,6 +154,9 @@
   
   struct lang_hooks_for_tree_dump tree_dump;
 
+  /* Process a #pragma redefine_extname directive.  */
+  void (*handle_pragma_extname) PARAMS((tree, tree));
+
   /* Whenever you add entries here, make sure you adjust langhooks-def.h
      and langhooks.c accordingly.  */
 };
Index: tree.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/tree.c,v
retrieving revision 1.236
diff -u -r1.236 tree.c
--- tree.c	2002/02/02 00:14:30	1.236
+++ tree.c	2002/02/03 12:09:23
@@ -167,6 +167,20 @@
 static void type_hash_mark PARAMS ((const void *));
 static int mark_tree_hashtable_entry PARAMS((void **, void *));
 
+/* Hashtable for external names. */
+
+struct extname
+{
+  tree ident;
+  tree extname;
+};
+
+#define EXTNAME_HASH_INITIAL_SIZE 50
+htab_t extname_hash_table;
+
+static int extname_eq PARAMS ((const void*, const void*));
+static unsigned int extname_hash PARAMS ((const void*));
+
 /* If non-null, these are language-specific helper functions for
    unsave_expr_now.  If present, LANG_UNSAVE is called before its
    argument (an UNSAVE_EXPR) is to be unsaved, and all other
@@ -189,6 +203,38 @@
 tree global_trees[TI_MAX];
 tree integer_types[itk_none];
 

+/* Record the association between a name and an external name.  */
+
+void
+add_external_name (old, new)
+     tree old, new;
+{
+  struct extname *h, in;
+  void **loc;
+  in.ident = old;
+  loc = htab_find_slot_with_hash (extname_hash_table, &in, 
+				  (hashval_t)old, INSERT);
+  h = xmalloc(sizeof(struct extname));
+  h->ident = old;
+  h->extname = new;
+  *(struct extname**)loc = h;
+}
+
+/* Find the external name, given the original name.  */
+
+tree
+find_external_name (old)
+     tree old;
+{
+  struct extname in, *h;
+  in.ident = old;
+  h = (struct extname*)htab_find_with_hash (extname_hash_table, &in, 
+					    (hashval_t)old);
+  if (h)
+    return h->extname;
+  return NULL;
+}
+
 /* Set the DECL_ASSEMBLER_NAME for DECL.  */
 void
 set_decl_assembler_name (decl)
@@ -231,6 +277,11 @@
   ggc_add_tree_root (global_trees, TI_MAX);
   ggc_add_tree_root (integer_types, itk_none);
 
+  /* Initialize hash table of external names.  */
+  extname_hash_table = htab_create (EXTNAME_HASH_INITIAL_SIZE, 
+				    extname_hash,
+				    extname_eq, 0);
+
   /* Set lang_set_decl_set_assembler_name to a default value.  */
   lang_set_decl_assembler_name = set_decl_assembler_name;
 }
@@ -3342,6 +3393,24 @@
       ++i;
 
   return i;
+}
+
+/* Returns the hash value of an identifier in the extname. */
+
+static unsigned int
+extname_hash (item)
+     const void *item;
+{
+  return (hashval_t)(((const struct extname *) item)->ident);
+}
+
+static int
+extname_eq (va, vb)
+     const void *va;
+     const void *vb;
+{
+  return ((const struct extname *)va)->ident
+    == ((const struct extname *)vb)->ident;
 }
 
 /* Nonzero if integer constants T1 and T2
Index: tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/tree.h,v
retrieving revision 1.303
diff -u -r1.303 tree.h
--- tree.h	2002/02/02 00:14:31	1.303
+++ tree.h	2002/02/03 12:09:25
@@ -2723,6 +2723,8 @@
 extern tree get_callee_fndecl                   PARAMS ((tree));
 extern void set_decl_assembler_name             PARAMS ((tree));
 extern int type_num_arguments                   PARAMS ((tree));
+extern void add_external_name			PARAMS ((tree, tree));
+extern tree find_external_name			PARAMS ((tree));
 

 /* In stmt.c */
 
Index: config/i386/sol2.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/i386/sol2.h,v
retrieving revision 1.19
diff -u -r1.19 sol2.h
--- config/i386/sol2.h	2002/01/27 04:18:10	1.19
+++ config/i386/sol2.h	2002/02/03 12:09:26
@@ -73,10 +73,12 @@
 #undef	WINT_TYPE_SIZE
 #define	WINT_TYPE_SIZE BITS_PER_WORD
 
+#define HANDLE_PRAGMA_REDEFINE_EXTNAME 1
+
 /* Add "sun" to the list of symbols defined for SVR4.  */
 #undef CPP_PREDEFINES
 #define CPP_PREDEFINES \
-  "-Dunix -D__svr4__ -D__SVR4 -Dsun -Asystem=svr4"
+  "-Dunix -D__svr4__ -D__SVR4 -Dsun  -D__PRAGMA_REDEFINE_EXTNAME -Asystem=svr4"
 
 /* Solaris 2/Intel as chokes on #line directives.  */
 #undef CPP_SPEC
Index: config/sparc/sol2.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/sparc/sol2.h,v
retrieving revision 1.34
diff -u -r1.34 sol2.h
--- config/sparc/sol2.h	2001/12/28 09:55:14	1.34
+++ config/sparc/sol2.h	2002/02/03 12:09:26
@@ -31,9 +31,11 @@
 #undef	WINT_TYPE_SIZE
 #define	WINT_TYPE_SIZE BITS_PER_WORD
 
+#define HANDLE_PRAGMA_REDEFINE_EXTNAME 1
+
 #undef CPP_PREDEFINES
 #define CPP_PREDEFINES \
-"-Dsparc -Dsun -Dunix -D__svr4__ -D__SVR4 \
+"-Dsparc -Dsun -Dunix -D__svr4__ -D__SVR4 -D__PRAGMA_REDEFINE_EXTNAME\
 -Asystem=unix -Asystem=svr4"
 
 #undef CPP_SUBTARGET_SPEC
Index: cp/cp-lang.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-lang.c,v
retrieving revision 1.9
diff -u -r1.9 cp-lang.c
--- cp/cp-lang.c	2001/12/05 23:48:14	1.9
+++ cp/cp-lang.c	2002/02/03 12:09:26
@@ -91,6 +91,8 @@
 #define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN cp_dump_tree
 #undef LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN
 #define LANG_HOOKS_TREE_DUMP_TYPE_QUALS_FN cp_type_quals
+#undef LANG_HOOKS_HANDLE_PRAGMA_EXTNAME
+#define LANG_HOOKS_HANDLE_PRAGMA_EXTNAME cp_handle_pragma_extname
 
 /* Each front end provides its own hooks, for toplev.c.  */
 const struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER;
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.677
diff -u -r1.677 cp-tree.h
--- cp/cp-tree.h	2002/02/01 19:32:46	1.677
+++ cp/cp-tree.h	2002/02/03 12:09:29
@@ -3781,6 +3781,7 @@
 extern void register_dtor_fn                    PARAMS ((tree));
 extern tmpl_spec_kind current_tmpl_spec_kind    PARAMS ((int));
 extern tree cp_fname_init			PARAMS ((const char *));
+extern void cp_handle_pragma_extname		PARAMS ((tree, tree));
 
 /* in decl2.c */
 extern void init_decl2				PARAMS ((void));
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.856
diff -u -r1.856 decl.c
--- cp/decl.c	2002/02/01 19:51:42	1.856
+++ cp/decl.c	2002/02/03 12:09:36
@@ -8055,6 +8055,7 @@
   tree ttype = NULL_TREE;
   const char *asmspec = NULL;
   int was_readonly = 0;
+  tree extname;
 
   if (! decl)
     {
@@ -8067,6 +8068,19 @@
   if (asmspec_tree)
       asmspec = TREE_STRING_POINTER (asmspec_tree);
 
+  if (CP_DECL_CONTEXT (decl) == global_namespace
+      && DECL_LANGUAGE (decl) == lang_c)
+    {
+      extname = find_external_name (DECL_NAME (decl));
+      if (extname) 
+	{
+	  if (asmspec_tree)
+	    error_with_decl (decl, "'%s' has both extname and asm spec.");
+	  else
+	    asmspec = IDENTIFIER_POINTER (extname);
+	}
+    }
+
   if (init && TREE_CODE (init) == NAMESPACE_DECL)
     {
       error ("cannot initialize `%D' to namespace `%D'",
@@ -14775,4 +14789,50 @@
 {
   /* A missing noreturn is ok for the `main' function.  */
   return DECL_MAIN_P (decl);
+}
+
+/* Handle #pragma redefine_extname.  */
+void
+cp_handle_pragma_extname (old, new)
+     tree old, new;
+{
+  tree decl = IDENTIFIER_GLOBAL_VALUE (old);
+  if (decl && TREE_CODE (decl) == OVERLOAD)
+    {
+      tree overload = decl;
+      decl = NULL;
+      for (; overload; overload = OVL_NEXT (overload))
+        if (DECL_LANGUAGE (OVL_CURRENT (overload)) == lang_c)
+          {
+            if (decl)
+              {
+                error ("Both '%D' and '%D' apply to extname",
+		       decl, OVL_CURRENT (overload));
+                return;
+              }
+            else
+              decl = OVL_CURRENT (overload);
+          }
+    }
+
+  if (decl)
+    {
+      if (TREE_CODE (decl) != FUNCTION_DECL
+	  && TREE_CODE (decl) != VAR_DECL)
+	error ("#pragma redefine_extname applied to '%D'", decl);
+      else
+        {
+          /* The compiler will access the assembler name immediately
+             after the declaration, so we cannot tell whether it
+             was a user-assigned name or a defaulted one. Therefore,
+             warn only if the names differ.  */
+          if (DECL_ASSEMBLER_NAME_SET_P (decl)
+              && DECL_ASSEMBLER_NAME (decl) != new
+              && DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
+            warning ("#pragma redefine_extname conflicts with declaration");
+          
+          SET_DECL_ASSEMBLER_NAME (decl, new);
+        }
+    }
+  add_external_name (old, new);
 }
Index: doc/extend.texi
===================================================================
RCS file: /cvs/gcc/egcs/gcc/doc/extend.texi,v
retrieving revision 1.59
diff -u -r1.59 extend.texi
--- doc/extend.texi	2002/01/28 20:07:00	1.59
+++ doc/extend.texi	2002/02/03 12:14:31
@@ -5740,6 +5740,7 @@
 @menu
 * ARM Pragmas::
 * Darwin Pragmas::
+* Solaris Pragmas::
 @end menu
 
 @node ARM Pragmas
@@ -5802,6 +5803,23 @@
 produce warnings for the listed variables.  The effect is similar to
 that of the @code{unused} attribute, except that this pragma may appear
 anywhere within the variables' scopes.
+@end table
+
+@node Solaris Pragmas
+@subsection Solaris Pragmas
+
+For compatibility with the SunPRO compiler, the following pragma
+is supported.
+
+@table @code
+@item redefine_extname @var{oldname} @var{newname}
+@cindex pragma, redefine_extname
+
+This macro gives the C function @var{oldname} the assembler label
+@var{newname}. The pragma must appear before the function declaration.
+This pragma is equivalent to the asm labels extension (@pxref{Asm
+Labels}). The preprocessor defines @code{__PRAGMA_REDEFINE_EXTNAME}
+if the pragma is available.
 @end table
 
 @node Unnamed Fields



More information about the Gcc-patches mailing list