aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2007-02-25 18:47:05 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2007-02-25 18:47:05 +0000
commitfc8600f9c12ccb952cb38fbad4a2f34e0d958473 (patch)
treecfcdaf9660cd0bdc1216594b6e66f5e22560aa3e /gcc
parent2a025b54f6867e218f4ec07a70c57833162c0c32 (diff)
downloadgcc-fc8600f9c12ccb952cb38fbad4a2f34e0d958473.zip
gcc-fc8600f9c12ccb952cb38fbad4a2f34e0d958473.tar.gz
gcc-fc8600f9c12ccb952cb38fbad4a2f34e0d958473.tar.bz2
extend.texi: Document optional priority argument to constructors and destructors.
* doc/extend.texi: Document optional priority argument to constructors and destructors. * tree.c (init_priority_for_decl): Adjust GTY markers. (init_ttree): Use priority-info hash functions for init_priority_for_decl. (tree_map_eq): Rename to ... (tree_map_base_eq): ... this. (tree_map_marked_p): Rename to ... (tree_map_base_marked_p): ... this. (tree_map_base_hash): New function. (decl_init_priority_lookup): Rework. (decl_fini_priority_lookup): New function. (decl_priority_info): New function. (decl_init_priority_insert): Use it. (decl_fini_priority_insert): Likewise. (decl_restrict_base_lookup): Adjust for refactoring of tree_map hierarchy. (decl_restrict_base_insert): Likewise. (decl_debug_expr_insert): Likewise. (decl_value_expr_lookup): Likewise. (decl_value_expr_insert): Likewise. * tree.h (priority_type): New type. (decl_init_priority_lookup): Use priority_type. (decl_fini_priority_lookup): New function. (decl_init_priority_insert): Use priority_type. (decl_fini_priority_insert): New function. (DECL_HAS_INIT_PRIORITY): Tweak comments. (DECL_INIT_PRIORITY): Likewise. (SET_DECL_INIT_PRIORITY): Add comment. (DECL_FINI_PRIORITY): New macro. (SET_DECL_FINI_PRIORITY): Likewise. (DEFAULT_INIT_PRIORITY): Document. (MAX_INIT_PRIORITY): Likewise. (MAX_RESERVED_INIT_PRIORITY): Likewise. (tree_map_base): New type. (tree_map_base_eq): New function. (tree_map_base_hash): Likewise. (tree_map_base_marked_p): Likewise. (tree_map): Inherit from tree_map_base. (tree_map_eq): Make it a macro. (tree_map_marked_p): Likewise. (tree_int_map): Inherit from tree_map_base. (tree_int_map_eq): Make it a macro. (tree_int_map_hash): Likewise. (tree_int_map_marked_p): Likewise. (tree_priority_map): New type. (tree_priority_map_eq): New macro. (tree_priority_map_hash): Likewise. (tree_priority_map_marked_p): Likewise. * varasm.c (emults_decl): Adjust for refactoring of tree_map hierarchy. (emutls_common_1): Likewise. * lambda-code.c (replace_uses_equiv_to_x_with_y): Likewise. * tree-ssa-structalias.c (heapvar_lookup): Adjust for refactoring of tree_map hierarchy. * tree-cfg.c (move_stmt_r): Likewise. (new_label_mapper): Likewise. * c-tree.h (c_expand_body): Move to ... * c-common.h (c_expand_body): ... here. * c-decl.c (c_expand_body): Move to ... * c-common.c (c_expand_body): ... here. (c_common_attribute_table): Allow 1 argument for the constructor and destructor attributes. (get_priority): New function. (handle_constructor_attribute): Set DECL_INIT_PRIORITY. (handle_destructor_attribute): Set DECL_FINI_PRIORITY. * cp-tree.h (static_ctors): Remove. * cp-tree.h (static_dtors): Likewise. * cp-objcp-common.c (decl_shadowed_for_var_lookup): Adjust for refactoring of tree_map hierarchy. (decl_shadowed_for_var_insert): Likewise. * semantics.c (expand_body): Use c_expand_body. (expand_or_defer_fn): Don't update static_ctors or static_dtors. * decl2.c (static_ctors): Remove. (static_dtors): Likewise. (generate_ctor_or_dtor_function): Pass NULL_TREE to objc_generate_static_init_call. Do not call static_[cd]tors. (generate_ctor_and_dtor_functions_for_priority): Do not check for static_[cd]tors. (cp_write_global_declarations): Likewise. * decl.c (annotate_value): Adjust for refactoring of tree_map hierarchy. * gcc.dg/initpri1.c: New test. * gcc.dg/initpri2.c: Likewise. * g++.dg/special/initpri1.C: New test. * g++.dg/special/initpri2.C: Likewise. * g++.dg/special/conpr-1.C: Use init_priority effective target. * g++.dg/special/conpr-2.C: Likewise. * g++.dg/special/conpr-3.C: Likewise. * g++.dg/special/conpr-4.C: Likewise. * g++.dg/special/initp1.C: Likewise. * g++.dg/special/ecos.exp: Remove code to detect availability of constructor priorities. * lib/target-support.exp (target_init_priority): New function. From-SVN: r122315
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog69
-rw-r--r--gcc/ada/ChangeLog5
-rw-r--r--gcc/ada/decl.c2
-rw-r--r--gcc/c-common.c84
-rw-r--r--gcc/c-common.h1
-rw-r--r--gcc/c-decl.c22
-rw-r--r--gcc/c-tree.h1
-rw-r--r--gcc/cp/ChangeLog17
-rw-r--r--gcc/cp/cp-objcp-common.c4
-rw-r--r--gcc/cp/cp-tree.h5
-rw-r--r--gcc/cp/decl2.c52
-rw-r--r--gcc/cp/semantics.c14
-rw-r--r--gcc/doc/extend.texi12
-rw-r--r--gcc/lambda-code.c4
-rw-r--r--gcc/testsuite/ChangeLog15
-rw-r--r--gcc/testsuite/g++.dg/special/conpr-1.C2
-rw-r--r--gcc/testsuite/g++.dg/special/conpr-2.C3
-rw-r--r--gcc/testsuite/g++.dg/special/conpr-3.C2
-rw-r--r--gcc/testsuite/g++.dg/special/conpr-4.C2
-rw-r--r--gcc/testsuite/g++.dg/special/ecos.exp10
-rw-r--r--gcc/testsuite/g++.dg/special/initp1.C3
-rw-r--r--gcc/testsuite/g++.dg/special/initpri1.C62
-rw-r--r--gcc/testsuite/g++.dg/special/initpri2.C18
-rw-r--r--gcc/testsuite/gcc.dg/initpri1.c62
-rw-r--r--gcc/testsuite/gcc.dg/initpri2.c18
-rw-r--r--gcc/testsuite/lib/target-supports.exp17
-rw-r--r--gcc/tree-cfg.c4
-rw-r--r--gcc/tree-ssa-structalias.c4
-rw-r--r--gcc/tree.c134
-rw-r--r--gcc/tree.h90
-rw-r--r--gcc/varasm.c14
31 files changed, 553 insertions, 199 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index cc9e79e..54d3ad5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,72 @@
+2007-02-25 Mark Mitchell <mark@codesourcery.com>
+
+ * doc/extend.texi: Document optional priority argument to
+ constructors and destructors.
+ * tree.c (init_priority_for_decl): Adjust GTY markers.
+ (init_ttree): Use priority-info hash functions for
+ init_priority_for_decl.
+ (tree_map_eq): Rename to ...
+ (tree_map_base_eq): ... this.
+ (tree_map_marked_p): Rename to ...
+ (tree_map_base_marked_p): ... this.
+ (tree_map_base_hash): New function.
+ (decl_init_priority_lookup): Rework.
+ (decl_fini_priority_lookup): New function.
+ (decl_priority_info): New function.
+ (decl_init_priority_insert): Use it.
+ (decl_fini_priority_insert): Likewise.
+ (decl_restrict_base_lookup): Adjust for refactoring of tree_map
+ hierarchy.
+ (decl_restrict_base_insert): Likewise.
+ (decl_debug_expr_insert): Likewise.
+ (decl_value_expr_lookup): Likewise.
+ (decl_value_expr_insert): Likewise.
+ * tree.h (priority_type): New type.
+ (decl_init_priority_lookup): Use priority_type.
+ (decl_fini_priority_lookup): New function.
+ (decl_init_priority_insert): Use priority_type.
+ (decl_fini_priority_insert): New function.
+ (DECL_HAS_INIT_PRIORITY): Tweak comments.
+ (DECL_INIT_PRIORITY): Likewise.
+ (SET_DECL_INIT_PRIORITY): Add comment.
+ (DECL_FINI_PRIORITY): New macro.
+ (SET_DECL_FINI_PRIORITY): Likewise.
+ (DEFAULT_INIT_PRIORITY): Document.
+ (MAX_INIT_PRIORITY): Likewise.
+ (MAX_RESERVED_INIT_PRIORITY): Likewise.
+ (tree_map_base): New type.
+ (tree_map_base_eq): New function.
+ (tree_map_base_hash): Likewise.
+ (tree_map_base_marked_p): Likewise.
+ (tree_map): Inherit from tree_map_base.
+ (tree_map_eq): Make it a macro.
+ (tree_map_marked_p): Likewise.
+ (tree_int_map): Inherit from tree_map_base.
+ (tree_int_map_eq): Make it a macro.
+ (tree_int_map_hash): Likewise.
+ (tree_int_map_marked_p): Likewise.
+ (tree_priority_map): New type.
+ (tree_priority_map_eq): New macro.
+ (tree_priority_map_hash): Likewise.
+ (tree_priority_map_marked_p): Likewise.
+ * varasm.c (emults_decl): Adjust for refactoring of tree_map
+ hierarchy.
+ (emutls_common_1): Likewise.
+ * lambda-code.c (replace_uses_equiv_to_x_with_y): Likewise.
+ * tree-ssa-structalias.c (heapvar_lookup): Adjust for refactoring
+ of tree_map hierarchy.
+ * tree-cfg.c (move_stmt_r): Likewise.
+ (new_label_mapper): Likewise.
+ * c-tree.h (c_expand_body): Move to ...
+ * c-common.h (c_expand_body): ... here.
+ * c-decl.c (c_expand_body): Move to ...
+ * c-common.c (c_expand_body): ... here.
+ (c_common_attribute_table): Allow 1 argument for the constructor
+ and destructor attributes.
+ (get_priority): New function.
+ (handle_constructor_attribute): Set DECL_INIT_PRIORITY.
+ (handle_destructor_attribute): Set DECL_FINI_PRIORITY.
+
2007-02-24 Jan Hubicka <jh@suse.cz>
PR middle-end/30509
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 6b7cc45..ddae48e 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,8 @@
+2007-02-24 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (annotate_value): Adjust for refactoring of tree_map
+ hierarchy.
+
2007-02-21 Ed Schonberg <schonberg@adacore.com>
PR ada/18819
diff --git a/gcc/ada/decl.c b/gcc/ada/decl.c
index af0e392..6b14064 100644
--- a/gcc/ada/decl.c
+++ b/gcc/ada/decl.c
@@ -5890,7 +5890,7 @@ annotate_value (tree gnu_size)
if (!annotate_value_cache)
annotate_value_cache = htab_create_ggc (512, tree_int_map_hash,
tree_int_map_eq, 0);
- in.from = gnu_size;
+ in.base.from = gnu_size;
h = (struct tree_int_map **)
htab_find_slot (annotate_value_cache, &in, INSERT);
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 51fd226..4eb0265 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -598,9 +598,9 @@ const struct attribute_spec c_common_attribute_table[] =
handle_const_attribute },
{ "transparent_union", 0, 0, false, false, false,
handle_transparent_union_attribute },
- { "constructor", 0, 0, true, false, false,
+ { "constructor", 0, 1, true, false, false,
handle_constructor_attribute },
- { "destructor", 0, 0, true, false, false,
+ { "destructor", 0, 1, true, false, false,
handle_destructor_attribute },
{ "mode", 1, 1, false, true, false,
handle_mode_attribute },
@@ -4220,6 +4220,29 @@ c_expand_expr (tree exp, rtx target, enum machine_mode tmode,
}
}
+
+/* Generate the RTL for the body of FNDECL. */
+
+void
+c_expand_body (tree fndecl)
+{
+
+ if (!DECL_INITIAL (fndecl)
+ || DECL_INITIAL (fndecl) == error_mark_node)
+ return;
+
+ tree_rest_of_compilation (fndecl);
+
+ if (DECL_STATIC_CONSTRUCTOR (fndecl)
+ && targetm.have_ctors_dtors)
+ targetm.asm_out.constructor (XEXP (DECL_RTL (fndecl), 0),
+ decl_init_priority_lookup (fndecl));
+ if (DECL_STATIC_DESTRUCTOR (fndecl)
+ && targetm.have_ctors_dtors)
+ targetm.asm_out.destructor (XEXP (DECL_RTL (fndecl), 0),
+ decl_fini_priority_lookup (fndecl));
+}
+
/* Hook used by staticp to handle language-specific tree codes. */
tree
@@ -4655,12 +4678,56 @@ handle_transparent_union_attribute (tree *node, tree name,
return NULL_TREE;
}
+/* Subroutine of handle_{con,de}structor_attribute. Evaluate ARGS to
+ get the requested priority for a constructor or destructor,
+ possibly issuing diagnostics for invalid or reserved
+ priorities. */
+
+static priority_type
+get_priority (tree args, bool is_destructor)
+{
+ HOST_WIDE_INT pri;
+
+ if (!args)
+ return DEFAULT_INIT_PRIORITY;
+
+ if (!host_integerp (TREE_VALUE (args), /*pos=*/0))
+ goto invalid;
+
+ pri = tree_low_cst (TREE_VALUE (args), /*pos=*/0);
+ if (pri < 0 || pri > MAX_INIT_PRIORITY)
+ goto invalid;
+
+ if (pri <= MAX_RESERVED_INIT_PRIORITY)
+ {
+ if (is_destructor)
+ warning (0,
+ "destructor priorities from 0 to %d are reserved "
+ "for the implementation",
+ MAX_RESERVED_INIT_PRIORITY);
+ else
+ warning (0,
+ "constructor priorities from 0 to %d are reserved "
+ "for the implementation",
+ MAX_RESERVED_INIT_PRIORITY);
+ }
+ return pri;
+
+ invalid:
+ if (is_destructor)
+ error ("destructor priorities must be integers from 0 to %d inclusive",
+ MAX_INIT_PRIORITY);
+ else
+ error ("constructor priorities must be integers from 0 to %d inclusive",
+ MAX_INIT_PRIORITY);
+ return DEFAULT_INIT_PRIORITY;
+}
+
/* Handle a "constructor" attribute; arguments as in
struct attribute_spec.handler. */
static tree
-handle_constructor_attribute (tree *node, tree name,
- tree ARG_UNUSED (args),
+handle_constructor_attribute (tree *node, tree name, tree args,
int ARG_UNUSED (flags),
bool *no_add_attrs)
{
@@ -4671,7 +4738,10 @@ handle_constructor_attribute (tree *node, tree name,
&& TREE_CODE (type) == FUNCTION_TYPE
&& decl_function_context (decl) == 0)
{
+ priority_type priority;
DECL_STATIC_CONSTRUCTOR (decl) = 1;
+ priority = get_priority (args, /*is_destructor=*/false);
+ SET_DECL_INIT_PRIORITY (decl, priority);
TREE_USED (decl) = 1;
}
else
@@ -4687,8 +4757,7 @@ handle_constructor_attribute (tree *node, tree name,
struct attribute_spec.handler. */
static tree
-handle_destructor_attribute (tree *node, tree name,
- tree ARG_UNUSED (args),
+handle_destructor_attribute (tree *node, tree name, tree args,
int ARG_UNUSED (flags),
bool *no_add_attrs)
{
@@ -4699,7 +4768,10 @@ handle_destructor_attribute (tree *node, tree name,
&& TREE_CODE (type) == FUNCTION_TYPE
&& decl_function_context (decl) == 0)
{
+ priority_type priority;
DECL_STATIC_DESTRUCTOR (decl) = 1;
+ priority = get_priority (args, /*is_destructor=*/true);
+ SET_DECL_FINI_PRIORITY (decl, priority);
TREE_USED (decl) = 1;
}
else
diff --git a/gcc/c-common.h b/gcc/c-common.h
index 5ad4582d..4e25ede 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -810,6 +810,7 @@ extern tree lookup_name (tree);
extern bool vector_types_convertible_p (tree t1, tree t2, bool emit_lax_note);
extern rtx c_expand_expr (tree, rtx, enum machine_mode, int, rtx *);
+extern void c_expand_body (tree);
extern tree c_staticp (tree);
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index ed0bf9c..ec567a5 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -6828,28 +6828,6 @@ finish_function (void)
cfun = NULL;
current_function_decl = NULL;
}
-
-/* Generate the RTL for the body of FNDECL. */
-
-void
-c_expand_body (tree fndecl)
-{
-
- if (!DECL_INITIAL (fndecl)
- || DECL_INITIAL (fndecl) == error_mark_node)
- return;
-
- tree_rest_of_compilation (fndecl);
-
- if (DECL_STATIC_CONSTRUCTOR (fndecl)
- && targetm.have_ctors_dtors)
- targetm.asm_out.constructor (XEXP (DECL_RTL (fndecl), 0),
- DEFAULT_INIT_PRIORITY);
- if (DECL_STATIC_DESTRUCTOR (fndecl)
- && targetm.have_ctors_dtors)
- targetm.asm_out.destructor (XEXP (DECL_RTL (fndecl), 0),
- DEFAULT_INIT_PRIORITY);
-}
/* Check the declarations given in a for-loop for satisfying the C99
constraints. If exactly one such decl is found, return it. */
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 87af5cb..b2fe228 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -441,7 +441,6 @@ extern int global_bindings_p (void);
extern void push_scope (void);
extern tree pop_scope (void);
extern void insert_block (tree);
-extern void c_expand_body (tree);
extern void c_init_decl_processing (void);
extern void c_dup_lang_specific_decl (tree);
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index bdef6b5..a9f4d25 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,20 @@
+2007-02-25 Mark Mitchell <mark@codesourcery.com>
+
+ * cp-tree.h (static_ctors): Remove.
+ * cp-tree.h (static_dtors): Likewise.
+ * cp-objcp-common.c (decl_shadowed_for_var_lookup): Adjust for
+ refactoring of tree_map hierarchy.
+ (decl_shadowed_for_var_insert): Likewise.
+ * semantics.c (expand_body): Use c_expand_body.
+ (expand_or_defer_fn): Don't update static_ctors or static_dtors.
+ * decl2.c (static_ctors): Remove.
+ (static_dtors): Likewise.
+ (generate_ctor_or_dtor_function): Pass NULL_TREE to
+ objc_generate_static_init_call. Do not call static_[cd]tors.
+ (generate_ctor_and_dtor_functions_for_priority): Do not check for
+ static_[cd]tors.
+ (cp_write_global_declarations): Likewise.
+
2007-02-23 Richard Guenther <rguenther@suse.de>
* class.c (note_name_declared_in_class): Make declaration
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index 2fdea26..372e8e5 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -228,7 +228,7 @@ tree
decl_shadowed_for_var_lookup (tree from)
{
struct tree_map *h, in;
- in.from = from;
+ in.base.from = from;
h = (struct tree_map *) htab_find_with_hash (shadowed_var_for_decl, &in,
htab_hash_pointer (from));
@@ -247,7 +247,7 @@ decl_shadowed_for_var_insert (tree from, tree to)
h = GGC_NEW (struct tree_map);
h->hash = htab_hash_pointer (from);
- h->from = from;
+ h->base.from = from;
h->to = to;
loc = htab_find_slot_with_hash (shadowed_var_for_decl, h, h->hash, INSERT);
*(struct tree_map **) loc = h;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index a070411..e03003e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3479,11 +3479,6 @@ extern int at_eof;
TREE_PURPOSE slot. */
extern GTY(()) tree static_aggregates;
-/* Functions called along with real static constructors and destructors. */
-
-extern GTY(()) tree static_ctors;
-extern GTY(()) tree static_dtors;
-
enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
/* These are uses as bits in flags passed to various functions to
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 68917b6..1feb3a7 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -97,11 +97,6 @@ static GTY(()) VEC(tree,gc) *deferred_fns;
int at_eof;
-/* Functions called along with real static constructors and destructors. */
-
-tree static_ctors;
-tree static_dtors;
-
/* Return a member function type (a METHOD_TYPE), given FNTYPE (a
@@ -2847,7 +2842,7 @@ generate_ctor_or_dtor_function (bool constructor_p, int priority,
&& constructor_p && objc_static_init_needed_p ())
{
body = start_objects (function_key, priority);
- static_ctors = objc_generate_static_init_call (static_ctors);
+ objc_generate_static_init_call (NULL_TREE);
}
/* Call the static storage duration function with appropriate
@@ -2870,29 +2865,6 @@ generate_ctor_or_dtor_function (bool constructor_p, int priority,
}
}
- /* If we're generating code for the DEFAULT_INIT_PRIORITY, throw in
- calls to any functions marked with attributes indicating that
- they should be called at initialization- or destruction-time. */
- if (priority == DEFAULT_INIT_PRIORITY)
- {
- tree fns;
-
- for (fns = constructor_p ? static_ctors : static_dtors;
- fns;
- fns = TREE_CHAIN (fns))
- {
- fndecl = TREE_VALUE (fns);
-
- /* Calls to pure/const functions will expand to nothing. */
- if (! (flags_from_decl_or_type (fndecl) & (ECF_CONST | ECF_PURE)))
- {
- if (! body)
- body = start_objects (function_key, priority);
- finish_expr_stmt (build_function_call (fndecl, NULL_TREE));
- }
- }
- }
-
/* Close out the function. */
if (body)
finish_objects (function_key, priority, body);
@@ -2910,11 +2882,9 @@ generate_ctor_and_dtor_functions_for_priority (splay_tree_node n, void * data)
/* Generate the functions themselves, but only if they are really
needed. */
- if (pi->initializations_p
- || (priority == DEFAULT_INIT_PRIORITY && static_ctors))
+ if (pi->initializations_p)
generate_ctor_or_dtor_function (/*constructor_p=*/true, priority, locus);
- if (pi->destructions_p
- || (priority == DEFAULT_INIT_PRIORITY && static_dtors))
+ if (pi->destructions_p)
generate_ctor_or_dtor_function (/*constructor_p=*/false, priority, locus);
/* Keep iterating. */
@@ -3309,17 +3279,11 @@ cp_write_global_declarations (void)
splay_tree_foreach (priority_info_map,
generate_ctor_and_dtor_functions_for_priority,
/*data=*/&locus);
- else
- {
- /* If we have a ctor or this is obj-c++ and we need a static init,
- call generate_ctor_or_dtor_function. */
- if (static_ctors || (c_dialect_objc () && objc_static_init_needed_p ()))
- generate_ctor_or_dtor_function (/*constructor_p=*/true,
- DEFAULT_INIT_PRIORITY, &locus);
- if (static_dtors)
- generate_ctor_or_dtor_function (/*constructor_p=*/false,
- DEFAULT_INIT_PRIORITY, &locus);
- }
+ else if (c_dialect_objc () && objc_static_init_needed_p ())
+ /* If this is obj-c++ and we need a static init, call
+ generate_ctor_or_dtor_function. */
+ generate_ctor_or_dtor_function (/*constructor_p=*/true,
+ DEFAULT_INIT_PRIORITY, &locus);
/* We're done with the splay-tree now. */
if (priority_info_map)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index c4cdd95..71c16e0 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3099,7 +3099,7 @@ expand_body (tree fn)
generating trees for a function. */
gcc_assert (function_depth == 0);
- tree_rest_of_compilation (fn);
+ c_expand_body (fn);
current_function_decl = saved_function;
@@ -3159,18 +3159,6 @@ expand_or_defer_fn (tree fn)
return;
}
- /* If this function is marked with the constructor attribute, add it
- to the list of functions to be called along with constructors
- from static duration objects. */
- if (DECL_STATIC_CONSTRUCTOR (fn))
- static_ctors = tree_cons (NULL_TREE, fn, static_ctors);
-
- /* If this function is marked with the destructor attribute, add it
- to the list of functions to be called along with destructors from
- static duration objects. */
- if (DECL_STATIC_DESTRUCTOR (fn))
- static_dtors = tree_cons (NULL_TREE, fn, static_dtors);
-
/* We make a decision about linkage for these functions at the end
of the compilation. Until that point, we do not want the back
end to output them -- but we do want it to see the bodies of
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 57cc6e1..ad3404a 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -1667,6 +1667,8 @@ specifies that the @samp{const} must be attached to the return value.
@item constructor
@itemx destructor
+@itemx constructor (@var{priority})
+@itemx destructor (@var{priority})
@cindex @code{constructor} function attribute
@cindex @code{destructor} function attribute
The @code{constructor} attribute causes the function to be called
@@ -1677,6 +1679,16 @@ been called. Functions with these attributes are useful for
initializing data that will be used implicitly during the execution of
the program.
+You may provide an optional integer priority to control the order in
+which constructor and destructor functions are run. A constructor
+with a smaller priority number runs before a constructor with a larger
+priority number; the opposite relationship holds for destructors. So,
+if you have a constructor that allocates a resource and a destructor
+that deallocates the same resource, both functions typically have the
+same priority. The priorities for constructor and destructor
+functions are the same as those specified for namespace-scope C++
+objects (@pxref{C++ Attributes}).
+
These attributes are not currently implemented for Objective-C@.
@item deprecated
diff --git a/gcc/lambda-code.c b/gcc/lambda-code.c
index 3a7fa5f..d763266 100644
--- a/gcc/lambda-code.c
+++ b/gcc/lambda-code.c
@@ -2153,7 +2153,7 @@ replace_uses_equiv_to_x_with_y (struct loop *loop, tree stmt, tree x,
/* Use REPLACEMENTS hash table to cache already created
temporaries. */
in.hash = htab_hash_pointer (use);
- in.from = use;
+ in.base.from = use;
h = htab_find_with_hash (replacements, &in, in.hash);
if (h != NULL)
{
@@ -2198,7 +2198,7 @@ replace_uses_equiv_to_x_with_y (struct loop *loop, tree stmt, tree x,
SET_USE (use_p, var);
h = ggc_alloc (sizeof (struct tree_map));
h->hash = in.hash;
- h->from = use;
+ h->base.from = use;
h->to = var;
loc = htab_find_slot_with_hash (replacements, h, in.hash, INSERT);
gcc_assert ((*(struct tree_map **)loc) == NULL);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c2e1df8..c5e15b9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,18 @@
+2007-02-25 Mark Mitchell <mark@codesourcery.com>
+
+ * gcc.dg/initpri1.c: New test.
+ * gcc.dg/initpri2.c: Likewise.
+ * g++.dg/special/initpri1.C: New test.
+ * g++.dg/special/initpri2.C: Likewise.
+ * g++.dg/special/conpr-1.C: Use init_priority effective target.
+ * g++.dg/special/conpr-2.C: Likewise.
+ * g++.dg/special/conpr-3.C: Likewise.
+ * g++.dg/special/conpr-4.C: Likewise.
+ * g++.dg/special/initp1.C: Likewise.
+ * g++.dg/special/ecos.exp: Remove code to detect availability of
+ constructor priorities.
+ * lib/target-support.exp (target_init_priority): New function.
+
2007-02-24 Jan Hubicka <jh@suse.cz>
* gcc.c-torture/execute/pr30778.c: New testcase.
diff --git a/gcc/testsuite/g++.dg/special/conpr-1.C b/gcc/testsuite/g++.dg/special/conpr-1.C
index c91753d..ef694db 100644
--- a/gcc/testsuite/g++.dg/special/conpr-1.C
+++ b/gcc/testsuite/g++.dg/special/conpr-1.C
@@ -1,4 +1,4 @@
-/* { dg-do run } */
+/* { dg-do run { target init_priority } } */
#include <stdlib.h>
diff --git a/gcc/testsuite/g++.dg/special/conpr-2.C b/gcc/testsuite/g++.dg/special/conpr-2.C
index 67333c8..ac82694 100644
--- a/gcc/testsuite/g++.dg/special/conpr-2.C
+++ b/gcc/testsuite/g++.dg/special/conpr-2.C
@@ -1,5 +1,4 @@
-/* This doesn't work on solaris2 for reasons described in PR 6482. */
-/* { dg-do run { xfail *-*-solaris2* } } */
+/* { dg-do run { target init_priority } } */
/* { dg-additional-sources "conpr-2a.cc" } */
#include <stdlib.h>
diff --git a/gcc/testsuite/g++.dg/special/conpr-3.C b/gcc/testsuite/g++.dg/special/conpr-3.C
index 04a080b..71fadcc 100644
--- a/gcc/testsuite/g++.dg/special/conpr-3.C
+++ b/gcc/testsuite/g++.dg/special/conpr-3.C
@@ -1,4 +1,4 @@
-/* { dg-do run } */
+/* { dg-do run { target init_priority } } */
/* { dg-additional-sources "conpr-3a.cc conpr-3b.cc" } */
#include <stdlib.h>
diff --git a/gcc/testsuite/g++.dg/special/conpr-4.C b/gcc/testsuite/g++.dg/special/conpr-4.C
index c04d188..40ce21d 100644
--- a/gcc/testsuite/g++.dg/special/conpr-4.C
+++ b/gcc/testsuite/g++.dg/special/conpr-4.C
@@ -1,4 +1,4 @@
-/* { dg-do run } */
+/* { dg-do run { target init_priority } } */
/* { dg-additional-sources "conpr-3b.cc conpr-3a.cc" } */
#include <stdlib.h>
diff --git a/gcc/testsuite/g++.dg/special/ecos.exp b/gcc/testsuite/g++.dg/special/ecos.exp
index 10f098f..6fbd811 100644
--- a/gcc/testsuite/g++.dg/special/ecos.exp
+++ b/gcc/testsuite/g++.dg/special/ecos.exp
@@ -24,16 +24,6 @@
# Load support procs.
load_lib g++-dg.exp
-# Test for whether or not __attribute__((init_priority)) is supported
-# by the platform.
-
-set comp_output [g++_target_compile \
- "$srcdir/$subdir/initp1.C" "initp1.S" assembly ""]
-remove-build-file "initp1.S"
-if { [string match "*init_priority*" $comp_output] } {
- return 0
-}
-
# Initialize 'dg'.
dg-init
diff --git a/gcc/testsuite/g++.dg/special/initp1.C b/gcc/testsuite/g++.dg/special/initp1.C
index adde34f..4a539a5 100644
--- a/gcc/testsuite/g++.dg/special/initp1.C
+++ b/gcc/testsuite/g++.dg/special/initp1.C
@@ -1,5 +1,4 @@
-/* This doesn't work on solaris2 for reasons described in PR 6482. */
-/* { dg-do run { xfail *-*-solaris2* } } */
+/* { dg-do run { target init_priority } } */
#include <stdlib.h>
class Two {
diff --git a/gcc/testsuite/g++.dg/special/initpri1.C b/gcc/testsuite/g++.dg/special/initpri1.C
new file mode 100644
index 0000000..bd24961
--- /dev/null
+++ b/gcc/testsuite/g++.dg/special/initpri1.C
@@ -0,0 +1,62 @@
+/* { dg-do run { target init_priority } } */
+
+extern "C" void abort ();
+
+int i;
+int j;
+
+void c1() __attribute__((constructor (500)));
+void c2() __attribute__((constructor (700)));
+void c3() __attribute__((constructor (600)));
+
+void c1() {
+ if (i++ != 0)
+ abort ();
+}
+
+void c2() {
+ if (i++ != 2)
+ abort ();
+}
+
+void c3() {
+ if (i++ != 1)
+ abort ();
+}
+
+void d1() __attribute__((destructor (500)));
+void d2() __attribute__((destructor (700)));
+void d3() __attribute__((destructor (600)));
+
+void d1() {
+ if (--i != 0)
+ abort ();
+}
+
+void d2() {
+ if (--i != 2)
+ abort ();
+}
+
+void d3() {
+ if (j != 2)
+ abort ();
+ if (--i != 1)
+ abort ();
+}
+
+void cd4() __attribute__((constructor (800), destructor (800)));
+
+void cd4() {
+ if (i != 3)
+ abort ();
+ ++j;
+}
+
+int main () {
+ if (i != 3)
+ return 1;
+ if (j != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/special/initpri2.C b/gcc/testsuite/g++.dg/special/initpri2.C
new file mode 100644
index 0000000..1000274
--- /dev/null
+++ b/gcc/testsuite/g++.dg/special/initpri2.C
@@ -0,0 +1,18 @@
+/* { dg-do compile { target init_priority } } */
+
+/* Priorities must be in the range [0, 65535]. */
+void c1()
+ __attribute__((constructor (-1))); /* { dg-error "priorities" } */
+void c2()
+ __attribute__((constructor (65536))); /* { dg-error "priorities" } */
+void d1()
+ __attribute__((destructor (-1))); /* { dg-error "priorities" } */
+void d2()
+ __attribute__((destructor (65536))); /* { dg-error "priorities" } */
+
+/* Priorities 0-100 are reserved for system libraries. */
+void c3()
+ __attribute__((constructor (50))); /* { dg-warning "reserved" } */
+void d3()
+ __attribute__((constructor (50))); /* { dg-warning "reserved" } */
+
diff --git a/gcc/testsuite/gcc.dg/initpri1.c b/gcc/testsuite/gcc.dg/initpri1.c
new file mode 100644
index 0000000..794ea2b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/initpri1.c
@@ -0,0 +1,62 @@
+/* { dg-do run { target init_priority } } */
+
+extern void abort ();
+
+int i;
+int j;
+
+void c1() __attribute__((constructor (500)));
+void c2() __attribute__((constructor (700)));
+void c3() __attribute__((constructor (600)));
+
+void c1() {
+ if (i++ != 0)
+ abort ();
+}
+
+void c2() {
+ if (i++ != 2)
+ abort ();
+}
+
+void c3() {
+ if (i++ != 1)
+ abort ();
+}
+
+void d1() __attribute__((destructor (500)));
+void d2() __attribute__((destructor (700)));
+void d3() __attribute__((destructor (600)));
+
+void d1() {
+ if (--i != 0)
+ abort ();
+}
+
+void d2() {
+ if (--i != 2)
+ abort ();
+}
+
+void d3() {
+ if (j != 2)
+ abort ();
+ if (--i != 1)
+ abort ();
+}
+
+void cd4() __attribute__((constructor (800), destructor (800)));
+
+void cd4() {
+ if (i != 3)
+ abort ();
+ ++j;
+}
+
+int main () {
+ if (i != 3)
+ return 1;
+ if (j != 1)
+ abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/initpri2.c b/gcc/testsuite/gcc.dg/initpri2.c
new file mode 100644
index 0000000..1000274
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/initpri2.c
@@ -0,0 +1,18 @@
+/* { dg-do compile { target init_priority } } */
+
+/* Priorities must be in the range [0, 65535]. */
+void c1()
+ __attribute__((constructor (-1))); /* { dg-error "priorities" } */
+void c2()
+ __attribute__((constructor (65536))); /* { dg-error "priorities" } */
+void d1()
+ __attribute__((destructor (-1))); /* { dg-error "priorities" } */
+void d2()
+ __attribute__((destructor (65536))); /* { dg-error "priorities" } */
+
+/* Priorities 0-100 are reserved for system libraries. */
+void c3()
+ __attribute__((constructor (50))); /* { dg-warning "reserved" } */
+void d3()
+ __attribute__((constructor (50))); /* { dg-warning "reserved" } */
+
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index a13ba3e..2682f8f 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -2089,6 +2089,23 @@ proc check_effective_target_dummy_wcsftime {} {
return [check_effective_target_uclibc]
}
+# Return 1 if constructors with initialization priority arguments are
+# supposed on this target.
+
+proc check_effective_target_init_priority {} {
+ # On Solaris2, initialization priorities are only supported with
+ # GNU ld, but the compiler accepts them even when using Sun ld.
+ # For more information, see PR 6482.
+ if { [istarget *-solaris2*] } {
+ return 1
+ }
+
+ return [check_no_compiler_messages init_priority assembly "
+ void f() __attribute__((constructor (1000)));
+ void f() \{\}
+ "]
+}
+
# Return 1 if the target matches the effective target 'arg', 0 otherwise.
# This can be used with any check_* proc that takes no argument and
# returns only 1 or 0. It could be used with check_* procs that take
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 593dc0d..202a69e 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -4606,7 +4606,7 @@ move_stmt_r (tree *tp, int *walk_subtrees, void *data)
if (p->new_label_map)
{
struct tree_map in, *out;
- in.from = t;
+ in.base.from = t;
out = htab_find_with_hash (p->new_label_map, &in, DECL_UID (t));
if (out)
*tp = t = out->to;
@@ -4795,7 +4795,7 @@ new_label_mapper (tree decl, void *data)
m = xmalloc (sizeof (struct tree_map));
m->hash = DECL_UID (decl);
- m->from = decl;
+ m->base.from = decl;
m->to = create_artificial_label ();
LABEL_DECL_UID (m->to) = LABEL_DECL_UID (decl);
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index a6a2a68..f031bf0 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -330,7 +330,7 @@ static tree
heapvar_lookup (tree from)
{
struct tree_map *h, in;
- in.from = from;
+ in.base.from = from;
h = htab_find_with_hash (heapvar_for_stmt, &in, htab_hash_pointer (from));
if (h)
@@ -349,7 +349,7 @@ heapvar_insert (tree from, tree to)
h = ggc_alloc (sizeof (struct tree_map));
h->hash = htab_hash_pointer (from);
- h->from = from;
+ h->base.from = from;
h->to = to;
loc = htab_find_slot_with_hash (heapvar_for_stmt, h, h->hash, INSERT);
*(struct tree_map **) loc = h;
diff --git a/gcc/tree.c b/gcc/tree.c
index d9982e8..f941892 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -146,7 +146,8 @@ static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
htab_t value_expr_for_decl;
-static GTY ((if_marked ("tree_int_map_marked_p"), param_is (struct tree_int_map)))
+static GTY ((if_marked ("tree_priority_map_marked_p"),
+ param_is (struct tree_priority_map)))
htab_t init_priority_for_decl;
static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map)))
@@ -220,8 +221,8 @@ init_ttree (void)
value_expr_for_decl = htab_create_ggc (512, tree_map_hash,
tree_map_eq, 0);
- init_priority_for_decl = htab_create_ggc (512, tree_int_map_hash,
- tree_int_map_eq, 0);
+ init_priority_for_decl = htab_create_ggc (512, tree_priority_map_hash,
+ tree_priority_map_eq, 0);
restrict_base_for_decl = htab_create_ggc (256, tree_map_hash,
tree_map_eq, 0);
@@ -4195,18 +4196,18 @@ build_variant_type_copy (tree type)
/* Return true if the from tree in both tree maps are equal. */
int
-tree_map_eq (const void *va, const void *vb)
+tree_map_base_eq (const void *va, const void *vb)
{
- const struct tree_map *a = va, *b = vb;
+ const struct tree_map_base *a = va, *b = vb;
return (a->from == b->from);
}
/* Hash a from tree in a tree_map. */
unsigned int
-tree_map_hash (const void *item)
+tree_map_base_hash (const void *item)
{
- return (((const struct tree_map *) item)->hash);
+ return htab_hash_pointer (((const struct tree_map_base *)item)->from);
}
/* Return true if this tree map structure is marked for garbage collection
@@ -4214,70 +4215,97 @@ tree_map_hash (const void *item)
structure goes away when the from tree goes away. */
int
-tree_map_marked_p (const void *p)
+tree_map_base_marked_p (const void *p)
{
- tree from = ((struct tree_map *) p)->from;
+ return ggc_marked_p (((struct tree_map_base *) p)->from);
+}
- return ggc_marked_p (from);
+unsigned int
+tree_map_hash (const void *item)
+{
+ return (((const struct tree_map *) item)->hash);
}
-/* Return true if the trees in the tree_int_map *'s VA and VB are equal. */
+/* Return the initialization priority for DECL. */
-int
-tree_int_map_eq (const void *va, const void *vb)
+priority_type
+decl_init_priority_lookup (tree decl)
{
- const struct tree_int_map *a = va, *b = vb;
- return (a->from == b->from);
+ struct tree_priority_map *h;
+ struct tree_map_base in;
+
+ gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
+ gcc_assert (TREE_CODE (decl) == VAR_DECL
+ ? DECL_HAS_INIT_PRIORITY_P (decl)
+ : DECL_STATIC_CONSTRUCTOR (decl));
+ in.from = decl;
+ h = htab_find (init_priority_for_decl, &in);
+ return h ? h->init : DEFAULT_INIT_PRIORITY;
}
-/* Hash a from tree in the tree_int_map * ITEM. */
+/* Return the finalization priority for DECL. */
-unsigned int
-tree_int_map_hash (const void *item)
+priority_type
+decl_fini_priority_lookup (tree decl)
{
- return htab_hash_pointer (((const struct tree_int_map *)item)->from);
+ struct tree_priority_map *h;
+ struct tree_map_base in;
+
+ gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
+ gcc_assert (DECL_STATIC_DESTRUCTOR (decl));
+ in.from = decl;
+ h = htab_find (init_priority_for_decl, &in);
+ return h ? h->fini : DEFAULT_INIT_PRIORITY;
}
-/* Return true if this tree int map structure is marked for garbage collection
- purposes. We simply return true if the from tree_int_map *P's from tree is marked, so that this
- structure goes away when the from tree goes away. */
+/* Return the initialization and finalization priority information for
+ DECL. If there is no previous priority information, a freshly
+ allocated structure is returned. */
-int
-tree_int_map_marked_p (const void *p)
+static struct tree_priority_map *
+decl_priority_info (tree decl)
{
- tree from = ((struct tree_int_map *) p)->from;
+ struct tree_priority_map in;
+ struct tree_priority_map *h;
+ void **loc;
+
+ in.base.from = decl;
+ loc = htab_find_slot (init_priority_for_decl, &in, INSERT);
+ h = *loc;
+ if (!h)
+ {
+ h = GGC_CNEW (struct tree_priority_map);
+ *loc = h;
+ h->base.from = decl;
+ h->init = DEFAULT_INIT_PRIORITY;
+ h->fini = DEFAULT_INIT_PRIORITY;
+ }
- return ggc_marked_p (from);
+ return h;
}
-/* Lookup an init priority for FROM, and return it if we find one. */
-unsigned short
-decl_init_priority_lookup (tree from)
+/* Set the initialization priority for DECL to PRIORITY. */
+
+void
+decl_init_priority_insert (tree decl, priority_type priority)
{
- struct tree_int_map *h, in;
- in.from = from;
+ struct tree_priority_map *h;
- h = htab_find_with_hash (init_priority_for_decl,
- &in, htab_hash_pointer (from));
- if (h)
- return h->to;
- return 0;
-}
+ gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
+ h = decl_priority_info (decl);
+ h->init = priority;
+}
-/* Insert a mapping FROM->TO in the init priority hashtable. */
+/* Set the finalization priority for DECL to PRIORITY. */
void
-decl_init_priority_insert (tree from, unsigned short to)
+decl_fini_priority_insert (tree decl, priority_type priority)
{
- struct tree_int_map *h;
- void **loc;
+ struct tree_priority_map *h;
- h = ggc_alloc (sizeof (struct tree_int_map));
- h->from = from;
- h->to = to;
- loc = htab_find_slot_with_hash (init_priority_for_decl, h,
- htab_hash_pointer (from), INSERT);
- *(struct tree_int_map **) loc = h;
+ gcc_assert (TREE_CODE (decl) == FUNCTION_DECL);
+ h = decl_priority_info (decl);
+ h->fini = priority;
}
/* Look up a restrict qualified base decl for FROM. */
@@ -4288,7 +4316,7 @@ decl_restrict_base_lookup (tree from)
struct tree_map *h;
struct tree_map in;
- in.from = from;
+ in.base.from = from;
h = htab_find_with_hash (restrict_base_for_decl, &in,
htab_hash_pointer (from));
return h ? h->to : NULL_TREE;
@@ -4304,7 +4332,7 @@ decl_restrict_base_insert (tree from, tree to)
h = ggc_alloc (sizeof (struct tree_map));
h->hash = htab_hash_pointer (from);
- h->from = from;
+ h->base.from = from;
h->to = to;
loc = htab_find_slot_with_hash (restrict_base_for_decl, h, h->hash, INSERT);
*(struct tree_map **) loc = h;
@@ -4352,7 +4380,7 @@ tree
decl_debug_expr_lookup (tree from)
{
struct tree_map *h, in;
- in.from = from;
+ in.base.from = from;
h = htab_find_with_hash (debug_expr_for_decl, &in, htab_hash_pointer (from));
if (h)
@@ -4370,7 +4398,7 @@ decl_debug_expr_insert (tree from, tree to)
h = ggc_alloc (sizeof (struct tree_map));
h->hash = htab_hash_pointer (from);
- h->from = from;
+ h->base.from = from;
h->to = to;
loc = htab_find_slot_with_hash (debug_expr_for_decl, h, h->hash, INSERT);
*(struct tree_map **) loc = h;
@@ -4382,7 +4410,7 @@ tree
decl_value_expr_lookup (tree from)
{
struct tree_map *h, in;
- in.from = from;
+ in.base.from = from;
h = htab_find_with_hash (value_expr_for_decl, &in, htab_hash_pointer (from));
if (h)
@@ -4400,7 +4428,7 @@ decl_value_expr_insert (tree from, tree to)
h = ggc_alloc (sizeof (struct tree_map));
h->hash = htab_hash_pointer (from);
- h->from = from;
+ h->base.from = from;
h->to = to;
loc = htab_find_slot_with_hash (value_expr_for_decl, h, h->hash, INSERT);
*(struct tree_map **) loc = h;
diff --git a/gcc/tree.h b/gcc/tree.h
index b656e1b..1e2ecd0 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2599,13 +2599,6 @@ struct tree_memory_partition_tag GTY(())
a C99 "extern inline" function. */
#define DECL_EXTERNAL(NODE) (DECL_COMMON_CHECK (NODE)->decl_common.decl_flag_2)
-/* In a VAR_DECL for a RECORD_TYPE, sets number for non-init_priority
- initializations. */
-#define DEFAULT_INIT_PRIORITY 65535
-#define MAX_INIT_PRIORITY 65535
-#define MAX_RESERVED_INIT_PRIORITY 100
-
-
/* Nonzero in a ..._DECL means this variable is ref'd from a nested function.
For VAR_DECL nodes, PARM_DECL nodes, and FUNCTION_DECL nodes.
@@ -3065,20 +3058,46 @@ extern void decl_debug_expr_insert (tree, tree);
#define SET_DECL_DEBUG_EXPR(NODE, VAL) \
(decl_debug_expr_insert (VAR_DECL_CHECK (NODE), VAL))
+/* An initializationp priority. */
+typedef unsigned short priority_type;
-extern unsigned short decl_init_priority_lookup (tree);
-extern void decl_init_priority_insert (tree, unsigned short);
-
-/* In a non-local VAR_DECL with static storage duration, this is the
- initialization priority. If this value is zero, the NODE will be
- initialized at the DEFAULT_INIT_PRIORITY. Only used by C++ FE*/
+extern priority_type decl_init_priority_lookup (tree);
+extern priority_type decl_fini_priority_lookup (tree);
+extern void decl_init_priority_insert (tree, priority_type);
+extern void decl_fini_priority_insert (tree, priority_type);
+/* In a non-local VAR_DECL with static storage duration, true if the
+ variable has an initialization priority. If false, the variable
+ will be initialized at the DEFAULT_INIT_PRIORITY. */
#define DECL_HAS_INIT_PRIORITY_P(NODE) \
(VAR_DECL_CHECK (NODE)->decl_with_vis.init_priority_p)
+
+/* For a VAR_DECL or FUNCTION_DECL with DECL_HAS_INIT_PRIORITY_P set,
+ the initialization priority of NODE. */
#define DECL_INIT_PRIORITY(NODE) \
- (decl_init_priority_lookup (VAR_DECL_CHECK (NODE)))
+ (decl_init_priority_lookup (NODE))
+/* Set the initialization priority for NODE to VAL. */
#define SET_DECL_INIT_PRIORITY(NODE, VAL) \
- (decl_init_priority_insert (VAR_DECL_CHECK (NODE), VAL))
+ (decl_init_priority_insert (NODE, VAL))
+
+/* For a FUNCTION_DECL with DECL_HAS_INIT_PRIORITY_P set, the
+ finalization priority of NODE. */
+#define DECL_FINI_PRIORITY(NODE) \
+ (decl_fini_priority_lookup (NODE))
+/* Set the finalization priority for NODE to VAL. */
+#define SET_DECL_FINI_PRIORITY(NODE, VAL) \
+ (decl_fini_priority_insert (NODE, VAL))
+
+/* The initialization priority for entities for which no explicit
+ initialization priority has been specified. */
+#define DEFAULT_INIT_PRIORITY 65535
+
+/* The maximum allowed initialization priority. */
+#define MAX_INIT_PRIORITY 65535
+
+/* The largest priority value reserved for use by system runtime
+ libraries. */
+#define MAX_RESERVED_INIT_PRIORITY 100
/* In a VAR_DECL, the model to use if the data should be allocated from
thread-local storage. */
@@ -4800,26 +4819,53 @@ extern tree get_base_address (tree t);
extern void vect_set_verbosity_level (const char *);
/* In tree.c. */
+
+struct tree_map_base GTY(())
+{
+ tree from;
+};
+
+extern int tree_map_base_eq (const void *, const void *);
+extern unsigned int tree_map_base_hash (const void *);
+extern int tree_map_base_marked_p (const void *);
+
+/* Map from a tree to another tree. */
+
struct tree_map GTY(())
{
+ struct tree_map_base base;
unsigned int hash;
- tree from;
tree to;
};
+#define tree_map_eq tree_map_base_eq
extern unsigned int tree_map_hash (const void *);
-extern int tree_map_marked_p (const void *);
-extern int tree_map_eq (const void *, const void *);
+#define tree_map_marked_p tree_map_base_marked_p
+
+/* Map from a tree to an int. */
struct tree_int_map GTY(())
{
- tree from;
+ struct tree_map_base base;
unsigned int to;
};
-extern unsigned int tree_int_map_hash (const void *);
-extern int tree_int_map_eq (const void *, const void *);
-extern int tree_int_map_marked_p (const void *);
+#define tree_int_map_eq tree_map_base_eq
+#define tree_int_map_hash tree_map_base_hash
+#define tree_int_map_marked_p tree_map_base_marked_p
+
+/* Map from a tree to initialization/finalization priorities. */
+
+struct tree_priority_map GTY(())
+{
+ struct tree_map_base base;
+ priority_type init;
+ priority_type fini;
+};
+
+#define tree_priority_map_eq tree_map_base_eq
+#define tree_priority_map_hash tree_map_base_hash
+#define tree_priority_map_marked_p tree_map_base_marked_p
/* In tree-ssa-address.c. */
extern tree tree_mem_ref_addr (tree, tree);
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 5671864..6c22145 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -343,7 +343,7 @@ emutls_decl (tree decl)
of the decl's pointer. In emutls_finish we iterate through the
hash table, and we want this traversal to be predictable. */
in.hash = htab_hash_string (IDENTIFIER_POINTER (name));
- in.from = decl;
+ in.base.from = decl;
loc = htab_find_slot_with_hash (emutls_htab, &in, in.hash, INSERT);
h = *loc;
if (h != NULL)
@@ -355,7 +355,7 @@ emutls_decl (tree decl)
h = ggc_alloc (sizeof (struct tree_map));
h->hash = in.hash;
- h->from = decl;
+ h->base.from = decl;
h->to = to;
*(struct tree_map **) loc = h;
@@ -394,9 +394,9 @@ emutls_common_1 (void **loc, void *xstmts)
tree args, x, *pstmts = (tree *) xstmts;
tree word_type_node;
- if (! DECL_COMMON (h->from)
- || (DECL_INITIAL (h->from)
- && DECL_INITIAL (h->from) != error_mark_node))
+ if (! DECL_COMMON (h->base.from)
+ || (DECL_INITIAL (h->base.from)
+ && DECL_INITIAL (h->base.from) != error_mark_node))
return 1;
word_type_node = lang_hooks.types.type_for_mode (word_mode, 1);
@@ -407,9 +407,9 @@ emutls_common_1 (void **loc, void *xstmts)
output. */
x = null_pointer_node;
args = tree_cons (NULL, x, NULL);
- x = build_int_cst (word_type_node, DECL_ALIGN_UNIT (h->from));
+ x = build_int_cst (word_type_node, DECL_ALIGN_UNIT (h->base.from));
args = tree_cons (NULL, x, args);
- x = fold_convert (word_type_node, DECL_SIZE_UNIT (h->from));
+ x = fold_convert (word_type_node, DECL_SIZE_UNIT (h->base.from));
args = tree_cons (NULL, x, args);
x = build_fold_addr_expr (h->to);
args = tree_cons (NULL, x, args);