OSDN Git Service

* c-pragma.c (maybe_apply_renaming_pragma): New.
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 22 Mar 2002 22:51:48 +0000 (22:51 +0000)
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 22 Mar 2002 22:51:48 +0000 (22:51 +0000)
        (handle_pragma_redefine_extname, pending_redefine_extname): New.
        (handle_pragma_extern_prefix, pragma_extern_prefix): New.
        (init_pragma): Register them.
        * c-pragma.h (maybe_apply_renaming_pragma): Declare.
        * c-decl.c (finish_decl): Call it.
        * cp/decl.c (cp_finish_decl): Likewise.
        * doc/extend.texi: Document the new pragmas.

        * config/alpha/osf.h (CPP_SUBTARGET_SPEC): Add __EXTERN_PREFIX.
        (HANDLE_PRAGMA_EXTERN_PREFIX): New.

        * config/i386/sol2.h (CPP_PREDEFINES): Add __PRAGMA_REDEFINE_EXTNAME.
        (HANDLE_PRAGMA_REDEFINE_EXTNAME): New.
        * config/sparc/sol2.h: Likewise.

        * g++.dg/other/pragma-re-1.C: New.
        * g++.dg/other/pragma-ep-1.C: New.
        * gcc.dg/pragma-re-1.c, gcc.dg/pragma-re-2.c: New.
        * gcc.dg/pragma-ep-1.c, gcc.dg/pragma-ep-2.c: New.
        * gcc.dg/pragma-ep-3.c: New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@51200 138bc75d-0d04-0410-961f-82ee72b054a4

15 files changed:
gcc/c-decl.c
gcc/c-pragma.c
gcc/c-pragma.h
gcc/config/alpha/osf.h
gcc/config/i386/sol2.h
gcc/config/sparc/sol2.h
gcc/cp/decl.c
gcc/doc/extend.texi
gcc/testsuite/g++.dg/other/pragma-ep-1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/other/pragma-re-1.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/pragma-ep-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pragma-ep-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pragma-ep-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pragma-re-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pragma-re-2.c [new file with mode: 0644]

index 9242b03..4e0dccd 100644 (file)
@@ -3453,6 +3453,8 @@ finish_decl (decl, init, asmspec_tree)
   const char *asmspec = 0;
 
   /* If a name was specified, get the string.  */
+  if (current_binding_level == global_binding_level)
+    asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
   if (asmspec_tree)
     asmspec = TREE_STRING_POINTER (asmspec_tree);
 
index 1a17e67..4bf7ce2 100644 (file)
@@ -351,6 +351,135 @@ maybe_apply_pragma_weak (decl)
 }
 #endif /* HANDLE_PRAGMA_WEAK */
 
+#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME
+static void handle_pragma_redefine_extname PARAMS ((cpp_reader *));
+
+static tree pending_redefine_extname;
+
+/* #pragma redefined_extname oldname newname */
+static void
+handle_pragma_redefine_extname (dummy)
+     cpp_reader *dummy ATTRIBUTE_UNUSED;
+{
+  tree oldname, newname, decl, 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");
+
+  decl = identifier_global_value (oldname);
+  if (decl && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
+    {
+      if (DECL_ASSEMBLER_NAME_SET_P (decl)
+         && DECL_ASSEMBLER_NAME (decl) != newname)
+        warning ("#pragma redefine_extname conflicts with declaration");
+      SET_DECL_ASSEMBLER_NAME (decl, newname);
+    }
+  else
+    pending_redefine_extname
+      = tree_cons (oldname, newname, pending_redefine_extname);
+}
+#endif
+
+#ifdef HANDLE_PRAGMA_EXTERN_PREFIX
+static void handle_pragma_extern_prefix PARAMS ((cpp_reader *));
+
+static tree pragma_extern_prefix;
+
+/* #pragma extern_prefix "prefix" */
+static void
+handle_pragma_extern_prefix (dummy)
+     cpp_reader *dummy ATTRIBUTE_UNUSED;
+{
+  tree prefix, x;
+  enum cpp_ttype t;
+
+  if (c_lex (&prefix) != CPP_STRING)
+    {
+      warning ("malformed #pragma extern_prefix, ignored");
+      return;
+    }
+  t = c_lex (&x);
+  if (t != CPP_EOF)
+    warning ("junk at end of #pragma extern_prefix");
+
+  /* Note that the length includes the null terminator.  */
+  pragma_extern_prefix = (TREE_STRING_LENGTH (prefix) > 1 ? prefix : NULL);
+}
+#endif
+
+/* Hook from the front ends to apply the results of one of the preceeding
+   pragmas that rename variables.  */
+
+tree
+maybe_apply_renaming_pragma (decl, asmname)
+     tree decl, asmname;
+{
+  tree oldname;
+
+  /* Copied from the check in set_decl_assembler_name.  */
+  if (TREE_CODE (decl) == FUNCTION_DECL
+      || (TREE_CODE (decl) == VAR_DECL 
+          && (TREE_STATIC (decl) 
+              || DECL_EXTERNAL (decl) 
+              || TREE_PUBLIC (decl))))
+    oldname = DECL_ASSEMBLER_NAME (decl);
+  else
+    return asmname;
+
+  /* If the name begins with a *, that's a sign of an asmname attached to
+     a previous declaration.  */
+  if (IDENTIFIER_POINTER (oldname)[0] == '*')
+    {
+      const char *oldasmname = IDENTIFIER_POINTER (oldname) + 1;
+      if (asmname && strcmp (TREE_STRING_POINTER (asmname), oldasmname) != 0)
+       warning ("asm declaration conficts with previous rename");
+      asmname = build_string (strlen (oldasmname), oldasmname);
+    }
+
+#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME
+  {
+    tree *p, t;
+
+    for (p = &pending_redefine_extname; (t = *p) ; p = &TREE_CHAIN (t))
+      if (oldname == TREE_PURPOSE (t))
+       {
+         const char *newname = IDENTIFIER_POINTER (TREE_VALUE (t));
+
+         if (asmname && strcmp (TREE_STRING_POINTER (asmname), newname) != 0)
+            warning ("#pragma redefine_extname conflicts with declaration");
+         *p = TREE_CHAIN (t);
+
+         return build_string (strlen (newname), newname);
+       }
+  }
+#endif
+
+#ifdef HANDLE_PRAGMA_EXTERN_PREFIX
+  if (pragma_extern_prefix && !asmname)
+    {
+      char *x = concat (TREE_STRING_POINTER (pragma_extern_prefix),
+                       IDENTIFIER_POINTER (oldname), NULL);
+      asmname = build_string (strlen (x), x);
+      free (x);
+      return asmname;
+    }
+#endif
+
+  return asmname;
+}
+
 void
 init_pragma ()
 {
@@ -361,6 +490,17 @@ init_pragma ()
   cpp_register_pragma (parse_in, 0, "weak", handle_pragma_weak);
   ggc_add_tree_root (&pending_weaks, 1);
 #endif
+#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME
+  cpp_register_pragma (parse_in, 0, "redefine_extname",
+                      handle_pragma_redefine_extname);
+  ggc_add_tree_root (&pending_redefine_extname, 1);
+#endif
+#ifdef HANDLE_PRAGMA_EXTERN_PREFIX
+  cpp_register_pragma (parse_in, 0, "extern_prefix",
+                      handle_pragma_extern_prefix);
+  ggc_add_tree_root (&pragma_extern_prefix, 1);
+#endif
+
 #ifdef REGISTER_TARGET_PRAGMAS
   REGISTER_TARGET_PRAGMAS (parse_in);
 #endif
index ea5a982..22e4f7a 100644 (file)
@@ -54,5 +54,6 @@ extern void cpp_register_pragma PARAMS ((cpp_reader *,
 #endif
 
 extern void maybe_apply_pragma_weak PARAMS ((tree));
+extern tree maybe_apply_renaming_pragma PARAMS ((tree, tree));
 
 #endif /* GCC_C_PRAGMA_H */
index 250974c..1123e06 100644 (file)
@@ -47,7 +47,8 @@ Boston, MA 02111-1307, USA.  */
 
 #undef CPP_SUBTARGET_SPEC
 #define CPP_SUBTARGET_SPEC \
-"%{pthread|threads:-D_REENTRANT} %{threads:-D_PTHREAD_USE_D4} %(cpp_xfloat)"
+"%{pthread|threads:-D_REENTRANT} %{threads:-D_PTHREAD_USE_D4} %(cpp_xfloat) \
+-D__EXTERN_PREFIX"
 
 /* Under OSF4, -p and -pg require -lprof1, and -lprof1 requires -lpdf.  */
 
@@ -209,3 +210,7 @@ __enable_execute_stack (addr)                                               \
 /* Handle #pragma weak and #pragma pack.  */
 #undef HANDLE_SYSV_PRAGMA
 #define HANDLE_SYSV_PRAGMA 1
+
+/* Handle #pragma extern_prefix.  Technically only needed for Tru64 5.x,
+   but easier to manipulate preprocessor bits from here.  */
+#define HANDLE_PRAGMA_EXTERN_PREFIX 1
index 01f8915..fedfa55 100644 (file)
@@ -75,10 +75,11 @@ Boston, MA 02111-1307, USA.  */
 #undef WINT_TYPE_SIZE
 #define        WINT_TYPE_SIZE BITS_PER_WORD
 
-/* Add "sun" to the list of symbols defined for SVR4.  */
+#define HANDLE_PRAGMA_REDEFINE_EXTNAME 1
+
 #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 4994584..68efafe 100644 (file)
@@ -31,9 +31,11 @@ Boston, MA 02111-1307, USA.  */
 #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 fcc87fe..06c82ab 100644 (file)
@@ -8071,6 +8071,8 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
     }
 
   /* If a name was specified, get the string.  */
+  if (current_binding_level == global_binding_level)
+    asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
   if (asmspec_tree)
     asmspec = TREE_STRING_POINTER (asmspec_tree);
 
index 59297d2..f1f499d 100644 (file)
@@ -5998,6 +5998,8 @@ for further explanation.
 @menu
 * ARM Pragmas::
 * Darwin Pragmas::
+* Solaris Pragmas::
+* Tru64 Pragmas::
 @end menu
 
 @node ARM Pragmas
@@ -6062,6 +6064,44 @@ 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 pragma 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 Tru64 Pragmas
+@subsection Tru64 Pragmas
+
+For compatibility with the Compaq C compiler, the following pragma
+is supported.
+
+@table @code
+@item extern_prefix @var{string}
+@cindex pragma, extern_prefix
+
+This pragma renames all subsequent function and variable declarations
+such that @var{string} is prepended to the name.  This effect may be
+terminated by using another @code{extern_prefix} pragma with the 
+empty string.
+
+This pragma is similar in intent to to the asm labels extension
+(@pxref{Asm Labels}) in that the system programmer wants to change
+the assembly-level ABI without changing the source-level API.  The
+preprocessor defines @code{__EXTERN_PREFIX} if the pragma is available.
+@end table
+
 @node Unnamed Fields
 @section Unnamed struct/union fields within structs/unions.
 @cindex struct
diff --git a/gcc/testsuite/g++.dg/other/pragma-ep-1.C b/gcc/testsuite/g++.dg/other/pragma-ep-1.C
new file mode 100644 (file)
index 0000000..99450cd
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-do compile { target *-*-osf5* } } */
+/* { dg-final { scan-assembler "xyzzy_one" } } */
+/* { dg-final { scan-assembler "xyzzy_two" } } */
+/* { dg-final { scan-assembler "xyzzz_three" } } */
+/* { dg-final { scan-assembler "four" } } */
+/* { dg-final { scan-assembler-not "_four" } } */
+
+#ifndef __EXTERN_PREFIX
+#error
+#endif
+
+#pragma extern_prefix "xyzzy_"
+
+extern "C" int one(void);
+extern "C" int two(void);
+
+#pragma extern_prefix "xyzzz_"
+
+extern "C" int three(void);
+
+#pragma extern_prefix ""
+
+extern "C" int four(void);
+
+void *p[] = {
+  (void *) one, (void *) two, (void *) three, (void *) four
+};
diff --git a/gcc/testsuite/g++.dg/other/pragma-re-1.C b/gcc/testsuite/g++.dg/other/pragma-re-1.C
new file mode 100644 (file)
index 0000000..ec567f9
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile { target *-*-solaris* } } */
+/* { dg-final { scan-assembler "bar" } } */
+/* { dg-final { scan-assembler-not "foo" } } */
+/* { dg-final { scan-assembler "_Z3bazv" } } */
+/* { dg-final { scan-assembler-not "baq" } } */
+
+#ifndef __PRAGMA_REDEFINE_EXTNAME
+#error 
+#endif
+
+#pragma redefine_extname foo bar
+extern "C" int foo(void);
+void *p = (void *)foo;
+
+#pragma redefine_extname baz baq
+extern int baz(void);
+void *q = (void *)baz;
diff --git a/gcc/testsuite/gcc.dg/pragma-ep-1.c b/gcc/testsuite/gcc.dg/pragma-ep-1.c
new file mode 100644 (file)
index 0000000..91ec640
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-do compile { target *-*-osf5* } } */
+/* { dg-final { scan-assembler "xyzzy_one" } } */
+/* { dg-final { scan-assembler "xyzzy_two" } } */
+/* { dg-final { scan-assembler "xyzzz_three" } } */
+/* { dg-final { scan-assembler "four" } } */
+/* { dg-final { scan-assembler-not "_four" } } */
+
+#ifndef __EXTERN_PREFIX
+#error
+#endif
+
+#pragma extern_prefix "xyzzy_"
+
+extern int one(void);
+extern int two(void);
+
+#pragma extern_prefix "xyzzz_"
+
+extern int three(void);
+
+#pragma extern_prefix ""
+
+extern int four(void);
+
+int (*p[]) (void) = {
+  one, two, three, four
+};
diff --git a/gcc/testsuite/gcc.dg/pragma-ep-2.c b/gcc/testsuite/gcc.dg/pragma-ep-2.c
new file mode 100644 (file)
index 0000000..6e5c467
--- /dev/null
@@ -0,0 +1,7 @@
+/* { dg-do compile { target *-*-osf5* } } */
+
+#pragma extern_prefix                  /* { dg-warning "malformed" } */
+#pragma extern_prefix foo              /* { dg-warning "malformed" } */
+#pragma extern_prefix "foo" 1          /* { dg-warning "junk" } */
+
+int bar; /* silence `ISO C forbids an empty source file' warning */
diff --git a/gcc/testsuite/gcc.dg/pragma-ep-3.c b/gcc/testsuite/gcc.dg/pragma-ep-3.c
new file mode 100644 (file)
index 0000000..95b38bc
--- /dev/null
@@ -0,0 +1,10 @@
+/* { dg-do compile { target alpha*-*-osf5* } */
+/* { dg-final { scan-assembler ",Xfoo" } } */
+
+#pragma extern_prefix "X"
+void foo(void) __attribute__((noreturn));
+void foo(void) __attribute__((noreturn));
+void bar()
+{
+  foo();
+}
diff --git a/gcc/testsuite/gcc.dg/pragma-re-1.c b/gcc/testsuite/gcc.dg/pragma-re-1.c
new file mode 100644 (file)
index 0000000..80b1d37
--- /dev/null
@@ -0,0 +1,11 @@
+/* { dg-do compile { target *-*-solaris* } } */
+/* { dg-final { scan-assembler "bar" } } */
+/* { dg-final { scan-assembler-not "foo" } } */
+
+#ifndef __PRAGMA_REDEFINE_EXTNAME
+#error 
+#endif
+
+#pragma redefine_extname foo bar
+extern int foo(void);
+void *p = (void *)foo;
diff --git a/gcc/testsuite/gcc.dg/pragma-re-2.c b/gcc/testsuite/gcc.dg/pragma-re-2.c
new file mode 100644 (file)
index 0000000..351cbfb
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do compile { target *-*-solaris* } } */
+
+#pragma redefine_extname               /* { dg-warning "malformed" } */
+#pragma redefine_extname foo           /* { dg-warning "malformed" } */
+#pragma redefine_extname foo 1         /* { dg-warning "malformed" } */
+#pragma redefine_extname foo bar 2     /* { dg-warning "junk" } */