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]

pragma redefine_extname, v2


This is the second version of the redefine_extname patch. I've
rewritten the patch to address all of Zack's concerns, in particular:
- lookup of external names is done in finish_decl of the C and C++
  front-ends.
- lookup uses a hash table. This hash table is not integrated into GC,
  since it maps identifiers to identifiers, which are GC roots, anyway.
- the implementation checks for interference with the asm() extension.
  It does not check for ordering constraints between the pragma and
  the declaration of the function, since apparently no such constraint
  exists (the Solaris headers have the pragma both before and after
  the declaration). Unfortunately, if the pragma appears after the
  declaration, it is not possible to check whether the assembler name
  was assigned through asm(), or by the default algorithm - atleast
  cc1plus will set the assembler name right after the declaration
  has been parsed.

Please let me know what further changes need to be made before it can
be accepted.

Regards,
Martin

2001-12-23  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.
	* gcc.c (cpp_options): Add -D__PRAGMA_REDEFINE_EXTNAME.
	* 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.
	* 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.284
diff -u -p -r1.284 c-decl.c
--- c-decl.c	2001/12/17 01:18:39	1.284
+++ c-decl.c	2001/12/23 17:02:14
@@ -3560,11 +3560,24 @@ finish_decl (decl, init, asmspec_tree)
   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;
@@ -7381,4 +7394,24 @@ build_void_list_node ()
 {
   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 somebody has accessed decl_assembler_name until here,
+         it will be 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 -p -r1.74 c-lang.c
--- c-lang.c	2001/12/17 22:43:40	1.74
+++ c-lang.c	2001/12/23 17:02:14
@@ -65,6 +65,8 @@ static void c_post_options PARAMS ((void
 #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 -p -r1.46 c-pragma.c
--- c-pragma.c	2001/11/13 03:20:58	1.46
+++ c-pragma.c	2001/12/23 17:12:22
@@ -32,6 +32,7 @@ Software Foundation, 59 Temple Place - S
 #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 @@ handle_pragma_weak (dummy)
 }
 #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 @@ init_pragma ()
 #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-pragma.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-pragma.h,v
retrieving revision 1.25
diff -u -p -r1.25 c-pragma.h
--- c-pragma.h	2001/10/14 17:43:58	1.25
+++ c-pragma.h	2001/12/23 17:02:14
@@ -41,6 +41,8 @@ Software Foundation, 59 Temple Place - S
 #define HANDLE_PRAGMA_PACK 1
 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
 
+#define HANDLE_PRAGMA_REDEFINE_EXTNAME 1
+
 extern void init_pragma PARAMS ((void));
 
 /* Duplicate prototypes for the register_pragma stuff and the typedef for
Index: c-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/c-tree.h,v
retrieving revision 1.78
diff -u -p -r1.78 c-tree.h
--- c-tree.h	2001/12/17 22:43:40	1.78
+++ c-tree.h	2001/12/23 17:02:15
@@ -231,6 +231,7 @@ extern tree xref_tag                    
 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-typeck.c */
 extern tree require_complete_type		PARAMS ((tree));
Index: gcc.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/gcc.c,v
retrieving revision 1.280
diff -u -p -r1.280 gcc.c
--- gcc.c	2001/12/15 20:31:05	1.280
+++ gcc.c	2001/12/23 17:02:31
@@ -687,7 +687,7 @@ static const char *cpp_options =
  %{fshort-wchar:-U__WCHAR_TYPE__ -D__WCHAR_TYPE__=short\\ unsigned\\ int}\
  %{ffreestanding:-D__STDC_HOSTED__=0} %{fno-hosted:-D__STDC_HOSTED__=0}\
  %{!ffreestanding:%{!fno-hosted:-D__STDC_HOSTED__=1}}\
- %{fshow-column} %{fno-show-column}\
+ %{fshow-column} %{fno-show-column} -D__PRAGMA_REDEFINE_EXTNAME\
  %{fleading-underscore} %{fno-leading-underscore}\
  %{fno-operator-names} %{ftabstop=*} %{remap}\
  %{g3:-dD} %{W*} %{w} %{pedantic*} %{H} %{d*} %C %{D*&U*&A*} %{i*} %Z %i\
Index: langhooks-def.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/langhooks-def.h,v
retrieving revision 1.8
diff -u -p -r1.8 langhooks-def.h
--- langhooks-def.h	2001/12/05 23:48:10	1.8
+++ langhooks-def.h	2001/12/23 17:02:31
@@ -82,6 +82,7 @@ void lhd_tree_inlining_end_inlining		PAR
 #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 @@ int lhd_tree_dump_type_quals			PARAMS ((
   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 -p -r1.15 langhooks.h
--- langhooks.h	2001/12/05 23:48:10	1.15
+++ langhooks.h	2001/12/23 17:02:31
@@ -154,6 +154,9 @@ struct lang_hooks
   
   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.229
diff -u -p -r1.229 tree.c
--- tree.c	2001/12/11 19:33:39	1.229
+++ tree.c	2001/12/23 17:02:39
@@ -167,6 +167,20 @@ static int type_hash_marked_p PARAMS ((c
 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 @@ void (*lang_set_decl_assembler_name)    
 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 @@ init_obstacks ()
   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;
 }
@@ -3336,6 +3387,24 @@ type_num_arguments (type)
       ++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.294
diff -u -p -r1.294 tree.h
--- tree.h	2001/12/11 19:33:39	1.294
+++ tree.h	2001/12/23 17:02:46
@@ -2711,6 +2713,8 @@ extern tree get_set_constructor_bytes		P
 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: cp/cp-lang.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-lang.c,v
retrieving revision 1.9
diff -u -p -r1.9 cp-lang.c
--- cp-lang.c	2001/12/05 23:48:14	1.9
+++ cp-lang.c	2001/12/23 17:02:50
@@ -91,6 +91,8 @@ static HOST_WIDE_INT cxx_get_alias_set P
 #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.667
diff -u -p -r1.667 cp-tree.h
--- cp-tree.h	2001/12/18 03:35:25	1.667
+++ cp-tree.h	2001/12/23 17:02:58
@@ -3717,6 +3717,7 @@ extern tree declare_global_var          
 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.844
diff -u -p -r1.844 decl.c
--- decl.c	2001/12/18 13:30:29	1.844
+++ decl.c	2001/12/23 17:03:59
@@ -8030,6 +8030,7 @@ cp_finish_decl (decl, init, asmspec_tree
   tree ttype = NULL_TREE;
   const char *asmspec = NULL;
   int was_readonly = 0;
+  tree extname;
 
   if (! decl)
     {
@@ -8042,6 +8043,19 @@ cp_finish_decl (decl, init, asmspec_tree
   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'",
@@ -14623,4 +14637,50 @@ cp_missing_noreturn_ok_p (decl)
 {
   /* 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.50
diff -u -p -r1.50 extend.texi
--- extend.texi	2001/12/21 02:36:37	1.50
+++ extend.texi	2001/12/23 17:04:16
@@ -4583,6 +4583,7 @@ for further explanation.
 @menu
 * ARM Pragmas::
 * Darwin Pragmas::
+* Solaris Pragmas::
 @end menu
 
 @node ARM Pragmas
@@ -4645,6 +4646,23 @@ This pragma declares variables to be pos
 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


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