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
This commit is contained in:
Mark Mitchell 2007-02-25 18:47:05 +00:00 committed by Mark Mitchell
parent 2a025b54f6
commit fc8600f9c1
31 changed files with 561 additions and 207 deletions

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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. */

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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.

View File

@ -1,4 +1,4 @@
/* { dg-do run } */
/* { dg-do run { target init_priority } } */
#include <stdlib.h>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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

View File

@ -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 {

View File

@ -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;
}

View File

@ -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" } */

View File

@ -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;
}

View File

@ -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" } */

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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 (from);
return ggc_marked_p (((struct tree_map_base *) p)->from);
}
/* Return true if the trees in the tree_int_map *'s VA and VB are equal. */
int
tree_int_map_eq (const void *va, const void *vb)
{
const struct tree_int_map *a = va, *b = vb;
return (a->from == b->from);
}
/* Hash a from tree in the tree_int_map * ITEM. */
unsigned int
tree_int_map_hash (const void *item)
tree_map_hash (const void *item)
{
return htab_hash_pointer (((const struct tree_int_map *)item)->from);
return (((const struct tree_map *) item)->hash);
}
/* 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 priority for DECL. */
int
tree_int_map_marked_p (const void *p)
priority_type
decl_init_priority_lookup (tree decl)
{
tree from = ((struct tree_int_map *) p)->from;
struct tree_priority_map *h;
struct tree_map_base in;
return ggc_marked_p (from);
}
/* Lookup an init priority for FROM, and return it if we find one. */
unsigned short
decl_init_priority_lookup (tree from)
{
struct tree_int_map *h, in;
in.from = from;
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));
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;
}
/* Insert a mapping FROM->TO in the init priority hashtable. */
/* Return the finalization priority for DECL. */
void
decl_init_priority_insert (tree from, unsigned short to)
priority_type
decl_fini_priority_lookup (tree decl)
{
struct tree_int_map *h;
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 the initialization and finalization priority information for
DECL. If there is no previous priority information, a freshly
allocated structure is returned. */
static struct tree_priority_map *
decl_priority_info (tree decl)
{
struct tree_priority_map in;
struct tree_priority_map *h;
void **loc;
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;
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 h;
}
/* Set the initialization priority for DECL to PRIORITY. */
void
decl_init_priority_insert (tree decl, priority_type priority)
{
struct tree_priority_map *h;
gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
h = decl_priority_info (decl);
h->init = priority;
}
/* Set the finalization priority for DECL to PRIORITY. */
void
decl_fini_priority_insert (tree decl, priority_type priority)
{
struct tree_priority_map *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;

View File

@ -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);

View File

@ -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);