* 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
+2002-03-14 Richard Henderson <rth@redhat.com>
+
+ * 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 <rth@redhat.com>
PR target/5312
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) \
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
#include "debug.h"
#include "timevar.h"
#include "c-common.h"
+#include "c-pragma.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
enum decl_context
/* 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)
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)))
{
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;
{
/* 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. */
#include "toplev.h"
#include "ggc.h"
#include "c-lex.h"
+#include "c-common.h"
#include "output.h"
#include "tm_p.h"
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));
int alignment;
tree id;
{
-
if (alignment_stack == NULL
|| alignment_stack->alignment != alignment
|| id != NULL_TREE)
#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;
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 ()
#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);
void (*) PARAMS ((cpp_reader *))));
#endif
+extern void maybe_apply_pragma_weak PARAMS ((tree));
+
#endif /* GCC_C_PRAGMA_H */
+2002-03-14 Richard Henderson <rth@redhat.com>
+
+ * 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 <jakub@redhat.com>
PR c++/5908
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) \
#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;
/* 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)
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);
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)
--- /dev/null
+/* { 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; }
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));
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)
{
#ifdef ASM_EMIT_BSS
case asm_dest_bss:
- globalize_decl (decl);
ASM_EMIT_BSS (decl, name, size, rounded);
break;
#endif
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. */
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");
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. */
#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);
}
if (TREE_PUBLIC (decl))
{
globalize_decl (decl);
-
maybe_assemble_visibility (decl);
}
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 ();
}