From 9af7fd5b82a9d848526e5f5edf0411d6dd2693fc Mon Sep 17 00:00:00 2001 From: mmitchel Date: Sun, 25 Feb 2007 18:47:05 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@122315 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 69 ++++++++++++++++ gcc/ada/ChangeLog | 5 ++ gcc/ada/decl.c | 2 +- gcc/c-common.c | 84 ++++++++++++++++++-- gcc/c-common.h | 1 + gcc/c-decl.c | 22 ------ gcc/c-tree.h | 1 - gcc/cp/ChangeLog | 17 ++++ gcc/cp/cp-objcp-common.c | 4 +- gcc/cp/cp-tree.h | 5 -- gcc/cp/decl2.c | 52 ++----------- gcc/cp/semantics.c | 14 +--- gcc/doc/extend.texi | 12 +++ gcc/lambda-code.c | 4 +- gcc/testsuite/ChangeLog | 15 ++++ gcc/testsuite/g++.dg/special/conpr-1.C | 2 +- gcc/testsuite/g++.dg/special/conpr-2.C | 3 +- gcc/testsuite/g++.dg/special/conpr-3.C | 2 +- gcc/testsuite/g++.dg/special/conpr-4.C | 2 +- gcc/testsuite/g++.dg/special/ecos.exp | 10 --- gcc/testsuite/g++.dg/special/initp1.C | 3 +- gcc/testsuite/g++.dg/special/initpri1.C | 62 +++++++++++++++ gcc/testsuite/g++.dg/special/initpri2.C | 18 +++++ gcc/testsuite/gcc.dg/initpri1.c | 62 +++++++++++++++ gcc/testsuite/gcc.dg/initpri2.c | 18 +++++ gcc/testsuite/lib/target-supports.exp | 17 ++++ gcc/tree-cfg.c | 4 +- gcc/tree-ssa-structalias.c | 4 +- gcc/tree.c | 134 +++++++++++++++++++------------- gcc/tree.h | 90 +++++++++++++++------ gcc/varasm.c | 14 ++-- 31 files changed, 553 insertions(+), 199 deletions(-) create mode 100644 gcc/testsuite/g++.dg/special/initpri1.C create mode 100644 gcc/testsuite/g++.dg/special/initpri2.C create mode 100644 gcc/testsuite/gcc.dg/initpri1.c create mode 100644 gcc/testsuite/gcc.dg/initpri2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cc9e79e10de..54d3ad52179 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,72 @@ +2007-02-25 Mark Mitchell + + * 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 PR middle-end/30509 diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 6b7cc450e38..ddae48e7bcd 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2007-02-24 Mark Mitchell + + * decl.c (annotate_value): Adjust for refactoring of tree_map + hierarchy. + 2007-02-21 Ed Schonberg PR ada/18819 diff --git a/gcc/ada/decl.c b/gcc/ada/decl.c index af0e39246b0..6b140646415 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 51fd22672cf..4eb0265a7a2 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 5ad4582d240..4e25ede957c 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 ed0bf9cb25d..ec567a5451d 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 87af5cbae9d..b2fe22893c4 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 bdef6b5734b..a9f4d254c47 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,20 @@ +2007-02-25 Mark Mitchell + + * 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 * 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 2fdea268106..372e8e5ac3e 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 a070411e625..e03003e1210 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 68917b68bd9..1feb3a7661f 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 c4cdd954982..71c16e07e11 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 57cc6e1c660..ad3404a0b3d 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 3a7fa5fc01f..d7632665fb5 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 c2e1df80a56..c5e15b90a0d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,18 @@ +2007-02-25 Mark Mitchell + + * 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 * 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 c91753dc495..ef694dbe6f8 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 diff --git a/gcc/testsuite/g++.dg/special/conpr-2.C b/gcc/testsuite/g++.dg/special/conpr-2.C index 67333c8a98b..ac826942a67 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 diff --git a/gcc/testsuite/g++.dg/special/conpr-3.C b/gcc/testsuite/g++.dg/special/conpr-3.C index 04a080bacef..71fadcc64d3 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 diff --git a/gcc/testsuite/g++.dg/special/conpr-4.C b/gcc/testsuite/g++.dg/special/conpr-4.C index c04d188ad70..40ce21d98b5 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 diff --git a/gcc/testsuite/g++.dg/special/ecos.exp b/gcc/testsuite/g++.dg/special/ecos.exp index 10f098fea43..6fbd8110610 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 adde34fefa6..4a539a5a4bd 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 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 00000000000..bd24961e46b --- /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 00000000000..100027430a5 --- /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 00000000000..794ea2b9e0b --- /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 00000000000..100027430a5 --- /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 a13ba3e292a..2682f8f4b7d 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 593dc0d03c1..202a69e2c8f 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 a6a2a68c3ca..f031bf0102f 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 d9982e8b2ec..f941892815d 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 b656e1bfa48..1e2ecd070ef 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 56718641866..6c221459285 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); -- 2.11.4.GIT