Commit 41c64394 by Richard Henderson

c-pragma.c (maybe_apply_renaming_pragma): New.

        * c-pragma.c (maybe_apply_renaming_pragma): New.
        (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.

From-SVN: r51200
parent 661fff62
......@@ -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);
......
......@@ -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
......
......@@ -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 */
......@@ -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
......@@ -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
......
......@@ -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
......
......@@ -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);
......
......@@ -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
......
/* { 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
};
/* { 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;
/* { 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
};
/* { 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 */
/* { 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();
}
/* { 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;
/* { 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" } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment