From: Richard Henderson Date: Fri, 15 Mar 2002 07:11:14 +0000 (-0800) Subject: c-decl.c: Include c-pragma.h. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=ecb0eecefbd769b20dc9842fb0881db7492ec225;p=gcc.git c-decl.c: Include c-pragma.h. * c-decl.c: Include c-pragma.h. (start_decl, start_function): Invoke maybe_apply_pragma_weak. (finish_function): Tidy. * c-pragma.c: Include c-common.h. (pending_weaks, apply_pragma_weak, maybe_apply_pragma_weak): New. (handle_pragma_weak): Use them. (init_pragma): Register pending_weaks. * c-pragma.h (maybe_apply_pragma_weak): Declare. * print-tree.c (print_node): Print DECL_WEAK. * varasm.c (mark_weak_decls): Remove. (remove_from_pending_weak_list): Remove. (add_weak): Remove. (asm_emit_uninitialised): Call globalize_decl for weak commons. (weak_decls): Make a tree_list. (declare_weak): Cons weak_decls directly. (globalize_decl): Remove weak_decls elements directly. (weak_finish): Simplify weak_decls walk. Don't weaken unused symbols. Don't pretend to handle aliases. (init_varasm_once): Update weak_decls registry. * Makefile.in: Update dependencies. * cp/decl.c: Include c-pragma.h. (start_decl, start_function): Invoke maybe_apply_pragma_weak. * cp/Make-lang.in: Update dependencies. * gcc.dg/weak-1.c: New. From-SVN: r50797 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 558a1897bfa..a1f9c16f420 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2002-03-14 Richard Henderson + + * c-decl.c: Include c-pragma.h. + (start_decl, start_function): Invoke maybe_apply_pragma_weak. + (finish_function): Tidy. + * c-pragma.c: Include c-common.h. + (pending_weaks, apply_pragma_weak, maybe_apply_pragma_weak): New. + (handle_pragma_weak): Use them. + (init_pragma): Register pending_weaks. + * c-pragma.h (maybe_apply_pragma_weak): Declare. + * print-tree.c (print_node): Print DECL_WEAK. + * varasm.c (mark_weak_decls): Remove. + (remove_from_pending_weak_list): Remove. + (add_weak): Remove. + (asm_emit_uninitialised): Call globalize_decl for weak commons. + (weak_decls): Make a tree_list. + (declare_weak): Cons weak_decls directly. + (globalize_decl): Remove weak_decls elements directly. + (weak_finish): Simplify weak_decls walk. Don't weaken unused + symbols. Don't pretend to handle aliases. + (init_varasm_once): Update weak_decls registry. + * Makefile.in: Update dependencies. + 2002-03-14 Richard Henderson PR target/5312 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 2cb9f84a2eb..df8281f945e 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -1148,7 +1148,7 @@ $(srcdir)/c-parse.y: c-parse.in c-decl.o : c-decl.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) $(C_TREE_H) \ $(GGC_H) $(TARGET_H) c-lex.h flags.h function.h output.h $(EXPR_H) \ - debug.h toplev.h intl.h $(TM_P_H) tree-inline.h $(TIMEVAR_H) + debug.h toplev.h intl.h $(TM_P_H) tree-inline.h $(TIMEVAR_H) c-pragma.h c-typeck.o : c-typeck.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \ $(TARGET_H) flags.h intl.h output.h $(EXPR_H) $(RTL_H) toplev.h $(TM_P_H) c-lang.o : c-lang.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \ @@ -1165,7 +1165,7 @@ c-aux-info.o : c-aux-info.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \ flags.h toplev.h c-convert.o : c-convert.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) flags.h toplev.h c-pragma.o: c-pragma.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) function.h \ - c-pragma.h toplev.h output.h $(GGC_H) $(TM_P_H) + c-pragma.h toplev.h output.h $(GGC_H) $(TM_P_H) $(C_COMMON_H) mbchar.o: mbchar.c $(CONFIG_H) $(SYSTEM_H) mbchar.h graph.o: graph.c $(CONFIG_H) $(SYSTEM_H) toplev.h flags.h output.h $(RTL_H) \ function.h hard-reg-set.h $(BASIC_BLOCK_H) graph.h diff --git a/gcc/c-decl.c b/gcc/c-decl.c index d15f47e4baa..9242b03b3f9 100644 --- a/gcc/c-decl.c +++ b/gcc/c-decl.c @@ -46,6 +46,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "debug.h" #include "timevar.h" #include "c-common.h" +#include "c-pragma.h" /* In grokdeclarator, distinguish syntactic contexts of declarators. */ enum decl_context @@ -3403,6 +3404,10 @@ start_decl (declarator, declspecs, initialized, attributes) /* Set attributes here so if duplicate decl, will have proper attributes. */ decl_attributes (&decl, attributes, 0); + /* If #pragma weak was used, mark the decl weak now. */ + if (current_binding_level == global_binding_level) + maybe_apply_pragma_weak (decl); + if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl) && DECL_UNINLINABLE (decl) @@ -6042,6 +6047,10 @@ start_function (declspecs, declarator, attributes) decl_attributes (&decl1, attributes, 0); + /* If #pragma weak was used, mark the decl weak now. */ + if (current_binding_level == global_binding_level) + maybe_apply_pragma_weak (decl1); + if (DECL_DECLARED_INLINE_P (decl1) && DECL_UNINLINABLE (decl1) && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1))) @@ -6691,9 +6700,11 @@ finish_function (nested) { tree fndecl = current_function_decl; -/* TREE_READONLY (fndecl) = 1; - This caused &foo to be of type ptr-to-const-function - which then got a warning when stored in a ptr-to-function variable. */ +#if 0 + /* This caused &foo to be of type ptr-to-const-function which then + got a warning when stored in a ptr-to-function variable. */ + TREE_READONLY (fndecl) = 1; +#endif poplevel (1, 0, 1); BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; @@ -6755,6 +6766,7 @@ finish_function (nested) { /* Generate RTL for the body of this function. */ c_expand_body (fndecl, nested, 1); + /* Let the error reporting routines know that we're outside a function. For a nested function, this value is used in pop_c_function_context and then reset via pop_function_context. */ diff --git a/gcc/c-pragma.c b/gcc/c-pragma.c index 26bf27735f1..1a17e67f1c5 100644 --- a/gcc/c-pragma.c +++ b/gcc/c-pragma.c @@ -30,6 +30,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "toplev.h" #include "ggc.h" #include "c-lex.h" +#include "c-common.h" #include "output.h" #include "tm_p.h" @@ -55,9 +56,9 @@ static struct align_stack * alignment_stack = NULL; maximum_field_alignment in effect. When the final pop_alignment() happens, we restore the value to this, not to a value of 0 for maximum_field_alignment. Value is in bits. */ -static int default_alignment; +static int default_alignment; #define SET_GLOBAL_ALIGNMENT(ALIGN) \ -(default_alignment = maximum_field_alignment = (ALIGN)) + (default_alignment = maximum_field_alignment = (ALIGN)) static void push_alignment PARAMS ((int, tree)); static void pop_alignment PARAMS ((tree)); @@ -69,7 +70,6 @@ push_alignment (alignment, id) int alignment; tree id; { - if (alignment_stack == NULL || alignment_stack->alignment != alignment || id != NULL_TREE) @@ -274,14 +274,53 @@ handle_pragma_pack (dummy) #endif /* HANDLE_PRAGMA_PACK */ #ifdef HANDLE_PRAGMA_WEAK +static void apply_pragma_weak PARAMS ((tree, tree)); static void handle_pragma_weak PARAMS ((cpp_reader *)); +static tree pending_weaks; + +static void +apply_pragma_weak (decl, value) + tree decl, value; +{ + if (value) + decl_attributes (&decl, build_tree_list (get_identifier ("alias"), + build_tree_list (NULL, value)), + 0); + declare_weak (decl); +} + +void +maybe_apply_pragma_weak (decl) + tree decl; +{ + tree *p, t, id; + + /* 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)))) + id = DECL_ASSEMBLER_NAME (decl); + else + return; + + for (p = &pending_weaks; (t = *p) ; p = &TREE_CHAIN (t)) + if (id == TREE_PURPOSE (t)) + { + apply_pragma_weak (decl, TREE_VALUE (t)); + *p = TREE_CHAIN (t); + break; + } +} + /* #pragma weak name [= value] */ static void handle_pragma_weak (dummy) cpp_reader *dummy ATTRIBUTE_UNUSED; { - tree name, value, x; + tree name, value, x, decl; enum cpp_ttype t; value = 0; @@ -298,10 +337,19 @@ handle_pragma_weak (dummy) if (t != CPP_EOF) warning ("junk at end of #pragma weak"); - add_weak (NULL_TREE, IDENTIFIER_POINTER (name), - value ? IDENTIFIER_POINTER (value) : NULL); + decl = identifier_global_value (name); + if (decl && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd') + apply_pragma_weak (decl, value); + else + pending_weaks = tree_cons (name, value, pending_weaks); } -#endif +#else +void +maybe_apply_pragma_weak (decl) + tree decl ATTRIBUTE_UNUSED; +{ +} +#endif /* HANDLE_PRAGMA_WEAK */ void init_pragma () @@ -311,6 +359,7 @@ init_pragma () #endif #ifdef HANDLE_PRAGMA_WEAK cpp_register_pragma (parse_in, 0, "weak", handle_pragma_weak); + ggc_add_tree_root (&pending_weaks, 1); #endif #ifdef REGISTER_TARGET_PRAGMAS REGISTER_TARGET_PRAGMAS (parse_in); diff --git a/gcc/c-pragma.h b/gcc/c-pragma.h index 8d0c4f58501..ea5a9826d61 100644 --- a/gcc/c-pragma.h +++ b/gcc/c-pragma.h @@ -53,4 +53,6 @@ extern void cpp_register_pragma PARAMS ((cpp_reader *, void (*) PARAMS ((cpp_reader *)))); #endif +extern void maybe_apply_pragma_weak PARAMS ((tree)); + #endif /* GCC_C_PRAGMA_H */ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 79fd46f8bee..2c9b1e55df2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2002-03-14 Richard Henderson + + * decl.c: Include c-pragma.h. + (start_decl, start_function): Invoke maybe_apply_pragma_weak. + * Make-lang.in: Update dependencies. + 2002-03-14 Jakub Jelinek PR c++/5908 diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index 1e721b6ac56..a4e8299382e 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -255,7 +255,7 @@ cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) toplev.h langhooks.h langhooks-def.h \ c-common.h cp/decl.o: cp/decl.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h stack.h \ output.h $(EXPR_H) except.h toplev.h hash.h $(GGC_H) $(RTL_H) \ - cp/operators.def $(TM_P_H) tree-inline.h diagnostic.h + cp/operators.def $(TM_P_H) tree-inline.h diagnostic.h c-pragma.h cp/decl2.o: cp/decl2.c $(CXX_TREE_H) flags.h cp/lex.h cp/decl.h $(EXPR_H) \ output.h except.h toplev.h $(GGC_H) $(RTL_H) cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) flags.h toplev.h output.h $(TM_P_H) \ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 12028df385d..a1f128ff95c 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -46,6 +46,7 @@ Boston, MA 02111-1307, USA. */ #include "tm_p.h" #include "target.h" #include "c-common.h" +#include "c-pragma.h" #include "diagnostic.h" extern const struct attribute_spec *lang_attribute_table; @@ -7256,6 +7257,10 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes) /* Set attributes here so if duplicate decl, will have proper attributes. */ cplus_decl_attributes (&decl, attributes, 0); + /* If #pragma weak was used, mark the decl weak now. */ + if (current_binding_level == global_binding_level) + maybe_apply_pragma_weak (decl); + if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl) && DECL_UNINLINABLE (decl) @@ -13476,6 +13481,10 @@ start_function (declspecs, declarator, attrs, flags) cplus_decl_attributes (&decl1, attrs, 0); + /* If #pragma weak was used, mark the decl weak now. */ + if (current_binding_level == global_binding_level) + maybe_apply_pragma_weak (decl1); + fntype = TREE_TYPE (decl1); restype = TREE_TYPE (fntype); diff --git a/gcc/print-tree.c b/gcc/print-tree.c index e5627e2bfa5..f5c7d88c1f6 100644 --- a/gcc/print-tree.c +++ b/gcc/print-tree.c @@ -317,6 +317,8 @@ print_node (file, prefix, node, indent) fputs (" common", file); if (DECL_EXTERNAL (node)) fputs (" external", file); + if (DECL_WEAK (node)) + fputs (" weak", file); if (DECL_REGISTER (node) && TREE_CODE (node) != FIELD_DECL && TREE_CODE (node) != FUNCTION_DECL && TREE_CODE (node) != LABEL_DECL) diff --git a/gcc/testsuite/gcc.dg/weak-1.c b/gcc/testsuite/gcc.dg/weak-1.c new file mode 100644 index 00000000000..95e56f098a6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/weak-1.c @@ -0,0 +1,51 @@ +/* { dg-do compile } */ +/* COFF does not support weak, and dg doesn't support UNSUPPORTED. */ +/* { dg-do compile { xfail *-*-coff i?86-pc-cygwin } } */ + +/* { dg-final { scan-assembler "weak[^ ]*[ ]_?a" } } */ +/* { dg-final { scan-assembler "weak[^ ]*[ ]_?b" } } */ +/* { dg-final { scan-assembler "weak[^ ]*[ ]_?c" } } */ +/* { dg-final { scan-assembler "weak[^ ]*[ ]_?d" } } */ +/* { dg-final { scan-assembler "weak[^ ]*[ ]_?e" } } */ +/* { dg-final { scan-assembler "weak[^ ]*[ ]_?g" } } */ +/* { dg-final { scan-assembler-not "weak[^ ]*[ ]_?i" } } */ +/* { dg-final { scan-assembler "weak[^ ]*[ ]_?j" } } */ + +#pragma weak a +int a; + +int b; +#pragma weak b + +#pragma weak c +extern int c; +int c; + +extern int d; +#pragma weak d +int d; + +#pragma weak e +void e(void) { } + +#if 0 +/* This permutation is illegal. */ +void f(void) { } +#pragma weak f +#endif + +#pragma weak g +int g = 1; + +#if 0 +/* This permutation is illegal. */ +int h = 1; +#pragma weak h +#endif + +#pragma weak i +extern int i; + +#pragma weak j +extern int j; +int use_j() { return j; } diff --git a/gcc/varasm.c b/gcc/varasm.c index 5d41f638ab1..06ee8b82db9 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -167,10 +167,6 @@ static unsigned HOST_WIDE_INT array_size_for_constructor PARAMS ((tree)); static unsigned min_align PARAMS ((unsigned, unsigned)); static void output_constructor PARAMS ((tree, HOST_WIDE_INT, unsigned int)); -static void mark_weak_decls PARAMS ((void *)); -#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL) -static void remove_from_pending_weak_list PARAMS ((const char *)); -#endif static void globalize_decl PARAMS ((tree)); static void maybe_assemble_visibility PARAMS ((tree)); static int in_named_entry_eq PARAMS ((const PTR, const PTR)); @@ -1399,6 +1395,17 @@ asm_emit_uninitialised (decl, name, size, rounded) destination = asm_dest_common; } + switch (destination) + { + case asm_dest_common: + if (! DECL_WEAK (decl)) + break; + case asm_dest_bss: + globalize_decl (decl); + default: + break; + } + if (flag_shared_data) { switch (destination) @@ -1429,7 +1436,6 @@ asm_emit_uninitialised (decl, name, size, rounded) { #ifdef ASM_EMIT_BSS case asm_dest_bss: - globalize_decl (decl); ASM_EMIT_BSS (decl, name, size, rounded); break; #endif @@ -4994,55 +5000,9 @@ output_constructor (exp, size, align) assemble_zeros (size - total_bytes); } - -/* This structure contains any weak symbol declarations waiting +/* This TREE_LIST contains any weak symbol declarations waiting to be emitted. */ -struct weak_syms -{ - struct weak_syms * next; - tree decl; - const char * name; - const char * value; -}; - -static struct weak_syms * weak_decls; - -/* Mark weak_decls for garbage collection. */ - -static void -mark_weak_decls (arg) - void *arg; -{ - struct weak_syms *t; - - for (t = *(struct weak_syms **) arg; t != NULL; t = t->next) - ggc_mark_tree (t->decl); -} - -/* Add function NAME to the weak symbols list. VALUE is a weak alias - associated with NAME. */ - -int -add_weak (decl, name, value) - tree decl; - const char *name; - const char *value; -{ - struct weak_syms *weak; - - weak = (struct weak_syms *) xmalloc (sizeof (struct weak_syms)); - - if (weak == NULL) - return 0; - - weak->next = weak_decls; - weak->decl = decl; - weak->name = name; - weak->value = value; - weak_decls = weak; - - return 1; -} +static tree weak_decls; /* Declare DECL to be a weak symbol. */ @@ -5055,7 +5015,10 @@ declare_weak (decl) else if (TREE_ASM_WRITTEN (decl)) error_with_decl (decl, "weak declaration of `%s' must precede definition"); else if (SUPPORTS_WEAK) - add_weak (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), NULL); + { + if (! DECL_WEAK (decl)) + weak_decls = tree_cons (NULL, decl, weak_decls); + } else warning_with_decl (decl, "weak declaration of `%s' not supported"); @@ -5067,59 +5030,30 @@ declare_weak (decl) void weak_finish () { - if (SUPPORTS_WEAK) + tree t; + + for (t = weak_decls; t ; t = TREE_CHAIN (t)) { - struct weak_syms *t; - for (t = weak_decls; t != NULL; t = t->next) - { + tree decl = TREE_VALUE (t); + const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + + if (! TREE_USED (decl)) + continue; + #ifdef ASM_WEAKEN_DECL - tree decl = t->decl; - if (decl == NULL_TREE) - { - tree name = get_identifier (t->name); - if (name) - decl = lookup_name (name); - } - ASM_WEAKEN_DECL (asm_out_file, decl, t->name, t->value); -#else -#ifdef ASM_OUTPUT_WEAK_ALIAS - ASM_OUTPUT_WEAK_ALIAS (asm_out_file, t->name, t->value); + ASM_WEAKEN_DECL (asm_out_file, decl, name, NULL); #else #ifdef ASM_WEAKEN_LABEL - if (t->value) - abort (); - ASM_WEAKEN_LABEL (asm_out_file, t->name); + ASM_WEAKEN_LABEL (asm_out_file, name); +#else +#ifdef ASM_OUTPUT_WEAK_ALIAS + warning ("only weak aliases are supported in this configuration"); + return; #endif #endif #endif - } - } -} - -/* Remove NAME from the pending list of weak symbols. This prevents - the compiler from emitting multiple .weak directives which confuses - some assemblers. */ -#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL) -static void -remove_from_pending_weak_list (name) - const char *name; -{ - struct weak_syms *t; - struct weak_syms **p; - - for (p = &weak_decls; *p; ) - { - t = *p; - if (strcmp (name, t->name) == 0) - { - *p = t->next; - free (t); - } - else - p = &(t->next); } } -#endif /* defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL) */ /* Emit the assembly bits to indicate that DECL is globally visible. */ @@ -5132,18 +5066,26 @@ globalize_decl (decl) #if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL) if (DECL_WEAK (decl)) { + tree *p, t; + #ifdef ASM_WEAKEN_DECL ASM_WEAKEN_DECL (asm_out_file, decl, name, 0); #else ASM_WEAKEN_LABEL (asm_out_file, name); #endif + /* Remove this function from the pending weak list so that we do not emit multiple .weak directives for it. */ - remove_from_pending_weak_list (name); + for (p = &weak_decls; (t = *p) ; p = &TREE_CHAIN (t)) + if (TREE_VALUE (t) == decl) + { + *p = TREE_CHAIN (t); + break; + } return; } - /* else */ #endif + ASM_GLOBALIZE_LABEL (asm_out_file, name); } @@ -5168,7 +5110,6 @@ assemble_alias (decl, target) if (TREE_PUBLIC (decl)) { globalize_decl (decl); - maybe_assemble_visibility (decl); } @@ -5282,7 +5223,7 @@ init_varasm_once () mark_const_hash_entry); ggc_add_root (&const_str_htab, 1, sizeof const_str_htab, mark_const_str_htab); - ggc_add_root (&weak_decls, 1, sizeof weak_decls, mark_weak_decls); + ggc_add_tree_root (&weak_decls, 1); const_alias_set = new_alias_set (); }