OSDN Git Service

* doc/extend.texi: Document optional priority argument to
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 25 Feb 2007 18:47:05 +0000 (18:47 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 25 Feb 2007 18:47:05 +0000 (18:47 +0000)
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

31 files changed:
gcc/ChangeLog
gcc/ada/ChangeLog
gcc/ada/decl.c
gcc/c-common.c
gcc/c-common.h
gcc/c-decl.c
gcc/c-tree.h
gcc/cp/ChangeLog
gcc/cp/cp-objcp-common.c
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/semantics.c
gcc/doc/extend.texi
gcc/lambda-code.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/special/conpr-1.C
gcc/testsuite/g++.dg/special/conpr-2.C
gcc/testsuite/g++.dg/special/conpr-3.C
gcc/testsuite/g++.dg/special/conpr-4.C
gcc/testsuite/g++.dg/special/ecos.exp
gcc/testsuite/g++.dg/special/initp1.C
gcc/testsuite/g++.dg/special/initpri1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/special/initpri2.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/initpri1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/initpri2.c [new file with mode: 0644]
gcc/testsuite/lib/target-supports.exp
gcc/tree-cfg.c
gcc/tree-ssa-structalias.c
gcc/tree.c
gcc/tree.h
gcc/varasm.c

index cc9e79e..54d3ad5 100644 (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
index 6b7cc45..ddae48e 100644 (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
index af0e392..6b14064 100644 (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);
 
index 51fd226..4eb0265 100644 (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
index 5ad4582..4e25ede 100644 (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);
 
index ed0bf9c..ec567a5 100644 (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);
-}
 \f
 /* Check the declarations given in a for-loop for satisfying the C99
    constraints.  If exactly one such decl is found, return it.  */
index 87af5cb..b2fe228 100644 (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);
index bdef6b5..a9f4d25 100644 (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
index 2fdea26..372e8e5 100644 (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;
index a070411..e03003e 100644 (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
index 68917b6..1feb3a7 100644 (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;
-
 \f
 
 /* 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)
index c4cdd95..71c16e0 100644 (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
index 57cc6e1..ad3404a 100644 (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
index 3a7fa5f..d763266 100644 (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);
index c2e1df8..c5e15b9 100644 (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.
index c91753d..ef694db 100644 (file)
@@ -1,4 +1,4 @@
-/* { dg-do run } */
+/* { dg-do run { target init_priority } } */
 
 #include <stdlib.h>
 
index 67333c8..ac82694 100644 (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>
index 04a080b..71fadcc 100644 (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>
index c04d188..40ce21d 100644 (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>
index 10f098f..6fbd811 100644 (file)
 # 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
 
index adde34f..4a539a5 100644 (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 {
diff --git a/gcc/testsuite/g++.dg/special/initpri1.C b/gcc/testsuite/g++.dg/special/initpri1.C
new file mode 100644 (file)
index 0000000..bd24961
--- /dev/null
@@ -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 (file)
index 0000000..1000274
--- /dev/null
@@ -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 (file)
index 0000000..794ea2b
--- /dev/null
@@ -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 (file)
index 0000000..1000274
--- /dev/null
@@ -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" } */
+
index a13ba3e..2682f8f 100644 (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
index 593dc0d..202a69e 100644 (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);
 
index a6a2a68..f031bf0 100644 (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;
index d9982e8..f941892 100644 (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 (((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;
index b656e1b..1e2ecd0 100644 (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);
index 5671864..6c22145 100644 (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);