mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-25 03:40:32 +08:00
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
This commit is contained in:
parent
661fff62a9
commit
41c643948c
gcc
@ -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);
|
||||
|
||||
|
140
gcc/c-pragma.c
140
gcc/c-pragma.c
@ -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
|
||||
|
27
gcc/testsuite/g++.dg/other/pragma-ep-1.C
Normal file
27
gcc/testsuite/g++.dg/other/pragma-ep-1.C
Normal file
@ -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
|
||||
};
|
17
gcc/testsuite/g++.dg/other/pragma-re-1.C
Normal file
17
gcc/testsuite/g++.dg/other/pragma-re-1.C
Normal file
@ -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;
|
27
gcc/testsuite/gcc.dg/pragma-ep-1.c
Normal file
27
gcc/testsuite/gcc.dg/pragma-ep-1.c
Normal file
@ -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
|
||||
};
|
7
gcc/testsuite/gcc.dg/pragma-ep-2.c
Normal file
7
gcc/testsuite/gcc.dg/pragma-ep-2.c
Normal file
@ -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 */
|
10
gcc/testsuite/gcc.dg/pragma-ep-3.c
Normal file
10
gcc/testsuite/gcc.dg/pragma-ep-3.c
Normal file
@ -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();
|
||||
}
|
11
gcc/testsuite/gcc.dg/pragma-re-1.c
Normal file
11
gcc/testsuite/gcc.dg/pragma-re-1.c
Normal file
@ -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;
|
6
gcc/testsuite/gcc.dg/pragma-re-2.c
Normal file
6
gcc/testsuite/gcc.dg/pragma-re-2.c
Normal file
@ -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" } */
|
Loading…
x
Reference in New Issue
Block a user