From: Zack Weinberg Date: Sun, 20 Jun 2004 08:34:54 +0000 (+0000) Subject: c-common.h (has_c_linkage): New interface. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=84b8b0e04d42732ea65d452aa74e3575f75de10b;p=gcc.git c-common.h (has_c_linkage): New interface. * c-common.h (has_c_linkage): New interface. * c-cppbuiltin.c: Include target.h. (c_cpp_builtins): Define __PRAGMA_REDEFINE_EXTNAME and __PRAGMA_EXTERN_PREFIX when appropriate. * c-pragma.c: Include target.h. Document clarified semantics of symbol-renaming #pragmas. (handle_pragma_redefine_extname, handle_pragma_extern_prefix) (maybe_apply_renaming_pragma): Rewrite according to clarified semantics. Always recognize, but do not necessarily execute. (init_pragma): Unconditionally register symbol-renaming pragmas. * system.h: Poison HANDLE_PRAGMA_REDEFINE_EXTNAME and HANDLE_PRAGMA_EXTERN_PREFIX. * target.h (struct gcc_target): Add handle_pragma_redefine_extname and handle_pragma_extern_prefix flags. * target-def.h: Add defaults for TARGET_HANDLE_PRAGMA_REDEFINE_EXTNAME and TARGET_HANDLE_PRAGMA_EXTERN_PREFIX. * Makefile.in (c-pragma.o, c-cppbuiltin.o): Update dependencies. * config/sol2.h: Define TARGET_HANDLE_PRAGMA_REDEFINE_EXTNAME, not HANDLE_PRAGMA_REDEFINE_EXTNAME. (TARGET_OS_CPP_BUILTINS): No need to define __PRAGMA_REDEFINE_EXTNAME. (TRANSFER_FROM_TRAMPOLINE): Prototype mprotect. * config/alpha/osf.h: Define TARGET_HANDLE_PRAGMA_EXTERN_PREFIX, not HANDLE_PRAGMA_EXTERN_PREFIX. (TARGET_OS_CPP_BUILTINS): No need to define __PRAGMA_EXTERN_PREFIX. * doc/extend.texi (Solaris Pragmas, Tru64 Pragmas): Combine into one section "Symbol-Renaming Pragmas"; clarify; document adjusted semantics. * builtins.c (expand_builtin): Do not issue error for a builtin with no special case code and no DECL_ASSEMBLER_NAME; just do the library call. * c-decl.c (builtin_function): Don't call make_decl_rtl. * c-objc-common.c (has_c_linkage): Stub implementation. * cgraphunit.c (cgraph_expand_function) (cgraph_remove_unreachable_nodes): Don't clear DECL_ARGUMENTS. cp: * cp-lang.c (has_c_linkage): Implement. * cp-tree.h (set_mangled_name_for_decl): Don't prototype. * decl.c (duplicate_decls): Use COPY_DECL_RTL. (builtin_function_1): Don't call make_decl_rtl. (build_cp_library_fn): Don't call set_mangled_name_for_decl. (grokvardecl): Don't call mangle_decl. * except.c (nothrow_libfn_p): Look at DECL_NAME, not DECL_ASSEMBLER_NAME. * method.c (set_mangled_name_for_decl): Delete. * name-lookup.c (pushdecl): When a local extern shadows a file-scope declaration of the same object, give both DECLs the same DECL_UID. * typeck.c (cxx_mark_addressable): Don't set TREE_ADDRESSABLE on DECL_ASSEMBLER_NAME. testsuite: * g++.dg/expr/enum1.C, g++.dg/opt/const3.C: Declare abort with extern "C". * g++.dg/other/pragma-re-1.C: Add comments. From-SVN: r83405 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 50cc6134356..acb2bffd3f5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,41 @@ +2004-06-20 Zack Weinberg + + * c-common.h (has_c_linkage): New interface. + * c-cppbuiltin.c: Include target.h. + (c_cpp_builtins): Define __PRAGMA_REDEFINE_EXTNAME and + __PRAGMA_EXTERN_PREFIX when appropriate. + * c-pragma.c: Include target.h. + Document clarified semantics of symbol-renaming #pragmas. + (handle_pragma_redefine_extname, handle_pragma_extern_prefix) + (maybe_apply_renaming_pragma): Rewrite according to clarified + semantics. Always recognize, but do not necessarily execute. + (init_pragma): Unconditionally register symbol-renaming pragmas. + * system.h: Poison HANDLE_PRAGMA_REDEFINE_EXTNAME + and HANDLE_PRAGMA_EXTERN_PREFIX. + * target.h (struct gcc_target): Add handle_pragma_redefine_extname + and handle_pragma_extern_prefix flags. + * target-def.h: Add defaults for TARGET_HANDLE_PRAGMA_REDEFINE_EXTNAME + and TARGET_HANDLE_PRAGMA_EXTERN_PREFIX. + * Makefile.in (c-pragma.o, c-cppbuiltin.o): Update dependencies. + * config/sol2.h: Define TARGET_HANDLE_PRAGMA_REDEFINE_EXTNAME, + not HANDLE_PRAGMA_REDEFINE_EXTNAME. + (TARGET_OS_CPP_BUILTINS): No need to define __PRAGMA_REDEFINE_EXTNAME. + (TRANSFER_FROM_TRAMPOLINE): Prototype mprotect. + * config/alpha/osf.h: Define TARGET_HANDLE_PRAGMA_EXTERN_PREFIX, + not HANDLE_PRAGMA_EXTERN_PREFIX. + (TARGET_OS_CPP_BUILTINS): No need to define __PRAGMA_EXTERN_PREFIX. + * doc/extend.texi (Solaris Pragmas, Tru64 Pragmas): Combine + into one section "Symbol-Renaming Pragmas"; clarify; document + adjusted semantics. + + * builtins.c (expand_builtin): Do not issue error for a builtin + with no special case code and no DECL_ASSEMBLER_NAME; just do the + library call. + * c-decl.c (builtin_function): Don't call make_decl_rtl. + * c-objc-common.c (has_c_linkage): Stub implementation. + * cgraphunit.c (cgraph_expand_function) + (cgraph_remove_unreachable_nodes): Don't clear DECL_ARGUMENTS. + 2004-06-19 Roger Sayle * builtins.c (fold_builtin_unordered_cmp): Take an EXP argument @@ -104,7 +142,7 @@ 2004-06-18 Richard Henderson - PR c++/16036 + PR c++/16036 * gimple-low.c (lower_function_body): Generate return statement for fall off the end of the function here ... * tree-cfg.c (make_edges): ... instead of here. @@ -267,10 +305,10 @@ UTAG_RETHROWEXC_VAR, UTAG_EVALONCE_VAR, struct val_stack, catch_count_stack, exc_binding_stack, if_nesting_count, blk_nesting_count, objc_enter_block, objc_exit_block, - objc_declare_variable, val_stack_push, val_stack_pop, + objc_declare_variable, val_stack_push, val_stack_pop, objc_build_try_enter_fragment, objc_build_extract_expr, objc_build_try_exit_fragment, objc_build_extract_fragment, - objc_build_try_prologue, objc_build_try_epilogue, + objc_build_try_prologue, objc_build_try_epilogue, objc_build_catch_stmt, objc_build_catch_epilogue, objc_build_finally_prologue, objc_build_finally_epilogue, objc_build_try_catch_finally_stmt, objc_build_synchronized_prologue, @@ -381,9 +419,9 @@ * tree-ssa-operands.h (struct def_optype_d): Change underlying type. (struct use_optype_d): Change underlying type. (def_operand_p, use_operand_p): New types for pointers to operands. - (USE_OP, DEF_OP, V_MAY_DEF_RESULT, V_MAY_DEF_OP, VUSE_OP, + (USE_OP, DEF_OP, V_MAY_DEF_RESULT, V_MAY_DEF_OP, VUSE_OP, V_MUST_DEF_OP): Use new pointer type instead of dereferencing directly. - (USE_FROM_PTR, DEF_FROM_PTR): New macros to "dereference" operand + (USE_FROM_PTR, DEF_FROM_PTR): New macros to "dereference" operand pointer types. (SET_USE, SET_DEF): New macros to set operands from their pointer. (SET_USE_OP, SET_DEF_OP, SET_V_MAY_DEF_RESULT, SET_V_MAY_DEF_OP, @@ -411,7 +449,7 @@ * tree.h (duplicate_ssa_name): Declare. 2004-06-17 David Ayers - + * c-parse.in: Unify Objective-C token names. 2004-06-17 Zack Weinberg diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 75b36868bb8..6c21b666a55 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1381,8 +1381,9 @@ c-aux-info.o : c-aux-info.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_ $(C_TREE_H) $(FLAGS_H) toplev.h c-convert.o : c-convert.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ $(FLAGS_H) toplev.h $(C_COMMON_H) real.h -c-pragma.o: c-pragma.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \ - function.h c-pragma.h toplev.h output.h $(GGC_H) $(TM_P_H) $(C_COMMON_H) gt-c-pragma.h +c-pragma.o: c-pragma.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \ + $(TREE_H) function.h c-pragma.h toplev.h output.h $(GGC_H) $(TM_P_H) \ + $(C_COMMON_H) $(TARGET_H) gt-c-pragma.h graph.o: graph.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) toplev.h $(FLAGS_H) output.h \ $(RTL_H) function.h hard-reg-set.h $(BASIC_BLOCK_H) graph.h sbitmap.o: sbitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(FLAGS_H) \ @@ -1424,8 +1425,8 @@ c-opts.o : c-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $< $(OUTPUT_OPTION) @TARGET_SYSTEM_ROOT_DEFINE@ c-cppbuiltin.o : c-cppbuiltin.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ - $(TREE_H) version.h $(C_COMMON_H) c-pragma.h $(FLAGS_H) toplev.h langhooks.h \ - output.h except.h real.h $(TM_P_H) + $(TREE_H) version.h $(C_COMMON_H) c-pragma.h $(FLAGS_H) toplev.h \ + langhooks.h output.h except.h real.h $(TARGET_H) $(TM_P_H) # A file used by all variants of C and some other languages. diff --git a/gcc/builtins.c b/gcc/builtins.c index 55619e1ced9..0959b1f32c8 100644 --- a/gcc/builtins.c +++ b/gcc/builtins.c @@ -6202,9 +6202,7 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, break; default: /* just do library call, if unknown builtin */ - if (!DECL_ASSEMBLER_NAME_SET_P (fndecl)) - error ("built-in function `%s' not currently supported", - IDENTIFIER_POINTER (DECL_NAME (fndecl))); + break; } /* The switch statement above can drop through to cause the function diff --git a/gcc/c-common.h b/gcc/c-common.h index b1c49b1eed9..91a18869b2d 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -303,6 +303,7 @@ extern int c_expand_decl (tree); extern int field_decl_cmp (const void *, const void *); extern void resort_sorted_fields (void *, void *, gt_pointer_operator, void *); +extern bool has_c_linkage (tree decl); /* Switches common to the C front ends. */ diff --git a/gcc/c-cppbuiltin.c b/gcc/c-cppbuiltin.c index b70653c086a..3f0f688861d 100644 --- a/gcc/c-cppbuiltin.c +++ b/gcc/c-cppbuiltin.c @@ -32,6 +32,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "except.h" /* For USING_SJLJ_EXCEPTIONS. */ #include "toplev.h" #include "tm_p.h" /* Target prototypes. */ +#include "target.h" #ifndef TARGET_OS_CPP_BUILTINS # define TARGET_OS_CPP_BUILTINS() @@ -409,6 +410,13 @@ c_cpp_builtins (cpp_reader *pfile) if (c_dialect_objc () && flag_next_runtime) cpp_define (pfile, "__NEXT_RUNTIME__"); + /* Show the availability of some target pragmas. */ + if (flag_mudflap || targetm.handle_pragma_redefine_extname) + cpp_define (pfile, "__PRAGMA_REDEFINE_EXTNAME"); + + if (targetm.handle_pragma_extern_prefix) + cpp_define (pfile, "__PRAGMA_EXTERN_PREFIX"); + /* A straightforward target hook doesn't work, because of problems linking that hook's body when part of non-C front ends. */ # define preprocessing_asm_p() (cpp_get_options (pfile)->lang == CLK_ASM) diff --git a/gcc/c-decl.c b/gcc/c-decl.c index ac8c5b7847d..cbf5795b83d 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -2382,7 +2382,6 @@ builtin_function (const char *name, tree type, int function_code, DECL_FUNCTION_CODE (decl) = function_code; if (library_name) SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name)); - make_decl_rtl (decl, NULL); /* Should never be called on a symbol with a preexisting meaning. */ if (I_SYMBOL_BINDING (id)) diff --git a/gcc/c-objc-common.c b/gcc/c-objc-common.c index f1faeefebf2..731e0631264 100644 --- a/gcc/c-objc-common.c +++ b/gcc/c-objc-common.c @@ -314,3 +314,9 @@ c_objc_common_truthvalue_conversion (tree expr) return c_common_truthvalue_conversion (expr); } +/* In C and ObjC, all decls have "C" linkage. */ +bool +has_c_linkage (tree decl ATTRIBUTE_UNUSED) +{ + return true; +} diff --git a/gcc/c-pragma.c b/gcc/c-pragma.c index 31a17a109d2..93836ea8652 100644 --- a/gcc/c-pragma.c +++ b/gcc/c-pragma.c @@ -34,6 +34,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "c-common.h" #include "output.h" #include "tm_p.h" +#include "target.h" #define GCC_BAD(msgid) do { warning (msgid); return; } while (0) #define GCC_BAD2(msgid, arg) do { warning (msgid, arg); return; } while (0) @@ -350,11 +351,43 @@ maybe_apply_pragma_weak (tree decl ATTRIBUTE_UNUSED) } #endif /* HANDLE_PRAGMA_WEAK */ +/* GCC supports two #pragma directives for renaming the external + symbol associated with a declaration (DECL_ASSEMBLER_NAME), for + compatibility with the Solaris and Tru64 system headers. GCC also + has its own notation for this, __asm__("name") annotations. + + Corner cases of these features and their interaction: + + 1) Both pragmas silently apply only to declarations with external + linkage (that is, TREE_PUBLIC || DECL_EXTERNAL). Asm labels + do not have this restriction. + + 2) In C++, both #pragmas silently apply only to extern "C" declarations. + Asm labels do not have this restriction. + + 3) If any of the three ways of changing DECL_ASSEMBLER_NAME is + applied to a decl whose DECL_ASSEMBLER_NAME is already set, and the + new name is different, a warning issues and the name does not change. + + 4) The "source name" for #pragma redefine_extname is the DECL_NAME, + *not* the DECL_ASSEMBLER_NAME. + + 5) If #pragma extern_prefix is in effect and a declaration occurs + with an __asm__ name, the #pragma extern_prefix is silently + ignored for that declaration. + + 6) If #pragma extern_prefix and #pragma redefine_extname apply to + the same declaration, whichever triggered first wins, and a warning + is issued. (We would like to have #pragma redefine_extname always + win, but it can appear either before or after the declaration, and + if it appears afterward, we have no way of knowing whether a modified + DECL_ASSEMBLER_NAME is due to #pragma extern_prefix.) */ + static GTY(()) tree pending_redefine_extname; static void handle_pragma_redefine_extname (cpp_reader *); -/* #pragma redefined_extname oldname newname */ +/* #pragma redefine_extname oldname newname */ static void handle_pragma_redefine_extname (cpp_reader *dummy ATTRIBUTE_UNUSED) { @@ -362,44 +395,67 @@ handle_pragma_redefine_extname (cpp_reader *dummy ATTRIBUTE_UNUSED) enum cpp_ttype t; if (c_lex (&oldname) != CPP_NAME) - { - warning ("malformed #pragma redefine_extname, ignored"); - return; - } + GCC_BAD ("malformed #pragma redefine_extname, ignored"); if (c_lex (&newname) != CPP_NAME) - { - warning ("malformed #pragma redefine_extname, ignored"); - return; - } + GCC_BAD ("malformed #pragma redefine_extname, ignored"); t = c_lex (&x); if (t != CPP_EOF) warning ("junk at end of #pragma redefine_extname"); + if (!flag_mudflap && !targetm.handle_pragma_redefine_extname) + { + if (warn_unknown_pragmas > in_system_header) + warning ("#pragma redefine_extname not supported on this target"); + return; + } + decl = identifier_global_value (oldname); - if (decl && (TREE_CODE (decl) == FUNCTION_DECL - || TREE_CODE (decl) == VAR_DECL)) + if (decl + && (TREE_PUBLIC (decl) || DECL_EXTERNAL (decl)) + && (TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == VAR_DECL) + && has_c_linkage (decl)) { - if (DECL_ASSEMBLER_NAME_SET_P (decl) - && DECL_ASSEMBLER_NAME (decl) != newname) - warning ("#pragma redefine_extname conflicts with declaration"); - change_decl_assembler_name (decl, newname); + if (DECL_ASSEMBLER_NAME_SET_P (decl)) + { + const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + name = targetm.strip_name_encoding (name); + + if (strcmp (name, IDENTIFIER_POINTER (newname))) + warning ("#pragma redefine_extname ignored due to conflict with " + "previous rename"); + } + else + change_decl_assembler_name (decl, newname); } else - add_to_renaming_pragma_list(oldname, newname); + /* We have to add this to the rename list even if there's already + a global value that doesn't meet the above criteria, because in + C++ "struct foo {...};" puts "foo" in the current namespace but + does *not* conflict with a subsequent declaration of a function + or variable foo. See g++.dg/other/pragma-re-2.C. */ + add_to_renaming_pragma_list (oldname, newname); } +/* This is called from here and from ia64.c. */ void add_to_renaming_pragma_list (tree oldname, tree newname) { + tree previous = purpose_member (oldname, pending_redefine_extname); + if (previous) + { + if (TREE_VALUE (previous) != newname) + warning ("#pragma redefine_extname ignored due to conflict with " + "previous #pragma redefine_extname"); + return; + } + pending_redefine_extname = tree_cons (oldname, newname, pending_redefine_extname); } static GTY(()) tree pragma_extern_prefix; -#ifdef HANDLE_PRAGMA_EXTERN_PREFIX -static void handle_pragma_extern_prefix (cpp_reader *); - /* #pragma extern_prefix "prefix" */ static void handle_pragma_extern_prefix (cpp_reader *dummy ATTRIBUTE_UNUSED) @@ -408,18 +464,17 @@ handle_pragma_extern_prefix (cpp_reader *dummy ATTRIBUTE_UNUSED) enum cpp_ttype t; if (c_lex (&prefix) != CPP_STRING) - { - warning ("malformed #pragma extern_prefix, ignored"); - return; - } + GCC_BAD ("malformed #pragma extern_prefix, ignored"); 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); + if (targetm.handle_pragma_extern_prefix) + /* Note that the length includes the null terminator. */ + pragma_extern_prefix = (TREE_STRING_LENGTH (prefix) > 1 ? prefix : NULL); + else if (warn_unknown_pragmas > in_system_header) + warning ("#pragma extern_prefix not supported on this target"); } -#endif /* Hook from the front ends to apply the results of one of the preceding pragmas that rename variables. */ @@ -427,56 +482,88 @@ handle_pragma_extern_prefix (cpp_reader *dummy ATTRIBUTE_UNUSED) tree maybe_apply_renaming_pragma (tree decl, tree 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 + tree *p, t; + + /* The renaming pragmas are only applied to declarations with + external linkage. */ + if ((TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL) + || (!TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl)) + || !has_c_linkage (decl)) 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] == '*') + /* If the DECL_ASSEMBLER_NAME is already set, it does not change, + but we may warn about a rename that conflicts. */ + if (DECL_ASSEMBLER_NAME_SET_P (decl)) { - const char *oldasmname = IDENTIFIER_POINTER (oldname) + 1; - if (asmname && strcmp (TREE_STRING_POINTER (asmname), oldasmname) != 0) - warning ("asm declaration conflicts with previous rename"); - asmname = build_string (strlen (oldasmname), oldasmname); + const char *oldname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + oldname = targetm.strip_name_encoding (oldname); + + if (asmname && strcmp (TREE_STRING_POINTER (asmname), oldname)) + warning ("asm declaration ignored due to " + "conflict with previous rename"); + + /* Take any pending redefine_extname off the list. */ + for (p = &pending_redefine_extname; (t = *p); p = &TREE_CHAIN (t)) + if (DECL_NAME (decl) == TREE_PURPOSE (t)) + { + /* Only warn if there is a conflict. */ + if (strcmp (IDENTIFIER_POINTER (TREE_VALUE (t)), oldname)) + warning ("#pragma redefine_extname ignored due to " + "conflict with previous rename"); + + *p = TREE_CHAIN (t); + break; + } + return 0; } - { - tree *p, t; + /* Find out if we have a pending #pragma redefine_extname. */ + for (p = &pending_redefine_extname; (t = *p); p = &TREE_CHAIN (t)) + if (DECL_NAME (decl) == TREE_PURPOSE (t)) + { + tree newname = TREE_VALUE (t); + *p = TREE_CHAIN (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 we already have an asmname, #pragma redefine_extname is + ignored (with a warning if it conflicts). */ + if (asmname) + { + if (strcmp (TREE_STRING_POINTER (asmname), + IDENTIFIER_POINTER (newname)) != 0) + warning ("#pragma redefine_extname ignored due to " + "conflict with __asm__ declaration"); + return asmname; + } - if (asmname && strcmp (TREE_STRING_POINTER (asmname), newname) != 0) - warning ("#pragma redefine_extname conflicts with declaration"); - *p = TREE_CHAIN (t); + /* Otherwise we use what we've got; #pragma extern_prefix is + silently ignored. */ + return build_string (IDENTIFIER_LENGTH (newname), + IDENTIFIER_POINTER (newname)); + } - return build_string (strlen (newname), newname); - } - } + /* If we've got an asmname, #pragma extern_prefix is silently ignored. */ + if (asmname) + return asmname; -#ifdef HANDLE_PRAGMA_EXTERN_PREFIX - if (pragma_extern_prefix && !asmname) + /* If #pragma extern_prefix is in effect, apply it. */ + if (pragma_extern_prefix) { - char *x = concat (TREE_STRING_POINTER (pragma_extern_prefix), - IDENTIFIER_POINTER (oldname), NULL); - asmname = build_string (strlen (x), x); - free (x); - return asmname; + const char *prefix = TREE_STRING_POINTER (pragma_extern_prefix); + size_t plen = TREE_STRING_LENGTH (pragma_extern_prefix) - 1; + + const char *id = IDENTIFIER_POINTER (DECL_NAME (decl)); + size_t ilen = IDENTIFIER_LENGTH (DECL_NAME (decl)); + + char *newname = alloca (plen + ilen + 1); + + memcpy (newname, prefix, plen); + memcpy (newname + plen, id, ilen + 1); + + return build_string (plen + ilen, newname); } -#endif - return asmname; + /* Nada. */ + return 0; } /* Front-end wrapper for pragma registration to avoid dragging @@ -498,15 +585,9 @@ init_pragma (void) #ifdef HANDLE_PRAGMA_WEAK c_register_pragma (0, "weak", handle_pragma_weak); #endif -#ifdef HANDLE_PRAGMA_REDEFINE_EXTNAME + c_register_pragma (0, "redefine_extname", handle_pragma_redefine_extname); -#else - if (flag_mudflap) - c_register_pragma (0, "redefine_extname", handle_pragma_redefine_extname); -#endif -#ifdef HANDLE_PRAGMA_EXTERN_PREFIX c_register_pragma (0, "extern_prefix", handle_pragma_extern_prefix); -#endif #ifdef REGISTER_TARGET_PRAGMAS REGISTER_TARGET_PRAGMAS (); diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 80fe8ce5d5a..67001f0dd12 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -804,7 +804,6 @@ cgraph_expand_function (struct cgraph_node *node) { DECL_SAVED_TREE (node->decl) = NULL; DECL_STRUCT_FUNCTION (node->decl) = NULL; - DECL_ARGUMENTS (node->decl) = NULL; DECL_INITIAL (node->decl) = error_mark_node; } } @@ -965,7 +964,6 @@ cgraph_remove_unreachable_nodes (void) { DECL_SAVED_TREE (node->decl) = NULL; DECL_STRUCT_FUNCTION (node->decl) = NULL; - DECL_ARGUMENTS (node->decl) = NULL; DECL_INITIAL (node->decl) = error_mark_node; } while (node->callees) diff --git a/gcc/config/alpha/osf.h b/gcc/config/alpha/osf.h index f8b4eca49b3..04b7bf1a332 100644 --- a/gcc/config/alpha/osf.h +++ b/gcc/config/alpha/osf.h @@ -41,7 +41,6 @@ Boston, MA 02111-1307, USA. */ builtin_define ("__digital__"); \ builtin_define ("__arch64__"); \ builtin_define ("_LONGLONG"); \ - builtin_define ("__PRAGMA_EXTERN_PREFIX"); \ builtin_assert ("system=unix"); \ builtin_assert ("system=xpg4"); \ /* Tru64 UNIX V5 has a 16 byte long \ @@ -211,4 +210,4 @@ __enable_execute_stack (void *addr) \ /* 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 +#define TARGET_HANDLE_PRAGMA_EXTERN_PREFIX 1 diff --git a/gcc/config/sol2.h b/gcc/config/sol2.h index 5dc489d36f2..1ff6308329b 100644 --- a/gcc/config/sol2.h +++ b/gcc/config/sol2.h @@ -39,7 +39,7 @@ Boston, MA 02111-1307, USA. */ #undef WINT_TYPE_SIZE #define WINT_TYPE_SIZE BITS_PER_WORD -#define HANDLE_PRAGMA_REDEFINE_EXTNAME 1 +#define TARGET_HANDLE_PRAGMA_REDEFINE_EXTNAME 1 /* ??? Note: in order for -compat-bsd to work fully, we must somehow arrange to fixincludes /usr/ucbinclude @@ -60,7 +60,6 @@ Boston, MA 02111-1307, USA. */ builtin_define_std ("sun"); \ builtin_define ("__svr4__"); \ builtin_define ("__SVR4"); \ - builtin_define ("__PRAGMA_REDEFINE_EXTNAME"); \ builtin_assert ("system=unix"); \ builtin_assert ("system=svr4"); \ /* For C++ we need to add some additional macro \ @@ -196,6 +195,7 @@ extern void __enable_execute_stack (void *); \ void \ __enable_execute_stack (void *addr) \ { \ + extern int mprotect(void *, size_t, int); \ if (!need_enable_exec_stack) \ return; \ else { \ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 73ead051906..e3048d3dba0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,21 @@ +2004-06-20 Zack Weinberg + + * cp-lang.c (has_c_linkage): Implement. + + * cp-tree.h (set_mangled_name_for_decl): Don't prototype. + * decl.c (duplicate_decls): Use COPY_DECL_RTL. + (builtin_function_1): Don't call make_decl_rtl. + (build_cp_library_fn): Don't call set_mangled_name_for_decl. + (grokvardecl): Don't call mangle_decl. + * except.c (nothrow_libfn_p): Look at DECL_NAME, not + DECL_ASSEMBLER_NAME. + * method.c (set_mangled_name_for_decl): Delete. + * name-lookup.c (pushdecl): When a local extern shadows a + file-scope declaration of the same object, give both DECLs the + same DECL_UID. + * typeck.c (cxx_mark_addressable): Don't set TREE_ADDRESSABLE + on DECL_ASSEMBLER_NAME. + 2004-06-19 Richard Henderson * cp-gimplify.c: Remove unnecessary prototypes. @@ -15,7 +33,7 @@ (finish_cond): Rewrite to handle template DECL_STMTs specially. Assume that non-template decls go land before the conditional. (simplify_loop_decl_cond): Likewise. - (begin_if_stmt, finish_if_stmt_cond, begin_while_stmt, + (begin_if_stmt, finish_if_stmt_cond, begin_while_stmt, finish_while_stmt_cond, finish_for_init_stmt, finish_for_cond, begin_switch_stmt, finish_switch_cond): Update to match. @@ -165,7 +183,7 @@ * cp-tree.h: Fix typo. * cp-tree.h: Include cgraph.h - (DECL_NEEDED_P): Use cgraph_*node on the decl instead of + (DECL_NEEDED_P): Use cgraph_*node on the decl instead of TREE_SYMBOL_REFERENCED on the DECL_ASSEMBLER_NAME of the decl. 2004-06-12 Jason Merrill @@ -288,8 +306,8 @@ PR c++/15554 * pt.c (tsubst_copy): Do not try to substitute for an enumeration - constant in a non-dependent context. - + constant in a non-dependent context. + PR c++/15057 * except.c (build_throw): Ensure that temp_expr has been initialized. @@ -316,7 +334,7 @@ * decl2.c (maybe_emit_vtables): If TARGET_WEAK_NOT_IN_ARCHIVE_TOC is nonzero, and if we see a noninline definition of a key method, make the vtables nonweak. - + 2004-06-02 Matt Austern * cp-tree.h (instantiate_decl): new boolean parameter, @@ -335,7 +353,7 @@ change it to an implicit instantiation. (instantiate_pending_templates): Add new argument to instantiate_decl. * tree.c (cp_cannot_inline_tree_fn): Likewise. - + 2004-06-02 Andrew Pinski * cp-tree.h: Fix typo. diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c index eb0e2210624..757ca08e845 100644 --- a/gcc/cp/cp-lang.c +++ b/gcc/cp/cp-lang.c @@ -353,3 +353,10 @@ void pop_file_scope (void) { } + +/* c-pragma.c needs to query whether a decl has extern "C" linkage. */ +bool +has_c_linkage (tree decl) +{ + return DECL_EXTERN_C_P (decl); +} diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 7a0c41d9305..1838c8288f9 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3855,7 +3855,6 @@ extern void cxx_finish (void); /* in method.c */ extern void init_method (void); -extern void set_mangled_name_for_decl (tree); extern tree make_thunk (tree, bool, tree, tree); extern void finish_thunk (tree); extern void use_thunk (tree, bool); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index b794b9e96f0..dfdfe564991 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -1259,7 +1259,7 @@ duplicate_decls (tree newdecl, tree olddecl) return NULL_TREE; /* Replace the old RTL to avoid problems with inlining. */ - SET_DECL_RTL (olddecl, DECL_RTL (newdecl)); + COPY_DECL_RTL (newdecl, olddecl); } /* Even if the types match, prefer the new declarations type for anticipated built-ins, for exception lists, etc... */ @@ -1288,7 +1288,7 @@ duplicate_decls (tree newdecl, tree olddecl) that all remnants of the builtin-ness of this function will be banished. */ SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl)); - SET_DECL_RTL (olddecl, DECL_RTL (newdecl)); + COPY_DECL_RTL (newdecl, olddecl); } } else if (TREE_CODE (olddecl) != TREE_CODE (newdecl)) @@ -1827,7 +1827,7 @@ duplicate_decls (tree newdecl, tree olddecl) { SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl)); COPY_DECL_ASSEMBLER_NAME (newdecl, olddecl); - SET_DECL_RTL (olddecl, DECL_RTL (newdecl)); + COPY_DECL_RTL (newdecl, olddecl); } if (! types_match || new_defines_function) { @@ -1851,7 +1851,7 @@ duplicate_decls (tree newdecl, tree olddecl) DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl); /* If we're keeping the built-in definition, keep the rtl, regardless of declaration matches. */ - SET_DECL_RTL (newdecl, DECL_RTL (olddecl)); + COPY_DECL_RTL (olddecl, newdecl); } DECL_RESULT (newdecl) = DECL_RESULT (olddecl); @@ -3183,7 +3183,6 @@ builtin_function_1 (const char* name, function in the namespace. */ if (libname) SET_DECL_ASSEMBLER_NAME (decl, get_identifier (libname)); - make_decl_rtl (decl, NULL); /* Warn if a function in the namespace for users is used without an occasion to consider it declared. */ @@ -3271,7 +3270,6 @@ build_cp_library_fn (tree name, enum tree_code operator_code, tree type) TREE_NOTHROW (fn) = TYPE_NOTHROW_P (type); DECL_CONTEXT (fn) = FROB_CONTEXT (current_namespace); SET_DECL_LANGUAGE (fn, lang_cplusplus); - set_mangled_name_for_decl (fn); return fn; } @@ -5829,12 +5827,6 @@ grokvardecl (tree type, else DECL_CONTEXT (decl) = scope; - if (name && scope && current_lang_name != lang_name_c) - /* We can't mangle lazily here because we don't have any - way to recover whether or not a variable was `extern - "C"' later. */ - mangle_decl (decl); - if (RIDBIT_SETP (RID_EXTERN, specbits)) { DECL_THIS_EXTERN (decl) = 1; diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 7e6e54e0def..e978a5416a8 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -841,7 +841,10 @@ nothrow_libfn_p (tree fn) /* Can't be a C library function. */ return 0; - id = DECL_ASSEMBLER_NAME (fn); + /* Being a C library function, DECL_ASSEMBLER_NAME == DECL_NAME + unless the system headers are playing rename tricks, and if + they are, we don't want to be confused by them. */ + id = DECL_NAME (fn); return !!libc_name_p (IDENTIFIER_POINTER (id), IDENTIFIER_LENGTH (id)); } diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 364cc0688b3..357ea868ed3 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -71,20 +71,6 @@ init_method (void) { init_mangle (); } - - -/* Set the mangled name (DECL_ASSEMBLER_NAME) for DECL. */ - -void -set_mangled_name_for_decl (tree decl) -{ - if (processing_template_decl) - /* There's no need to mangle the name of a template function. */ - return; - - mangle_decl (decl); -} - /* Return a this or result adjusting thunk to FUNCTION. THIS_ADJUSTING indicates whether it is a this or result adjusting thunk. diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 401f6505d0c..1b755c92320 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -677,9 +677,15 @@ pushdecl (tree x) if (decls_match (x, t)) /* The standard only says that the local extern inherits linkage from the previous decl; in - particular, default args are not shared. It would - be nice to propagate inlining info, though. FIXME. */ - TREE_PUBLIC (x) = TREE_PUBLIC (t); + particular, default args are not shared. We must + also tell cgraph to treat these decls as the same, + or we may neglect to emit an "unused" static - we + do this by making the DECL_UIDs equal, which should + be viewed as a kludge. FIXME. */ + { + TREE_PUBLIC (x) = TREE_PUBLIC (t); + DECL_UID (x) = DECL_UID (t); + } } else if (TREE_CODE (t) == PARM_DECL) { diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index bcdd316131b..95040834cc8 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -4318,7 +4318,6 @@ cxx_mark_addressable (tree exp) case FUNCTION_DECL: TREE_ADDRESSABLE (x) = 1; - TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1; return true; case CONSTRUCTOR: diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 204c64b1006..6c8ea7d0754 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -7197,8 +7197,7 @@ for further explanation. * ARM Pragmas:: * RS/6000 and PowerPC Pragmas:: * Darwin Pragmas:: -* Solaris Pragmas:: -* Tru64 Pragmas:: +* Symbol-Renaming Pragmas:: @end menu @node ARM Pragmas @@ -7282,45 +7281,68 @@ 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 +@node Symbol-Renaming Pragmas +@subsection Symbol-Renaming Pragmas -For compatibility with the SunPRO compiler, the following pragma -is supported. +For compatibility with the Solaris and Tru64 UNIX system headers, GCC +supports two @code{#pragma} directives which change the name used in +assembly for a given declaration. These pragmas are only available on +platforms whose system headers need them. To get this effect on all +platforms supported by GCC, use the asm labels extension (@pxref{Asm +Labels}). @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. +This pragma gives the C function @var{oldname} the assembly symbol +@var{newname}. The preprocessor macro @code{__PRAGMA_REDEFINE_EXTNAME} +will be defined if this pragma is available (currently only on +Solaris). -@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{__PRAGMA_EXTERN_PREFIX} if the pragma is -available. +This pragma causes all subsequent external function and variable +declarations to have @var{string} prepended to their assembly symbols. +This effect may be terminated with another @code{extern_prefix} pragma +whose argument is an empty string. The preprocessor macro +@code{__PRAGMA_EXTERN_PREFIX} will be defined if this pragma is +available (currently only on Tru64 UNIX). @end table +These pragmas and the asm labels extension interact in a complicated +manner. Here are some corner cases you may want to be aware of. + +@enumerate +@item Both pragmas silently apply only to declarations with external +linkage. Asm labels do not have this restriction. + +@item In C++, both pragmas silently apply only to declarations with +``C'' linkage. Again, asm labels do not have this restriction. + +@item If any of the three ways of changing the assembly name of a +declaration is applied to a declaration whose assembly name has +already been determined (either by a previous use of one of these +features, or because the compiler needed the assembly name in order to +generate code), and the new name is different, a warning issues and +the name does not change. + +@item The @var{oldname} used by @code{#pragma redefine_extname} is +always the C-language name. + +@item If @code{#pragma extern_prefix} is in effect, and a declaration +occurs with an asm label attached, the prefix is silently ignored for +that declaration. + +@item If @code{#pragma extern_prefix} and @code{#pragma redefine_extname} +apply to the same declaration, whichever triggered first wins, and a +warning issues if they contradict each other. (We would like to have +@code{#pragma redefine_extname} always win, for consistency with asm +labels, but if @code{#pragma extern_prefix} triggers first we have no +way of knowing that that happened.) +@end enumerate + @node Unnamed Fields @section Unnamed struct/union fields within structs/unions. @cindex struct diff --git a/gcc/system.h b/gcc/system.h index d51c3286711..abbfb41752f 100644 --- a/gcc/system.h +++ b/gcc/system.h @@ -579,7 +579,8 @@ extern int snprintf (char *, size_t, const char *, ...); STRUCT_VALUE_INCOMING STRICT_ARGUMENT_NAMING \ PROMOTE_FUNCTION_RETURN PROMOTE_PROTOTYPES STRUCT_VALUE_REGNUM \ SETUP_INCOMING_VARARGS EXPAND_BUILTIN_SAVEREGS \ - DEFAULT_SHORT_ENUMS SPLIT_COMPLEX_ARGS MD_ASM_CLOBBERS + DEFAULT_SHORT_ENUMS SPLIT_COMPLEX_ARGS MD_ASM_CLOBBERS \ + HANDLE_PRAGMA_REDEFINE_EXTNAME HANDLE_PRAGMA_EXTERN_PREFIX /* Other obsolete target macros, or macros that used to be in target headers and were not used, and may be obsolete or may never have diff --git a/gcc/target-def.h b/gcc/target-def.h index 40e9610ef61..c537c9f70e0 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -381,6 +381,15 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. TARGET_GIMPLIFY_VA_ARG_EXPR, \ } + +#ifndef TARGET_HANDLE_PRAGMA_REDEFINE_EXTNAME +#define TARGET_HANDLE_PRAGMA_REDEFINE_EXTNAME 0 +#endif + +#ifndef TARGET_HANDLE_PRAGMA_EXTERN_PREFIX +#define TARGET_HANDLE_PRAGMA_EXTERN_PREFIX 0 +#endif + /* The whole shebang. */ #define TARGET_INITIALIZER \ { \ @@ -433,6 +442,8 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. TARGET_TERMINATE_DW2_EH_FRAME_INFO, \ TARGET_ASM_FILE_START_APP_OFF, \ TARGET_ASM_FILE_START_FILE_DIRECTIVE, \ + TARGET_HANDLE_PRAGMA_REDEFINE_EXTNAME, \ + TARGET_HANDLE_PRAGMA_EXTERN_PREFIX, \ } #include "hooks.h" diff --git a/gcc/target.h b/gcc/target.h index 3b9af5da4f2..902db41fd9a 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -502,6 +502,12 @@ struct gcc_target at the beginning of assembly output. */ bool file_start_file_directive; + /* True if #pragma redefine_extname is to be supported. */ + bool handle_pragma_redefine_extname; + + /* True if #pragma extern_prefix is to be supported. */ + bool handle_pragma_extern_prefix; + /* Leave the boolean fields at the end. */ }; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3061f062248..3cee3778ddf 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,6 +1,12 @@ +2004-06-20 Zack Weinberg + + * g++.dg/expr/enum1.C, g++.dg/opt/const3.C: Declare abort with + extern "C". + * g++.dg/other/pragma-re-1.C: Add comments. + 2004-06-19 Bud Davis - - PR gfortran/16080 + + PR gfortran/16080 * gfortran.fortran-torture/execute/read_null_string.f90: New file. 2004-06-19 Andrew Pinski diff --git a/gcc/testsuite/g++.dg/expr/enum1.C b/gcc/testsuite/g++.dg/expr/enum1.C index df2a823d551..40dc5faf66d 100644 --- a/gcc/testsuite/g++.dg/expr/enum1.C +++ b/gcc/testsuite/g++.dg/expr/enum1.C @@ -1,6 +1,6 @@ // { dg-do run } -void abort(); +extern "C" void abort(); int main() { enum { shelf = 4 } t = shelf; diff --git a/gcc/testsuite/g++.dg/opt/const3.C b/gcc/testsuite/g++.dg/opt/const3.C index a3539ab15c8..c7c0a1645de 100644 --- a/gcc/testsuite/g++.dg/opt/const3.C +++ b/gcc/testsuite/g++.dg/opt/const3.C @@ -5,7 +5,7 @@ // { dg-do run } // { dg-options "-O2" } -extern void abort(void); +extern "C" void abort(void); typedef __SIZE_TYPE__ size_t; diff --git a/gcc/testsuite/g++.dg/other/pragma-re-1.C b/gcc/testsuite/g++.dg/other/pragma-re-1.C index ec567f93460..b29ac99ba4e 100644 --- a/gcc/testsuite/g++.dg/other/pragma-re-1.C +++ b/gcc/testsuite/g++.dg/other/pragma-re-1.C @@ -8,10 +8,13 @@ #error #endif +/* This one is expected to work. */ #pragma redefine_extname foo bar extern "C" int foo(void); void *p = (void *)foo; +/* This one is expected not to work (redefine_extname + can only be applied to extern "C" names). */ #pragma redefine_extname baz baq extern int baz(void); void *q = (void *)baz;