public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATH 0/6] ggc finalizers and TLC
@ 2014-04-29 11:08 tsaunders
  2014-04-29 11:09 ` [PATCH 2/6] don't have gengtype autocreate allocation macros for variably sized types tsaunders
                   ` (5 more replies)
  0 siblings, 6 replies; 18+ messages in thread
From: tsaunders @ 2014-04-29 11:08 UTC (permalink / raw)
  To: gcc-patches

Hi,

First we clean up the allocation functions for gc memory by removing macros
CXX_MEM_STAT_INFo makes useless, and using templates instead of autogenerating
code.  Then we can add support for finalizers and automatically install
finalizers for types that have non trivial destructors.

Trev


 GIT:
[PATCH 1/6] rm a bunch of _stat allocation functions

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 3/6] use templates instead of gengtype for typed allocation functions
  2014-04-29 11:08 [PATH 0/6] ggc finalizers and TLC tsaunders
  2014-04-29 11:09 ` [PATCH 2/6] don't have gengtype autocreate allocation macros for variably sized types tsaunders
@ 2014-04-29 11:09 ` tsaunders
  2014-04-29 12:41   ` Richard Biener
  2014-04-29 11:09 ` [PATCH 4/6] remove unused function tsaunders
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 18+ messages in thread
From: tsaunders @ 2014-04-29 11:09 UTC (permalink / raw)
  To: gcc-patches; +Cc: Trevor Saunders

From: Trevor Saunders <tsaunders@mozilla.com>

Hi,

much less code to accomplish the same thing.

bootstrapped + regtested on x86_64-unknown-linux-gnu ok?

Trev

gcc/ada/ChangeLog:

	* gcc-interface/ada-tree.h: Remove usage of variable_size gty
	annotation.

gcc/cp/ChangeLog:

	* cp-cilkplus.c (cilk_install_body_with_frame_cleanup): Adjust.
	* cp-objcp-common.c (decl_shadowed_for_var_insert): Adjust.
	* cp-tree.h: Remove usage of variable_size gty attribute.
	* decl.c (make_label_decl): Adjust.
	(check_goto): Likewise.
	(start_preparsed_function): Likewise.
	(save_function_data): Likewise.
	* lex.c (init_reswords): Likewise.
	(retrofit_lang_decl): Likewise.
	(cxx_dup_lang_specific_decl): Likewise.
	(copy_lang_type): Likewise.
	(cxx_make_type): Likewise.
	* name-lookup.c (binding_entry_make): Likewise.
	(binding_table_construct): Likewise.
	(binding_table_new): Likewise.
	(cxx_binding_make): Likewise.
	(pushdecl_maybe_friend_1): Likewise.
	(begin_scope): Likewise.
	(push_to_top_level): Likewise.
	* parser.c (cp_lexer_alloc): Likewise.
	(cp_lexer_new_from_tokens): Likewise.
	(cp_token_cache_new): Likewise.
	(cp_parser_context_new): Likewise.
	(cp_parser_new): Likewise.
	(cp_parser_nested_name_specifier_opt): Likewise.
	(cp_parser_template_id): Likewise.
	* pt.c (maybe_process_partial_specialization): Likewise.
	(register_specialization): Likewise.
	(add_pending_template): Likewise.
	(lookup_template_class_1): Likewise.
	(push_tinst_level): Likewise.
	* semantics.c (register_constexpr_fundef): Likewise.
	(cxx_eval_call_expression): Likewise.
	* typeck2.c (abstract_virtuals_error_sfinae): Likewise.

gcc/objc/ChangeLog:

	* objc-act.c (objc_build_string_object): Adjust.
	(continue_class): Likewise.
	* objc-act.h (ALLOC_OBJC_TYPE_LANG_SPECIFIC): Likewise.
	* objc-map.c (objc_map_alloc_ggc): Likewise.
	(objc_map_private_resize): Likewise.
	* objc-next-runtime-abi-02.c (objc_next_runtime_abi_02_init):
	Likewise.
	(hash_name_enter): Likewise.

gcc/go/ChangeLog:

	* go-lang.c (struct GTY): Don't use variable_size gty attribute.

gcc/ChangeLog:

	* alias.c (record_alias_subset): Adjust.
	* bitmap.c (bitmap_element_allocate): Likewise.
	(bitmap_gc_alloc_stat): Likewise.
	* cfg.c (init_flow): Likewise.
	(alloc_block): Likewise.
	(unchecked_make_edge): Likewise.
	* cfgloop.c (alloc_loop): Likewise.
	(flow_loops_find): Likewise.
	(rescan_loop_exit): Likewise.
	* cfgrtl.c (init_rtl_bb_info): Likewise.
	* cgraph.c (insert_new_cgraph_node_version): Likewise.
	(cgraph_allocate_node): Likewise.
	(cgraph_create_edge_1): Likewise.
	(cgraph_allocate_init_indirect_info): Likewise.
	* cgraphclones.c (cgraph_clone_edge): Likewise.
	* cgraphunit.c (add_asm_node): Likewise.
	(init_lowered_empty_function): Likewise.
	* config/i386/i386.c (get_dllimport_decl): Likewise.
	(ix86_init_machine_status): Likewise.
	(assign_386_stack_local): Likewise.
	* coverage.c (coverage_end_function): Likewise.
	* dbxout.c (dbxout_init): Likewise.
	* doc/gty.texi: Don't mention variable_size attribute.
	* dwarf2cfi.c (new_cfi): Adjust.
	(new_cfi_row): Likewise.
	(copy_cfi_row): Likewise.
	(create_cie_data): Likewise.
	* dwarf2out.c (dwarf2out_alloc_current_fde): Likewise.
	(new_loc_descr): Likewise.
	(find_AT_string_in_table): Likewise.
	(add_addr_table_entry): Likewise.
	(new_die): Likewise.
	(add_var_loc_to_decl): Likewise.
	(clone_die): Likewise.
	(clone_as_declaration): Likewise.
	(break_out_comdat_types): Likewise.
	(new_loc_list): Likewise.
	(add_loc_descr_to_each): Likewise.
	(add_location_or_const_value_attribute): Likewise.
	(add_linkage_name): Likewise.
	(lookup_filename): Likewise.
	(dwarf2out_var_location): Likewise.
	(new_line_info_table): Likewise.
	(dwarf2out_init): Likewise.
	* emit-rtl.c (set_mem_attrs): Likewise.
	(get_reg_attrs): Likewise.
	(start_sequence): Likewise.
	(init_emit): Likewise.
	(init_emit_regs): Likewise.
	* except.c (init_eh_for_function): Likewise.
	(gen_eh_region): Likewise.
	(gen_eh_region_catch): Likewise.
	(gen_eh_landing_pad): Likewise.
	(add_call_site): Likewise.
	* function.c (add_frame_space): Likewise.
	(insert_temp_slot_address): Likewise.
	(assign_stack_temp_for_type): Likewise.
	(get_hard_reg_initial_val): Likewise.
	(allocate_struct_function): Likewise.
	(prepare_function_start): Likewise.
	(types_used_by_var_decl_insert): Likewise.
	* gengtype.c (variable_size_p): Remove function.
	(enum alloc_quantity): Remove enum.
	(write_typed_alloc_def): Remove function.
	(write_typed_struct_alloc_def): Likewise.
	(write_typed_typedef_alloc_def): Likewise.
	(write_typed_alloc_defns): Likewise.
	(main): Adjust.
	* ggc-common.c (ggc_cleared_alloc_htab_ignore_args): Adjust.
	(ggc_cleared_alloc_ptr_array_two_args): Likewise.
	* ggc.h (ggc_alloc): new function.
	(ggc_cleared_alloc): Likewise.
	(ggc_vec_alloc): Template on type of vector element, and remove
	element size argument.
	(ggc_cleared_vec_alloc): Likewise.
	* gimple.c (gimple_build_omp_for): Adjust.
	(gimple_copy): Likewise.
	* ipa-cp.c (get_replacement_map): Likewise.
	(find_aggregate_values_for_callers_subset): Likewise.
	(known_aggs_to_agg_replacement_list): Likewise.
	* ipa-devirt.c (get_odr_type): Likewise.
	* ipa-prop.c (ipa_node_duplication_hook): Likewise.
	(read_agg_replacement_chain): Likewise.
	* loop-iv.c (get_simple_loop_desc): Likewise.
	* lto-cgraph.c (input_node_opt_summary): Likewise.
	* lto-section-in.c (lto_new_in_decl_state): Likewise.
	* lto-streamer-in.c (lto_input_eh_catch_list): Likewise.
	(input_eh_region): Likewise.
	(input_eh_lp): Likewise.
	(input_cfg): Likewise.
	* optabs.c (set_optab_libfunc): Likewise.
	(set_conv_libfunc): Likewise.
	* passes.c (do_per_function_toporder): Likewise.
	* rtl.h: Don't use variable_size gty attribute.
	* sese.c (if_region_set_false_region): Adjust.
	* stringpool.c (gt_pch_save_stringpool): Likewise.
	* target-globals.c (save_target_globals): Likewise.
	* toplev.c (general_init): Likewise.
	* trans-mem.c (record_tm_replacement): Likewise.
	(split_bb_make_tm_edge): Likewise.
	* tree-cfg.c (move_sese_region_to_fn): Likewise.
	* tree-data-ref.h (lambda_vector_new): Likewise.
	* tree-eh.c (add_stmt_to_eh_lp_fn): Likewise.
	* tree-iterator.c (tsi_link_before): Likewise.
	(tsi_link_after): Likewise.
	* tree-scalar-evolution.c (new_scev_info_str): Likewise.
	* tree-ssa-loop-niter.c (record_estimate): Likewise.
	* tree-ssa-operands.h: Don't use variable_size gty attribute.
	* tree-ssa.c (init_tree_ssa): Adjust.
	* tree-ssanames.c (set_range_info): Likewise.
	(get_ptr_info): Likewise.
	(duplicate_ssa_name_ptr_info): Likewise.
	(duplicate_ssa_name_range_info): Likewise.
	* tree-streamer-in.c (unpack_ts_real_cst_value_fields): Likewise.
	(unpack_ts_fixed_cst_value_fields): Likewise.
	* tree.c (build_fixed): Likewise.
	(build_real): Likewise.
	(build_string): Likewise.
	(decl_priority_info): Likewise.
	(decl_debug_expr_insert): Likewise.
	(decl_value_expr_insert): Likewise.
	(decl_debug_args_insert): Likewise.
	(type_hash_add): Likewise.
	(build_omp_clause): Likewise.
	* ubsan.c (decl_for_type_insert): Likewise.
	* varasm.c (get_unnamed_section): Likewise.
	(get_noswitch_section): Likewise.
	(get_section): Likewise.
	(get_block_for_section): Likewise.
	(create_block_symbol): Likewise.
	(build_constant_desc): Likewise.
	(create_constant_pool): Likewise.
	(force_const_mem): Likewise.
	(record_tm_clone_pair): Likewise.
	* varpool.c (varpool_create_empty_node): Likewise.

gcc/c-family/ChangeLog:

	* c-common.h (sorted_fields_type): Remove variable_size GTY attribute.
	* c-pragma.c (push_alignment): Adjust.
	(handle_pragma_push_options): Likewise.

gcc/fortran/ChangeLog:

	* f95-lang.c (pushlevel): Adjust.
	* trans-decl.c (gfc_allocate_lang_decl): Likewise.
	(gfc_find_module): Likewise.
	* trans-types.c (gfc_get_nodesc_array_type): Likewise.
	(gfc_get_array_type_bounds): Likewise.
	(gfc_nonrestricted_type): Likewise.
	* trans.h: Don't use variable_size gty attribute.

gcc/c/ChangeLog:

	* c-decl.c (bind): Adjust.
	(record_inline_static): Likewise.
	(push_scope): Likewise.
	(make_label): Likewise.
	(lookup_label_for_goto): Likewise.
	(finish_struct): Likewise.
	(finish_enum): Likewise.
	(store_parm_decls): Likewise.
	(c_push_function_context): Likewise.
	* c-lang.h: Remove usage of variable_size gty attribute.
	* c-parser.c (c_parse_init): Adjust.
	(c_parse_file): Likewise.

gcc/lto/ChangeLog:

	* lto-tree.h: Don't use variable_size gty attribute.
	* lto.c (lto_read_in_decl_state): Adjust.
	(create_subid_section_table): Likewise.
	(lto_flatten_files): Likewise.
	(read_cgraph_and_symbols): Likewise.

gcc/java/ChangeLog:

	* class.c (add_method_1): Adjust.
	(java_treetreehash_new): Likewise.
	* constants.c (set_constant_entry): Likewise.
	(cpool_for_class): Likewise.
	* decl.c (make_binding_level): Likewise.
	(java_dup_lang_specific_decl): Likewise.
	* expr.c (add_type_assertion): Likewise.
	* java-tree.h (MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC): Likewise.
	(lang_decl): don't use variable_size gty attribute.
	(MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC): Adjust.
	(lang_type): Don't use variable_size gty attribute.
	* jcf-parse.c (java_parse_file): Adjust.
	(process_zip_dir): Likewise.
	* jcf.h: Remove usage of variable_size gty attribute.
---
 gcc/ada/gcc-interface/ada-tree.h    |  10 +--
 gcc/alias.c                         |   2 +-
 gcc/bitmap.c                        |   4 +-
 gcc/c-family/c-common.h             |   2 +-
 gcc/c-family/c-pragma.c             |   7 +-
 gcc/c/c-decl.c                      |  23 +++----
 gcc/c/c-lang.h                      |   4 +-
 gcc/c/c-parser.c                    |   4 +-
 gcc/cfg.c                           |  10 +--
 gcc/cfgloop.c                       |   8 +--
 gcc/cfgrtl.c                        |   2 +-
 gcc/cgraph.c                        |   8 +--
 gcc/cgraphclones.c                  |   2 +-
 gcc/cgraphunit.c                    |   4 +-
 gcc/config/i386/i386.c              |   6 +-
 gcc/coverage.c                      |   2 +-
 gcc/cp/cp-cilkplus.c                |   2 +-
 gcc/cp/cp-objcp-common.c            |   2 +-
 gcc/cp/cp-tree.h                    |   4 +-
 gcc/cp/decl.c                       |   8 +--
 gcc/cp/lex.c                        |   2 +-
 gcc/cp/name-lookup.c                |  14 ++--
 gcc/cp/parser.c                     |  14 ++--
 gcc/cp/pt.c                         |  10 +--
 gcc/cp/semantics.c                  |   4 +-
 gcc/cp/typeck2.c                    |   2 +-
 gcc/dbxout.c                        |   2 +-
 gcc/doc/gty.texi                    |  32 ---------
 gcc/dwarf2cfi.c                     |   8 +--
 gcc/dwarf2out.c                     |  44 ++++++-------
 gcc/emit-rtl.c                      |  10 +--
 gcc/except.c                        |  10 +--
 gcc/fortran/f95-lang.c              |   2 +-
 gcc/fortran/trans-decl.c            |   6 +-
 gcc/fortran/trans-types.c           |  15 ++---
 gcc/fortran/trans.h                 |   7 +-
 gcc/function.c                      |  18 ++---
 gcc/gengtype.c                      | 128 ------------------------------------
 gcc/ggc-common.c                    |   4 +-
 gcc/ggc.h                           |  31 +++++++--
 gcc/gimple.c                        |   9 +--
 gcc/go/go-lang.c                    |   2 +-
 gcc/ipa-cp.c                        |   6 +-
 gcc/ipa-devirt.c                    |   2 +-
 gcc/ipa-prop.c                      |   4 +-
 gcc/java/class.c                    |   6 +-
 gcc/java/constants.c                |   9 +--
 gcc/java/decl.c                     |   4 +-
 gcc/java/expr.c                     |   2 +-
 gcc/java/java-tree.h                |  15 ++---
 gcc/java/jcf-parse.c                |   6 +-
 gcc/java/jcf.h                      |   2 +-
 gcc/loop-iv.c                       |   2 +-
 gcc/lto-cgraph.c                    |   2 +-
 gcc/lto-section-in.c                |   2 +-
 gcc/lto-streamer-in.c               |   8 +--
 gcc/lto/lto-tree.h                  |   4 +-
 gcc/lto/lto.c                       |   8 +--
 gcc/objc/objc-act.c                 |   4 +-
 gcc/objc/objc-act.h                 |   4 +-
 gcc/objc/objc-map.c                 |  10 +--
 gcc/objc/objc-next-runtime-abi-02.c |   4 +-
 gcc/optabs.c                        |   4 +-
 gcc/passes.c                        |   2 +-
 gcc/rtl.h                           |   4 +-
 gcc/sese.c                          |   2 +-
 gcc/stringpool.c                    |   4 +-
 gcc/target-globals.c                |   4 +-
 gcc/toplev.c                        |   2 +-
 gcc/trans-mem.c                     |   4 +-
 gcc/tree-cfg.c                      |   2 +-
 gcc/tree-data-ref.h                 |   2 +-
 gcc/tree-eh.c                       |   2 +-
 gcc/tree-iterator.c                 |   4 +-
 gcc/tree-scalar-evolution.c         |   2 +-
 gcc/tree-ssa-loop-niter.c           |   2 +-
 gcc/tree-ssa-operands.h             |   2 +-
 gcc/tree-ssa.c                      |   2 +-
 gcc/tree-ssanames.c                 |   8 +--
 gcc/tree-streamer-in.c              |   4 +-
 gcc/tree.c                          |  14 ++--
 gcc/ubsan.c                         |   2 +-
 gcc/varasm.c                        |  16 ++---
 gcc/varpool.c                       |   2 +-
 84 files changed, 250 insertions(+), 432 deletions(-)

diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h
index 5ea386f..30f8ec4 100644
--- a/gcc/ada/gcc-interface/ada-tree.h
+++ b/gcc/ada/gcc-interface/ada-tree.h
@@ -32,13 +32,9 @@ union GTY((desc ("0"),
 		       desc ("tree_node_structure (&%h)"))) generic;
 };
 
-/* Ada uses the lang_decl and lang_type fields to hold a tree.
-
-   FIXME: the variable_size annotation here is needed because these types are
-   variable-sized in some other front-ends.  Due to gengtype deficiency, the
-   GTY options of such types have to agree across all front-ends.  */
-struct GTY((variable_size)) lang_type { tree t; };
-struct GTY((variable_size)) lang_decl { tree t; };
+/* Ada uses the lang_decl and lang_type fields to hold a tree.  */
+struct GTY(()) lang_type { tree t; };
+struct GTY(()) lang_decl { tree t; };
 
 /* Macros to get and set the tree in TYPE_LANG_SPECIFIC.  */
 #define GET_TYPE_LANG_SPECIFIC(NODE) \
diff --git a/gcc/alias.c b/gcc/alias.c
index 5f37402..bd45fcc 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -943,7 +943,7 @@ record_alias_subset (alias_set_type superset, alias_set_type subset)
     {
       /* Create an entry for the SUPERSET, so that we have a place to
 	 attach the SUBSET.  */
-      superset_entry = ggc_alloc_cleared_alias_set_entry_d ();
+      superset_entry = ggc_cleared_alloc<alias_set_entry_d> ();
       superset_entry->alias_set = superset;
       superset_entry->children
 	= splay_tree_new_ggc (splay_tree_compare_ints,
diff --git a/gcc/bitmap.c b/gcc/bitmap.c
index 4855a66..b2914e1 100644
--- a/gcc/bitmap.c
+++ b/gcc/bitmap.c
@@ -244,7 +244,7 @@ bitmap_element_allocate (bitmap head)
 	  /*  Inner list was just a singleton.  */
 	  bitmap_ggc_free = element->prev;
       else
-	element = ggc_alloc_bitmap_element ();
+	element = ggc_alloc<bitmap_element> ();
     }
 
   if (GATHER_STATISTICS)
@@ -388,7 +388,7 @@ bitmap_gc_alloc_stat (ALONE_MEM_STAT_DECL)
 {
   bitmap map;
 
-  map = ggc_alloc_bitmap_head ();
+  map = ggc_alloc<bitmap_head> ();
   bitmap_initialize_stat (map, NULL PASS_MEM_STAT);
 
   if (GATHER_STATISTICS)
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 57b7dce..d3b1099 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -440,7 +440,7 @@ extern GTY(()) tree c_global_trees[CTI_MAX];
 
 /* In a RECORD_TYPE, a sorted array of the fields of the type, not a
    tree for size reasons.  */
-struct GTY((variable_size)) sorted_fields_type {
+struct GTY(()) sorted_fields_type {
   int len;
   tree GTY((length ("%h.len"))) elts[1];
 };
diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
index 9e2a00e..7b016ab 100644
--- a/gcc/c-family/c-pragma.c
+++ b/gcc/c-family/c-pragma.c
@@ -74,9 +74,7 @@ static void pop_alignment (tree);
 static void
 push_alignment (int alignment, tree id)
 {
-  align_stack * entry;
-
-  entry = ggc_alloc_align_stack ();
+  align_stack * entry = ggc_alloc<align_stack> ();
 
   entry->alignment  = alignment;
   entry->id	    = id;
@@ -911,7 +909,6 @@ handle_pragma_push_options (cpp_reader *ARG_UNUSED(dummy))
 {
   enum cpp_ttype token;
   tree x = 0;
-  opt_stack *p;
 
   token = pragma_lex (&x);
   if (token != CPP_EOF)
@@ -920,7 +917,7 @@ handle_pragma_push_options (cpp_reader *ARG_UNUSED(dummy))
       return;
     }
 
-  p = ggc_alloc_opt_stack ();
+  opt_stack *p = ggc_alloc<opt_stack> ();
   p->prev = options_stack;
   options_stack = p;
 
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index e8b8166..2400849 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -638,7 +638,7 @@ bind (tree name, tree decl, struct c_scope *scope, bool invisible,
       binding_freelist = b->prev;
     }
   else
-    b = ggc_alloc_c_binding ();
+    b = ggc_alloc<c_binding> ();
 
   b->shadowed = 0;
   b->decl = decl;
@@ -755,7 +755,7 @@ void
 record_inline_static (location_t loc, tree func, tree decl,
 		      enum c_inline_static_type type)
 {
-  struct c_inline_static *csi = ggc_alloc_c_inline_static ();
+  c_inline_static *csi = ggc_alloc<c_inline_static> ();
   csi->location = loc;
   csi->function = func;
   csi->static_decl = decl;
@@ -952,7 +952,7 @@ push_scope (void)
 	  scope_freelist = scope->outer;
 	}
       else
-	scope = ggc_alloc_cleared_c_scope ();
+	scope = ggc_cleared_alloc<c_scope> ();
 
       /* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes.  */
       if (current_scope)
@@ -3084,12 +3084,10 @@ make_label (location_t location, tree name, bool defining,
 	    struct c_label_vars **p_label_vars)
 {
   tree label = build_decl (location, LABEL_DECL, name, void_type_node);
-  struct c_label_vars *label_vars;
-
   DECL_CONTEXT (label) = current_function_decl;
   DECL_MODE (label) = VOIDmode;
 
-  label_vars = ggc_alloc_c_label_vars ();
+  c_label_vars *label_vars = ggc_alloc<c_label_vars> ();
   label_vars->shadowed = NULL;
   set_spot_bindings (&label_vars->label_bindings, defining);
   label_vars->decls_in_scope = make_tree_vector ();
@@ -3185,9 +3183,8 @@ lookup_label_for_goto (location_t loc, tree name)
      list for possible later warnings.  */
   if (label_vars->label_bindings.scope == NULL)
     {
-      struct c_goto_bindings *g;
+      c_goto_bindings *g = ggc_alloc<c_goto_bindings> ();
 
-      g = ggc_alloc_c_goto_bindings ();
       g->loc = loc;
       set_spot_bindings (&g->goto_bindings, true);
       vec_safe_push (label_vars->gotos, g);
@@ -7423,8 +7420,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
 	  ensure that this lives as long as the rest of the struct decl.
 	  All decls in an inline function need to be saved.  */
 
-	space = (struct lang_type *) ggc_internal_cleared_alloc
-	  (sizeof (struct lang_type));
+	space = ggc_cleared_alloc<struct lang_type> ();
 	space2 = (sorted_fields_type *) ggc_internal_alloc
 	  (sizeof (struct sorted_fields_type) + len * sizeof (tree));
 
@@ -7705,8 +7701,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
 
   /* Record the min/max values so that we can warn about bit-field
      enumerations that are too small for the values.  */
-  lt = (struct lang_type *) ggc_internal_cleared_alloc
-    (sizeof (struct lang_type));
+  lt = ggc_cleared_alloc<struct lang_type> ();
   lt->enum_min = minnode;
   lt->enum_max = maxnode;
   TYPE_LANG_SPECIFIC (enumtype) = lt;
@@ -8477,7 +8472,7 @@ store_parm_decls (void)
   allocate_struct_function (fndecl, false);
 
   if (warn_unused_local_typedefs)
-    cfun->language = ggc_alloc_cleared_language_function ();
+    cfun->language = ggc_cleared_alloc<language_function> ();
 
   /* Begin the statement tree for this function.  */
   DECL_SAVED_TREE (fndecl) = push_stmt_list ();
@@ -8801,7 +8796,7 @@ c_push_function_context (void)
   /* cfun->language might have been already allocated by the use of
      -Wunused-local-typedefs.  In that case, just re-use it.  */
   if (p == NULL)
-    cfun->language = p = ggc_alloc_cleared_language_function ();
+    cfun->language = p = ggc_cleared_alloc<language_function> ();
 
   p->base.x_stmt_tree = c_stmt_tree;
   c_stmt_tree.x_cur_stmt_list = vec_safe_copy (c_stmt_tree.x_cur_stmt_list);
diff --git a/gcc/c/c-lang.h b/gcc/c/c-lang.h
index 7fcf333..e974906 100644
--- a/gcc/c/c-lang.h
+++ b/gcc/c/c-lang.h
@@ -23,7 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "c-family/c-common.h"
 #include "ggc.h"
 
-struct GTY((variable_size)) lang_type {
+struct GTY(()) lang_type {
   /* In a RECORD_TYPE, a sorted array of the fields of the type.  */
   struct sorted_fields_type * GTY ((reorder ("resort_sorted_fields"))) s;
   /* In an ENUMERAL_TYPE, the min and max values.  */
@@ -35,7 +35,7 @@ struct GTY((variable_size)) lang_type {
   tree objc_info;
 };
 
-struct GTY((variable_size)) lang_decl {
+struct GTY(()) lang_decl {
   char dummy;
 };
 
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 56f79f6..2843e9d 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -90,7 +90,7 @@ c_parse_init (void)
   if (!c_dialect_objc ())
     mask |= D_OBJC | D_CXX_OBJC;
 
-  ridpointers = ggc_alloc_cleared_vec_tree ((int) RID_MAX);
+  ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX);
   for (i = 0; i < num_c_common_reswords; i++)
     {
       /* If a keyword is disabled, do not enter it into the table
@@ -14039,7 +14039,7 @@ c_parse_file (void)
   if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
     c_parser_pragma_pch_preprocess (&tparser);
 
-  the_parser = ggc_alloc_c_parser ();
+  the_parser = ggc_alloc<c_parser> ();
   *the_parser = tparser;
   if (tparser.tokens == &tparser.tokens_buf[0])
     the_parser->tokens = &the_parser->tokens_buf[0];
diff --git a/gcc/cfg.c b/gcc/cfg.c
index 3b6349a..aef1145 100644
--- a/gcc/cfg.c
+++ b/gcc/cfg.c
@@ -68,13 +68,13 @@ void
 init_flow (struct function *the_fun)
 {
   if (!the_fun->cfg)
-    the_fun->cfg = ggc_alloc_cleared_control_flow_graph ();
+    the_fun->cfg = ggc_cleared_alloc<control_flow_graph> ();
   n_edges_for_fn (the_fun) = 0;
   ENTRY_BLOCK_PTR_FOR_FN (the_fun)
-    = ggc_alloc_cleared_basic_block_def ();
+    = ggc_cleared_alloc<basic_block_def> ();
   ENTRY_BLOCK_PTR_FOR_FN (the_fun)->index = ENTRY_BLOCK;
   EXIT_BLOCK_PTR_FOR_FN (the_fun)
-    = ggc_alloc_cleared_basic_block_def ();
+    = ggc_cleared_alloc<basic_block_def> ();
   EXIT_BLOCK_PTR_FOR_FN (the_fun)->index = EXIT_BLOCK;
   ENTRY_BLOCK_PTR_FOR_FN (the_fun)->next_bb
     = EXIT_BLOCK_PTR_FOR_FN (the_fun);
@@ -123,7 +123,7 @@ basic_block
 alloc_block (void)
 {
   basic_block bb;
-  bb = ggc_alloc_cleared_basic_block_def ();
+  bb = ggc_cleared_alloc<basic_block_def> ();
   return bb;
 }
 
@@ -261,7 +261,7 @@ edge
 unchecked_make_edge (basic_block src, basic_block dst, int flags)
 {
   edge e;
-  e = ggc_alloc_cleared_edge_def ();
+  e = ggc_cleared_alloc<edge_def> ();
   n_edges_for_fn (cfun)++;
 
   e->src = src;
diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
index 70744d8..3ff5b6a 100644
--- a/gcc/cfgloop.c
+++ b/gcc/cfgloop.c
@@ -331,9 +331,9 @@ flow_loop_tree_node_remove (struct loop *loop)
 struct loop *
 alloc_loop (void)
 {
-  struct loop *loop = ggc_alloc_cleared_loop ();
+  struct loop *loop = ggc_cleared_alloc<struct loop> ();
 
-  loop->exits = ggc_alloc_cleared_loop_exit ();
+  loop->exits = ggc_cleared_alloc<loop_exit> ();
   loop->exits->next = loop->exits->prev = loop->exits;
   loop->can_be_parallel = false;
 
@@ -414,7 +414,7 @@ flow_loops_find (struct loops *loops)
 
   if (!loops)
     {
-      loops = ggc_alloc_cleared_loops ();
+      loops = ggc_cleared_alloc<struct loops> ();
       init_loops_structure (cfun, loops, 1);
     }
 
@@ -1028,7 +1028,7 @@ rescan_loop_exit (edge e, bool new_edge, bool removed)
 	   aloop != cloop;
 	   aloop = loop_outer (aloop))
 	{
-	  exit = ggc_alloc_loop_exit ();
+	  exit = ggc_alloc<loop_exit> ();
 	  exit->e = e;
 
 	  exit->next = aloop->exits->next;
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 5dd27d2..06fc43e 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -4954,7 +4954,7 @@ init_rtl_bb_info (basic_block bb)
 {
   gcc_assert (!bb->il.x.rtl);
   bb->il.x.head_ = NULL;
-  bb->il.x.rtl = ggc_alloc_cleared_rtl_bb_info ();
+  bb->il.x.rtl = ggc_cleared_alloc<rtl_bb_info> ();
 }
 
 /* Returns true if it is possible to remove edge E by redirecting
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index ee192ed..f28492e 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -198,7 +198,7 @@ insert_new_cgraph_node_version (struct cgraph_node *node)
   void **slot;
   
   version_info_node = NULL;
-  version_info_node = ggc_alloc_cleared_cgraph_function_version_info ();
+  version_info_node = ggc_cleared_alloc<cgraph_function_version_info> ();
   version_info_node->this_node = node;
 
   if (cgraph_fnver_htab == NULL)
@@ -507,7 +507,7 @@ cgraph_allocate_node (void)
     }
   else
     {
-      node = ggc_alloc_cleared_cgraph_node ();
+      node = ggc_cleared_alloc<cgraph_node> ();
       node->uid = cgraph_max_uid++;
     }
 
@@ -866,7 +866,7 @@ cgraph_create_edge_1 (struct cgraph_node *caller, struct cgraph_node *callee,
     }
   else
     {
-      edge = ggc_alloc_cgraph_edge ();
+      edge = ggc_alloc<struct cgraph_edge> ();
       edge->uid = cgraph_edge_max_uid++;
     }
 
@@ -938,7 +938,7 @@ cgraph_allocate_init_indirect_info (void)
 {
   struct cgraph_indirect_call_info *ii;
 
-  ii = ggc_alloc_cleared_cgraph_indirect_call_info ();
+  ii = ggc_cleared_alloc<cgraph_indirect_call_info> ();
   ii->param_index = -1;
   return ii;
 }
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index 48b5379..d61e0f7 100644
--- a/gcc/cgraphclones.c
+++ b/gcc/cgraphclones.c
@@ -146,7 +146,7 @@ cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n,
       if (e->indirect_info)
 	{
 	  new_edge->indirect_info
-	    = ggc_alloc_cleared_cgraph_indirect_call_info ();
+	    = ggc_cleared_alloc<cgraph_indirect_call_info> ();
 	  *new_edge->indirect_info = *e->indirect_info;
 	}
     }
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 7bf9a07..acb9a7a 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -570,7 +570,7 @@ add_asm_node (tree asm_str)
 {
   struct asm_node *node;
 
-  node = ggc_alloc_cleared_asm_node ();
+  node = ggc_cleared_alloc<asm_node> ();
   node->asm_str = asm_str;
   node->order = symtab_order++;
   node->next = NULL;
@@ -1337,7 +1337,7 @@ init_lowered_empty_function (tree decl, bool in_ssa)
   cfun->curr_properties |= (PROP_gimple_lcf | PROP_gimple_leh | PROP_gimple_any
 			    | PROP_cfg | PROP_loops);
 
-  set_loops_for_fn (cfun, ggc_alloc_cleared_loops ());
+  set_loops_for_fn (cfun, ggc_cleared_alloc<loops> ());
   init_loops_structure (cfun, loops_for_fn (cfun), 1);
   loops_for_fn (cfun)->state |= LOOPS_MAY_HAVE_MULTIPLE_LATCHES;
 
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 895ebbb..848788e 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -13643,7 +13643,7 @@ get_dllimport_decl (tree decl, bool beimport)
   if (h)
     return h->to;
 
-  *loc = h = ggc_alloc_tree_map ();
+  *loc = h = ggc_alloc<tree_map> ();
   h->hash = in.hash;
   h->base.from = decl;
   h->to = to = build_decl (DECL_SOURCE_LOCATION (decl),
@@ -24990,7 +24990,7 @@ ix86_init_machine_status (void)
 {
   struct machine_function *f;
 
-  f = ggc_alloc_cleared_machine_function ();
+  f = ggc_cleared_alloc<machine_function> ();
   f->use_fast_prologue_epilogue_nregs = -1;
   f->call_abi = ix86_abi;
 
@@ -25014,7 +25014,7 @@ assign_386_stack_local (enum machine_mode mode, enum ix86_stack_slot n)
     if (s->mode == mode && s->n == n)
       return validize_mem (copy_rtx (s->rtl));
 
-  s = ggc_alloc_stack_local_entry ();
+  s = ggc_alloc<stack_local_entry> ();
   s->n = n;
   s->mode = mode;
   s->rtl = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
diff --git a/gcc/coverage.c b/gcc/coverage.c
index ff1e67d..5e9005e 100644
--- a/gcc/coverage.c
+++ b/gcc/coverage.c
@@ -667,7 +667,7 @@ coverage_end_function (unsigned lineno_checksum, unsigned cfg_checksum)
 	 list.  */
       if (!DECL_EXTERNAL (current_function_decl))
 	{
-	  item = ggc_alloc_coverage_data ();
+	  item = ggc_alloc<coverage_data> ();
 	  
 	  item->ident = current_function_funcdef_no + 1;
 	  item->lineno_checksum = lineno_checksum;
diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c
index f3a2aff..daa9b8e 100644
--- a/gcc/cp/cp-cilkplus.c
+++ b/gcc/cp/cp-cilkplus.c
@@ -118,7 +118,7 @@ cilk_install_body_with_frame_cleanup (tree fndecl, tree orig_body, void *wd)
   tree dtor = create_cilk_function_exit (frame, false, false);
   add_local_decl (cfun, frame);
 
-  cfun->language = ggc_alloc_cleared_language_function ();
+  cfun->language = ggc_cleared_alloc<language_function> ();
   
   location_t loc = EXPR_LOCATION (orig_body);
   tree list = alloc_stmt_list ();
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index aa0ff83..78dddef 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -208,7 +208,7 @@ decl_shadowed_for_var_insert (tree from, tree to)
   struct tree_decl_map *h;
   void **loc;
 
-  h = ggc_alloc_tree_decl_map ();
+  h = ggc_alloc<tree_decl_map> ();
   h->base.from = from;
   h->to = to;
   loc = htab_find_slot_with_hash (shadowed_var_for_decl, h, DECL_UID (from),
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 9fbc7f8..b76af3c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1482,7 +1482,7 @@ struct GTY(()) lang_type_ptrmem {
   tree record;
 };
 
-struct GTY((variable_size)) lang_type {
+struct GTY(()) lang_type {
   union lang_type_u
   {
     struct lang_type_header GTY((skip (""))) h;
@@ -2060,7 +2060,7 @@ struct GTY(()) lang_decl_parm {
    union rather than a struct containing a union as its only field, but
    tree.h declares it as a struct.  */
 
-struct GTY((variable_size)) lang_decl {
+struct GTY(()) lang_decl {
   union GTY((desc ("%h.base.selector"))) lang_decl_u {
     struct lang_decl_base GTY ((default)) base;
     struct lang_decl_min GTY((tag ("0"))) min;
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 7ce55c8..4ad6f16 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2700,7 +2700,7 @@ make_label_decl (tree id, int local_p)
   /* Record this label on the list of labels used in this function.
      We do this before calling make_label_decl so that we get the
      IDENTIFIER_LABEL_VALUE before the new label is declared.  */
-  ent = ggc_alloc_cleared_named_label_entry ();
+  ent = ggc_cleared_alloc<named_label_entry> ();
   ent->label_decl = decl;
 
   slot = htab_find_slot (named_labels, ent, INSERT);
@@ -2931,7 +2931,7 @@ check_goto (tree decl)
 	  && ent->uses->names_in_scope == current_binding_level->names)
 	return;
 
-      new_use = ggc_alloc_named_label_use_entry ();
+      new_use = ggc_alloc<named_label_use_entry> ();
       new_use->binding_level = current_binding_level;
       new_use->names_in_scope = current_binding_level->names;
       new_use->o_goto_locus = input_location;
@@ -13301,7 +13301,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
 
   /* Initialize the language data structures.  Whenever we start
      a new function, we destroy temporaries in the usual way.  */
-  cfun->language = ggc_alloc_cleared_language_function ();
+  cfun->language = ggc_cleared_alloc<language_function> ();
   current_stmt_tree ()->stmts_are_full_exprs_p = 1;
   current_binding_level = bl;
 
@@ -13603,7 +13603,7 @@ save_function_data (tree decl)
   gcc_assert (!DECL_PENDING_INLINE_P (decl));
 
   /* Make a copy.  */
-  f = ggc_alloc_language_function ();
+  f = ggc_alloc<language_function> ();
   memcpy (f, cp_function_chain, sizeof (struct language_function));
   DECL_SAVED_FUNCTION_DATA (decl) = f;
 
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 46c28ae..57b779d 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -182,7 +182,7 @@ init_reswords (void)
   /* The Objective-C keywords are all context-dependent.  */
   mask |= D_OBJC;
 
-  ridpointers = ggc_alloc_cleared_vec_tree ((int) RID_MAX);
+  ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX);
   for (i = 0; i < num_c_common_reswords; i++)
     {
       if (c_common_reswords[i].disable & D_CONLY)
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index d900560..2baeeb7 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -105,7 +105,7 @@ binding_entry_make (tree name, tree type)
       free_binding_entry = entry->chain;
     }
   else
-    entry = ggc_alloc_binding_entry_s ();
+    entry = ggc_alloc<binding_entry_s> ();
 
   entry->name = name;
   entry->type = type;
@@ -147,7 +147,7 @@ binding_table_construct (binding_table table, size_t chain_count)
 {
   table->chain_count = chain_count;
   table->entry_count = 0;
-  table->chain = ggc_alloc_cleared_vec_binding_entry (table->chain_count);
+  table->chain = ggc_cleared_vec_alloc<binding_entry> (table->chain_count);
 }
 
 /* Make TABLE's entries ready for reuse.  */
@@ -181,7 +181,7 @@ binding_table_free (binding_table table)
 static inline binding_table
 binding_table_new (size_t chain_count)
 {
-  binding_table table = ggc_alloc_binding_table_s ();
+  binding_table table = ggc_alloc<binding_table_s> ();
   table->chain = NULL;
   binding_table_construct (table, chain_count);
   return table;
@@ -299,7 +299,7 @@ cxx_binding_make (tree value, tree type)
       free_bindings = binding->previous;
     }
   else
-    binding = ggc_alloc_cxx_binding ();
+    binding = ggc_alloc<cxx_binding> ();
 
   cxx_binding_init (binding, value, type);
 
@@ -775,7 +775,7 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
 		      = htab_create_ggc (20, cxx_int_tree_map_hash,
 					 cxx_int_tree_map_eq, NULL);
 
-		  h = ggc_alloc_cxx_int_tree_map ();
+		  h = ggc_alloc<cxx_int_tree_map> ();
 		  h->uid = DECL_UID (x);
 		  h->to = t;
 		  loc = htab_find_slot_with_hash
@@ -1544,7 +1544,7 @@ begin_scope (scope_kind kind, tree entity)
       free_binding_level = scope->level_chain;
     }
   else
-    scope = ggc_alloc_cleared_cp_binding_level ();
+    scope = ggc_cleared_alloc<cp_binding_level> ();
 
   scope->this_entity = entity;
   scope->more_cleanups_ok = true;
@@ -6074,7 +6074,7 @@ push_to_top_level (void)
   bool need_pop;
 
   bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
-  s = ggc_alloc_cleared_saved_scope ();
+  s = ggc_cleared_alloc<saved_scope> ();
 
   b = scope_chain ? current_binding_level : 0;
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c1d94ae..a2f9355 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -602,7 +602,7 @@ cp_lexer_alloc (void)
   c_common_no_more_pch ();
 
   /* Allocate the memory.  */
-  lexer = ggc_alloc_cleared_cp_lexer ();
+  lexer = ggc_cleared_alloc<cp_lexer> ();
 
   /* Initially we are not debugging.  */
   lexer->debugging_p = false;
@@ -665,7 +665,7 @@ cp_lexer_new_from_tokens (cp_token_cache *cache)
 {
   cp_token *first = cache->first;
   cp_token *last = cache->last;
-  cp_lexer *lexer = ggc_alloc_cleared_cp_lexer ();
+  cp_lexer *lexer = ggc_cleared_alloc<cp_lexer> ();
 
   /* We do not own the buffer.  */
   lexer->buffer = NULL;
@@ -1240,7 +1240,7 @@ cp_lexer_stop_debugging (cp_lexer* lexer)
 static cp_token_cache *
 cp_token_cache_new (cp_token *first, cp_token *last)
 {
-  cp_token_cache *cache = ggc_alloc_cp_token_cache ();
+  cp_token_cache *cache = ggc_alloc<cp_token_cache> ();
   cache->first = first;
   cache->last = last;
   return cache;
@@ -1822,7 +1822,7 @@ cp_parser_context_new (cp_parser_context* next)
       memset (context, 0, sizeof (*context));
     }
   else
-    context = ggc_alloc_cleared_cp_parser_context ();
+    context = ggc_cleared_alloc<cp_parser_context> ();
 
   /* No errors have occurred yet in this context.  */
   context->status = CP_PARSER_STATUS_KIND_NO_ERROR;
@@ -3411,7 +3411,7 @@ cp_parser_new (void)
   for (i = 0; i < sizeof (binops) / sizeof (binops[0]); i++)
     binops_by_token[binops[i].token_type] = binops[i];
 
-  parser = ggc_alloc_cleared_cp_parser ();
+  parser = ggc_cleared_alloc<cp_parser> ();
   parser->lexer = lexer;
   parser->context = cp_parser_context_new (NULL);
 
@@ -5425,7 +5425,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
       token->type = CPP_NESTED_NAME_SPECIFIER;
       /* Retrieve any deferred checks.  Do not pop this access checks yet
 	 so the memory will not be reclaimed during token replacing below.  */
-      token->u.tree_check_value = ggc_alloc_cleared_tree_check ();
+      token->u.tree_check_value = ggc_cleared_alloc<struct tree_check> ();
       token->u.tree_check_value->value = parser->scope;
       token->u.tree_check_value->checks = get_deferred_access_checks ();
       token->u.tree_check_value->qualifying_scope =
@@ -13500,7 +13500,7 @@ cp_parser_template_id (cp_parser *parser,
       token->type = CPP_TEMPLATE_ID;
       /* Retrieve any deferred checks.  Do not pop this access checks yet
 	 so the memory will not be reclaimed during token replacing below.  */
-      token->u.tree_check_value = ggc_alloc_cleared_tree_check ();
+      token->u.tree_check_value = ggc_cleared_alloc<struct tree_check> ();
       token->u.tree_check_value->value = template_id;
       token->u.tree_check_value->checks = get_deferred_access_checks ();
       token->keyword = RID_MAX;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index c74e7ae..b1e6c14 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -940,7 +940,7 @@ maybe_process_partial_specialization (tree type)
 		  elt.args = INNERMOST_TEMPLATE_ARGS (elt.args);
 
 		  slot = htab_find_slot (type_specializations, &elt, INSERT);
-		  entry = ggc_alloc_spec_entry ();
+		  entry = ggc_alloc<spec_entry> ();
 		  *entry = elt;
 		  *slot = entry;
 		}
@@ -1477,7 +1477,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
 
   if (slot != NULL /* !optimize_specialization_lookup_p (tmpl) */)
     {
-      spec_entry *entry = ggc_alloc_spec_entry ();
+      spec_entry *entry = ggc_alloc<spec_entry> ();
       gcc_assert (tmpl && args && spec);
       *entry = elt;
       *slot = entry;
@@ -7177,7 +7177,7 @@ add_pending_template (tree d)
   if (level)
     push_tinst_level (d);
 
-  pt = ggc_alloc_pending_template ();
+  pt = ggc_alloc<pending_template> ();
   pt->next = NULL;
   pt->tinst = current_tinst_level;
   if (last_pending_template)
@@ -7807,7 +7807,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
       elt.spec = t;
       slot = htab_find_slot_with_hash (type_specializations,
 				       &elt, hash, INSERT);
-      entry = ggc_alloc_spec_entry ();
+      entry = ggc_alloc<spec_entry> ();
       *entry = elt;
       *slot = entry;
 
@@ -8232,7 +8232,7 @@ push_tinst_level (tree d)
   if (limit_bad_template_recursion (d))
     return 0;
 
-  new_level = ggc_alloc_tinst_level ();
+  new_level = ggc_alloc<tinst_level> ();
   new_level->decl = d;
   new_level->locus = input_location;
   new_level->errors = errorcount+sorrycount;
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 3f8ca44..a8b8dab 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -8024,7 +8024,7 @@ register_constexpr_fundef (tree fun, tree body)
     htab_find_slot (constexpr_fundef_table, &entry, INSERT);
 
   gcc_assert (*slot == NULL);
-  *slot = ggc_alloc_constexpr_fundef ();
+  *slot = ggc_alloc<constexpr_fundef> ();
   **slot = entry;
 
   return fun;
@@ -8465,7 +8465,7 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
     {
       /* We need to keep a pointer to the entry, not just the slot, as the
 	 slot can move in the call to cxx_eval_builtin_function_call.  */
-      *slot = entry = ggc_alloc_constexpr_call ();
+      *slot = entry = ggc_alloc<constexpr_call> ();
       *entry = new_call;
     }
   /* Calls which are in progress have their result set to NULL
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 68e518a..b7fa77b 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -293,7 +293,7 @@ abstract_virtuals_error_sfinae (tree decl, tree type, abstract_class_use use,
       slot = htab_find_slot_with_hash (abstract_pending_vars, type,
 				      (hashval_t)TYPE_UID (type), INSERT);
 
-      pat = ggc_alloc_pending_abstract_type ();
+      pat = ggc_alloc<pending_abstract_type> ();
       pat->type = type;
       pat->decl = decl;
       pat->use = use;
diff --git a/gcc/dbxout.c b/gcc/dbxout.c
index 5fbbdf6..0fe9bfe 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -1025,7 +1025,7 @@ dbxout_init (const char *input_file_name)
   const char *mapped_name;
 
   typevec_len = 100;
-  typevec = ggc_alloc_cleared_vec_typeinfo (typevec_len);
+  typevec = ggc_cleared_vec_alloc<typeinfo> (typevec_len);
 
   /* stabstr_ob contains one string, which will be just fine with
      1-byte alignment.  */
diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi
index d32ac00..e50eef6 100644
--- a/gcc/doc/gty.texi
+++ b/gcc/doc/gty.texi
@@ -382,38 +382,6 @@ of pointers.  @code{reorder} functions can be expensive.  When
 possible, it is better to depend on properties of the data, like an ID
 number or the hash of a string instead.
 
-@findex variable_size
-@item variable_size
-
-The type machinery expects the types to be of constant size.  When this
-is not true, for example, with structs that have array fields or unions,
-the type machinery cannot tell how many bytes need to be allocated at
-each allocation.  The @code{variable_size} is used to mark such types.
-The type machinery then provides allocators that take a parameter
-indicating an exact size of object being allocated.  Note that the size
-must be provided in bytes whereas the @code{length} option works with
-array lengths in number of elements.
-
-For example,
-@smallexample
-struct GTY((variable_size)) sorted_fields_type @{
-  int len;
-  tree GTY((length ("%h.len"))) elts[1];
-@};
-@end smallexample
-
-Then the objects of @code{struct sorted_fields_type} are allocated in GC
-memory as follows:
-@smallexample
-  field_vec = ggc_alloc_sorted_fields_type (size);
-@end smallexample
-
-If @var{field_vec->elts} stores @var{n} elements, then @var{size}
-could be calculated as follows:
-@smallexample
-  size_t size = sizeof (struct sorted_fields_type) + n * sizeof (tree);
-@end smallexample
-
 @findex atomic
 @item atomic
 
diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index 4180890..47fd028 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -356,7 +356,7 @@ need_data_align_sf_opcode (HOST_WIDE_INT off)
 static inline dw_cfi_ref
 new_cfi (void)
 {
-  dw_cfi_ref cfi = ggc_alloc_dw_cfi_node ();
+  dw_cfi_ref cfi = ggc_alloc<dw_cfi_node> ();
 
   cfi->dw_cfi_oprnd1.dw_cfi_reg_num = 0;
   cfi->dw_cfi_oprnd2.dw_cfi_reg_num = 0;
@@ -369,7 +369,7 @@ new_cfi (void)
 static dw_cfi_row *
 new_cfi_row (void)
 {
-  dw_cfi_row *row = ggc_alloc_cleared_dw_cfi_row ();
+  dw_cfi_row *row = ggc_cleared_alloc<dw_cfi_row> ();
 
   row->cfa.reg = INVALID_REGNUM;
 
@@ -381,7 +381,7 @@ new_cfi_row (void)
 static dw_cfi_row *
 copy_cfi_row (dw_cfi_row *src)
 {
-  dw_cfi_row *dst = ggc_alloc_dw_cfi_row ();
+  dw_cfi_row *dst = ggc_alloc<dw_cfi_row> ();
 
   *dst = *src;
   dst->reg_save = vec_safe_copy (src->reg_save);
@@ -2892,7 +2892,7 @@ create_cie_data (void)
 	case 0:
 	  break;
 	case 1:
-	  cie_return_save = ggc_alloc_reg_saved_in_data ();
+	  cie_return_save = ggc_alloc<reg_saved_in_data> ();
 	  *cie_return_save = cie_trace.regs_saved_in_regs[0];
 	  cie_trace.regs_saved_in_regs.release ();
 	  break;
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 6133fa3..9e99e46 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -982,7 +982,7 @@ dwarf2out_alloc_current_fde (void)
 {
   dw_fde_ref fde;
 
-  fde = ggc_alloc_cleared_dw_fde_node ();
+  fde = ggc_cleared_alloc<dw_fde_node> ();
   fde->decl = current_function_decl;
   fde->funcdef_number = current_function_funcdef_no;
   fde->fde_index = vec_safe_length (fde_vec);
@@ -1305,7 +1305,7 @@ static inline dw_loc_descr_ref
 new_loc_descr (enum dwarf_location_atom op, unsigned HOST_WIDE_INT oprnd1,
 	       unsigned HOST_WIDE_INT oprnd2)
 {
-  dw_loc_descr_ref descr = ggc_alloc_cleared_dw_loc_descr_node ();
+  dw_loc_descr_ref descr = ggc_cleared_alloc<dw_loc_descr_node> ();
 
   descr->dw_loc_opc = op;
   descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const;
@@ -3872,7 +3872,7 @@ find_AT_string_in_table (const char *str, htab_t table)
 				   htab_hash_string (str), INSERT);
   if (*slot == NULL)
     {
-      node = ggc_alloc_cleared_indirect_string_node ();
+      node = ggc_cleared_alloc<indirect_string_node> ();
       node->str = ggc_strdup (str);
       *slot = node;
     }
@@ -4203,7 +4203,7 @@ add_addr_table_entry (void *addr, enum ate_kind kind)
 
   if (*slot == HTAB_EMPTY_ENTRY)
     {
-      node = ggc_alloc_cleared_addr_table_entry ();
+      node = ggc_cleared_alloc<addr_table_entry> ();
       init_addr_table_entry (node, kind, addr);
       *slot = node;
     }
@@ -4779,7 +4779,7 @@ splice_child_die (dw_die_ref parent, dw_die_ref child)
 static inline dw_die_ref
 new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
 {
-  dw_die_ref die = ggc_alloc_cleared_die_node ();
+  dw_die_ref die = ggc_cleared_alloc<die_node> ();
 
   die->die_tag = tag_value;
 
@@ -4789,7 +4789,7 @@ new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
     {
       limbo_die_node *limbo_node;
 
-      limbo_node = ggc_alloc_cleared_limbo_die_node ();
+      limbo_node = ggc_cleared_alloc<limbo_die_node> ();
       limbo_node->die = die;
       limbo_node->created_for = t;
       limbo_node->next = limbo_die_list;
@@ -5106,7 +5106,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
   slot = htab_find_slot_with_hash (decl_loc_table, decl, decl_id, INSERT);
   if (*slot == NULL)
     {
-      temp = ggc_alloc_cleared_var_loc_list ();
+      temp = ggc_cleared_alloc<var_loc_list> ();
       temp->decl_id = decl_id;
       *slot = temp;
     }
@@ -5131,7 +5131,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
 	  || (NOTE_VAR_LOCATION_STATUS (temp->first->loc)
 	      != NOTE_VAR_LOCATION_STATUS (loc_note))))
     {
-      loc = ggc_alloc_cleared_var_loc_node ();
+      loc = ggc_cleared_alloc<var_loc_node> ();
       temp->first->next = loc;
       temp->last = loc;
       loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
@@ -5221,7 +5221,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
 	      memset (loc, '\0', sizeof (*loc));
 	    }
 	  else
-	    loc = ggc_alloc_cleared_var_loc_node ();
+	    loc = ggc_cleared_alloc<var_loc_node> ();
 	  if (bitsize == -1 || piece_loc == NULL)
 	    loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
 	  else
@@ -5238,7 +5238,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
     }
   else
     {
-      loc = ggc_alloc_cleared_var_loc_node ();
+      loc = ggc_cleared_alloc<var_loc_node> ();
       temp->first = loc;
       temp->last = loc;
       loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
@@ -6868,7 +6868,7 @@ clone_die (dw_die_ref die)
   dw_attr_ref a;
   unsigned ix;
 
-  clone = ggc_alloc_cleared_die_node ();
+  clone = ggc_cleared_alloc<die_node> ();
   clone->die_tag = die->die_tag;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -6914,7 +6914,7 @@ clone_as_declaration (dw_die_ref die)
       return clone;
     }
 
-  clone = ggc_alloc_cleared_die_node ();
+  clone = ggc_cleared_alloc<die_node> ();
   clone->die_tag = die->die_tag;
 
   FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
@@ -7274,7 +7274,7 @@ break_out_comdat_types (dw_die_ref die)
         unit = new_die (DW_TAG_type_unit, NULL, NULL);
         add_AT_unsigned (unit, DW_AT_language,
                          get_AT_unsigned (comp_unit_die (), DW_AT_language));
-        type_node = ggc_alloc_cleared_comdat_type_node ();
+        type_node = ggc_cleared_alloc<comdat_type_node> ();
         type_node->root_die = unit;
         type_node->next = comdat_type_list;
         comdat_type_list = type_node;
@@ -8347,7 +8347,7 @@ static inline dw_loc_list_ref
 new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end,
 	      const char *section)
 {
-  dw_loc_list_ref retlist = ggc_alloc_cleared_dw_loc_list_node ();
+  dw_loc_list_ref retlist = ggc_cleared_alloc<dw_loc_list_node> ();
 
   retlist->begin = begin;
   retlist->begin_entry = NULL;
@@ -13891,12 +13891,12 @@ add_loc_descr_to_each (dw_loc_list_ref list, dw_loc_descr_ref ref)
   list = list->dw_loc_next;
   while (list)
     {
-      copy = ggc_alloc_dw_loc_descr_node ();
+      copy = ggc_alloc<dw_loc_descr_node> ();
       memcpy (copy, ref, sizeof (dw_loc_descr_node));
       add_loc_descr (&list->expr, copy);
       while (copy->dw_loc_next)
 	{
-	  dw_loc_descr_ref new_copy = ggc_alloc_dw_loc_descr_node ();
+	  dw_loc_descr_ref new_copy = ggc_alloc<dw_loc_descr_node> ();
 	  memcpy (new_copy, copy->dw_loc_next, sizeof (dw_loc_descr_node));
 	  copy->dw_loc_next = new_copy;
 	  copy = new_copy;
@@ -15678,7 +15678,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
 	{
 	  slot = htab_find_slot_with_hash (cached_dw_loc_list_table, decl,
 					   DECL_UID (decl), INSERT);
-	  cache = ggc_alloc_cleared_cached_dw_loc_list ();
+	  cache = ggc_cleared_alloc<cached_dw_loc_list> ();
 	  cache->decl_id = DECL_UID (decl);
 	  cache->loc_list = list;
 	  *slot = cache;
@@ -16639,7 +16639,7 @@ add_linkage_name (dw_die_ref die, tree decl)
 	{
 	  limbo_die_node *asm_name;
 
-	  asm_name = ggc_alloc_cleared_limbo_die_node ();
+	  asm_name = ggc_cleared_alloc<limbo_die_node> ();
 	  asm_name->die = die;
 	  asm_name->created_for = decl;
 	  asm_name->next = deferred_asm_name;
@@ -20968,7 +20968,7 @@ lookup_filename (const char *file_name)
   if (*slot)
     return (struct dwarf_file_data *) *slot;
 
-  created = ggc_alloc_dwarf_file_data ();
+  created = ggc_alloc<dwarf_file_data> ();
   created->filename = file_name;
   created->emitted_number = 0;
   *slot = created;
@@ -21278,7 +21278,7 @@ dwarf2out_var_location (rtx loc_note)
   if (!var_loc_p)
     {
       struct call_arg_loc_node *ca_loc
-	= ggc_alloc_cleared_call_arg_loc_node ();
+	= ggc_cleared_alloc<call_arg_loc_node> ();
       rtx prev = prev_real_insn (loc_note), x;
       ca_loc->call_arg_loc_note = loc_note;
       ca_loc->next = NULL;
@@ -21353,7 +21353,7 @@ new_line_info_table (void)
 {
   dw_line_info_table *table;
 
-  table = ggc_alloc_cleared_dw_line_info_table_struct ();
+  table = ggc_cleared_alloc<dw_line_info_table_struct> ();
   table->file_num = 1;
   table->line_num = 1;
   table->is_stmt = DWARF_LINE_DEFAULT_IS_STMT_START;
@@ -22122,7 +22122,7 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
   vec_alloc (decl_scope_table, 256);
 
   /* Allocate the initial hunk of the abbrev_die_table.  */
-  abbrev_die_table = ggc_alloc_cleared_vec_dw_die_ref
+  abbrev_die_table = ggc_cleared_vec_alloc<dw_die_ref>
     (ABBREV_DIE_TABLE_INCREMENT);
   abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT;
   /* Zero-th entry is allocated, but unused.  */
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index e3fd0a5..2b64a9f 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -275,7 +275,7 @@ set_mem_attrs (rtx mem, mem_attrs *attrs)
   if (!MEM_ATTRS (mem)
       || !mem_attrs_eq_p (attrs, MEM_ATTRS (mem)))
     {
-      MEM_ATTRS (mem) = ggc_alloc_mem_attrs ();
+      MEM_ATTRS (mem) = ggc_alloc<mem_attrs> ();
       memcpy (MEM_ATTRS (mem), attrs, sizeof (mem_attrs));
     }
 }
@@ -322,7 +322,7 @@ get_reg_attrs (tree decl, int offset)
   slot = htab_find_slot (reg_attrs_htab, &attrs, INSERT);
   if (*slot == 0)
     {
-      *slot = ggc_alloc_reg_attrs ();
+      *slot = ggc_alloc<reg_attrs> ();
       memcpy (*slot, &attrs, sizeof (reg_attrs));
     }
 
@@ -5123,7 +5123,7 @@ start_sequence (void)
       free_sequence_stack = tem->next;
     }
   else
-    tem = ggc_alloc_sequence_stack ();
+    tem = ggc_alloc<sequence_stack> ();
 
   tem->next = seq_stack;
   tem->first = get_insns ();
@@ -5456,7 +5456,7 @@ init_emit (void)
   crtl->emit.regno_pointer_align
     = XCNEWVEC (unsigned char, crtl->emit.regno_pointer_align_length);
 
-  regno_reg_rtx = ggc_alloc_vec_rtx (crtl->emit.regno_pointer_align_length);
+  regno_reg_rtx = ggc_vec_alloc<rtx> (crtl->emit.regno_pointer_align_length);
 
   /* Put copies of all the hard registers into regno_reg_rtx.  */
   memcpy (regno_reg_rtx,
@@ -5606,7 +5606,7 @@ init_emit_regs (void)
   for (i = 0; i < (int) MAX_MACHINE_MODE; i++)
     {
       mode = (enum machine_mode) i;
-      attrs = ggc_alloc_cleared_mem_attrs ();
+      attrs = ggc_cleared_alloc<mem_attrs> ();
       attrs->align = BITS_PER_UNIT;
       attrs->addrspace = ADDR_SPACE_GENERIC;
       if (mode != BLKmode)
diff --git a/gcc/except.c b/gcc/except.c
index 5b33c9c..3da0003 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -333,7 +333,7 @@ init_eh (void)
 void
 init_eh_for_function (void)
 {
-  cfun->eh = ggc_alloc_cleared_eh_status ();
+  cfun->eh = ggc_cleared_alloc<eh_status> ();
 
   /* Make sure zero'th entries are used.  */
   vec_safe_push (cfun->eh->region_array, (eh_region)0);
@@ -350,7 +350,7 @@ gen_eh_region (enum eh_region_type type, eh_region outer)
   eh_region new_eh;
 
   /* Insert a new blank region as a leaf in the tree.  */
-  new_eh = ggc_alloc_cleared_eh_region_d ();
+  new_eh = ggc_cleared_alloc<eh_region_d> ();
   new_eh->type = type;
   new_eh->outer = outer;
   if (outer)
@@ -407,7 +407,7 @@ gen_eh_region_catch (eh_region t, tree type_or_list)
 	add_type_for_runtime (TREE_VALUE (type_node));
     }
 
-  c = ggc_alloc_cleared_eh_catch_d ();
+  c = ggc_cleared_alloc<eh_catch_d> ();
   c->type_list = type_list;
   l = t->u.eh_try.last_catch;
   c->prev_catch = l;
@@ -441,7 +441,7 @@ gen_eh_region_must_not_throw (eh_region outer)
 eh_landing_pad
 gen_eh_landing_pad (eh_region region)
 {
-  eh_landing_pad lp = ggc_alloc_cleared_eh_landing_pad_d ();
+  eh_landing_pad lp = ggc_cleared_alloc<eh_landing_pad_d> ();
 
   lp->next_lp = region->landing_pads;
   lp->region = region;
@@ -2451,7 +2451,7 @@ add_call_site (rtx landing_pad, int action, int section)
 {
   call_site_record record;
 
-  record = ggc_alloc_call_site_record_d ();
+  record = ggc_alloc<call_site_record_d> ();
   record->landing_pad = landing_pad;
   record->action = action;
 
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
index e25e92a..adee07c 100644
--- a/gcc/fortran/f95-lang.c
+++ b/gcc/fortran/f95-lang.c
@@ -323,7 +323,7 @@ getdecls (void)
 void
 pushlevel (void)
 {
-  struct binding_level *newlevel = ggc_alloc_binding_level ();
+  struct binding_level *newlevel = ggc_alloc<binding_level> ();
 
   *newlevel = clear_binding_level;
 
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index beb99a6..a8882e7 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -615,9 +615,7 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
 void
 gfc_allocate_lang_decl (tree decl)
 {
-  DECL_LANG_SPECIFIC (decl)
-    = (struct lang_decl *) ggc_internal_cleared_alloc (sizeof
-						       (struct lang_decl));
+  DECL_LANG_SPECIFIC (decl) = ggc_cleared_alloc<struct lang_decl> ();
 }
 
 /* Remember a symbol to generate initialization/cleanup code at function
@@ -4119,7 +4117,7 @@ gfc_find_module (const char *name)
 				   htab_hash_string (name), INSERT);
   if (*slot == NULL)
     {
-      struct module_htab_entry *entry = ggc_alloc_cleared_module_htab_entry ();
+      module_htab_entry *entry = ggc_cleared_alloc<module_htab_entry> ();
 
       entry->name = gfc_get_string (name);
       entry->decls = htab_create_ggc (10, module_htab_decls_hash,
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 84503ce..ab3d601 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -1511,9 +1511,7 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, gfc_packed packed,
     type = build_variant_type_copy (etype);
 
   GFC_ARRAY_TYPE_P (type) = 1;
-  TYPE_LANG_SPECIFIC (type)
-      = (struct lang_type *) ggc_internal_cleared_alloc
-      (sizeof (struct lang_type));
+  TYPE_LANG_SPECIFIC (type) = ggc_cleared_alloc<struct lang_type> ();
 
   known_stride = (packed != PACKED_NO);
   known_offset = 1;
@@ -1815,9 +1813,7 @@ gfc_get_array_type_bounds (tree etype, int dimen, int codimen, tree * lbound,
   TYPE_NAMELESS (fat_type) = 1;
 
   GFC_DESCRIPTOR_TYPE_P (fat_type) = 1;
-  TYPE_LANG_SPECIFIC (fat_type)
-    = (struct lang_type *) ggc_internal_cleared_alloc
-    (sizeof (struct lang_type));
+  TYPE_LANG_SPECIFIC (fat_type) = ggc_cleared_alloc<struct lang_type> ();
 
   GFC_TYPE_ARRAY_RANK (fat_type) = dimen;
   GFC_TYPE_ARRAY_CORANK (fat_type) = codimen;
@@ -1991,9 +1987,7 @@ gfc_nonrestricted_type (tree t)
     return t;
 
   if (!TYPE_LANG_SPECIFIC (t))
-    TYPE_LANG_SPECIFIC (t)
-      = (struct lang_type *) ggc_internal_cleared_alloc
-      (sizeof (struct lang_type));
+    TYPE_LANG_SPECIFIC (t) = ggc_cleared_alloc<struct lang_type> ();
   /* If we're dealing with this very node already further up
      the call chain (recursion via pointers and struct members)
      we haven't yet determined if we really need a new type node.
@@ -2045,8 +2039,7 @@ gfc_nonrestricted_type (tree t)
 		  if (dataptr_type != GFC_TYPE_ARRAY_DATAPTR_TYPE (t))
 		    {
 		      TYPE_LANG_SPECIFIC (ret)
-			= (struct lang_type *) ggc_internal_cleared_alloc
-		       	(sizeof (struct lang_type));
+			= ggc_cleared_alloc<struct lang_type> ();
 		      *TYPE_LANG_SPECIFIC (ret) = *TYPE_LANG_SPECIFIC (t);
 		      GFC_TYPE_ARRAY_DATAPTR_TYPE (ret) = dataptr_type;
 		    }
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index f8d29ec..0345ca0 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -792,10 +792,7 @@ enum gfc_array_kind
 };
 
 /* Array types only.  */
-/* FIXME: the variable_size annotation here is needed because these types are
-   variable-sized in some other frontends.  Due to gengtype deficiency the GTY
-   options of such types have to agree across all frontends. */
-struct GTY((variable_size))	lang_type	 {
+struct GTY(())	lang_type	 {
   int rank, corank;
   enum gfc_array_kind akind;
   tree lbound[GFC_MAX_DIMENSIONS];
@@ -812,7 +809,7 @@ struct GTY((variable_size))	lang_type	 {
   tree caf_offset;
 };
 
-struct GTY((variable_size)) lang_decl {
+struct GTY(()) lang_decl {
   /* Dummy variables.  */
   tree saved_descriptor;
   /* Assigned integer nodes.  Stringlength is the IO format string's length.
diff --git a/gcc/function.c b/gcc/function.c
index 383a52a..4ebc255 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -306,7 +306,7 @@ try_fit_stack_local (HOST_WIDE_INT start, HOST_WIDE_INT length,
 static void
 add_frame_space (HOST_WIDE_INT start, HOST_WIDE_INT end)
 {
-  struct frame_space *space = ggc_alloc_frame_space ();
+  struct frame_space *space = ggc_alloc<frame_space> ();
   space->next = crtl->frame_space_list;
   crtl->frame_space_list = space;
   space->start = start;
@@ -654,7 +654,7 @@ static void
 insert_temp_slot_address (rtx address, struct temp_slot *temp_slot)
 {
   void **slot;
-  struct temp_slot_address_entry *t = ggc_alloc_temp_slot_address_entry ();
+  struct temp_slot_address_entry *t = ggc_alloc<temp_slot_address_entry> ();
   t->address = address;
   t->temp_slot = temp_slot;
   t->hash = temp_slot_address_compute_hash (t);
@@ -801,7 +801,7 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
 
 	  if (best_p->size - rounded_size >= alignment)
 	    {
-	      p = ggc_alloc_temp_slot ();
+	      p = ggc_alloc<temp_slot> ();
 	      p->in_use = 0;
 	      p->size = best_p->size - rounded_size;
 	      p->base_offset = best_p->base_offset + rounded_size;
@@ -825,7 +825,7 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
     {
       HOST_WIDE_INT frame_offset_old = frame_offset;
 
-      p = ggc_alloc_temp_slot ();
+      p = ggc_alloc<temp_slot> ();
 
       /* We are passing an explicit alignment request to assign_stack_local.
 	 One side effect of that is assign_stack_local will not round SIZE
@@ -1253,10 +1253,10 @@ get_hard_reg_initial_val (enum machine_mode mode, unsigned int regno)
   ivs = crtl->hard_reg_initial_vals;
   if (ivs == 0)
     {
-      ivs = ggc_alloc_initial_value_struct ();
+      ivs = ggc_alloc<initial_value_struct> ();
       ivs->num_entries = 0;
       ivs->max_entries = 5;
-      ivs->entries = ggc_alloc_vec_initial_value_pair (5);
+      ivs->entries = ggc_vec_alloc<initial_value_pair> (5);
       crtl->hard_reg_initial_vals = ivs;
     }
 
@@ -4498,7 +4498,7 @@ allocate_struct_function (tree fndecl, bool abstract_p)
 {
   tree fntype = fndecl ? TREE_TYPE (fndecl) : NULL_TREE;
 
-  cfun = ggc_alloc_cleared_function ();
+  cfun = ggc_cleared_alloc<function> ();
 
   init_eh_for_function ();
 
@@ -4572,7 +4572,7 @@ prepare_function_start (void)
 
   if (flag_stack_usage_info)
     {
-      cfun->su = ggc_alloc_cleared_stack_usage ();
+      cfun->su = ggc_cleared_alloc<stack_usage> ();
       cfun->su->static_stack_size = -1;
     }
 
@@ -6936,7 +6936,7 @@ types_used_by_var_decl_insert (tree type, tree var_decl)
       if (*slot == NULL)
 	{
 	  struct types_used_by_vars_entry *entry;
-	  entry = ggc_alloc_types_used_by_vars_entry ();
+	  entry = ggc_alloc<types_used_by_vars_entry> ();
 	  entry->type = type;
 	  entry->var_decl = var_decl;
 	  *slot = entry;
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index b3c966c..d85300b 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -4938,133 +4938,6 @@ write_roots (pair_p variables, bool emit_pch)
 		     "gt_pch_scalar_rtab");
 }
 
-/* TRUE if type S has the GTY variable_size annotation.  */
-
-static bool
-variable_size_p (const type_p s)
-{
-  options_p o;
-  for (o = s->u.s.opt; o; o = o->next)
-    if (strcmp (o->name, "variable_size") == 0)
-      return true;
-  return false;
-}
-
-enum alloc_quantity
-{ single, vector };
-
-/* Writes one typed allocator definition into output F for type
-   identifier TYPE_NAME with optional type specifier TYPE_SPECIFIER.
-   The allocator name will contain ALLOCATOR_TYPE.  If VARIABLE_SIZE
-   is true, the allocator will have an extra parameter specifying
-   number of bytes to allocate.  If QUANTITY is set to VECTOR, a
-   vector allocator will be output.  */
-
-static void
-write_typed_alloc_def (outf_p f, 
-                       bool variable_size, const char *type_specifier,
-                       const char *type_name, const char *allocator_type,
-                       enum alloc_quantity quantity)
-{
-  bool two_args = variable_size && (quantity == vector);
-  if (variable_size)
-    return;
-
-  gcc_assert (f != NULL);
-  const char *type_name_as_id = filter_type_name (type_name);
-  oprintf (f, "#define ggc_alloc_%s%s", allocator_type, type_name_as_id);
-  oprintf (f, "(%s%s%s) ",
-	   (variable_size ? "SIZE" : ""),
-	   (two_args ? ", " : ""),
-	   (quantity == vector) ? "n" : "");
-  oprintf (f, "((%s%s *)", type_specifier, type_name);
-  oprintf (f, "(ggc_internal_%salloc (", allocator_type);
-  if (variable_size)
-    oprintf (f, "SIZE");
-  else
-    oprintf (f, "sizeof (%s%s)", type_specifier, type_name);
-  if (quantity == vector)
-    oprintf (f, ", n");
-  oprintf (f, " MEM_STAT_INFO)))\n");
-  if (type_name_as_id != type_name)
-    free (CONST_CAST (char *, type_name_as_id));
-}
-
-/* Writes a typed allocator definition into output F for a struct or
-   union S, with a given ALLOCATOR_TYPE and QUANTITY for ZONE.  */
-
-static void
-write_typed_struct_alloc_def (outf_p f,
-			      const type_p s, const char *allocator_type,
-			      enum alloc_quantity quantity)
-{
-  gcc_assert (union_or_struct_p (s));
-  write_typed_alloc_def (f, variable_size_p (s), get_type_specifier (s),
-                         s->u.s.tag, allocator_type, quantity);
-}
-
-/* Writes a typed allocator definition into output F for a typedef P,
-   with a given ALLOCATOR_TYPE and QUANTITY for ZONE.  */
-
-static void
-write_typed_typedef_alloc_def (outf_p f,
-                               const pair_p p, const char *allocator_type,
-                               enum alloc_quantity quantity)
-{
-  write_typed_alloc_def (f, variable_size_p (p->type), "", p->name,
-                         allocator_type, quantity);
-}
-
-/* Writes typed allocator definitions into output F for the types in
-   STRUCTURES and TYPEDEFS that are used by GC.  */
-
-static void
-write_typed_alloc_defns (outf_p f,
-                         const type_p structures, const pair_p typedefs)
-{
-  type_p s;
-  pair_p p;
-
-  gcc_assert (f != NULL);
-  oprintf (f,
-	   "\n/* Allocators for known structs and unions.  */\n\n");
-  for (s = structures; s; s = s->next)
-    {
-      if (!USED_BY_TYPED_GC_P (s))
-	continue;
-      gcc_assert (union_or_struct_p (s));
-      /* In plugin mode onput output ggc_alloc macro definitions
-	 relevant to plugin input files.  */
-      if (nb_plugin_files > 0 
-	  && ((s->u.s.line.file == NULL) || !s->u.s.line.file->inpisplugin))
-	continue;
-      write_typed_struct_alloc_def (f, s, "", single);
-      write_typed_struct_alloc_def (f, s, "cleared_", single);
-      write_typed_struct_alloc_def (f, s, "vec_", vector);
-      write_typed_struct_alloc_def (f, s, "cleared_vec_", vector);
-    }
-
-  oprintf (f, "\n/* Allocators for known typedefs.  */\n");
-  for (p = typedefs; p; p = p->next)
-    {
-      s = p->type;
-      if (!USED_BY_TYPED_GC_P (s) || (strcmp (p->name, s->u.s.tag) == 0))
-	continue;
-      /* In plugin mode onput output ggc_alloc macro definitions
-	 relevant to plugin input files.  */
-      if (nb_plugin_files > 0) 
-	{
-	  struct fileloc* filoc = type_fileloc (s);
-	  if (!filoc || !filoc->file->inpisplugin)
-	    continue;
-	};
-      write_typed_typedef_alloc_def (f, p, "", single);
-      write_typed_typedef_alloc_def (f, p, "cleared_", single);
-      write_typed_typedef_alloc_def (f, p, "vec_", vector);
-      write_typed_typedef_alloc_def (f, p, "cleared_vec_", vector);
-    }
-}
-
 /* Prints not-as-ugly version of a typename of T to OF.  Trades the uniquness
    guaranteee for somewhat increased readability.  If name conflicts do happen,
    this funcion will have to be adjusted to be more like
@@ -5775,7 +5648,6 @@ main (int argc, char **argv)
   open_base_files ();
 
   output_header = plugin_output ? plugin_output : header_file;
-  write_typed_alloc_defns (output_header, structures, typedefs);
   DBGPRINT_COUNT_TYPE ("structures before write_types outputheader",
 		       structures);
   DBGPRINT_COUNT_TYPE ("param_structs before write_types outputheader",
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index e1cc48e..e89cc64 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -232,7 +232,7 @@ ggc_cleared_alloc_htab_ignore_args (size_t c ATTRIBUTE_UNUSED,
 				    size_t n ATTRIBUTE_UNUSED)
 {
   gcc_assert (c * n == sizeof (struct htab));
-  return ggc_alloc_cleared_htab ();
+  return ggc_cleared_alloc<htab> ();
 }
 
 /* TODO: once we actually use type information in GGC, create a new tag
@@ -241,7 +241,7 @@ void *
 ggc_cleared_alloc_ptr_array_two_args (size_t c, size_t n)
 {
   gcc_assert (sizeof (PTR *) == n);
-  return ggc_internal_cleared_vec_alloc (sizeof (PTR *), c);
+  return ggc_cleared_vec_alloc<PTR *> (c);
 }
 
 /* These are for splay_tree_new_ggc.  */
diff --git a/gcc/ggc.h b/gcc/ggc.h
index 736305d..2c567de 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -156,16 +156,35 @@ extern void dump_ggc_loc_statistics (bool);
 #define GGC_RESIZEVEC(T, P, N) \
     ((T *) ggc_realloc ((P), (N) * sizeof (T) MEM_STAT_INFO))
 
-static inline void *
-ggc_internal_vec_alloc (size_t s, size_t c MEM_STAT_DECL)
+template<typename T>
+static inline T *
+ggc_alloc (ALONE_CXX_MEM_STAT_INFO)
 {
-    return ggc_internal_alloc (c * s PASS_MEM_STAT);
+  return static_cast<T *> (ggc_internal_alloc (sizeof (T) PASS_MEM_STAT));
 }
 
-static inline void *
-ggc_internal_cleared_vec_alloc (size_t s, size_t c CXX_MEM_STAT_INFO)
+template<typename T>
+static inline T *
+ggc_cleared_alloc (ALONE_CXX_MEM_STAT_INFO)
+{
+  return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T)
+						       PASS_MEM_STAT));
+}
+
+template<typename T>
+static inline T *
+ggc_vec_alloc (size_t c CXX_MEM_STAT_INFO)
+{
+    return static_cast<T *> (ggc_internal_alloc (c * sizeof (T)
+						 PASS_MEM_STAT));
+}
+
+template<typename T>
+static inline T *
+ggc_cleared_vec_alloc (size_t c CXX_MEM_STAT_INFO)
 {
-    return ggc_internal_cleared_alloc (c * s PASS_MEM_STAT);
+    return static_cast<T *> (ggc_internal_cleared_alloc (c * sizeof (T)
+							 PASS_MEM_STAT));
 }
 
 static inline void *
diff --git a/gcc/gimple.c b/gcc/gimple.c
index fc6ecb9..165a4bd 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -835,8 +835,7 @@ gimple_build_omp_for (gimple_seq body, int kind, tree clauses, size_t collapse,
   gimple_omp_for_set_clauses (p, clauses);
   gimple_omp_for_set_kind (p, kind);
   p->collapse = collapse;
-  p->iter =  static_cast <struct gimple_omp_for_iter *> (
-   ggc_internal_cleared_vec_alloc (sizeof (*p->iter), collapse));
+  p->iter =  ggc_cleared_vec_alloc<gimple_omp_for_iter> (collapse);
 
   if (pre_body)
     gimple_omp_for_set_pre_body (p, pre_body);
@@ -1664,10 +1663,8 @@ gimple_copy (gimple stmt)
 	  {
 	    gimple_statement_omp_for *omp_for_copy =
 	      as_a <gimple_statement_omp_for *> (copy);
-	    omp_for_copy->iter =
-	      static_cast <struct gimple_omp_for_iter *> (
-		  ggc_internal_vec_alloc (sizeof (struct gimple_omp_for_iter),
-					  gimple_omp_for_collapse (stmt)));
+	    omp_for_copy->iter = ggc_vec_alloc<gimple_omp_for_iter>
+	      ( gimple_omp_for_collapse (stmt));
           }
 	  for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
 	    {
diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c
index c0f2f1f..7231b34 100644
--- a/gcc/go/go-lang.c
+++ b/gcc/go/go-lang.c
@@ -51,7 +51,7 @@ struct GTY(()) lang_type
 
 /* Language-dependent contents of a decl.  */
 
-struct GTY((variable_size)) lang_decl
+struct GTY(()) lang_decl
 {
   char dummy;
 };
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 479963c..d1f882a 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -2599,7 +2599,7 @@ get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
   struct ipa_replace_map *replace_map;
 
 
-  replace_map = ggc_alloc_ipa_replace_map ();
+  replace_map = ggc_alloc<ipa_replace_map> ();
   if (dump_file)
     {
       fprintf (dump_file, "    replacing ");
@@ -3182,7 +3182,7 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node,
 	  if (!item->value)
 	    continue;
 
-	  v = ggc_alloc_ipa_agg_replacement_value ();
+	  v = ggc_alloc<ipa_agg_replacement_value> ();
 	  v->index = i;
 	  v->offset = item->offset;
 	  v->value = item->value;
@@ -3212,7 +3212,7 @@ known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
     FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
       {
 	struct ipa_agg_replacement_value *v;
-	v = ggc_alloc_ipa_agg_replacement_value ();
+	v = ggc_alloc<ipa_agg_replacement_value> ();
 	v->index = i;
 	v->offset = item->offset;
 	v->value = item->value;
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index 4ff31fc..bacbeec 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -491,7 +491,7 @@ get_odr_type (tree type, bool insert)
       tree binfo = TYPE_BINFO (type);
       unsigned int i;
 
-      val = ggc_alloc_cleared_odr_type_d ();
+      val = ggc_cleared_alloc<odr_type_d> ();
       val->type = type;
       val->bases = vNULL;
       val->derived_types = vNULL;
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 9f144fa..336dd97 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -3311,7 +3311,7 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
     {
       struct ipa_agg_replacement_value *v;
 
-      v = ggc_alloc_ipa_agg_replacement_value ();
+      v = ggc_alloc<ipa_agg_replacement_value> ();
       memcpy (v, old_av, sizeof (*v));
       v->next = new_av;
       new_av = v;
@@ -4670,7 +4670,7 @@ read_agg_replacement_chain (struct lto_input_block *ib,
       struct ipa_agg_replacement_value *av;
       struct bitpack_d bp;
 
-      av = ggc_alloc_ipa_agg_replacement_value ();
+      av = ggc_alloc<ipa_agg_replacement_value> ();
       av->offset = streamer_read_uhwi (ib);
       av->index = streamer_read_uhwi (ib);
       av->value = stream_read_tree (ib, data_in);
diff --git a/gcc/java/class.c b/gcc/java/class.c
index 94c2568..a1e4a86 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -764,9 +764,7 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type)
   fndecl = build_decl (input_location, FUNCTION_DECL, name, method_type);
   DECL_CONTEXT (fndecl) = this_class;
 
-  DECL_LANG_SPECIFIC (fndecl)
-    = (struct lang_decl *) ggc_internal_cleared_alloc
-    (sizeof (struct lang_decl));
+  DECL_LANG_SPECIFIC (fndecl) = ggc_cleared_alloc<struct lang_decl> ();
   DECL_LANG_SPECIFIC (fndecl)->desc = LANG_DECL_FUNC;
 
   /* Initialize the static initializer test table.  */
@@ -3195,7 +3193,7 @@ java_treetreehash_new (htab_t ht, tree t)
   e = htab_find_slot_with_hash (ht, t, hv, INSERT);
   if (*e == NULL)
     {
-      tthe = ggc_alloc_cleared_treetreehash_entry ();
+      tthe = ggc_cleared_alloc<treetreehash_entry> ();
       tthe->key = t;
       *e = tthe;
     }
diff --git a/gcc/java/constants.c b/gcc/java/constants.c
index 51449ef..2e317c9 100644
--- a/gcc/java/constants.c
+++ b/gcc/java/constants.c
@@ -46,11 +46,8 @@ set_constant_entry (CPool *cpool, int index, int tag, jword value)
   if (cpool->data == NULL)
     {
       cpool->capacity = 100;
-      cpool->tags = (uint8 *) ggc_internal_cleared_alloc (sizeof (uint8)
-							  * cpool->capacity);
-      cpool->data = (cpool_entry *) ggc_internal_cleared_alloc (sizeof
-						       (union cpool_entry)
-						       * cpool->capacity);
+      cpool->tags = ggc_cleared_vec_alloc<uint8> (cpool->capacity);
+      cpool->data = ggc_cleared_vec_alloc<cpool_entry> (cpool->capacity);
       cpool->count = 1;
     }
   if (index >= cpool->capacity)
@@ -338,7 +335,7 @@ cpool_for_class (tree klass)
 
   if (cpool == NULL)
     {
-      cpool = ggc_alloc_cleared_CPool ();
+      cpool = ggc_cleared_alloc<CPool> ();
       TYPE_CPOOL (klass) = cpool;
     }
   return cpool;
diff --git a/gcc/java/decl.c b/gcc/java/decl.c
index 9f2f0ca..841fb4c 100644
--- a/gcc/java/decl.c
+++ b/gcc/java/decl.c
@@ -1307,7 +1307,7 @@ static struct binding_level *
 make_binding_level (void)
 {
   /* NOSTRICT */
-  return ggc_alloc_cleared_binding_level ();
+  return ggc_cleared_alloc<binding_level> ();
 }
 
 void
@@ -1646,7 +1646,7 @@ java_dup_lang_specific_decl (tree node)
     return;
 
   lang_decl_size = sizeof (struct lang_decl);
-  x = (struct lang_decl *) ggc_internal_alloc (lang_decl_size);
+  x = ggc_alloc<struct lang_decl> ();
   memcpy (x, DECL_LANG_SPECIFIC (node), lang_decl_size);
   DECL_LANG_SPECIFIC (node) = x;
 }
diff --git a/gcc/java/expr.c b/gcc/java/expr.c
index 69f6819..0fa5724 100644
--- a/gcc/java/expr.c
+++ b/gcc/java/expr.c
@@ -470,7 +470,7 @@ add_type_assertion (tree klass, int assertion_code, tree op1, tree op2)
   if (*as_pp)
     return;
 
-  *as_pp = ggc_alloc_type_assertion ();
+  *as_pp = ggc_alloc<type_assertion> ();
   **(type_assertion **)as_pp = as;
 }
 
diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
index 43a8258..e832f44 100644
--- a/gcc/java/java-tree.h
+++ b/gcc/java/java-tree.h
@@ -699,9 +699,7 @@ union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
 #define MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC(T)                       \
   if (DECL_LANG_SPECIFIC (T) == NULL)                                \
     {                                                                \
-      DECL_LANG_SPECIFIC ((T))                                       \
-        = (struct lang_decl *) ggc_internal_cleared_alloc            \
-      (sizeof (struct lang_decl));                                   \
+      DECL_LANG_SPECIFIC ((T)) = ggc_cleared_alloc<struct lang_decl> (); \
       DECL_LANG_SPECIFIC (T)->desc = LANG_DECL_VAR;                  \
     }
 
@@ -809,7 +807,7 @@ struct GTY(()) lang_decl_var {
 
 enum lang_decl_desc {LANG_DECL_FUNC, LANG_DECL_VAR};
 
-struct GTY((variable_size)) lang_decl {
+struct GTY(()) lang_decl {
   enum lang_decl_desc desc;
   union lang_decl_u
     {
@@ -826,9 +824,7 @@ struct GTY((variable_size)) lang_decl {
 #define TYPE_CPOOL_DATA_REF(T)	(TYPE_LANG_SPECIFIC (T)->cpool_data_ref)
 #define MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC(T) \
   if (TYPE_LANG_SPECIFIC ((T)) == NULL)		\
-     TYPE_LANG_SPECIFIC ((T))			\
-       = (struct lang_type *) ggc_internal_cleared_alloc \
-(sizeof (struct lang_type));     \
+     TYPE_LANG_SPECIFIC ((T)) = ggc_cleared_alloc<struct lang_type> ();
 
 #define TYPE_DUMMY(T)		(TYPE_LANG_SPECIFIC(T)->dummy_class)
 
@@ -871,10 +867,7 @@ typedef struct GTY(()) method_entry_d {
 } method_entry;
 
 
-/* FIXME: the variable_size annotation here is needed because these types are
-   variable-sized in some other frontends.  Due to gengtype deficiency the GTY
-   options of such types have to agree across all frontends. */
-struct GTY((variable_size)) lang_type {
+struct GTY(()) lang_type {
   tree signature;
   struct JCF *jcf;
   struct CPool *cpool;
diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
index afe35f0..e57a044 100644
--- a/gcc/java/jcf-parse.c
+++ b/gcc/java/jcf-parse.c
@@ -1905,7 +1905,7 @@ java_parse_file (void)
       if (magic == 0xcafebabe)
 	{
 	  CLASS_FILE_P (node) = 1;
-	  current_jcf = ggc_alloc_cleared_JCF ();
+	  current_jcf = ggc_cleared_alloc<JCF> ();
 	  current_jcf->read_state = finput;
 	  current_jcf->filbuf = jcf_filbuf_from_stdio;
 	  jcf_parse (current_jcf);
@@ -1922,7 +1922,7 @@ java_parse_file (void)
 	}
       else if (magic == (JCF_u4)ZIPMAGIC)
 	{
-	  main_jcf = ggc_alloc_cleared_JCF ();
+	  main_jcf = ggc_cleared_alloc<JCF> ();
 	  main_jcf->read_state = finput;
 	  main_jcf->filbuf = jcf_filbuf_from_stdio;
 	  linemap_add (line_table, LC_ENTER, false, filename, 0);
@@ -2178,7 +2178,7 @@ process_zip_dir (FILE *finput)
 
       class_name = compute_class_name (zdir);
       file_name  = XNEWVEC (char, zdir->filename_length+1);
-      jcf = ggc_alloc_cleared_JCF ();
+      jcf = ggc_cleared_alloc<JCF> ();
 
       strncpy (file_name, class_name_in_zip_dir, zdir->filename_length);
       file_name [zdir->filename_length] = '\0';
diff --git a/gcc/java/jcf.h b/gcc/java/jcf.h
index 8aa077e..0988d65 100644
--- a/gcc/java/jcf.h
+++ b/gcc/java/jcf.h
@@ -65,7 +65,7 @@ jcf_open_exact_case (const char* filename, int oflag);
 struct JCF;
 typedef int (*jcf_filbuf_t) (struct JCF*, int needed);
 
-union GTY((variable_size)) cpool_entry {
+union GTY(()) cpool_entry {
   jword GTY ((tag ("0"))) w;
   tree GTY ((tag ("1"))) t;
 };
diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c
index 42bcb75..6acc4c9 100644
--- a/gcc/loop-iv.c
+++ b/gcc/loop-iv.c
@@ -3036,7 +3036,7 @@ get_simple_loop_desc (struct loop *loop)
 
   /* At least desc->infinite is not always initialized by
      find_simple_loop_exit.  */
-  desc = ggc_alloc_cleared_niter_desc ();
+  desc = ggc_cleared_alloc<niter_desc> ();
   iv_analysis_loop_init (loop);
   find_simple_exit (loop, desc);
   loop->simple_loop_desc = desc;
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 58084cd..d4a6d38 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -1755,7 +1755,7 @@ input_node_opt_summary (struct cgraph_node *node,
   count = streamer_read_uhwi (ib_main);
   for (i = 0; i < count; i++)
     {
-      struct ipa_replace_map *map = ggc_alloc_ipa_replace_map ();
+      struct ipa_replace_map *map = ggc_alloc<ipa_replace_map> ();
 
       vec_safe_push (node->clone.tree_map, map);
       map->parm_num = streamer_read_uhwi (ib_main);
diff --git a/gcc/lto-section-in.c b/gcc/lto-section-in.c
index 9aa7639..d887763 100644
--- a/gcc/lto-section-in.c
+++ b/gcc/lto-section-in.c
@@ -364,7 +364,7 @@ lto_get_decl_name_mapping (struct lto_file_decl_data *decl_data,
 struct lto_in_decl_state *
 lto_new_in_decl_state (void)
 {
-  return ggc_alloc_cleared_lto_in_decl_state ();
+  return ggc_cleared_alloc<lto_in_decl_state> ();
 }
 
 /* Delete STATE and its components. */
diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
index 20835f7..deb9b1c 100644
--- a/gcc/lto-streamer-in.c
+++ b/gcc/lto-streamer-in.c
@@ -279,7 +279,7 @@ lto_input_eh_catch_list (struct lto_input_block *ib, struct data_in *data_in,
       lto_tag_check_range (tag, LTO_eh_catch, LTO_eh_catch);
 
       /* Read the catch node.  */
-      n = ggc_alloc_cleared_eh_catch_d ();
+      n = ggc_cleared_alloc<eh_catch_d> ();
       n->type_list = stream_read_tree (ib, data_in);
       n->filter_list = stream_read_tree (ib, data_in);
       n->label = stream_read_tree (ib, data_in);
@@ -319,7 +319,7 @@ input_eh_region (struct lto_input_block *ib, struct data_in *data_in, int ix)
   if (tag == LTO_null)
     return NULL;
 
-  r = ggc_alloc_cleared_eh_region_d ();
+  r = ggc_cleared_alloc<eh_region_d> ();
   r->index = streamer_read_hwi (ib);
 
   gcc_assert (r->index == ix);
@@ -396,7 +396,7 @@ input_eh_lp (struct lto_input_block *ib, struct data_in *data_in, int ix)
 
   lto_tag_check_range (tag, LTO_eh_landing_pad, LTO_eh_landing_pad);
 
-  lp = ggc_alloc_cleared_eh_landing_pad_d ();
+  lp = ggc_cleared_alloc<eh_landing_pad_d> ();
   lp->index = streamer_read_hwi (ib);
   gcc_assert (lp->index == ix);
   lp->next_lp = (eh_landing_pad) (intptr_t) streamer_read_hwi (ib);
@@ -682,7 +682,7 @@ input_cfg (struct lto_input_block *ib, struct data_in *data_in,
   if (n_loops == 0)
     return;
 
-  struct loops *loops = ggc_alloc_cleared_loops ();
+  struct loops *loops = ggc_cleared_alloc<struct loops> ();
   init_loops_structure (fn, loops, n_loops);
   set_loops_for_fn (fn, loops);
 
diff --git a/gcc/lto/lto-tree.h b/gcc/lto/lto-tree.h
index b1c3d2a..4e3f5d6 100644
--- a/gcc/lto/lto-tree.h
+++ b/gcc/lto/lto-tree.h
@@ -28,12 +28,12 @@ struct GTY(()) lang_identifier
   struct tree_identifier base;
 };
 
-struct GTY((variable_size)) lang_decl
+struct GTY(()) lang_decl
 {
   int dummy;  /* Added because ggc does not like empty structs.  */
 };
 
-struct GTY((variable_size)) lang_type
+struct GTY(()) lang_type
 {
   int dummy;  /* Added because ggc does not like empty structs.  */
 };
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 5f4478a..38e1149 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -244,7 +244,7 @@ lto_read_in_decl_state (struct data_in *data_in, const uint32_t *data,
   for (i = 0; i < LTO_N_DECL_STREAMS; i++)
     {
       uint32_t size = *data++;
-      tree *decls = ggc_alloc_vec_tree (size);
+      tree *decls = ggc_vec_alloc<tree> (size);
 
       for (j = 0; j < size; j++)
 	decls[j] = streamer_tree_cache_get_tree (data_in->reader_cache, data[j]);
@@ -2159,7 +2159,7 @@ create_subid_section_table (struct lto_section_slot *ls, splay_tree file_ids,
     }
   else
     {
-      file_data = ggc_alloc_lto_file_decl_data ();
+      file_data = ggc_alloc<lto_file_decl_data> ();
       memset(file_data, 0, sizeof (struct lto_file_decl_data));
       file_data->id = id;
       file_data->section_hash_table = lto_obj_create_section_hash_table ();;
@@ -2860,7 +2860,7 @@ lto_flatten_files (struct lto_file_decl_data **orig, int count, int last_file_ix
 
   lto_stats.num_input_files = count;
   all_file_decl_data
-    = ggc_alloc_cleared_vec_lto_file_decl_data_ptr (count + 1);
+    = ggc_cleared_vec_alloc<lto_file_decl_data_ptr> (count + 1);
   /* Set the hooks so that all of the ipa passes can read in their data.  */
   lto_set_in_hooks (all_file_decl_data, get_section_data, free_section_data);
   for (i = 0, k = 0; i < last_file_ix; i++) 
@@ -2903,7 +2903,7 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
   timevar_push (TV_IPA_LTO_DECL_IN);
 
   real_file_decl_data
-    = decl_data = ggc_alloc_cleared_vec_lto_file_decl_data_ptr (nfiles + 1);
+    = decl_data = ggc_cleared_vec_alloc<lto_file_decl_data_ptr> (nfiles + 1);
   real_file_count = nfiles;
 
   /* Read the resolution file.  */
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index cda345b..551325a 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -3198,7 +3198,7 @@ objc_build_string_object (tree string)
 
   if (!desc)
     {
-      *loc = desc = ggc_alloc_string_descriptor ();
+      *loc = desc = ggc_alloc<string_descriptor> ();
       desc->literal = string;
       desc->constructor =
 	(*runtime.build_const_string_constructor) (input_location, string, length);
@@ -7040,7 +7040,7 @@ continue_class (tree klass)
 	uprivate_record = CLASS_STATIC_TEMPLATE (implementation_template);
 	objc_instance_type = build_pointer_type (uprivate_record);
 
-	imp_entry = ggc_alloc_imp_entry ();
+	imp_entry = ggc_alloc<struct imp_entry> ();
 
 	imp_entry->next = imp_list;
 	imp_entry->imp_context = klass;
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index a050727..7e1e265 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -192,9 +192,7 @@ typedef enum objc_property_assign_semantics {
 #define SIZEOF_OBJC_TYPE_LANG_SPECIFIC sizeof (struct lang_type)
 #define ALLOC_OBJC_TYPE_LANG_SPECIFIC(NODE)				\
   do {									\
-    TYPE_LANG_SPECIFIC (NODE)						\
-      = (struct lang_type *) ggc_internal_cleared_alloc     \
-      (sizeof (struct lang_type));	\
+      TYPE_LANG_SPECIFIC (NODE) = ggc_cleared_alloc<struct lang_type> (); \
   } while (0)
 
 #define TYPE_HAS_OBJC_INFO(TYPE)				\
diff --git a/gcc/objc/objc-map.c b/gcc/objc/objc-map.c
index 386d2c5..aaee729 100644
--- a/gcc/objc/objc-map.c
+++ b/gcc/objc/objc-map.c
@@ -56,7 +56,7 @@ next_power_of_two (size_t x)
 objc_map_t
 objc_map_alloc_ggc (size_t initial_capacity)
 {
-  objc_map_t map = (objc_map_t) ggc_internal_cleared_vec_alloc (1, sizeof (struct objc_map_private));
+  objc_map_t map = ggc_cleared_alloc<objc_map_private> ();
   if (map == NULL)
     OUT_OF_MEMORY;
   
@@ -67,8 +67,8 @@ objc_map_alloc_ggc (size_t initial_capacity)
   map->maximum_load_factor = 70;
   map->max_number_of_non_empty_slots = (initial_capacity * map->maximum_load_factor) / 100;
 
-  map->slots = (tree *)ggc_internal_cleared_vec_alloc (initial_capacity, sizeof (tree));
-  map->values = (tree *)ggc_internal_cleared_vec_alloc (initial_capacity, sizeof (tree));
+  map->slots = ggc_cleared_vec_alloc<tree> (initial_capacity);
+  map->values = ggc_cleared_vec_alloc<tree> (initial_capacity);
 
   if (map->slots == NULL)
     OUT_OF_MEMORY;
@@ -112,8 +112,8 @@ objc_map_private_resize (objc_map_t map, size_t new_number_of_slots)
   map->max_number_of_non_empty_slots = (map->number_of_slots * map->maximum_load_factor) / 100;
 
 
-  map->slots = (tree *)ggc_internal_cleared_vec_alloc (map->number_of_slots, sizeof (tree));
-  map->values = (tree *)ggc_internal_cleared_vec_alloc (map->number_of_slots, sizeof (tree));
+  map->slots = ggc_cleared_vec_alloc<tree> (map->number_of_slots);
+  map->values = ggc_cleared_vec_alloc<tree> (map->number_of_slots);
 
   if (map->slots == NULL)
     OUT_OF_MEMORY;
diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
index ee43d2d..85033a3 100644
--- a/gcc/objc/objc-next-runtime-abi-02.c
+++ b/gcc/objc/objc-next-runtime-abi-02.c
@@ -238,7 +238,7 @@ static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
 bool
 objc_next_runtime_abi_02_init (objc_runtime_hooks *rthooks)
 {
-  extern_names = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
+  extern_names = ggc_cleared_vec_alloc<hash> (SIZEHASHTABLE);
 
   if (flag_objc_exceptions && flag_objc_sjlj_exceptions)
     {
@@ -857,7 +857,7 @@ hash_name_enter (hash *hashlist, tree id)
   hash obj;
   int slot = IDENTIFIER_HASH_VALUE (DECL_NAME (id)) % SIZEHASHTABLE;
 
-  obj = ggc_alloc_hashed_entry ();
+  obj = ggc_alloc<hashed_entry> ();
   obj->list = 0;
   obj->next = hashlist[slot];
   obj->key = id;
diff --git a/gcc/optabs.c b/gcc/optabs.c
index 54f07ab..e465cbc 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -6156,7 +6156,7 @@ set_optab_libfunc (optab op, enum machine_mode mode, const char *name)
     val = 0;
   slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
   if (*slot == NULL)
-    *slot = ggc_alloc_libfunc_entry ();
+    *slot = ggc_alloc<libfunc_entry> ();
   (*slot)->op = op;
   (*slot)->mode1 = mode;
   (*slot)->mode2 = VOIDmode;
@@ -6184,7 +6184,7 @@ set_conv_libfunc (convert_optab optab, enum machine_mode tmode,
     val = 0;
   slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
   if (*slot == NULL)
-    *slot = ggc_alloc_libfunc_entry ();
+    *slot = ggc_alloc<libfunc_entry> ();
   (*slot)->op = optab;
   (*slot)->mode1 = tmode;
   (*slot)->mode2 = fmode;
diff --git a/gcc/passes.c b/gcc/passes.c
index fb60fc8..78277a2 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -1542,7 +1542,7 @@ do_per_function_toporder (void (*callback) (void *data), void *data)
   else
     {
       gcc_assert (!order);
-      order = ggc_alloc_vec_cgraph_node_ptr (cgraph_n_nodes);
+      order = ggc_vec_alloc<cgraph_node_ptr> (cgraph_n_nodes);
       nnodes = ipa_reverse_postorder (order);
       for (i = nnodes - 1; i >= 0; i--)
         order[i]->process = 1;
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 595b699..d8dca30 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -251,7 +251,7 @@ struct GTY(()) object_block {
 /* RTL expression ("rtx").  */
 
 struct GTY((chain_next ("RTX_NEXT (&%h)"),
-	    chain_prev ("RTX_PREV (&%h)"), variable_size)) rtx_def {
+	    chain_prev ("RTX_PREV (&%h)"))) rtx_def {
   /* The kind of expression this is.  */
   ENUM_BITFIELD(rtx_code) code: 16;
 
@@ -382,7 +382,7 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"),
    for a variable number of things.  The principle use is inside
    PARALLEL expressions.  */
 
-struct GTY((variable_size)) rtvec_def {
+struct GTY(()) rtvec_def {
   int num_elem;		/* number of elements */
   rtx GTY ((length ("%h.num_elem"))) elem[1];
 };
diff --git a/gcc/sese.c b/gcc/sese.c
index 342c5e8..a0b0899 100644
--- a/gcc/sese.c
+++ b/gcc/sese.c
@@ -698,7 +698,7 @@ if_region_set_false_region (ifsese if_region, sese region)
 
   if (slot)
     {
-      struct loop_exit *loop_exit = ggc_alloc_cleared_loop_exit ();
+      struct loop_exit *loop_exit = ggc_cleared_alloc<struct loop_exit> ();
 
       memcpy (loop_exit, *((struct loop_exit **) slot), sizeof (struct loop_exit));
       htab_clear_slot (current_loops->exits, slot);
diff --git a/gcc/stringpool.c b/gcc/stringpool.c
index e317525..c880cb1 100644
--- a/gcc/stringpool.c
+++ b/gcc/stringpool.c
@@ -258,10 +258,10 @@ static GTY(()) struct string_pool_data * spd;
 void
 gt_pch_save_stringpool (void)
 {
-  spd = ggc_alloc_string_pool_data ();
+  spd = ggc_alloc<string_pool_data> ();
   spd->nslots = ident_hash->nslots;
   spd->nelements = ident_hash->nelements;
-  spd->entries = ggc_alloc_vec_ht_identifier_ptr (spd->nslots);
+  spd->entries = ggc_vec_alloc<ht_identifier_ptr> (spd->nslots);
   memcpy (spd->entries, ident_hash->entries,
 	  spd->nslots * sizeof (spd->entries[0]));
 }
diff --git a/gcc/target-globals.c b/gcc/target-globals.c
index 7cf95ae..5f1a208 100644
--- a/gcc/target-globals.c
+++ b/gcc/target-globals.c
@@ -83,13 +83,13 @@ save_target_globals (void)
   g = (struct target_globals *) p;
   g->flag_state = &p->flag_state;
   g->regs = ggc_internal_cleared_alloc (sizeof (struct target_regs));
-  g->rtl = ggc_alloc_cleared_target_rtl ();
+  g->rtl = ggc_cleared_alloc<target_rtl> ();
   g->hard_regs
     = ggc_internal_cleared_alloc (sizeof (struct target_hard_regs));
   g->reload = ggc_internal_cleared_alloc (sizeof (struct target_reload));
   g->expmed =  ggc_internal_cleared_alloc (sizeof (struct target_expmed));
   g->optabs = &p->optabs;
-  g->libfuncs = ggc_alloc_cleared_target_libfuncs ();
+  g->libfuncs = ggc_cleared_alloc<target_libfuncs> ();
   g->cfgloop = &p->cfgloop;
   g->ira = ggc_internal_cleared_alloc (sizeof (struct target_ira));
   g->ira_int = ggc_internal_cleared_alloc (sizeof (struct target_ira_int));
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 9535bd0..2f9c9f5 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1156,7 +1156,7 @@ general_init (const char *argv0)
      table.  */
   init_ggc ();
   init_stringpool ();
-  line_table = ggc_alloc_line_maps ();
+  line_table = ggc_alloc<line_maps> ();
   linemap_init (line_table);
   line_table->reallocator = realloc_for_line_map;
   line_table->round_alloc_size = ggc_round_alloc_size;
diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
index 417ca8a..52777d5 100644
--- a/gcc/trans-mem.c
+++ b/gcc/trans-mem.c
@@ -479,7 +479,7 @@ record_tm_replacement (tree from, tree to)
   if (tm_wrap_map == NULL)
     tm_wrap_map = htab_create_ggc (32, tree_map_hash, tree_map_eq, 0);
 
-  h = ggc_alloc_tree_map ();
+  h = ggc_alloc<tree_map> ();
   h->hash = htab_hash_pointer (from);
   h->base.from = from;
   h->to = to;
@@ -3070,7 +3070,7 @@ split_bb_make_tm_edge (gimple stmt, basic_block dest_bb,
   struct tm_restart_node *n = (struct tm_restart_node *) *slot;
   if (n == NULL)
     {
-      n = ggc_alloc_tm_restart_node ();
+      n = ggc_alloc<tm_restart_node> ();
       *n = dummy;
     }
   else
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 0fb2681..446e0f2 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -6893,7 +6893,7 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
     }
 
   /* Initialize an empty loop tree.  */
-  struct loops *loops = ggc_alloc_cleared_loops ();
+  struct loops *loops = ggc_cleared_alloc<struct loops> ();
   init_loops_structure (dest_cfun, loops, 1);
   loops->state = LOOPS_MAY_HAVE_MULTIPLE_LATCHES;
   set_loops_for_fn (dest_cfun, loops);
diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h
index 8810a3e..f4075fc 100644
--- a/gcc/tree-data-ref.h
+++ b/gcc/tree-data-ref.h
@@ -565,7 +565,7 @@ lambda_vector_gcd (lambda_vector vector, int size)
 static inline lambda_vector
 lambda_vector_new (int size)
 {
-  return (lambda_vector) ggc_internal_cleared_alloc (sizeof (int) * size);
+  return ggc_cleared_vec_alloc<int> (size);
 }
 
 /* Clear out vector VEC1 of length SIZE.  */
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 960c04a..914ef68 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -82,7 +82,7 @@ add_stmt_to_eh_lp_fn (struct function *ifun, gimple t, int num)
 
   gcc_assert (num != 0);
 
-  n = ggc_alloc_throw_stmt_node ();
+  n = ggc_alloc<throw_stmt_node> ();
   n->stmt = t;
   n->lp_nr = num;
 
diff --git a/gcc/tree-iterator.c b/gcc/tree-iterator.c
index 37ee752..c4412ba 100644
--- a/gcc/tree-iterator.c
+++ b/gcc/tree-iterator.c
@@ -131,7 +131,7 @@ tsi_link_before (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
     }
   else
     {
-      head = ggc_alloc_tree_statement_list_node ();
+      head = ggc_alloc<tree_statement_list_node> ();
       head->prev = NULL;
       head->next = NULL;
       head->stmt = t;
@@ -207,7 +207,7 @@ tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
     }
   else
     {
-      head = ggc_alloc_tree_statement_list_node ();
+      head = ggc_alloc<tree_statement_list_node> ();
       head->prev = NULL;
       head->next = NULL;
       head->stmt = t;
diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
index f1ddc24..fc0b0d1 100644
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -332,7 +332,7 @@ new_scev_info_str (basic_block instantiated_below, tree var)
 {
   struct scev_info_str *res;
 
-  res = ggc_alloc_scev_info_str ();
+  res = ggc_alloc<scev_info_str> ();
   res->name_version = SSA_NAME_VERSION (var);
   res->chrec = chrec_not_analyzed_yet;
   res->instantiated_below = instantiated_below->index;
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 7628363..04effab 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -2678,7 +2678,7 @@ record_estimate (struct loop *loop, tree bound, double_int i_bound,
 	  || loop->nb_iterations == NULL_TREE
 	  || TREE_CODE (loop->nb_iterations) != INTEGER_CST))
     {
-      struct nb_iter_bound *elt = ggc_alloc_nb_iter_bound ();
+      struct nb_iter_bound *elt = ggc_alloc<nb_iter_bound> ();
 
       elt->bound = i_bound;
       elt->stmt = at_stmt;
diff --git a/gcc/tree-ssa-operands.h b/gcc/tree-ssa-operands.h
index 5f9edd4..42fe5a7 100644
--- a/gcc/tree-ssa-operands.h
+++ b/gcc/tree-ssa-operands.h
@@ -45,7 +45,7 @@ typedef struct use_optype_d *use_optype_p;
    operand memory manager.  Operands are suballocated out of this block.  The
    MEM array varies in size.  */
 
-struct GTY((chain_next("%h.next"), variable_size)) ssa_operand_memory_d {
+struct GTY((chain_next("%h.next"))) ssa_operand_memory_d {
   struct ssa_operand_memory_d *next;
   char mem[1];
 };
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 1ea639d..f6f9dc9 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -1120,7 +1120,7 @@ uid_ssaname_map_hash (const void *item)
 void
 init_tree_ssa (struct function *fn)
 {
-  fn->gimple_df = ggc_alloc_cleared_gimple_df ();
+  fn->gimple_df = ggc_cleared_alloc<gimple_df> ();
   fn->gimple_df->default_defs = htab_create_ggc (20, uid_ssaname_map_hash,
 				                 uid_ssaname_map_eq, NULL);
   pt_solution_reset (&fn->gimple_df->escaped);
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index 02db6a5..b013149 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -196,7 +196,7 @@ set_range_info (tree name, enum value_range_type range_type, double_int min,
   /* Allocate if not available.  */
   if (ri == NULL)
     {
-      ri = ggc_alloc_cleared_range_info_def ();
+      ri = ggc_cleared_alloc<range_info_def> ();
       SSA_NAME_RANGE_INFO (name) = ri;
       ri->nonzero_bits = double_int::mask (TYPE_PRECISION (TREE_TYPE (name)));
     }
@@ -437,7 +437,7 @@ get_ptr_info (tree t)
   pi = SSA_NAME_PTR_INFO (t);
   if (pi == NULL)
     {
-      pi = ggc_alloc_cleared_ptr_info_def ();
+      pi = ggc_cleared_alloc<ptr_info_def> ();
       pt_solution_reset (&pi->pt);
       mark_ptr_info_alignment_unknown (pi);
       SSA_NAME_PTR_INFO (t) = pi;
@@ -481,7 +481,7 @@ duplicate_ssa_name_ptr_info (tree name, struct ptr_info_def *ptr_info)
   if (!ptr_info)
     return;
 
-  new_ptr_info = ggc_alloc_ptr_info_def ();
+  new_ptr_info = ggc_alloc<ptr_info_def> ();
   *new_ptr_info = *ptr_info;
 
   SSA_NAME_PTR_INFO (name) = new_ptr_info;
@@ -502,7 +502,7 @@ duplicate_ssa_name_range_info (tree name, enum value_range_type range_type,
   if (!range_info)
     return;
 
-  new_range_info = ggc_alloc_range_info_def ();
+  new_range_info = ggc_alloc<range_info_def> ();
   *new_range_info = *range_info;
 
   gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE);
diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
index b02bb6b..aa61187 100644
--- a/gcc/tree-streamer-in.c
+++ b/gcc/tree-streamer-in.c
@@ -176,7 +176,7 @@ unpack_ts_real_cst_value_fields (struct bitpack_d *bp, tree expr)
   for (i = 0; i < SIGSZ; i++)
     r.sig[i] = (unsigned long) bp_unpack_value (bp, HOST_BITS_PER_LONG);
 
-  rp = ggc_alloc_real_value ();
+  rp = ggc_alloc<real_value> ();
   memcpy (rp, &r, sizeof (REAL_VALUE_TYPE));
   TREE_REAL_CST_PTR (expr) = rp;
 }
@@ -188,7 +188,7 @@ unpack_ts_real_cst_value_fields (struct bitpack_d *bp, tree expr)
 static void
 unpack_ts_fixed_cst_value_fields (struct bitpack_d *bp, tree expr)
 {
-  FIXED_VALUE_TYPE *fp = ggc_alloc_fixed_value ();
+  FIXED_VALUE_TYPE *fp = ggc_alloc<fixed_value> ();
   fp->mode = bp_unpack_enum (bp, machine_mode, MAX_MACHINE_MODE);
   fp->data.low = bp_unpack_var_len_int (bp);
   fp->data.high = bp_unpack_var_len_int (bp);
diff --git a/gcc/tree.c b/gcc/tree.c
index 365faf2..9a3e7e9 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1577,7 +1577,7 @@ build_fixed (tree type, FIXED_VALUE_TYPE f)
   FIXED_VALUE_TYPE *fp;
 
   v = make_node (FIXED_CST);
-  fp = ggc_alloc_fixed_value ();
+  fp = ggc_alloc<fixed_value> ();
   memcpy (fp, &f, sizeof (FIXED_VALUE_TYPE));
 
   TREE_TYPE (v) = type;
@@ -1598,7 +1598,7 @@ build_real (tree type, REAL_VALUE_TYPE d)
      Consider doing it via real_convert now.  */
 
   v = make_node (REAL_CST);
-  dp = ggc_alloc_real_value ();
+  dp = ggc_alloc<real_value> ();
   memcpy (dp, &d, sizeof (REAL_VALUE_TYPE));
 
   TREE_TYPE (v) = type;
@@ -6390,7 +6390,7 @@ decl_priority_info (tree decl)
   h = (struct tree_priority_map *) *loc;
   if (!h)
     {
-      h = ggc_alloc_cleared_tree_priority_map ();
+      h = ggc_cleared_alloc<tree_priority_map> ();
       *loc = h;
       h->base.from = decl;
       h->init = DEFAULT_INIT_PRIORITY;
@@ -6473,7 +6473,7 @@ decl_debug_expr_insert (tree from, tree to)
   struct tree_decl_map *h;
   void **loc;
 
-  h = ggc_alloc_tree_decl_map ();
+  h = ggc_alloc<tree_decl_map> ();
   h->base.from = from;
   h->to = to;
   loc = htab_find_slot_with_hash (debug_expr_for_decl, h, DECL_UID (from),
@@ -6504,7 +6504,7 @@ decl_value_expr_insert (tree from, tree to)
   struct tree_decl_map *h;
   void **loc;
 
-  h = ggc_alloc_tree_decl_map ();
+  h = ggc_alloc<tree_decl_map> ();
   h->base.from = from;
   h->to = to;
   loc = htab_find_slot_with_hash (value_expr_for_decl, h, DECL_UID (from),
@@ -6545,7 +6545,7 @@ decl_debug_args_insert (tree from)
   if (debug_args_for_decl == NULL)
     debug_args_for_decl = htab_create_ggc (64, tree_vec_map_hash,
 					   tree_vec_map_eq, 0);
-  h = ggc_alloc_tree_vec_map ();
+  h = ggc_alloc<tree_vec_map> ();
   h->base.from = from;
   h->to = NULL;
   loc = htab_find_slot_with_hash (debug_args_for_decl, h, DECL_UID (from),
@@ -6728,7 +6728,7 @@ type_hash_add (hashval_t hashcode, tree type)
   struct type_hash *h;
   void **loc;
 
-  h = ggc_alloc_type_hash ();
+  h = ggc_alloc<type_hash> ();
   h->hash = hashcode;
   h->type = type;
   loc = htab_find_slot_with_hash (type_hash_table, h, hashcode, INSERT);
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index d9d740c..11461d0 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -99,7 +99,7 @@ decl_for_type_insert (tree type, tree decl)
   struct tree_type_map *h;
   void **slot;
 
-  h = ggc_alloc_tree_type_map ();
+  h = ggc_alloc<tree_type_map> ();
   h->type.from = type;
   h->decl = decl;
   slot = htab_find_slot_with_hash (decl_tree_for_type, h, TYPE_UID (type),
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 3b42faa..4c59d35 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -242,7 +242,7 @@ get_unnamed_section (unsigned int flags, void (*callback) (const void *),
 {
   section *sect;
 
-  sect = ggc_alloc_section ();
+  sect = ggc_alloc<section> ();
   sect->unnamed.common.flags = flags | SECTION_UNNAMED;
   sect->unnamed.callback = callback;
   sect->unnamed.data = data;
@@ -259,7 +259,7 @@ get_noswitch_section (unsigned int flags, noswitch_section_callback callback)
 {
   section *sect;
 
-  sect = ggc_alloc_section ();
+  sect = ggc_alloc<section> ();
   sect->noswitch.common.flags = flags | SECTION_NOSWITCH;
   sect->noswitch.callback = callback;
 
@@ -280,7 +280,7 @@ get_section (const char *name, unsigned int flags, tree decl)
   flags |= SECTION_NAMED;
   if (*slot == NULL)
     {
-      sect = ggc_alloc_section ();
+      sect = ggc_alloc<section> ();
       sect->named.common.flags = flags;
       sect->named.name = ggc_strdup (name);
       sect->named.decl = decl;
@@ -361,7 +361,7 @@ get_block_for_section (section *sect)
   block = (struct object_block *) *slot;
   if (block == NULL)
     {
-      block = ggc_alloc_cleared_object_block ();
+      block = ggc_cleared_alloc<object_block> ();
       block->sect = sect;
       *slot = block;
     }
@@ -3203,7 +3203,7 @@ build_constant_desc (tree exp)
   int labelno;
   tree decl;
 
-  desc = ggc_alloc_constant_descriptor_tree ();
+  desc = ggc_alloc<constant_descriptor_tree> ();
   desc->value = copy_constant (exp);
 
   /* Create a string containing the label name, in LABEL.  */
@@ -3607,7 +3607,7 @@ create_constant_pool (void)
 {
   struct rtx_constant_pool *pool;
 
-  pool = ggc_alloc_rtx_constant_pool ();
+  pool = ggc_alloc<rtx_constant_pool> ();
   pool->const_rtx_htab = htab_create_ggc (31, const_desc_rtx_hash,
 					  const_desc_rtx_eq, NULL);
   pool->first = NULL;
@@ -3673,7 +3673,7 @@ force_const_mem (enum machine_mode mode, rtx x)
     return copy_rtx (desc->mem);
 
   /* Otherwise, create a new descriptor.  */
-  desc = ggc_alloc_constant_descriptor_rtx ();
+  desc = ggc_alloc<constant_descriptor_rtx> ();
   *slot = desc;
 
   /* Align the location counter as required by EXP's data type.  */
@@ -5721,7 +5721,7 @@ record_tm_clone_pair (tree o, tree n)
   if (tm_clone_hash == NULL)
     tm_clone_hash = htab_create_ggc (32, tree_map_hash, tree_map_eq, 0);
 
-  h = ggc_alloc_tree_map ();
+  h = ggc_alloc<tree_map> ();
   h->hash = htab_hash_pointer (o);
   h->base.from = o;
   h->to = n;
diff --git a/gcc/varpool.c b/gcc/varpool.c
index 69172c6..45ff88d 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -135,7 +135,7 @@ varpool_call_variable_insertion_hooks (varpool_node *node)
 varpool_node *
 varpool_create_empty_node (void)
 {   
-  varpool_node *node = ggc_alloc_cleared_varpool_node ();
+  varpool_node *node = ggc_cleared_alloc<varpool_node> ();
   node->type = SYMTAB_VARIABLE;
   return node;
 }   
-- 
2.0.0.rc0

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 1/6] rm a bunch of _stat allocation functions
  2014-04-29 11:08 [PATH 0/6] ggc finalizers and TLC tsaunders
                   ` (3 preceding siblings ...)
  2014-04-29 11:09 ` [PATCH 6/6] move many members of target_globals out of gc memory tsaunders
@ 2014-04-29 11:09 ` tsaunders
  2014-04-29 12:19   ` Richard Biener
  2014-04-29 11:59 ` [PATCH 5/6] add finalizers to ggc tsaunders
  5 siblings, 1 reply; 18+ messages in thread
From: tsaunders @ 2014-04-29 11:09 UTC (permalink / raw)
  To: gcc-patches; +Cc: Trevor Saunders

From: Trevor Saunders <tsaunders@mozilla.com>

Hi,

C++ default args allow us to name the function foo instead of foo_stat with a
wrapper macro foo.

bootstrapped + regtested x86_64-unknown-linux-gnu, ok?

Trev

gcc/ChangeLog:

2014-04-23  tbsaunde  <tbsaunde@my.domain.org>

	* dwarf2out.c (tree_add_const_value_attribute): Call
	ggc_internal_cleared_alloc instead of ggc_alloc_cleared_atomic.
	* gengtype.c (write_typed_alloc_def): Call ggc_internal_<x>alloc
	instead of ggc_internal_<x>alloc_stat.
	* ggc-common.c (ggc_internal_cleared_alloc): Drop _stat suffix.
	(ggc_realloc): Likewise.
	* ggc-none.c (ggc_internal_alloc): Likewise.
	(ggc_internal_cleared_alloc): Likewise.
	* ggc-page.c: Likewise.
	* ggc.h (ggc_internal_alloc_stat): Likewise.
	(ggc_internal_alloc): Remove macro.
	(ggc_internal_cleared_alloc_stat): Drop _stat suffix.
	(ggc_internal_cleared_alloc): Remove macro.
	(GGC_RESIZEVEC): Adjust.
	(ggc_resizevar): Remove macro.
	(ggc_internal_vec_alloc_stat): Drop _stat suffix.
	(ggc_internal_cleared_vec_alloc_stat): Likewise.
	(ggc_internal_vec_cleared_alloc): Remove macro.
	(ggc_alloc_atomic_stat): Drop _stat suffix.
	(ggc_alloc_atomic): Remove macro.
	(ggc_alloc_cleared_atomic): Remove macro.
	(ggc_alloc_string_stat): Drop _stat suffix.
	(ggc_alloc_string): Remove macro.
	(ggc_alloc_rtx_def_stat): Adjust.
	(ggc_alloc_tree_node_stat): Likewise.
	(ggc_alloc_cleared_tree_node_stat): Likewise.
	(ggc_alloc_cleared_gimple_statement_stat): Likewise.
	(ggc_alloc_cleared_simd_clone_stat): Likewise.
	* gimple.c (gimple_build_omp_for): Likewise.
	(gimple_copy): Likewise.
	* stringpool.c (ggc_alloc_string_stat): Drop _stat suffix.
	* toplev.c (realloc_for_line_map): Adjust.
	* tree-data-ref.h (lambda_vector_new): Likewise.
	* tree-phinodes.c (allocate_phi_node): Likewise.
	* tree.c (grow_tree_vec_stat): Likewise.
	* vec.h (va_gc::reserve): Adjust.

gcc/java/ChangeLog:

2014-04-23  tbsaunde  <tbsaunde@my.domain.org>

	* constants.c (set_constant_entry): Adjust.
---
 gcc/dwarf2out.c      |  2 +-
 gcc/gengtype.c       |  2 +-
 gcc/ggc-common.c     | 10 ++++----
 gcc/ggc-none.c       |  4 ++--
 gcc/ggc-page.c       |  2 +-
 gcc/ggc.h            | 65 +++++++++++++++++++---------------------------------
 gcc/gimple.c         |  8 +++----
 gcc/java/constants.c |  4 ++--
 gcc/stringpool.c     |  4 ++--
 gcc/toplev.c         |  2 +-
 gcc/tree-data-ref.h  |  2 +-
 gcc/tree-phinodes.c  |  2 +-
 gcc/tree.c           |  2 +-
 gcc/vec.h            |  5 ++--
 14 files changed, 48 insertions(+), 66 deletions(-)

diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 1272326..6133fa3 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -15875,7 +15875,7 @@ tree_add_const_value_attribute (dw_die_ref die, tree t)
       if (size > 0 && (int) size == size)
 	{
 	  unsigned char *array = (unsigned char *)
-	    ggc_alloc_cleared_atomic (size);
+	    ggc_internal_cleared_alloc (size);
 
 	  if (native_encode_initializer (init, array, size))
 	    {
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 031004a..e8fcd9f 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -4975,7 +4975,7 @@ write_typed_alloc_def (outf_p f,
 	   (two_args ? ", " : ""),
 	   (quantity == vector) ? "n" : "");
   oprintf (f, "((%s%s *)", type_specifier, type_name);
-  oprintf (f, "(ggc_internal_%salloc_stat (", allocator_type);
+  oprintf (f, "(ggc_internal_%salloc (", allocator_type);
   if (variable_size)
     oprintf (f, "SIZE");
   else
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index 97c9b87..e1cc48e 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -174,22 +174,22 @@ ggc_mark_roots (void)
 
 /* Allocate a block of memory, then clear it.  */
 void *
-ggc_internal_cleared_alloc_stat (size_t size MEM_STAT_DECL)
+ggc_internal_cleared_alloc (size_t size MEM_STAT_DECL)
 {
-  void *buf = ggc_internal_alloc_stat (size PASS_MEM_STAT);
+  void *buf = ggc_internal_alloc (size PASS_MEM_STAT);
   memset (buf, 0, size);
   return buf;
 }
 
 /* Resize a block of memory, possibly re-allocating it.  */
 void *
-ggc_realloc_stat (void *x, size_t size MEM_STAT_DECL)
+ggc_realloc (void *x, size_t size MEM_STAT_DECL)
 {
   void *r;
   size_t old_size;
 
   if (x == NULL)
-    return ggc_internal_alloc_stat (size PASS_MEM_STAT);
+    return ggc_internal_alloc (size PASS_MEM_STAT);
 
   old_size = ggc_get_size (x);
 
@@ -211,7 +211,7 @@ ggc_realloc_stat (void *x, size_t size MEM_STAT_DECL)
       return x;
     }
 
-  r = ggc_internal_alloc_stat (size PASS_MEM_STAT);
+  r = ggc_internal_alloc (size PASS_MEM_STAT);
 
   /* Since ggc_get_size returns the size of the pool, not the size of the
      individually allocated object, we'd access parts of the old object
diff --git a/gcc/ggc-none.c b/gcc/ggc-none.c
index e690019..aad89bf 100644
--- a/gcc/ggc-none.c
+++ b/gcc/ggc-none.c
@@ -41,13 +41,13 @@ ggc_round_alloc_size (size_t requested_size)
 }
 
 void *
-ggc_internal_alloc_stat (size_t size MEM_STAT_DECL)
+ggc_internal_alloc (size_t size MEM_STAT_DECL)
 {
   return xmalloc (size);
 }
 
 void *
-ggc_internal_cleared_alloc_stat (size_t size MEM_STAT_DECL)
+ggc_internal_cleared_alloc (size_t size MEM_STAT_DECL)
 {
   return xcalloc (size, 1);
 }
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index ccc87ea..ae5e88a 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -1202,7 +1202,7 @@ ggc_round_alloc_size (size_t requested_size)
 /* Allocate a chunk of memory of SIZE bytes.  Its contents are undefined.  */
 
 void *
-ggc_internal_alloc_stat (size_t size MEM_STAT_DECL)
+ggc_internal_alloc (size_t size MEM_STAT_DECL)
 {
   size_t order, word, bit, object_offset, object_size;
   struct page_entry *entry;
diff --git a/gcc/ggc.h b/gcc/ggc.h
index 55f3fe9..0af69f5 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -136,59 +136,44 @@ extern void gt_pch_save (FILE *f);
 /* Allocation.  */
 
 /* The internal primitive.  */
-extern void *ggc_internal_alloc_stat (size_t MEM_STAT_DECL)
-  ATTRIBUTE_MALLOC;
+extern void *ggc_internal_alloc (size_t CXX_MEM_STAT_INFO) ATTRIBUTE_MALLOC;
 
 extern size_t ggc_round_alloc_size (size_t requested_size);
 
-#define ggc_internal_alloc(s) ggc_internal_alloc_stat (s MEM_STAT_INFO)
-
 /* Allocates cleared memory.  */
-extern void *ggc_internal_cleared_alloc_stat (size_t MEM_STAT_DECL)
+extern void *ggc_internal_cleared_alloc (size_t CXX_MEM_STAT_INFO)
   ATTRIBUTE_MALLOC;
-#define ggc_internal_cleared_alloc(s) ggc_internal_cleared_alloc_stat (s MEM_STAT_INFO)
 
 /* Resize a block.  */
-extern void *ggc_realloc_stat (void *, size_t MEM_STAT_DECL);
+extern void *ggc_realloc (void *, size_t CXX_MEM_STAT_INFO);
 
 /* Free a block.  To be used when known for certain it's not reachable.  */
 extern void ggc_free (void *);
 
 extern void dump_ggc_loc_statistics (bool);
 
-/* Reallocators.  */
+/* Reallocator.  */
 #define GGC_RESIZEVEC(T, P, N) \
-    ((T *) ggc_realloc_stat ((P), (N) * sizeof (T) MEM_STAT_INFO))
-
-#define GGC_RESIZEVAR(T, P, N)                          \
-    ((T *) ggc_realloc_stat ((P), (N) MEM_STAT_INFO))
+    ((T *) ggc_realloc ((P), (N) * sizeof (T) MEM_STAT_INFO))
 
 static inline void *
-ggc_internal_vec_alloc_stat (size_t s, size_t c MEM_STAT_DECL)
+ggc_internal_vec_alloc (size_t s, size_t c MEM_STAT_DECL)
 {
-    return ggc_internal_alloc_stat (c * s PASS_MEM_STAT);
+    return ggc_internal_alloc (c * s PASS_MEM_STAT);
 }
 
 static inline void *
-ggc_internal_cleared_vec_alloc_stat (size_t s, size_t c MEM_STAT_DECL)
+ggc_internal_cleared_vec_alloc (size_t s, size_t c CXX_MEM_STAT_INFO)
 {
-    return ggc_internal_cleared_alloc_stat (c * s PASS_MEM_STAT);
+    return ggc_internal_cleared_alloc (c * s PASS_MEM_STAT);
 }
 
-#define ggc_internal_cleared_vec_alloc(s, c) \
-    (ggc_internal_cleared_vec_alloc_stat ((s), (c) MEM_STAT_INFO))
-
 static inline void *
-ggc_alloc_atomic_stat (size_t s MEM_STAT_DECL)
+ggc_alloc_atomic (size_t s CXX_MEM_STAT_INFO)
 {
-    return ggc_internal_alloc_stat (s PASS_MEM_STAT);
+    return ggc_internal_alloc (s PASS_MEM_STAT);
 }
 
-#define ggc_alloc_atomic(S)  (ggc_alloc_atomic_stat ((S) MEM_STAT_INFO))
-
-#define ggc_alloc_cleared_atomic(S)             \
-    (ggc_internal_cleared_alloc_stat ((S) MEM_STAT_INFO))
-
 extern void *ggc_cleared_alloc_htab_ignore_args (size_t, size_t)
   ATTRIBUTE_MALLOC;
 
@@ -213,13 +198,11 @@ extern void ggc_splay_dont_free (void *, void *);
 /* Allocate a gc-able string, and fill it with LENGTH bytes from CONTENTS.
    If LENGTH is -1, then CONTENTS is assumed to be a
    null-terminated string and the memory sized accordingly.  */
-extern const char *ggc_alloc_string_stat (const char *contents, int length
-                                          MEM_STAT_DECL);
-
-#define ggc_alloc_string(c, l) ggc_alloc_string_stat (c, l MEM_STAT_INFO)
+extern const char *ggc_alloc_string (const char *contents, int length
+                                     CXX_MEM_STAT_INFO);
 
 /* Make a copy of S, in GC-able memory.  */
-#define ggc_strdup(S) ggc_alloc_string_stat ((S), -1 MEM_STAT_INFO)
+#define ggc_strdup(S) ggc_alloc_string ((S), -1 MEM_STAT_INFO)
 
 /* Invoke the collector.  Garbage collection occurs only when this
    function is called, not during allocations.  */
@@ -253,35 +236,35 @@ extern void init_ggc_heuristics (void);
 /* Memory statistics passing versions of some allocators.  Too few of them to
    make gengtype produce them, so just define the needed ones here.  */
 static inline struct rtx_def *
-ggc_alloc_rtx_def_stat (size_t s MEM_STAT_DECL)
+ggc_alloc_rtx_def_stat (size_t s CXX_MEM_STAT_INFO)
 {
-  return (struct rtx_def *) ggc_internal_alloc_stat (s PASS_MEM_STAT);
+  return (struct rtx_def *) ggc_internal_alloc (s PASS_MEM_STAT);
 }
 
 static inline union tree_node *
-ggc_alloc_tree_node_stat (size_t s MEM_STAT_DECL)
+ggc_alloc_tree_node_stat (size_t s CXX_MEM_STAT_INFO)
 {
-  return (union tree_node *) ggc_internal_alloc_stat (s PASS_MEM_STAT);
+  return (union tree_node *) ggc_internal_alloc (s PASS_MEM_STAT);
 }
 
 static inline union tree_node *
-ggc_alloc_cleared_tree_node_stat (size_t s MEM_STAT_DECL)
+ggc_alloc_cleared_tree_node_stat (size_t s CXX_MEM_STAT_INFO)
 {
-  return (union tree_node *) ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT);
+  return (union tree_node *) ggc_internal_cleared_alloc (s PASS_MEM_STAT);
 }
 
 static inline struct gimple_statement_base *
-ggc_alloc_cleared_gimple_statement_stat (size_t s MEM_STAT_DECL)
+ggc_alloc_cleared_gimple_statement_stat (size_t s CXX_MEM_STAT_INFO)
 {
   return (struct gimple_statement_base *)
-    ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT);
+    ggc_internal_cleared_alloc (s PASS_MEM_STAT);
 }
 
 static inline struct simd_clone *
-ggc_alloc_cleared_simd_clone_stat (size_t s MEM_STAT_DECL)
+ggc_alloc_cleared_simd_clone_stat (size_t s CXX_MEM_STAT_INFO)
 {
   return (struct simd_clone *)
-    ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT);
+    ggc_internal_cleared_alloc (s PASS_MEM_STAT);
 }
 
 #endif
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 8552a17..fc6ecb9 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -836,8 +836,7 @@ gimple_build_omp_for (gimple_seq body, int kind, tree clauses, size_t collapse,
   gimple_omp_for_set_kind (p, kind);
   p->collapse = collapse;
   p->iter =  static_cast <struct gimple_omp_for_iter *> (
-   ggc_internal_cleared_vec_alloc_stat (sizeof (*p->iter),
-					collapse MEM_STAT_INFO));
+   ggc_internal_cleared_vec_alloc (sizeof (*p->iter), collapse));
 
   if (pre_body)
     gimple_omp_for_set_pre_body (p, pre_body);
@@ -1667,9 +1666,8 @@ gimple_copy (gimple stmt)
 	      as_a <gimple_statement_omp_for *> (copy);
 	    omp_for_copy->iter =
 	      static_cast <struct gimple_omp_for_iter *> (
-		  ggc_internal_vec_alloc_stat (sizeof (struct gimple_omp_for_iter),
-					       gimple_omp_for_collapse (stmt)
-					       MEM_STAT_INFO));
+		  ggc_internal_vec_alloc (sizeof (struct gimple_omp_for_iter),
+					  gimple_omp_for_collapse (stmt)));
           }
 	  for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
 	    {
diff --git a/gcc/java/constants.c b/gcc/java/constants.c
index 7e9cf2e..c0295e9 100644
--- a/gcc/java/constants.c
+++ b/gcc/java/constants.c
@@ -46,8 +46,8 @@ set_constant_entry (CPool *cpool, int index, int tag, jword value)
   if (cpool->data == NULL)
     {
       cpool->capacity = 100;
-      cpool->tags = (uint8 *) ggc_alloc_cleared_atomic (sizeof (uint8)
-						* cpool->capacity);
+      cpool->tags = (uint8 *) ggc_internal_cleared_alloc (sizeof (uint8)
+							  * cpool->capacity);
       cpool->data = ggc_alloc_cleared_vec_cpool_entry (sizeof
 						       (union cpool_entry),
 						       cpool->capacity);
diff --git a/gcc/stringpool.c b/gcc/stringpool.c
index 4b6900c..e317525 100644
--- a/gcc/stringpool.c
+++ b/gcc/stringpool.c
@@ -79,7 +79,7 @@ alloc_node (cpp_hash_table *table ATTRIBUTE_UNUSED)
    nul-terminated string, and the length is calculated using strlen.  */
 
 const char *
-ggc_alloc_string_stat (const char *contents, int length MEM_STAT_DECL)
+ggc_alloc_string (const char *contents, int length MEM_STAT_DECL)
 {
   char *result;
 
@@ -91,7 +91,7 @@ ggc_alloc_string_stat (const char *contents, int length MEM_STAT_DECL)
   if (length == 1 && ISDIGIT (contents[0]))
     return digit_string (contents[0] - '0');
 
-  result = (char *) ggc_alloc_atomic_stat (length + 1 PASS_MEM_STAT);
+  result = (char *) ggc_internal_cleared_alloc (length + 1 PASS_MEM_STAT);
   memcpy (result, contents, length);
   result[length] = '\0';
   return (const char *) result;
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 0f7d452..9535bd0 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -957,7 +957,7 @@ init_asm_output (const char *name)
 static void *
 realloc_for_line_map (void *ptr, size_t len)
 {
-  return GGC_RESIZEVAR (void, ptr, len);
+  return ggc_realloc (ptr, len);
 }
 
 /* A helper function: used as the allocator function for
diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h
index 9d819e4..8810a3e 100644
--- a/gcc/tree-data-ref.h
+++ b/gcc/tree-data-ref.h
@@ -565,7 +565,7 @@ lambda_vector_gcd (lambda_vector vector, int size)
 static inline lambda_vector
 lambda_vector_new (int size)
 {
-  return (lambda_vector) ggc_alloc_cleared_atomic (sizeof (int) * size);
+  return (lambda_vector) ggc_internal_cleared_alloc (sizeof (int) * size);
 }
 
 /* Clear out vector VEC1 of length SIZE.  */
diff --git a/gcc/tree-phinodes.c b/gcc/tree-phinodes.c
index 0be431e..5bd8233 100644
--- a/gcc/tree-phinodes.c
+++ b/gcc/tree-phinodes.c
@@ -124,7 +124,7 @@ allocate_phi_node (size_t len)
   else
     {
       phi = static_cast <gimple_statement_phi *> (
-	ggc_internal_alloc_stat (size MEM_STAT_INFO));
+	ggc_internal_alloc (size));
       if (GATHER_STATISTICS)
 	{
 	  enum gimple_alloc_kind kind = gimple_alloc_kind (GIMPLE_PHI);
diff --git a/gcc/tree.c b/gcc/tree.c
index 8b44ecc..aa74fd0 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1892,7 +1892,7 @@ grow_tree_vec_stat (tree v, int len MEM_STAT_DECL)
 
   record_node_allocation_statistics (TREE_VEC, length - oldlength);
 
-  v = (tree) ggc_realloc_stat (v, length PASS_MEM_STAT);
+  v = (tree) ggc_realloc (v, length PASS_MEM_STAT);
 
   TREE_VEC_LENGTH (v) = len;
 
diff --git a/gcc/vec.h b/gcc/vec.h
index 5873023..2e5313d 100644
--- a/gcc/vec.h
+++ b/gcc/vec.h
@@ -48,9 +48,10 @@ along with GCC; see the file COPYING3.  If not see
      weak.  There are files compiled with -DGENERATOR_FILE that already
      include ggc.h.  We only need to provide these definitions if ggc.h
      has not been included.  Sigh.  */
+
   extern void ggc_free (void *);
   extern size_t ggc_round_alloc_size (size_t requested_size);
-  extern void *ggc_realloc_stat (void *, size_t MEM_STAT_DECL);
+  extern void *ggc_realloc (void *, size_t CXX_MEM_STAT_INFO);
 #  endif  // GCC_GGC_H
 #endif	// VEC_GC_ENABLED
 
@@ -396,7 +397,7 @@ va_gc::reserve (vec<T, A, vl_embed> *&v, unsigned reserve, bool exact
   size = vec_offset + alloc * elt_size;
 
   unsigned nelem = v ? v->length () : 0;
-  v = static_cast <vec<T, A, vl_embed> *> (::ggc_realloc_stat (v, size
+  v = static_cast <vec<T, A, vl_embed> *> (::ggc_realloc (v, size
 							       PASS_MEM_STAT));
   v->embedded_init (alloc, nelem);
 }
-- 
2.0.0.rc0

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 4/6] remove unused function
  2014-04-29 11:08 [PATH 0/6] ggc finalizers and TLC tsaunders
  2014-04-29 11:09 ` [PATCH 2/6] don't have gengtype autocreate allocation macros for variably sized types tsaunders
  2014-04-29 11:09 ` [PATCH 3/6] use templates instead of gengtype for typed allocation functions tsaunders
@ 2014-04-29 11:09 ` tsaunders
  2014-04-29 12:25   ` Richard Biener
  2014-04-29 11:09 ` [PATCH 6/6] move many members of target_globals out of gc memory tsaunders
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 18+ messages in thread
From: tsaunders @ 2014-04-29 11:09 UTC (permalink / raw)
  To: gcc-patches; +Cc: Trevor Saunders

From: Trevor Saunders <tsaunders@mozilla.com>

Hi,

its unused so rm it.

bootstrapped + regtested on x86_64-unknown-linux-gnu ok?

Trev

gcc/ChangeLog:

	*ggc.h (ggc_alloc_cleared_simd_clone_stat): Remove function.
---
 gcc/ggc.h | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/gcc/ggc.h b/gcc/ggc.h
index 2c567de..50fb199 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -279,11 +279,4 @@ ggc_alloc_cleared_gimple_statement_stat (size_t s CXX_MEM_STAT_INFO)
     ggc_internal_cleared_alloc (s PASS_MEM_STAT);
 }
 
-static inline struct simd_clone *
-ggc_alloc_cleared_simd_clone_stat (size_t s CXX_MEM_STAT_INFO)
-{
-  return (struct simd_clone *)
-    ggc_internal_cleared_alloc (s PASS_MEM_STAT);
-}
-
 #endif
-- 
2.0.0.rc0

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 6/6] move many members of target_globals out of gc memory
  2014-04-29 11:08 [PATH 0/6] ggc finalizers and TLC tsaunders
                   ` (2 preceding siblings ...)
  2014-04-29 11:09 ` [PATCH 4/6] remove unused function tsaunders
@ 2014-04-29 11:09 ` tsaunders
  2014-04-29 11:09 ` [PATCH 1/6] rm a bunch of _stat allocation functions tsaunders
  2014-04-29 11:59 ` [PATCH 5/6] add finalizers to ggc tsaunders
  5 siblings, 0 replies; 18+ messages in thread
From: tsaunders @ 2014-04-29 11:09 UTC (permalink / raw)
  To: gcc-patches; +Cc: Trevor Saunders

From: Trevor Saunders <tsaunders@mozilla.com>

Hi,

add a user of gc finalizers.

bootstrapped + regtested on x86_64-unknown-linux-gnu, ok?

Trev

gcc/ChangeLog:

	* target-globals.c (target_globals::~target_globals): new destructor.
	(target_globals_extra): Move out of save_target_globals.
	(save_target_globals): Adjust.
	* target-globals.h (target_globals): Mark members that don't point
	into gc memory GTY((skip)).
---
 gcc/target-globals.c | 56 +++++++++++++++++++++++++++++++++-------------------
 gcc/target-globals.h | 16 ++++++++-------
 2 files changed, 45 insertions(+), 27 deletions(-)

diff --git a/gcc/target-globals.c b/gcc/target-globals.c
index 5f1a208..8a64d3c 100644
--- a/gcc/target-globals.c
+++ b/gcc/target-globals.c
@@ -64,36 +64,52 @@ struct target_globals default_target_globals = {
   &default_target_lower_subreg
 };
 
+target_globals::    ~target_globals ()
+{
+  /* default_target_globals is weird and statically allocated, so don't try and
+     free its members.  */
+  if (this == &default_target_globals)
+    return;
+
+  free (regs);
+  free (hard_regs);
+  free (reload);
+  free (expmed);
+  free (ira);
+  free (ira_int);
+  free (lra_int);
+}
+
+struct target_globals_extra
+{
+  struct target_globals g;
+  struct target_flag_state flag_state;
+  struct target_optabs optabs;
+  struct target_cfgloop cfgloop;
+  struct target_builtins builtins;
+  struct target_gcse gcse;
+  struct target_bb_reorder bb_reorder;
+  struct target_lower_subreg lower_subreg;
+};
+
 struct target_globals *
 save_target_globals (void)
 {
   struct target_globals *g;
-  struct target_globals_extra {
-    struct target_globals g;
-    struct target_flag_state flag_state;
-    struct target_optabs optabs;
-    struct target_cfgloop cfgloop;
-    struct target_builtins builtins;
-    struct target_gcse gcse;
-    struct target_bb_reorder bb_reorder;
-    struct target_lower_subreg lower_subreg;
-  } *p;
-  p = (struct target_globals_extra *)
-      ggc_internal_cleared_alloc (sizeof (struct target_globals_extra));
+  target_globals_extra *p = ggc_cleared_alloc<target_globals_extra> ();
   g = (struct target_globals *) p;
   g->flag_state = &p->flag_state;
-  g->regs = ggc_internal_cleared_alloc (sizeof (struct target_regs));
+  g->regs = XCNEW (target_regs);
   g->rtl = ggc_cleared_alloc<target_rtl> ();
-  g->hard_regs
-    = ggc_internal_cleared_alloc (sizeof (struct target_hard_regs));
-  g->reload = ggc_internal_cleared_alloc (sizeof (struct target_reload));
-  g->expmed =  ggc_internal_cleared_alloc (sizeof (struct target_expmed));
+  g->hard_regs = XCNEW (target_hard_regs);
+  g->reload = XCNEW (target_reload);
+  g->expmed =  XCNEW (target_expmed);
   g->optabs = &p->optabs;
   g->libfuncs = ggc_cleared_alloc<target_libfuncs> ();
   g->cfgloop = &p->cfgloop;
-  g->ira = ggc_internal_cleared_alloc (sizeof (struct target_ira));
-  g->ira_int = ggc_internal_cleared_alloc (sizeof (struct target_ira_int));
-  g->lra_int = ggc_internal_cleared_alloc (sizeof (struct target_lra_int));
+  g->ira = XCNEW (target_ira);
+  g->ira_int = XCNEW (target_ira_int);
+  g->lra_int = XCNEW (target_lra_int);
   g->builtins = &p->builtins;
   g->gcse = &p->gcse;
   g->bb_reorder = &p->bb_reorder;
diff --git a/gcc/target-globals.h b/gcc/target-globals.h
index e848a01..82fd4f2 100644
--- a/gcc/target-globals.h
+++ b/gcc/target-globals.h
@@ -40,18 +40,20 @@ extern struct target_lower_subreg *this_target_lower_subreg;
 #endif
 
 struct GTY(()) target_globals {
+    ~target_globals ();
+
   struct target_flag_state *GTY((skip)) flag_state;
-  void *GTY((atomic)) regs;
+  void *GTY((skip)) regs;
   struct target_rtl *rtl;
-  void *GTY((atomic)) hard_regs;
-  void *GTY((atomic)) reload;
-  void *GTY((atomic)) expmed;
+  void *GTY((skip)) hard_regs;
+  void *GTY((skip)) reload;
+  void *GTY((skip)) expmed;
   struct target_optabs *GTY((skip)) optabs;
   struct target_libfuncs *libfuncs;
   struct target_cfgloop *GTY((skip)) cfgloop;
-  void *GTY((atomic)) ira;
-  void *GTY((atomic)) ira_int;
-  void *GTY((atomic)) lra_int;
+  void *GTY((skip)) ira;
+  void *GTY((skip)) ira_int;
+  void *GTY((skip)) lra_int;
   struct target_builtins *GTY((skip)) builtins;
   struct target_gcse *GTY((skip)) gcse;
   struct target_bb_reorder *GTY((skip)) bb_reorder;
-- 
2.0.0.rc0

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 2/6] don't have gengtype autocreate allocation macros for variably sized types
  2014-04-29 11:08 [PATH 0/6] ggc finalizers and TLC tsaunders
@ 2014-04-29 11:09 ` tsaunders
  2014-04-29 12:32   ` Richard Biener
  2014-04-29 11:09 ` [PATCH 3/6] use templates instead of gengtype for typed allocation functions tsaunders
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 18+ messages in thread
From: tsaunders @ 2014-04-29 11:09 UTC (permalink / raw)
  To: gcc-patches; +Cc: Trevor Saunders

From: Trevor Saunders <tsaunders@mozilla.com>

Hi,

	the template allocation functions won't work with things that are
actually variably sized, so its simpler to stop relying on gengtype for them
first.  However it turns out most of the usage of variably sized things in
gengtype is to deal with gengtype badness instead of actually variably sized
things so the next patch will remove a bit of the mess in this one.

bootstrapped + regtested on x86_64-unknown-linux-gnu, ok?

Trev

gcc/ChangeLog:

2014-04-23  Trevor Saunders  <tsaunders@mozilla.com>

	* gengtype.c (write_typed_alloc_def): Don't write anything if the type
	is variably sized.
	* ggc.h: Adjust.
	* tree-ssa-operands.c (ssa_operand_alloc): Likewise.
	* tree.c (build_string): Likewise.
	(build_omp_clause): Likewise.
	* varasm.c (create_block_symbol): Likewise.

gcc/c/ChangeLog:

2014-04-23  Trevor Saunders  <tsaunders@mozilla.com>

	* c-decl.c (finish_struct): Adjust.
	(finish_enum): Likewise.

gcc/java/ChangeLog:

2014-04-23  Trevor Saunders  <tsaunders@mozilla.com>

	* class.c (add_method_1): Adjust.
	* constants.c (set_constant_entry): Likewise.
	* decl.c (java_dup_lang_specific_decl): Likewise.
	* java-tree.h (MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC): Likewise.
	(MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC): Likewise.
	* jcf-reader.c (jcf_parse_constant_pool): Adjust.

gcc/objc/ChangeLog:

2014-04-23  Trevor Saunders  <tsaunders@mozilla.com>

	* objc-act.h: Adjust.

gcc/cp/ChangeLog:

2014-04-23  Trevor Saunders  <tsaunders@mozilla.com>

	* class.c (sorted_fields_type_new): Adjust.
	* cp-tree.h (more_aggr_init_expr_args_p): Likewise.
	* lex.c (retrofit_lang_decl): Likewise.
	(cxx_dup_lang_specific_decl): Likewise.
	(copy_lang_type): Likewise.
	(cxx_make_type): Likewise.

gcc/fortran/ChangeLog:

2014-04-23  Trevor Saunders  <tsaunders@mozilla.com>

	* trans-decl.c (gfc_allocate_lang_decl): Adjust.
	* trans-types.c (gfc_get_nodesc_array_type): Likewise.
	(gfc_get_array_type_bounds): Likewise.
	(gfc_nonrestricted_type): Likewise.
---
 gcc/c/c-decl.c            |  8 +++++---
 gcc/cp/class.c            |  2 +-
 gcc/cp/cp-tree.h          |  3 ++-
 gcc/cp/lex.c              |  9 +++++----
 gcc/fortran/trans-decl.c  |  5 +++--
 gcc/fortran/trans-types.c | 13 ++++++++-----
 gcc/gengtype.c            |  3 +++
 gcc/ggc.h                 |  2 +-
 gcc/java/class.c          |  3 ++-
 gcc/java/constants.c      |  6 +++---
 gcc/java/decl.c           |  2 +-
 gcc/java/java-tree.h      |  6 ++++--
 gcc/java/jcf-reader.c     |  3 ++-
 gcc/objc/objc-act.h       |  3 ++-
 gcc/tree-ssa-operands.c   |  4 ++--
 gcc/tree.c                |  4 ++--
 gcc/varasm.c              |  2 +-
 17 files changed, 47 insertions(+), 31 deletions(-)

diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index e30876c..e8b8166 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -7423,8 +7423,9 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
 	  ensure that this lives as long as the rest of the struct decl.
 	  All decls in an inline function need to be saved.  */
 
-	space = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
-	space2 = ggc_alloc_sorted_fields_type
+	space = (struct lang_type *) ggc_internal_cleared_alloc
+	  (sizeof (struct lang_type));
+	space2 = (sorted_fields_type *) ggc_internal_alloc
 	  (sizeof (struct sorted_fields_type) + len * sizeof (tree));
 
 	len = 0;
@@ -7704,7 +7705,8 @@ finish_enum (tree enumtype, tree values, tree attributes)
 
   /* Record the min/max values so that we can warn about bit-field
      enumerations that are too small for the values.  */
-  lt = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+  lt = (struct lang_type *) ggc_internal_cleared_alloc
+    (sizeof (struct lang_type));
   lt->enum_min = minnode;
   lt->enum_max = maxnode;
   TYPE_LANG_SPECIFIC (enumtype) = lt;
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 334bfd5..86058b5 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -6490,7 +6490,7 @@ static struct sorted_fields_type *
 sorted_fields_type_new (int n)
 {
   struct sorted_fields_type *sft;
-  sft = ggc_alloc_sorted_fields_type (sizeof (struct sorted_fields_type)
+  sft = (sorted_fields_type *) ggc_internal_alloc (sizeof (sorted_fields_type)
 				      + n * sizeof (tree));
   sft->len = n;
 
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f459e55..9fbc7f8 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3586,7 +3586,8 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
   do {									\
     if (TYPE_LANG_SPECIFIC (NODE) == NULL)				\
       {									\
-	TYPE_LANG_SPECIFIC (NODE) = ggc_alloc_cleared_lang_type		\
+	TYPE_LANG_SPECIFIC (NODE)                                       \
+	= (struct lang_type *) ggc_internal_cleared_alloc		\
 	 (sizeof (struct lang_type_ptrmem));				\
 	TYPE_LANG_SPECIFIC (NODE)->u.ptrmem.h.is_lang_type_class = 0;	\
       }									\
diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
index 3fe275e..46c28ae 100644
--- a/gcc/cp/lex.c
+++ b/gcc/cp/lex.c
@@ -555,7 +555,7 @@ retrofit_lang_decl (tree t)
   else
     gcc_unreachable ();
 
-  ld = ggc_alloc_cleared_lang_decl (size);
+  ld = (struct lang_decl *) ggc_internal_cleared_alloc (size);
 
   ld->u.base.selector = sel;
 
@@ -597,7 +597,7 @@ cxx_dup_lang_specific_decl (tree node)
   else
     gcc_unreachable ();
 
-  ld = ggc_alloc_lang_decl (size);
+  ld = (struct lang_decl *) ggc_internal_alloc (size);
   memcpy (ld, DECL_LANG_SPECIFIC (node), size);
   DECL_LANG_SPECIFIC (node) = ld;
 
@@ -635,7 +635,7 @@ copy_lang_type (tree node)
     size = sizeof (struct lang_type);
   else
     size = sizeof (struct lang_type_ptrmem);
-  lt = ggc_alloc_lang_type (size);
+  lt = (struct lang_type *) ggc_internal_alloc (size);
   memcpy (lt, TYPE_LANG_SPECIFIC (node), size);
   TYPE_LANG_SPECIFIC (node) = lt;
 
@@ -668,7 +668,8 @@ cxx_make_type (enum tree_code code)
       || code == BOUND_TEMPLATE_TEMPLATE_PARM)
     {
       struct lang_type *pi
-          = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+          = (struct lang_type *) ggc_internal_cleared_alloc
+	  (sizeof (struct lang_type));
 
       TYPE_LANG_SPECIFIC (t) = pi;
       pi->u.c.h.is_lang_type_class = 1;
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index cf7b661..beb99a6 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -615,8 +615,9 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
 void
 gfc_allocate_lang_decl (tree decl)
 {
-  DECL_LANG_SPECIFIC (decl) = ggc_alloc_cleared_lang_decl(sizeof
-							  (struct lang_decl));
+  DECL_LANG_SPECIFIC (decl)
+    = (struct lang_decl *) ggc_internal_cleared_alloc (sizeof
+						       (struct lang_decl));
 }
 
 /* Remember a symbol to generate initialization/cleanup code at function
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 243feb7..84503ce 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -1512,7 +1512,8 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, gfc_packed packed,
 
   GFC_ARRAY_TYPE_P (type) = 1;
   TYPE_LANG_SPECIFIC (type)
-      = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+      = (struct lang_type *) ggc_internal_cleared_alloc
+      (sizeof (struct lang_type));
 
   known_stride = (packed != PACKED_NO);
   known_offset = 1;
@@ -1815,7 +1816,8 @@ gfc_get_array_type_bounds (tree etype, int dimen, int codimen, tree * lbound,
 
   GFC_DESCRIPTOR_TYPE_P (fat_type) = 1;
   TYPE_LANG_SPECIFIC (fat_type)
-    = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+    = (struct lang_type *) ggc_internal_cleared_alloc
+    (sizeof (struct lang_type));
 
   GFC_TYPE_ARRAY_RANK (fat_type) = dimen;
   GFC_TYPE_ARRAY_CORANK (fat_type) = codimen;
@@ -1990,7 +1992,8 @@ gfc_nonrestricted_type (tree t)
 
   if (!TYPE_LANG_SPECIFIC (t))
     TYPE_LANG_SPECIFIC (t)
-      = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+      = (struct lang_type *) ggc_internal_cleared_alloc
+      (sizeof (struct lang_type));
   /* If we're dealing with this very node already further up
      the call chain (recursion via pointers and struct members)
      we haven't yet determined if we really need a new type node.
@@ -2042,8 +2045,8 @@ gfc_nonrestricted_type (tree t)
 		  if (dataptr_type != GFC_TYPE_ARRAY_DATAPTR_TYPE (t))
 		    {
 		      TYPE_LANG_SPECIFIC (ret)
-			= ggc_alloc_cleared_lang_type (sizeof (struct
-							       lang_type));
+			= (struct lang_type *) ggc_internal_cleared_alloc
+		       	(sizeof (struct lang_type));
 		      *TYPE_LANG_SPECIFIC (ret) = *TYPE_LANG_SPECIFIC (t);
 		      GFC_TYPE_ARRAY_DATAPTR_TYPE (ret) = dataptr_type;
 		    }
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index e8fcd9f..b3c966c 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -4967,6 +4967,9 @@ write_typed_alloc_def (outf_p f,
                        enum alloc_quantity quantity)
 {
   bool two_args = variable_size && (quantity == vector);
+  if (variable_size)
+    return;
+
   gcc_assert (f != NULL);
   const char *type_name_as_id = filter_type_name (type_name);
   oprintf (f, "#define ggc_alloc_%s%s", allocator_type, type_name_as_id);
diff --git a/gcc/ggc.h b/gcc/ggc.h
index 0af69f5..736305d 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -230,7 +230,7 @@ extern void stringpool_statistics (void);
 extern void init_ggc_heuristics (void);
 
 #define ggc_alloc_rtvec_sized(NELT)				\
-  ggc_alloc_rtvec_def (sizeof (struct rtvec_def)		\
+  (rtvec_def *) ggc_internal_alloc (sizeof (struct rtvec_def)		\
 		       + ((NELT) - 1) * sizeof (rtx))		\
 
 /* Memory statistics passing versions of some allocators.  Too few of them to
diff --git a/gcc/java/class.c b/gcc/java/class.c
index bbe7c86..94c2568 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -765,7 +765,8 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type)
   DECL_CONTEXT (fndecl) = this_class;
 
   DECL_LANG_SPECIFIC (fndecl)
-    = ggc_alloc_cleared_lang_decl(sizeof (struct lang_decl));
+    = (struct lang_decl *) ggc_internal_cleared_alloc
+    (sizeof (struct lang_decl));
   DECL_LANG_SPECIFIC (fndecl)->desc = LANG_DECL_FUNC;
 
   /* Initialize the static initializer test table.  */
diff --git a/gcc/java/constants.c b/gcc/java/constants.c
index c0295e9..51449ef 100644
--- a/gcc/java/constants.c
+++ b/gcc/java/constants.c
@@ -48,9 +48,9 @@ set_constant_entry (CPool *cpool, int index, int tag, jword value)
       cpool->capacity = 100;
       cpool->tags = (uint8 *) ggc_internal_cleared_alloc (sizeof (uint8)
 							  * cpool->capacity);
-      cpool->data = ggc_alloc_cleared_vec_cpool_entry (sizeof
-						       (union cpool_entry),
-						       cpool->capacity);
+      cpool->data = (cpool_entry *) ggc_internal_cleared_alloc (sizeof
+						       (union cpool_entry)
+						       * cpool->capacity);
       cpool->count = 1;
     }
   if (index >= cpool->capacity)
diff --git a/gcc/java/decl.c b/gcc/java/decl.c
index 53d6f89..9f2f0ca 100644
--- a/gcc/java/decl.c
+++ b/gcc/java/decl.c
@@ -1646,7 +1646,7 @@ java_dup_lang_specific_decl (tree node)
     return;
 
   lang_decl_size = sizeof (struct lang_decl);
-  x = ggc_alloc_lang_decl (lang_decl_size);
+  x = (struct lang_decl *) ggc_internal_alloc (lang_decl_size);
   memcpy (x, DECL_LANG_SPECIFIC (node), lang_decl_size);
   DECL_LANG_SPECIFIC (node) = x;
 }
diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
index 806d2d7..43a8258 100644
--- a/gcc/java/java-tree.h
+++ b/gcc/java/java-tree.h
@@ -700,7 +700,8 @@ union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
   if (DECL_LANG_SPECIFIC (T) == NULL)                                \
     {                                                                \
       DECL_LANG_SPECIFIC ((T))                                       \
-        = ggc_alloc_cleared_lang_decl (sizeof (struct lang_decl));   \
+        = (struct lang_decl *) ggc_internal_cleared_alloc            \
+      (sizeof (struct lang_decl));                                   \
       DECL_LANG_SPECIFIC (T)->desc = LANG_DECL_VAR;                  \
     }
 
@@ -826,7 +827,8 @@ struct GTY((variable_size)) lang_decl {
 #define MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC(T) \
   if (TYPE_LANG_SPECIFIC ((T)) == NULL)		\
      TYPE_LANG_SPECIFIC ((T))			\
-       = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
+       = (struct lang_type *) ggc_internal_cleared_alloc \
+(sizeof (struct lang_type));     \
 
 #define TYPE_DUMMY(T)		(TYPE_LANG_SPECIFIC(T)->dummy_class)
 
diff --git a/gcc/java/jcf-reader.c b/gcc/java/jcf-reader.c
index 10def13..f25bbab 100644
--- a/gcc/java/jcf-reader.c
+++ b/gcc/java/jcf-reader.c
@@ -341,7 +341,8 @@ jcf_parse_constant_pool (JCF* jcf)
   int i, n;
   JPOOL_SIZE (jcf) = (JCF_FILL (jcf, 2), JCF_readu2 (jcf));
   jcf->cpool.tags = (uint8 *) ggc_alloc_atomic (JPOOL_SIZE (jcf));
-  jcf->cpool.data = ggc_alloc_cpool_entry (sizeof (jword) * JPOOL_SIZE (jcf));
+  jcf->cpool.data = (cpool_entry *) ggc_internal_cleared_alloc
+    (sizeof (jword) * JPOOL_SIZE (jcf));
   jcf->cpool.tags[0] = 0;
 #ifdef HANDLE_START_CONSTANT_POOL
   HANDLE_START_CONSTANT_POOL (JPOOL_SIZE (jcf));
diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
index 0c7fa04..a050727 100644
--- a/gcc/objc/objc-act.h
+++ b/gcc/objc/objc-act.h
@@ -193,7 +193,8 @@ typedef enum objc_property_assign_semantics {
 #define ALLOC_OBJC_TYPE_LANG_SPECIFIC(NODE)				\
   do {									\
     TYPE_LANG_SPECIFIC (NODE)						\
-      = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));	\
+      = (struct lang_type *) ggc_internal_cleared_alloc     \
+      (sizeof (struct lang_type));	\
   } while (0)
 
 #define TYPE_HAS_OBJC_INFO(TYPE)				\
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index 03d3e4d..492eee7 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -276,8 +276,8 @@ ssa_operand_alloc (struct function *fn, unsigned size)
 	}
 
 
-      ptr = ggc_alloc_ssa_operand_memory_d (sizeof (void *)
-                        + gimple_ssa_operands (fn)->ssa_operand_mem_size);
+      ptr = (ssa_operand_memory_d *) ggc_internal_alloc
+	(sizeof (void *) + gimple_ssa_operands (fn)->ssa_operand_mem_size);
 
       ptr->next = gimple_ssa_operands (fn)->operand_memory;
       gimple_ssa_operands (fn)->operand_memory = ptr;
diff --git a/gcc/tree.c b/gcc/tree.c
index aa74fd0..365faf2 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1656,7 +1656,7 @@ build_string (int len, const char *str)
 
   record_node_allocation_statistics (STRING_CST, length);
 
-  s = ggc_alloc_tree_node (length);
+  s = (tree) ggc_internal_alloc (length);
 
   memset (s, 0, sizeof (struct tree_typed));
   TREE_SET_CODE (s, STRING_CST);
@@ -10368,7 +10368,7 @@ build_omp_clause (location_t loc, enum omp_clause_code code)
 
   record_node_allocation_statistics (OMP_CLAUSE, size);
 
-  t = ggc_alloc_tree_node (size);
+  t = (tree) ggc_internal_alloc (size);
   memset (t, 0, size);
   TREE_SET_CODE (t, OMP_CLAUSE);
   OMP_CLAUSE_SET_CODE (t, code);
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 8e8c5f6..3b42faa 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -381,7 +381,7 @@ create_block_symbol (const char *label, struct object_block *block,
 
   /* Create the extended SYMBOL_REF.  */
   size = RTX_HDR_SIZE + sizeof (struct block_symbol);
-  symbol = ggc_alloc_rtx_def (size);
+  symbol = (rtx) ggc_internal_alloc (size);
 
   /* Initialize the normal SYMBOL_REF fields.  */
   memset (symbol, 0, size);
-- 
2.0.0.rc0

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 5/6] add finalizers to ggc
  2014-04-29 11:08 [PATH 0/6] ggc finalizers and TLC tsaunders
                   ` (4 preceding siblings ...)
  2014-04-29 11:09 ` [PATCH 1/6] rm a bunch of _stat allocation functions tsaunders
@ 2014-04-29 11:59 ` tsaunders
  2014-04-29 13:00   ` Richard Biener
  5 siblings, 1 reply; 18+ messages in thread
From: tsaunders @ 2014-04-29 11:59 UTC (permalink / raw)
  To: gcc-patches; +Cc: Trevor Saunders

From: Trevor Saunders <tsaunders@mozilla.com>

Hi,

This implements finalizers by keeping a list of registered finalizers
and after every mark but before sweeping check to see if any of them are
for unmarked blocks.

bootstrapped + regtested on x86_64-unknown-linux-gnu, ok?

Trev

gcc/ChangeLog:

	* ggc-common.c (ggc_internal_cleared_alloc): Adjust.
	* ggc-none.c (ggc_internal_alloc): Assert if a finalizer is passed.
	(ggc_internal_cleared_alloc): Likewise.
	* ggc-page.c (finalizer): New class.
	(globals::finalizer_lists): New member.
	(ggc_internal_alloc): Record the finalizer if any for the block being
	allocated.
	(ggc_handle_finalizers): New function.
	(ggc_collect): Call ggc_handle_finalizers.
	* ggc.h (ggc_internal_alloc):Add arguments to allow installing a
	finalizer.
	(ggc_internal_cleared_alloc): Likewise.
	(finalize): New function.
	(need_finalization_p): Likewise.
	(ggc_alloc): Install the type's destructor as the finalizer if it
	might do something.
	(ggc_cleared_alloc): Likewise.
	(ggc_vec_alloc): Likewise.
	(ggc_cleared_vec_alloc): Likewise.
---
 gcc/ggc-common.c |  5 +++--
 gcc/ggc-none.c   |  8 ++++++--
 gcc/ggc-page.c   | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
 gcc/ggc.h        | 52 ++++++++++++++++++++++++++++++++++++++++++++++------
 4 files changed, 104 insertions(+), 11 deletions(-)

diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index e89cc64..b11a10c 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -174,9 +174,10 @@ ggc_mark_roots (void)
 
 /* Allocate a block of memory, then clear it.  */
 void *
-ggc_internal_cleared_alloc (size_t size MEM_STAT_DECL)
+ggc_internal_cleared_alloc (size_t size, void (*f)(void *), size_t s, size_t n
+			    MEM_STAT_DECL)
 {
-  void *buf = ggc_internal_alloc (size PASS_MEM_STAT);
+  void *buf = ggc_internal_alloc (size, f, s, n PASS_MEM_STAT);
   memset (buf, 0, size);
   return buf;
 }
diff --git a/gcc/ggc-none.c b/gcc/ggc-none.c
index aad89bf..97d3566 100644
--- a/gcc/ggc-none.c
+++ b/gcc/ggc-none.c
@@ -41,14 +41,18 @@ ggc_round_alloc_size (size_t requested_size)
 }
 
 void *
-ggc_internal_alloc (size_t size MEM_STAT_DECL)
+ggc_internal_alloc (size_t size, void (*f)(void *), size_t, size_t
+		    MEM_STAT_DECL)
 {
+  gcc_assert (!f); // ggc-none doesn't support finalizers
   return xmalloc (size);
 }
 
 void *
-ggc_internal_cleared_alloc (size_t size MEM_STAT_DECL)
+ggc_internal_cleared_alloc (size_t size, void (*f)(void *), size_t, size_t
+			    MEM_STAT_DECL)
 {
+  gcc_assert (!f); // ggc-none doesn't support finalizers
   return xcalloc (size, 1);
 }
 
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index ae5e88a..208b526 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -332,6 +332,27 @@ typedef struct page_table_chain
 
 #endif
 
+class finalizer
+{
+public:
+  finalizer (uintptr_t addr, void (*f)(void *), size_t s, size_t n) :
+    m_addr (addr), m_function (f), m_object_size (s), m_n_objects (n) {}
+
+  void call () const
+    {
+      for (size_t i = 0; i < m_n_objects; i++)
+	m_function (reinterpret_cast<void *> (m_addr + (i * m_object_size)));
+    }
+
+  uintptr_t addr () const { return m_addr; }
+
+private:
+  uintptr_t m_addr;
+  void (*m_function)(void *);
+  size_t m_object_size;
+  size_t m_n_objects;
+};
+
 #ifdef ENABLE_GC_ALWAYS_COLLECT
 /* List of free objects to be verified as actually free on the
    next collection.  */
@@ -425,6 +446,9 @@ static struct globals
      better runtime data access pattern.  */
   unsigned long **save_in_use;
 
+  /* finalizer_lists[i] is the list of finalizers for blocks of order i.  */
+  vec<finalizer> finalizer_lists[NUM_ORDERS];
+
 #ifdef ENABLE_GC_ALWAYS_COLLECT
   /* List of free objects to be verified as actually free on the
      next collection.  */
@@ -1202,7 +1226,8 @@ ggc_round_alloc_size (size_t requested_size)
 /* Allocate a chunk of memory of SIZE bytes.  Its contents are undefined.  */
 
 void *
-ggc_internal_alloc (size_t size MEM_STAT_DECL)
+ggc_internal_alloc (size_t size, void (*f)(void *), size_t s, size_t n
+		    MEM_STAT_DECL)
 {
   size_t order, word, bit, object_offset, object_size;
   struct page_entry *entry;
@@ -1345,6 +1370,10 @@ ggc_internal_alloc (size_t size MEM_STAT_DECL)
   /* For timevar statistics.  */
   timevar_ggc_mem_total += object_size;
 
+  if (f)
+    G.finalizer_lists[order]
+      .safe_push (finalizer (reinterpret_cast<uintptr_t> (result), f, s, n));
+
   if (GATHER_STATISTICS)
     {
       size_t overhead = object_size - size;
@@ -1811,6 +1840,24 @@ clear_marks (void)
     }
 }
 
+static void
+ggc_handle_finalizers ()
+{
+  for (unsigned int order = 2; order < NUM_ORDERS; order++)
+    {
+      unsigned int length = G.finalizer_lists[order].length ();
+      for (unsigned int i = length - 1; i < length; i--)
+	{
+	  finalizer &f = G.finalizer_lists[order][i];
+	  if (!ggc_marked_p (reinterpret_cast<void *> (f.addr ())))
+	    {
+	      f.call ();
+	      G.finalizer_lists[order].ordered_remove (i);
+	    }
+	}
+    }
+}
+
 /* Free all empty pages.  Partially empty pages need no attention
    because the `mark' bit doubles as an `unused' bit.  */
 
@@ -2075,6 +2122,7 @@ ggc_collect (void)
 
   clear_marks ();
   ggc_mark_roots ();
+  ggc_handle_finalizers ();
 
   if (GATHER_STATISTICS)
     ggc_prune_overhead_list ();
diff --git a/gcc/ggc.h b/gcc/ggc.h
index 50fb199..4c59597 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -136,13 +136,16 @@ extern void gt_pch_save (FILE *f);
 /* Allocation.  */
 
 /* The internal primitive.  */
-extern void *ggc_internal_alloc (size_t CXX_MEM_STAT_INFO) ATTRIBUTE_MALLOC;
+extern void *ggc_internal_alloc (size_t, void (*)(void *) = NULL, size_t = 0,
+				 size_t = 1 CXX_MEM_STAT_INFO)
+     ATTRIBUTE_MALLOC;
 
 extern size_t ggc_round_alloc_size (size_t requested_size);
 
 /* Allocates cleared memory.  */
-extern void *ggc_internal_cleared_alloc (size_t CXX_MEM_STAT_INFO)
-  ATTRIBUTE_MALLOC;
+extern void *ggc_internal_cleared_alloc (size_t, void (*)(void *) = NULL,
+					 size_t = 0, size_t = 1
+					 CXX_MEM_STAT_INFO) ATTRIBUTE_MALLOC;
 
 /* Resize a block.  */
 extern void *ggc_realloc (void *, size_t CXX_MEM_STAT_INFO);
@@ -157,24 +160,55 @@ extern void dump_ggc_loc_statistics (bool);
     ((T *) ggc_realloc ((P), (N) * sizeof (T) MEM_STAT_INFO))
 
 template<typename T>
+void
+finalize (void *p)
+{
+  static_cast<T *> (p)->~T ();
+}
+
+template<typename T>
+static inline bool
+need_finalization_p ()
+{
+#if GCC_VERSION >= 4003
+  return !__has_trivial_destructor (T);
+#else
+  return true;
+#endif
+}
+
+template<typename T>
 static inline T *
 ggc_alloc (ALONE_CXX_MEM_STAT_INFO)
 {
-  return static_cast<T *> (ggc_internal_alloc (sizeof (T) PASS_MEM_STAT));
+  if (need_finalization_p<T> ())
+    return static_cast<T *> (ggc_internal_alloc (sizeof (T), finalize<T>
+						 PASS_MEM_STAT));
+  else
+    return static_cast<T *> (ggc_internal_alloc (sizeof (T) PASS_MEM_STAT));
 }
 
 template<typename T>
 static inline T *
 ggc_cleared_alloc (ALONE_CXX_MEM_STAT_INFO)
 {
-  return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T)
-						       PASS_MEM_STAT));
+  if (need_finalization_p<T> ())
+    return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T),
+							 finalize<T>
+							 PASS_MEM_STAT));
+  else
+    return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T)
+							 PASS_MEM_STAT));
 }
 
 template<typename T>
 static inline T *
 ggc_vec_alloc (size_t c CXX_MEM_STAT_INFO)
 {
+  if (need_finalization_p<T> ())
+    return static_cast<T *> (ggc_internal_alloc (c * sizeof (T), finalize<T>,
+						 sizeof (T), c PASS_MEM_STAT));
+  else
     return static_cast<T *> (ggc_internal_alloc (c * sizeof (T)
 						 PASS_MEM_STAT));
 }
@@ -183,6 +217,12 @@ template<typename T>
 static inline T *
 ggc_cleared_vec_alloc (size_t c CXX_MEM_STAT_INFO)
 {
+  if (need_finalization_p<T> ())
+    return static_cast<T *> (ggc_internal_cleared_alloc (c * sizeof (T),
+							 finalize<T>,
+							 sizeof (T), c
+							 PASS_MEM_STAT));
+  else
     return static_cast<T *> (ggc_internal_cleared_alloc (c * sizeof (T)
 							 PASS_MEM_STAT));
 }
-- 
2.0.0.rc0

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/6] rm a bunch of _stat allocation functions
  2014-04-29 11:09 ` [PATCH 1/6] rm a bunch of _stat allocation functions tsaunders
@ 2014-04-29 12:19   ` Richard Biener
  0 siblings, 0 replies; 18+ messages in thread
From: Richard Biener @ 2014-04-29 12:19 UTC (permalink / raw)
  To: tsaunders; +Cc: GCC Patches

On Tue, Apr 29, 2014 at 1:08 PM,  <tsaunders@mozilla.com> wrote:
> From: Trevor Saunders <tsaunders@mozilla.com>
>
> Hi,
>
> C++ default args allow us to name the function foo instead of foo_stat with a
> wrapper macro foo.
>
> bootstrapped + regtested x86_64-unknown-linux-gnu, ok?

Ok if it also bootstraps with --enable-gather-detailed-mem-stats.

Thanks,
Richard.

> Trev
>
> gcc/ChangeLog:
>
> 2014-04-23  tbsaunde  <tbsaunde@my.domain.org>
>
>         * dwarf2out.c (tree_add_const_value_attribute): Call
>         ggc_internal_cleared_alloc instead of ggc_alloc_cleared_atomic.
>         * gengtype.c (write_typed_alloc_def): Call ggc_internal_<x>alloc
>         instead of ggc_internal_<x>alloc_stat.
>         * ggc-common.c (ggc_internal_cleared_alloc): Drop _stat suffix.
>         (ggc_realloc): Likewise.
>         * ggc-none.c (ggc_internal_alloc): Likewise.
>         (ggc_internal_cleared_alloc): Likewise.
>         * ggc-page.c: Likewise.
>         * ggc.h (ggc_internal_alloc_stat): Likewise.
>         (ggc_internal_alloc): Remove macro.
>         (ggc_internal_cleared_alloc_stat): Drop _stat suffix.
>         (ggc_internal_cleared_alloc): Remove macro.
>         (GGC_RESIZEVEC): Adjust.
>         (ggc_resizevar): Remove macro.
>         (ggc_internal_vec_alloc_stat): Drop _stat suffix.
>         (ggc_internal_cleared_vec_alloc_stat): Likewise.
>         (ggc_internal_vec_cleared_alloc): Remove macro.
>         (ggc_alloc_atomic_stat): Drop _stat suffix.
>         (ggc_alloc_atomic): Remove macro.
>         (ggc_alloc_cleared_atomic): Remove macro.
>         (ggc_alloc_string_stat): Drop _stat suffix.
>         (ggc_alloc_string): Remove macro.
>         (ggc_alloc_rtx_def_stat): Adjust.
>         (ggc_alloc_tree_node_stat): Likewise.
>         (ggc_alloc_cleared_tree_node_stat): Likewise.
>         (ggc_alloc_cleared_gimple_statement_stat): Likewise.
>         (ggc_alloc_cleared_simd_clone_stat): Likewise.
>         * gimple.c (gimple_build_omp_for): Likewise.
>         (gimple_copy): Likewise.
>         * stringpool.c (ggc_alloc_string_stat): Drop _stat suffix.
>         * toplev.c (realloc_for_line_map): Adjust.
>         * tree-data-ref.h (lambda_vector_new): Likewise.
>         * tree-phinodes.c (allocate_phi_node): Likewise.
>         * tree.c (grow_tree_vec_stat): Likewise.
>         * vec.h (va_gc::reserve): Adjust.
>
> gcc/java/ChangeLog:
>
> 2014-04-23  tbsaunde  <tbsaunde@my.domain.org>
>
>         * constants.c (set_constant_entry): Adjust.
> ---
>  gcc/dwarf2out.c      |  2 +-
>  gcc/gengtype.c       |  2 +-
>  gcc/ggc-common.c     | 10 ++++----
>  gcc/ggc-none.c       |  4 ++--
>  gcc/ggc-page.c       |  2 +-
>  gcc/ggc.h            | 65 +++++++++++++++++++---------------------------------
>  gcc/gimple.c         |  8 +++----
>  gcc/java/constants.c |  4 ++--
>  gcc/stringpool.c     |  4 ++--
>  gcc/toplev.c         |  2 +-
>  gcc/tree-data-ref.h  |  2 +-
>  gcc/tree-phinodes.c  |  2 +-
>  gcc/tree.c           |  2 +-
>  gcc/vec.h            |  5 ++--
>  14 files changed, 48 insertions(+), 66 deletions(-)
>
> diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
> index 1272326..6133fa3 100644
> --- a/gcc/dwarf2out.c
> +++ b/gcc/dwarf2out.c
> @@ -15875,7 +15875,7 @@ tree_add_const_value_attribute (dw_die_ref die, tree t)
>        if (size > 0 && (int) size == size)
>         {
>           unsigned char *array = (unsigned char *)
> -           ggc_alloc_cleared_atomic (size);
> +           ggc_internal_cleared_alloc (size);
>
>           if (native_encode_initializer (init, array, size))
>             {
> diff --git a/gcc/gengtype.c b/gcc/gengtype.c
> index 031004a..e8fcd9f 100644
> --- a/gcc/gengtype.c
> +++ b/gcc/gengtype.c
> @@ -4975,7 +4975,7 @@ write_typed_alloc_def (outf_p f,
>            (two_args ? ", " : ""),
>            (quantity == vector) ? "n" : "");
>    oprintf (f, "((%s%s *)", type_specifier, type_name);
> -  oprintf (f, "(ggc_internal_%salloc_stat (", allocator_type);
> +  oprintf (f, "(ggc_internal_%salloc (", allocator_type);
>    if (variable_size)
>      oprintf (f, "SIZE");
>    else
> diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
> index 97c9b87..e1cc48e 100644
> --- a/gcc/ggc-common.c
> +++ b/gcc/ggc-common.c
> @@ -174,22 +174,22 @@ ggc_mark_roots (void)
>
>  /* Allocate a block of memory, then clear it.  */
>  void *
> -ggc_internal_cleared_alloc_stat (size_t size MEM_STAT_DECL)
> +ggc_internal_cleared_alloc (size_t size MEM_STAT_DECL)
>  {
> -  void *buf = ggc_internal_alloc_stat (size PASS_MEM_STAT);
> +  void *buf = ggc_internal_alloc (size PASS_MEM_STAT);
>    memset (buf, 0, size);
>    return buf;
>  }
>
>  /* Resize a block of memory, possibly re-allocating it.  */
>  void *
> -ggc_realloc_stat (void *x, size_t size MEM_STAT_DECL)
> +ggc_realloc (void *x, size_t size MEM_STAT_DECL)
>  {
>    void *r;
>    size_t old_size;
>
>    if (x == NULL)
> -    return ggc_internal_alloc_stat (size PASS_MEM_STAT);
> +    return ggc_internal_alloc (size PASS_MEM_STAT);
>
>    old_size = ggc_get_size (x);
>
> @@ -211,7 +211,7 @@ ggc_realloc_stat (void *x, size_t size MEM_STAT_DECL)
>        return x;
>      }
>
> -  r = ggc_internal_alloc_stat (size PASS_MEM_STAT);
> +  r = ggc_internal_alloc (size PASS_MEM_STAT);
>
>    /* Since ggc_get_size returns the size of the pool, not the size of the
>       individually allocated object, we'd access parts of the old object
> diff --git a/gcc/ggc-none.c b/gcc/ggc-none.c
> index e690019..aad89bf 100644
> --- a/gcc/ggc-none.c
> +++ b/gcc/ggc-none.c
> @@ -41,13 +41,13 @@ ggc_round_alloc_size (size_t requested_size)
>  }
>
>  void *
> -ggc_internal_alloc_stat (size_t size MEM_STAT_DECL)
> +ggc_internal_alloc (size_t size MEM_STAT_DECL)
>  {
>    return xmalloc (size);
>  }
>
>  void *
> -ggc_internal_cleared_alloc_stat (size_t size MEM_STAT_DECL)
> +ggc_internal_cleared_alloc (size_t size MEM_STAT_DECL)
>  {
>    return xcalloc (size, 1);
>  }
> diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
> index ccc87ea..ae5e88a 100644
> --- a/gcc/ggc-page.c
> +++ b/gcc/ggc-page.c
> @@ -1202,7 +1202,7 @@ ggc_round_alloc_size (size_t requested_size)
>  /* Allocate a chunk of memory of SIZE bytes.  Its contents are undefined.  */
>
>  void *
> -ggc_internal_alloc_stat (size_t size MEM_STAT_DECL)
> +ggc_internal_alloc (size_t size MEM_STAT_DECL)
>  {
>    size_t order, word, bit, object_offset, object_size;
>    struct page_entry *entry;
> diff --git a/gcc/ggc.h b/gcc/ggc.h
> index 55f3fe9..0af69f5 100644
> --- a/gcc/ggc.h
> +++ b/gcc/ggc.h
> @@ -136,59 +136,44 @@ extern void gt_pch_save (FILE *f);
>  /* Allocation.  */
>
>  /* The internal primitive.  */
> -extern void *ggc_internal_alloc_stat (size_t MEM_STAT_DECL)
> -  ATTRIBUTE_MALLOC;
> +extern void *ggc_internal_alloc (size_t CXX_MEM_STAT_INFO) ATTRIBUTE_MALLOC;
>
>  extern size_t ggc_round_alloc_size (size_t requested_size);
>
> -#define ggc_internal_alloc(s) ggc_internal_alloc_stat (s MEM_STAT_INFO)
> -
>  /* Allocates cleared memory.  */
> -extern void *ggc_internal_cleared_alloc_stat (size_t MEM_STAT_DECL)
> +extern void *ggc_internal_cleared_alloc (size_t CXX_MEM_STAT_INFO)
>    ATTRIBUTE_MALLOC;
> -#define ggc_internal_cleared_alloc(s) ggc_internal_cleared_alloc_stat (s MEM_STAT_INFO)
>
>  /* Resize a block.  */
> -extern void *ggc_realloc_stat (void *, size_t MEM_STAT_DECL);
> +extern void *ggc_realloc (void *, size_t CXX_MEM_STAT_INFO);
>
>  /* Free a block.  To be used when known for certain it's not reachable.  */
>  extern void ggc_free (void *);
>
>  extern void dump_ggc_loc_statistics (bool);
>
> -/* Reallocators.  */
> +/* Reallocator.  */
>  #define GGC_RESIZEVEC(T, P, N) \
> -    ((T *) ggc_realloc_stat ((P), (N) * sizeof (T) MEM_STAT_INFO))
> -
> -#define GGC_RESIZEVAR(T, P, N)                          \
> -    ((T *) ggc_realloc_stat ((P), (N) MEM_STAT_INFO))
> +    ((T *) ggc_realloc ((P), (N) * sizeof (T) MEM_STAT_INFO))
>
>  static inline void *
> -ggc_internal_vec_alloc_stat (size_t s, size_t c MEM_STAT_DECL)
> +ggc_internal_vec_alloc (size_t s, size_t c MEM_STAT_DECL)
>  {
> -    return ggc_internal_alloc_stat (c * s PASS_MEM_STAT);
> +    return ggc_internal_alloc (c * s PASS_MEM_STAT);
>  }
>
>  static inline void *
> -ggc_internal_cleared_vec_alloc_stat (size_t s, size_t c MEM_STAT_DECL)
> +ggc_internal_cleared_vec_alloc (size_t s, size_t c CXX_MEM_STAT_INFO)
>  {
> -    return ggc_internal_cleared_alloc_stat (c * s PASS_MEM_STAT);
> +    return ggc_internal_cleared_alloc (c * s PASS_MEM_STAT);
>  }
>
> -#define ggc_internal_cleared_vec_alloc(s, c) \
> -    (ggc_internal_cleared_vec_alloc_stat ((s), (c) MEM_STAT_INFO))
> -
>  static inline void *
> -ggc_alloc_atomic_stat (size_t s MEM_STAT_DECL)
> +ggc_alloc_atomic (size_t s CXX_MEM_STAT_INFO)
>  {
> -    return ggc_internal_alloc_stat (s PASS_MEM_STAT);
> +    return ggc_internal_alloc (s PASS_MEM_STAT);
>  }
>
> -#define ggc_alloc_atomic(S)  (ggc_alloc_atomic_stat ((S) MEM_STAT_INFO))
> -
> -#define ggc_alloc_cleared_atomic(S)             \
> -    (ggc_internal_cleared_alloc_stat ((S) MEM_STAT_INFO))
> -
>  extern void *ggc_cleared_alloc_htab_ignore_args (size_t, size_t)
>    ATTRIBUTE_MALLOC;
>
> @@ -213,13 +198,11 @@ extern void ggc_splay_dont_free (void *, void *);
>  /* Allocate a gc-able string, and fill it with LENGTH bytes from CONTENTS.
>     If LENGTH is -1, then CONTENTS is assumed to be a
>     null-terminated string and the memory sized accordingly.  */
> -extern const char *ggc_alloc_string_stat (const char *contents, int length
> -                                          MEM_STAT_DECL);
> -
> -#define ggc_alloc_string(c, l) ggc_alloc_string_stat (c, l MEM_STAT_INFO)
> +extern const char *ggc_alloc_string (const char *contents, int length
> +                                     CXX_MEM_STAT_INFO);
>
>  /* Make a copy of S, in GC-able memory.  */
> -#define ggc_strdup(S) ggc_alloc_string_stat ((S), -1 MEM_STAT_INFO)
> +#define ggc_strdup(S) ggc_alloc_string ((S), -1 MEM_STAT_INFO)
>
>  /* Invoke the collector.  Garbage collection occurs only when this
>     function is called, not during allocations.  */
> @@ -253,35 +236,35 @@ extern void init_ggc_heuristics (void);
>  /* Memory statistics passing versions of some allocators.  Too few of them to
>     make gengtype produce them, so just define the needed ones here.  */
>  static inline struct rtx_def *
> -ggc_alloc_rtx_def_stat (size_t s MEM_STAT_DECL)
> +ggc_alloc_rtx_def_stat (size_t s CXX_MEM_STAT_INFO)
>  {
> -  return (struct rtx_def *) ggc_internal_alloc_stat (s PASS_MEM_STAT);
> +  return (struct rtx_def *) ggc_internal_alloc (s PASS_MEM_STAT);
>  }
>
>  static inline union tree_node *
> -ggc_alloc_tree_node_stat (size_t s MEM_STAT_DECL)
> +ggc_alloc_tree_node_stat (size_t s CXX_MEM_STAT_INFO)
>  {
> -  return (union tree_node *) ggc_internal_alloc_stat (s PASS_MEM_STAT);
> +  return (union tree_node *) ggc_internal_alloc (s PASS_MEM_STAT);
>  }
>
>  static inline union tree_node *
> -ggc_alloc_cleared_tree_node_stat (size_t s MEM_STAT_DECL)
> +ggc_alloc_cleared_tree_node_stat (size_t s CXX_MEM_STAT_INFO)
>  {
> -  return (union tree_node *) ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT);
> +  return (union tree_node *) ggc_internal_cleared_alloc (s PASS_MEM_STAT);
>  }
>
>  static inline struct gimple_statement_base *
> -ggc_alloc_cleared_gimple_statement_stat (size_t s MEM_STAT_DECL)
> +ggc_alloc_cleared_gimple_statement_stat (size_t s CXX_MEM_STAT_INFO)
>  {
>    return (struct gimple_statement_base *)
> -    ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT);
> +    ggc_internal_cleared_alloc (s PASS_MEM_STAT);
>  }
>
>  static inline struct simd_clone *
> -ggc_alloc_cleared_simd_clone_stat (size_t s MEM_STAT_DECL)
> +ggc_alloc_cleared_simd_clone_stat (size_t s CXX_MEM_STAT_INFO)
>  {
>    return (struct simd_clone *)
> -    ggc_internal_cleared_alloc_stat (s PASS_MEM_STAT);
> +    ggc_internal_cleared_alloc (s PASS_MEM_STAT);
>  }
>
>  #endif
> diff --git a/gcc/gimple.c b/gcc/gimple.c
> index 8552a17..fc6ecb9 100644
> --- a/gcc/gimple.c
> +++ b/gcc/gimple.c
> @@ -836,8 +836,7 @@ gimple_build_omp_for (gimple_seq body, int kind, tree clauses, size_t collapse,
>    gimple_omp_for_set_kind (p, kind);
>    p->collapse = collapse;
>    p->iter =  static_cast <struct gimple_omp_for_iter *> (
> -   ggc_internal_cleared_vec_alloc_stat (sizeof (*p->iter),
> -                                       collapse MEM_STAT_INFO));
> +   ggc_internal_cleared_vec_alloc (sizeof (*p->iter), collapse));
>
>    if (pre_body)
>      gimple_omp_for_set_pre_body (p, pre_body);
> @@ -1667,9 +1666,8 @@ gimple_copy (gimple stmt)
>               as_a <gimple_statement_omp_for *> (copy);
>             omp_for_copy->iter =
>               static_cast <struct gimple_omp_for_iter *> (
> -                 ggc_internal_vec_alloc_stat (sizeof (struct gimple_omp_for_iter),
> -                                              gimple_omp_for_collapse (stmt)
> -                                              MEM_STAT_INFO));
> +                 ggc_internal_vec_alloc (sizeof (struct gimple_omp_for_iter),
> +                                         gimple_omp_for_collapse (stmt)));
>            }
>           for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
>             {
> diff --git a/gcc/java/constants.c b/gcc/java/constants.c
> index 7e9cf2e..c0295e9 100644
> --- a/gcc/java/constants.c
> +++ b/gcc/java/constants.c
> @@ -46,8 +46,8 @@ set_constant_entry (CPool *cpool, int index, int tag, jword value)
>    if (cpool->data == NULL)
>      {
>        cpool->capacity = 100;
> -      cpool->tags = (uint8 *) ggc_alloc_cleared_atomic (sizeof (uint8)
> -                                               * cpool->capacity);
> +      cpool->tags = (uint8 *) ggc_internal_cleared_alloc (sizeof (uint8)
> +                                                         * cpool->capacity);
>        cpool->data = ggc_alloc_cleared_vec_cpool_entry (sizeof
>                                                        (union cpool_entry),
>                                                        cpool->capacity);
> diff --git a/gcc/stringpool.c b/gcc/stringpool.c
> index 4b6900c..e317525 100644
> --- a/gcc/stringpool.c
> +++ b/gcc/stringpool.c
> @@ -79,7 +79,7 @@ alloc_node (cpp_hash_table *table ATTRIBUTE_UNUSED)
>     nul-terminated string, and the length is calculated using strlen.  */
>
>  const char *
> -ggc_alloc_string_stat (const char *contents, int length MEM_STAT_DECL)
> +ggc_alloc_string (const char *contents, int length MEM_STAT_DECL)
>  {
>    char *result;
>
> @@ -91,7 +91,7 @@ ggc_alloc_string_stat (const char *contents, int length MEM_STAT_DECL)
>    if (length == 1 && ISDIGIT (contents[0]))
>      return digit_string (contents[0] - '0');
>
> -  result = (char *) ggc_alloc_atomic_stat (length + 1 PASS_MEM_STAT);
> +  result = (char *) ggc_internal_cleared_alloc (length + 1 PASS_MEM_STAT);
>    memcpy (result, contents, length);
>    result[length] = '\0';
>    return (const char *) result;
> diff --git a/gcc/toplev.c b/gcc/toplev.c
> index 0f7d452..9535bd0 100644
> --- a/gcc/toplev.c
> +++ b/gcc/toplev.c
> @@ -957,7 +957,7 @@ init_asm_output (const char *name)
>  static void *
>  realloc_for_line_map (void *ptr, size_t len)
>  {
> -  return GGC_RESIZEVAR (void, ptr, len);
> +  return ggc_realloc (ptr, len);
>  }
>
>  /* A helper function: used as the allocator function for
> diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h
> index 9d819e4..8810a3e 100644
> --- a/gcc/tree-data-ref.h
> +++ b/gcc/tree-data-ref.h
> @@ -565,7 +565,7 @@ lambda_vector_gcd (lambda_vector vector, int size)
>  static inline lambda_vector
>  lambda_vector_new (int size)
>  {
> -  return (lambda_vector) ggc_alloc_cleared_atomic (sizeof (int) * size);
> +  return (lambda_vector) ggc_internal_cleared_alloc (sizeof (int) * size);
>  }
>
>  /* Clear out vector VEC1 of length SIZE.  */
> diff --git a/gcc/tree-phinodes.c b/gcc/tree-phinodes.c
> index 0be431e..5bd8233 100644
> --- a/gcc/tree-phinodes.c
> +++ b/gcc/tree-phinodes.c
> @@ -124,7 +124,7 @@ allocate_phi_node (size_t len)
>    else
>      {
>        phi = static_cast <gimple_statement_phi *> (
> -       ggc_internal_alloc_stat (size MEM_STAT_INFO));
> +       ggc_internal_alloc (size));
>        if (GATHER_STATISTICS)
>         {
>           enum gimple_alloc_kind kind = gimple_alloc_kind (GIMPLE_PHI);
> diff --git a/gcc/tree.c b/gcc/tree.c
> index 8b44ecc..aa74fd0 100644
> --- a/gcc/tree.c
> +++ b/gcc/tree.c
> @@ -1892,7 +1892,7 @@ grow_tree_vec_stat (tree v, int len MEM_STAT_DECL)
>
>    record_node_allocation_statistics (TREE_VEC, length - oldlength);
>
> -  v = (tree) ggc_realloc_stat (v, length PASS_MEM_STAT);
> +  v = (tree) ggc_realloc (v, length PASS_MEM_STAT);
>
>    TREE_VEC_LENGTH (v) = len;
>
> diff --git a/gcc/vec.h b/gcc/vec.h
> index 5873023..2e5313d 100644
> --- a/gcc/vec.h
> +++ b/gcc/vec.h
> @@ -48,9 +48,10 @@ along with GCC; see the file COPYING3.  If not see
>       weak.  There are files compiled with -DGENERATOR_FILE that already
>       include ggc.h.  We only need to provide these definitions if ggc.h
>       has not been included.  Sigh.  */
> +
>    extern void ggc_free (void *);
>    extern size_t ggc_round_alloc_size (size_t requested_size);
> -  extern void *ggc_realloc_stat (void *, size_t MEM_STAT_DECL);
> +  extern void *ggc_realloc (void *, size_t CXX_MEM_STAT_INFO);
>  #  endif  // GCC_GGC_H
>  #endif // VEC_GC_ENABLED
>
> @@ -396,7 +397,7 @@ va_gc::reserve (vec<T, A, vl_embed> *&v, unsigned reserve, bool exact
>    size = vec_offset + alloc * elt_size;
>
>    unsigned nelem = v ? v->length () : 0;
> -  v = static_cast <vec<T, A, vl_embed> *> (::ggc_realloc_stat (v, size
> +  v = static_cast <vec<T, A, vl_embed> *> (::ggc_realloc (v, size
>                                                                PASS_MEM_STAT));
>    v->embedded_init (alloc, nelem);
>  }
> --
> 2.0.0.rc0
>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/6] remove unused function
  2014-04-29 11:09 ` [PATCH 4/6] remove unused function tsaunders
@ 2014-04-29 12:25   ` Richard Biener
  0 siblings, 0 replies; 18+ messages in thread
From: Richard Biener @ 2014-04-29 12:25 UTC (permalink / raw)
  To: tsaunders; +Cc: GCC Patches

On Tue, Apr 29, 2014 at 1:08 PM,  <tsaunders@mozilla.com> wrote:
> From: Trevor Saunders <tsaunders@mozilla.com>
>
> Hi,
>
> its unused so rm it.
>
> bootstrapped + regtested on x86_64-unknown-linux-gnu ok?

Ok.

Thanks,
Richard.

> Trev
>
> gcc/ChangeLog:
>
>         *ggc.h (ggc_alloc_cleared_simd_clone_stat): Remove function.
> ---
>  gcc/ggc.h | 7 -------
>  1 file changed, 7 deletions(-)
>
> diff --git a/gcc/ggc.h b/gcc/ggc.h
> index 2c567de..50fb199 100644
> --- a/gcc/ggc.h
> +++ b/gcc/ggc.h
> @@ -279,11 +279,4 @@ ggc_alloc_cleared_gimple_statement_stat (size_t s CXX_MEM_STAT_INFO)
>      ggc_internal_cleared_alloc (s PASS_MEM_STAT);
>  }
>
> -static inline struct simd_clone *
> -ggc_alloc_cleared_simd_clone_stat (size_t s CXX_MEM_STAT_INFO)
> -{
> -  return (struct simd_clone *)
> -    ggc_internal_cleared_alloc (s PASS_MEM_STAT);
> -}
> -
>  #endif
> --
> 2.0.0.rc0
>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/6] don't have gengtype autocreate allocation macros for variably sized types
  2014-04-29 11:09 ` [PATCH 2/6] don't have gengtype autocreate allocation macros for variably sized types tsaunders
@ 2014-04-29 12:32   ` Richard Biener
  2014-04-30  9:17     ` Laurynas Biveinis
  0 siblings, 1 reply; 18+ messages in thread
From: Richard Biener @ 2014-04-29 12:32 UTC (permalink / raw)
  To: tsaunders, Laurynas Biveinis; +Cc: GCC Patches

On Tue, Apr 29, 2014 at 1:08 PM,  <tsaunders@mozilla.com> wrote:
> From: Trevor Saunders <tsaunders@mozilla.com>
>
> Hi,
>
>         the template allocation functions won't work with things that are
> actually variably sized, so its simpler to stop relying on gengtype for them
> first.  However it turns out most of the usage of variably sized things in
> gengtype is to deal with gengtype badness instead of actually variably sized
> things so the next patch will remove a bit of the mess in this one.
>
> bootstrapped + regtested on x86_64-unknown-linux-gnu, ok?
>
> Trev
>
> gcc/ChangeLog:
>
> 2014-04-23  Trevor Saunders  <tsaunders@mozilla.com>
>
>         * gengtype.c (write_typed_alloc_def): Don't write anything if the type
>         is variably sized.
>         * ggc.h: Adjust.
>         * tree-ssa-operands.c (ssa_operand_alloc): Likewise.
>         * tree.c (build_string): Likewise.
>         (build_omp_clause): Likewise.
>         * varasm.c (create_block_symbol): Likewise.
>
> gcc/c/ChangeLog:
>
> 2014-04-23  Trevor Saunders  <tsaunders@mozilla.com>
>
>         * c-decl.c (finish_struct): Adjust.
>         (finish_enum): Likewise.
>
> gcc/java/ChangeLog:
>
> 2014-04-23  Trevor Saunders  <tsaunders@mozilla.com>
>
>         * class.c (add_method_1): Adjust.
>         * constants.c (set_constant_entry): Likewise.
>         * decl.c (java_dup_lang_specific_decl): Likewise.
>         * java-tree.h (MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC): Likewise.
>         (MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC): Likewise.
>         * jcf-reader.c (jcf_parse_constant_pool): Adjust.
>
> gcc/objc/ChangeLog:
>
> 2014-04-23  Trevor Saunders  <tsaunders@mozilla.com>
>
>         * objc-act.h: Adjust.
>
> gcc/cp/ChangeLog:
>
> 2014-04-23  Trevor Saunders  <tsaunders@mozilla.com>
>
>         * class.c (sorted_fields_type_new): Adjust.
>         * cp-tree.h (more_aggr_init_expr_args_p): Likewise.
>         * lex.c (retrofit_lang_decl): Likewise.
>         (cxx_dup_lang_specific_decl): Likewise.
>         (copy_lang_type): Likewise.
>         (cxx_make_type): Likewise.
>
> gcc/fortran/ChangeLog:
>
> 2014-04-23  Trevor Saunders  <tsaunders@mozilla.com>
>
>         * trans-decl.c (gfc_allocate_lang_decl): Adjust.
>         * trans-types.c (gfc_get_nodesc_array_type): Likewise.
>         (gfc_get_array_type_bounds): Likewise.
>         (gfc_nonrestricted_type): Likewise.
> ---
>  gcc/c/c-decl.c            |  8 +++++---
>  gcc/cp/class.c            |  2 +-
>  gcc/cp/cp-tree.h          |  3 ++-
>  gcc/cp/lex.c              |  9 +++++----
>  gcc/fortran/trans-decl.c  |  5 +++--
>  gcc/fortran/trans-types.c | 13 ++++++++-----
>  gcc/gengtype.c            |  3 +++
>  gcc/ggc.h                 |  2 +-
>  gcc/java/class.c          |  3 ++-
>  gcc/java/constants.c      |  6 +++---
>  gcc/java/decl.c           |  2 +-
>  gcc/java/java-tree.h      |  6 ++++--
>  gcc/java/jcf-reader.c     |  3 ++-
>  gcc/objc/objc-act.h       |  3 ++-
>  gcc/tree-ssa-operands.c   |  4 ++--
>  gcc/tree.c                |  4 ++--
>  gcc/varasm.c              |  2 +-
>  17 files changed, 47 insertions(+), 31 deletions(-)
>
> diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
> index e30876c..e8b8166 100644
> --- a/gcc/c/c-decl.c
> +++ b/gcc/c/c-decl.c
> @@ -7423,8 +7423,9 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
>           ensure that this lives as long as the rest of the struct decl.
>           All decls in an inline function need to be saved.  */
>
> -       space = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
> -       space2 = ggc_alloc_sorted_fields_type
> +       space = (struct lang_type *) ggc_internal_cleared_alloc
> +         (sizeof (struct lang_type));
> +       space2 = (sorted_fields_type *) ggc_internal_alloc
>           (sizeof (struct sorted_fields_type) + len * sizeof (tree));

ISTR we went to typed allocs as part of a transition which not
fully materialized?  I actually dislike that we get back the
ugly casts here - so, can we keep the allocators or use
a macro similar to the XNEW family?

>
>         len = 0;
> @@ -7704,7 +7705,8 @@ finish_enum (tree enumtype, tree values, tree attributes)
>
>    /* Record the min/max values so that we can warn about bit-field
>       enumerations that are too small for the values.  */
> -  lt = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
> +  lt = (struct lang_type *) ggc_internal_cleared_alloc
> +    (sizeof (struct lang_type));
>    lt->enum_min = minnode;
>    lt->enum_max = maxnode;
>    TYPE_LANG_SPECIFIC (enumtype) = lt;
> diff --git a/gcc/cp/class.c b/gcc/cp/class.c
> index 334bfd5..86058b5 100644
> --- a/gcc/cp/class.c
> +++ b/gcc/cp/class.c
> @@ -6490,7 +6490,7 @@ static struct sorted_fields_type *
>  sorted_fields_type_new (int n)
>  {
>    struct sorted_fields_type *sft;
> -  sft = ggc_alloc_sorted_fields_type (sizeof (struct sorted_fields_type)
> +  sft = (sorted_fields_type *) ggc_internal_alloc (sizeof (sorted_fields_type)
>                                       + n * sizeof (tree));
>    sft->len = n;
>
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index f459e55..9fbc7f8 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -3586,7 +3586,8 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
>    do {                                                                 \
>      if (TYPE_LANG_SPECIFIC (NODE) == NULL)                             \
>        {                                                                        \
> -       TYPE_LANG_SPECIFIC (NODE) = ggc_alloc_cleared_lang_type         \
> +       TYPE_LANG_SPECIFIC (NODE)                                       \
> +       = (struct lang_type *) ggc_internal_cleared_alloc               \
>          (sizeof (struct lang_type_ptrmem));                            \
>         TYPE_LANG_SPECIFIC (NODE)->u.ptrmem.h.is_lang_type_class = 0;   \
>        }                                                                        \
> diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
> index 3fe275e..46c28ae 100644
> --- a/gcc/cp/lex.c
> +++ b/gcc/cp/lex.c
> @@ -555,7 +555,7 @@ retrofit_lang_decl (tree t)
>    else
>      gcc_unreachable ();
>
> -  ld = ggc_alloc_cleared_lang_decl (size);
> +  ld = (struct lang_decl *) ggc_internal_cleared_alloc (size);
>
>    ld->u.base.selector = sel;
>
> @@ -597,7 +597,7 @@ cxx_dup_lang_specific_decl (tree node)
>    else
>      gcc_unreachable ();
>
> -  ld = ggc_alloc_lang_decl (size);
> +  ld = (struct lang_decl *) ggc_internal_alloc (size);
>    memcpy (ld, DECL_LANG_SPECIFIC (node), size);
>    DECL_LANG_SPECIFIC (node) = ld;
>
> @@ -635,7 +635,7 @@ copy_lang_type (tree node)
>      size = sizeof (struct lang_type);
>    else
>      size = sizeof (struct lang_type_ptrmem);
> -  lt = ggc_alloc_lang_type (size);
> +  lt = (struct lang_type *) ggc_internal_alloc (size);
>    memcpy (lt, TYPE_LANG_SPECIFIC (node), size);
>    TYPE_LANG_SPECIFIC (node) = lt;
>
> @@ -668,7 +668,8 @@ cxx_make_type (enum tree_code code)
>        || code == BOUND_TEMPLATE_TEMPLATE_PARM)
>      {
>        struct lang_type *pi
> -          = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
> +          = (struct lang_type *) ggc_internal_cleared_alloc
> +         (sizeof (struct lang_type));
>
>        TYPE_LANG_SPECIFIC (t) = pi;
>        pi->u.c.h.is_lang_type_class = 1;
> diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
> index cf7b661..beb99a6 100644
> --- a/gcc/fortran/trans-decl.c
> +++ b/gcc/fortran/trans-decl.c
> @@ -615,8 +615,9 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
>  void
>  gfc_allocate_lang_decl (tree decl)
>  {
> -  DECL_LANG_SPECIFIC (decl) = ggc_alloc_cleared_lang_decl(sizeof
> -                                                         (struct lang_decl));
> +  DECL_LANG_SPECIFIC (decl)
> +    = (struct lang_decl *) ggc_internal_cleared_alloc (sizeof
> +                                                      (struct lang_decl));
>  }
>
>  /* Remember a symbol to generate initialization/cleanup code at function
> diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
> index 243feb7..84503ce 100644
> --- a/gcc/fortran/trans-types.c
> +++ b/gcc/fortran/trans-types.c
> @@ -1512,7 +1512,8 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, gfc_packed packed,
>
>    GFC_ARRAY_TYPE_P (type) = 1;
>    TYPE_LANG_SPECIFIC (type)
> -      = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
> +      = (struct lang_type *) ggc_internal_cleared_alloc
> +      (sizeof (struct lang_type));
>
>    known_stride = (packed != PACKED_NO);
>    known_offset = 1;
> @@ -1815,7 +1816,8 @@ gfc_get_array_type_bounds (tree etype, int dimen, int codimen, tree * lbound,
>
>    GFC_DESCRIPTOR_TYPE_P (fat_type) = 1;
>    TYPE_LANG_SPECIFIC (fat_type)
> -    = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
> +    = (struct lang_type *) ggc_internal_cleared_alloc
> +    (sizeof (struct lang_type));
>
>    GFC_TYPE_ARRAY_RANK (fat_type) = dimen;
>    GFC_TYPE_ARRAY_CORANK (fat_type) = codimen;
> @@ -1990,7 +1992,8 @@ gfc_nonrestricted_type (tree t)
>
>    if (!TYPE_LANG_SPECIFIC (t))
>      TYPE_LANG_SPECIFIC (t)
> -      = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
> +      = (struct lang_type *) ggc_internal_cleared_alloc
> +      (sizeof (struct lang_type));
>    /* If we're dealing with this very node already further up
>       the call chain (recursion via pointers and struct members)
>       we haven't yet determined if we really need a new type node.
> @@ -2042,8 +2045,8 @@ gfc_nonrestricted_type (tree t)
>                   if (dataptr_type != GFC_TYPE_ARRAY_DATAPTR_TYPE (t))
>                     {
>                       TYPE_LANG_SPECIFIC (ret)
> -                       = ggc_alloc_cleared_lang_type (sizeof (struct
> -                                                              lang_type));
> +                       = (struct lang_type *) ggc_internal_cleared_alloc
> +                       (sizeof (struct lang_type));
>                       *TYPE_LANG_SPECIFIC (ret) = *TYPE_LANG_SPECIFIC (t);
>                       GFC_TYPE_ARRAY_DATAPTR_TYPE (ret) = dataptr_type;
>                     }
> diff --git a/gcc/gengtype.c b/gcc/gengtype.c
> index e8fcd9f..b3c966c 100644
> --- a/gcc/gengtype.c
> +++ b/gcc/gengtype.c
> @@ -4967,6 +4967,9 @@ write_typed_alloc_def (outf_p f,
>                         enum alloc_quantity quantity)
>  {
>    bool two_args = variable_size && (quantity == vector);
> +  if (variable_size)
> +    return;
> +

It appears that two_args will be unused after this change, but as said,
I'd like to keep the typed allocators.

What is the actual problem you are solving?

Thanks,
Richard.

>    gcc_assert (f != NULL);
>    const char *type_name_as_id = filter_type_name (type_name);
>    oprintf (f, "#define ggc_alloc_%s%s", allocator_type, type_name_as_id);
> diff --git a/gcc/ggc.h b/gcc/ggc.h
> index 0af69f5..736305d 100644
> --- a/gcc/ggc.h
> +++ b/gcc/ggc.h
> @@ -230,7 +230,7 @@ extern void stringpool_statistics (void);
>  extern void init_ggc_heuristics (void);
>
>  #define ggc_alloc_rtvec_sized(NELT)                            \
> -  ggc_alloc_rtvec_def (sizeof (struct rtvec_def)               \
> +  (rtvec_def *) ggc_internal_alloc (sizeof (struct rtvec_def)          \
>                        + ((NELT) - 1) * sizeof (rtx))           \
>
>  /* Memory statistics passing versions of some allocators.  Too few of them to
> diff --git a/gcc/java/class.c b/gcc/java/class.c
> index bbe7c86..94c2568 100644
> --- a/gcc/java/class.c
> +++ b/gcc/java/class.c
> @@ -765,7 +765,8 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type)
>    DECL_CONTEXT (fndecl) = this_class;
>
>    DECL_LANG_SPECIFIC (fndecl)
> -    = ggc_alloc_cleared_lang_decl(sizeof (struct lang_decl));
> +    = (struct lang_decl *) ggc_internal_cleared_alloc
> +    (sizeof (struct lang_decl));
>    DECL_LANG_SPECIFIC (fndecl)->desc = LANG_DECL_FUNC;
>
>    /* Initialize the static initializer test table.  */
> diff --git a/gcc/java/constants.c b/gcc/java/constants.c
> index c0295e9..51449ef 100644
> --- a/gcc/java/constants.c
> +++ b/gcc/java/constants.c
> @@ -48,9 +48,9 @@ set_constant_entry (CPool *cpool, int index, int tag, jword value)
>        cpool->capacity = 100;
>        cpool->tags = (uint8 *) ggc_internal_cleared_alloc (sizeof (uint8)
>                                                           * cpool->capacity);
> -      cpool->data = ggc_alloc_cleared_vec_cpool_entry (sizeof
> -                                                      (union cpool_entry),
> -                                                      cpool->capacity);
> +      cpool->data = (cpool_entry *) ggc_internal_cleared_alloc (sizeof
> +                                                      (union cpool_entry)
> +                                                      * cpool->capacity);
>        cpool->count = 1;
>      }
>    if (index >= cpool->capacity)
> diff --git a/gcc/java/decl.c b/gcc/java/decl.c
> index 53d6f89..9f2f0ca 100644
> --- a/gcc/java/decl.c
> +++ b/gcc/java/decl.c
> @@ -1646,7 +1646,7 @@ java_dup_lang_specific_decl (tree node)
>      return;
>
>    lang_decl_size = sizeof (struct lang_decl);
> -  x = ggc_alloc_lang_decl (lang_decl_size);
> +  x = (struct lang_decl *) ggc_internal_alloc (lang_decl_size);
>    memcpy (x, DECL_LANG_SPECIFIC (node), lang_decl_size);
>    DECL_LANG_SPECIFIC (node) = x;
>  }
> diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
> index 806d2d7..43a8258 100644
> --- a/gcc/java/java-tree.h
> +++ b/gcc/java/java-tree.h
> @@ -700,7 +700,8 @@ union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
>    if (DECL_LANG_SPECIFIC (T) == NULL)                                \
>      {                                                                \
>        DECL_LANG_SPECIFIC ((T))                                       \
> -        = ggc_alloc_cleared_lang_decl (sizeof (struct lang_decl));   \
> +        = (struct lang_decl *) ggc_internal_cleared_alloc            \
> +      (sizeof (struct lang_decl));                                   \
>        DECL_LANG_SPECIFIC (T)->desc = LANG_DECL_VAR;                  \
>      }
>
> @@ -826,7 +827,8 @@ struct GTY((variable_size)) lang_decl {
>  #define MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC(T) \
>    if (TYPE_LANG_SPECIFIC ((T)) == NULL)                \
>       TYPE_LANG_SPECIFIC ((T))                  \
> -       = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));
> +       = (struct lang_type *) ggc_internal_cleared_alloc \
> +(sizeof (struct lang_type));     \
>
>  #define TYPE_DUMMY(T)          (TYPE_LANG_SPECIFIC(T)->dummy_class)
>
> diff --git a/gcc/java/jcf-reader.c b/gcc/java/jcf-reader.c
> index 10def13..f25bbab 100644
> --- a/gcc/java/jcf-reader.c
> +++ b/gcc/java/jcf-reader.c
> @@ -341,7 +341,8 @@ jcf_parse_constant_pool (JCF* jcf)
>    int i, n;
>    JPOOL_SIZE (jcf) = (JCF_FILL (jcf, 2), JCF_readu2 (jcf));
>    jcf->cpool.tags = (uint8 *) ggc_alloc_atomic (JPOOL_SIZE (jcf));
> -  jcf->cpool.data = ggc_alloc_cpool_entry (sizeof (jword) * JPOOL_SIZE (jcf));
> +  jcf->cpool.data = (cpool_entry *) ggc_internal_cleared_alloc
> +    (sizeof (jword) * JPOOL_SIZE (jcf));
>    jcf->cpool.tags[0] = 0;
>  #ifdef HANDLE_START_CONSTANT_POOL
>    HANDLE_START_CONSTANT_POOL (JPOOL_SIZE (jcf));
> diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
> index 0c7fa04..a050727 100644
> --- a/gcc/objc/objc-act.h
> +++ b/gcc/objc/objc-act.h
> @@ -193,7 +193,8 @@ typedef enum objc_property_assign_semantics {
>  #define ALLOC_OBJC_TYPE_LANG_SPECIFIC(NODE)                            \
>    do {                                                                 \
>      TYPE_LANG_SPECIFIC (NODE)                                          \
> -      = ggc_alloc_cleared_lang_type (sizeof (struct lang_type));       \
> +      = (struct lang_type *) ggc_internal_cleared_alloc     \
> +      (sizeof (struct lang_type));     \
>    } while (0)
>
>  #define TYPE_HAS_OBJC_INFO(TYPE)                               \
> diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
> index 03d3e4d..492eee7 100644
> --- a/gcc/tree-ssa-operands.c
> +++ b/gcc/tree-ssa-operands.c
> @@ -276,8 +276,8 @@ ssa_operand_alloc (struct function *fn, unsigned size)
>         }
>
>
> -      ptr = ggc_alloc_ssa_operand_memory_d (sizeof (void *)
> -                        + gimple_ssa_operands (fn)->ssa_operand_mem_size);
> +      ptr = (ssa_operand_memory_d *) ggc_internal_alloc
> +       (sizeof (void *) + gimple_ssa_operands (fn)->ssa_operand_mem_size);
>
>        ptr->next = gimple_ssa_operands (fn)->operand_memory;
>        gimple_ssa_operands (fn)->operand_memory = ptr;
> diff --git a/gcc/tree.c b/gcc/tree.c
> index aa74fd0..365faf2 100644
> --- a/gcc/tree.c
> +++ b/gcc/tree.c
> @@ -1656,7 +1656,7 @@ build_string (int len, const char *str)
>
>    record_node_allocation_statistics (STRING_CST, length);
>
> -  s = ggc_alloc_tree_node (length);
> +  s = (tree) ggc_internal_alloc (length);
>
>    memset (s, 0, sizeof (struct tree_typed));
>    TREE_SET_CODE (s, STRING_CST);
> @@ -10368,7 +10368,7 @@ build_omp_clause (location_t loc, enum omp_clause_code code)
>
>    record_node_allocation_statistics (OMP_CLAUSE, size);
>
> -  t = ggc_alloc_tree_node (size);
> +  t = (tree) ggc_internal_alloc (size);
>    memset (t, 0, size);
>    TREE_SET_CODE (t, OMP_CLAUSE);
>    OMP_CLAUSE_SET_CODE (t, code);
> diff --git a/gcc/varasm.c b/gcc/varasm.c
> index 8e8c5f6..3b42faa 100644
> --- a/gcc/varasm.c
> +++ b/gcc/varasm.c
> @@ -381,7 +381,7 @@ create_block_symbol (const char *label, struct object_block *block,
>
>    /* Create the extended SYMBOL_REF.  */
>    size = RTX_HDR_SIZE + sizeof (struct block_symbol);
> -  symbol = ggc_alloc_rtx_def (size);
> +  symbol = (rtx) ggc_internal_alloc (size);
>
>    /* Initialize the normal SYMBOL_REF fields.  */
>    memset (symbol, 0, size);
> --
> 2.0.0.rc0
>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 3/6] use templates instead of gengtype for typed allocation functions
  2014-04-29 11:09 ` [PATCH 3/6] use templates instead of gengtype for typed allocation functions tsaunders
@ 2014-04-29 12:41   ` Richard Biener
  2014-04-29 13:08     ` Trevor Saunders
  0 siblings, 1 reply; 18+ messages in thread
From: Richard Biener @ 2014-04-29 12:41 UTC (permalink / raw)
  To: tsaunders; +Cc: GCC Patches

On Tue, Apr 29, 2014 at 1:08 PM,  <tsaunders@mozilla.com> wrote:
> From: Trevor Saunders <tsaunders@mozilla.com>
>
> Hi,
>
> much less code to accomplish the same thing.

Agreed.  Does that fix the comment on the last patch about
dropping typed allocations of variable lengths, as I see you
introduce ggc_vec_alloc () here?

> bootstrapped + regtested on x86_64-unknown-linux-gnu ok?

If so, then ok.

Thanks,
Richard.

> Trev
>
> gcc/ada/ChangeLog:
>
>         * gcc-interface/ada-tree.h: Remove usage of variable_size gty
>         annotation.
>
> gcc/cp/ChangeLog:
>
>         * cp-cilkplus.c (cilk_install_body_with_frame_cleanup): Adjust.
>         * cp-objcp-common.c (decl_shadowed_for_var_insert): Adjust.
>         * cp-tree.h: Remove usage of variable_size gty attribute.
>         * decl.c (make_label_decl): Adjust.
>         (check_goto): Likewise.
>         (start_preparsed_function): Likewise.
>         (save_function_data): Likewise.
>         * lex.c (init_reswords): Likewise.
>         (retrofit_lang_decl): Likewise.
>         (cxx_dup_lang_specific_decl): Likewise.
>         (copy_lang_type): Likewise.
>         (cxx_make_type): Likewise.
>         * name-lookup.c (binding_entry_make): Likewise.
>         (binding_table_construct): Likewise.
>         (binding_table_new): Likewise.
>         (cxx_binding_make): Likewise.
>         (pushdecl_maybe_friend_1): Likewise.
>         (begin_scope): Likewise.
>         (push_to_top_level): Likewise.
>         * parser.c (cp_lexer_alloc): Likewise.
>         (cp_lexer_new_from_tokens): Likewise.
>         (cp_token_cache_new): Likewise.
>         (cp_parser_context_new): Likewise.
>         (cp_parser_new): Likewise.
>         (cp_parser_nested_name_specifier_opt): Likewise.
>         (cp_parser_template_id): Likewise.
>         * pt.c (maybe_process_partial_specialization): Likewise.
>         (register_specialization): Likewise.
>         (add_pending_template): Likewise.
>         (lookup_template_class_1): Likewise.
>         (push_tinst_level): Likewise.
>         * semantics.c (register_constexpr_fundef): Likewise.
>         (cxx_eval_call_expression): Likewise.
>         * typeck2.c (abstract_virtuals_error_sfinae): Likewise.
>
> gcc/objc/ChangeLog:
>
>         * objc-act.c (objc_build_string_object): Adjust.
>         (continue_class): Likewise.
>         * objc-act.h (ALLOC_OBJC_TYPE_LANG_SPECIFIC): Likewise.
>         * objc-map.c (objc_map_alloc_ggc): Likewise.
>         (objc_map_private_resize): Likewise.
>         * objc-next-runtime-abi-02.c (objc_next_runtime_abi_02_init):
>         Likewise.
>         (hash_name_enter): Likewise.
>
> gcc/go/ChangeLog:
>
>         * go-lang.c (struct GTY): Don't use variable_size gty attribute.
>
> gcc/ChangeLog:
>
>         * alias.c (record_alias_subset): Adjust.
>         * bitmap.c (bitmap_element_allocate): Likewise.
>         (bitmap_gc_alloc_stat): Likewise.
>         * cfg.c (init_flow): Likewise.
>         (alloc_block): Likewise.
>         (unchecked_make_edge): Likewise.
>         * cfgloop.c (alloc_loop): Likewise.
>         (flow_loops_find): Likewise.
>         (rescan_loop_exit): Likewise.
>         * cfgrtl.c (init_rtl_bb_info): Likewise.
>         * cgraph.c (insert_new_cgraph_node_version): Likewise.
>         (cgraph_allocate_node): Likewise.
>         (cgraph_create_edge_1): Likewise.
>         (cgraph_allocate_init_indirect_info): Likewise.
>         * cgraphclones.c (cgraph_clone_edge): Likewise.
>         * cgraphunit.c (add_asm_node): Likewise.
>         (init_lowered_empty_function): Likewise.
>         * config/i386/i386.c (get_dllimport_decl): Likewise.
>         (ix86_init_machine_status): Likewise.
>         (assign_386_stack_local): Likewise.
>         * coverage.c (coverage_end_function): Likewise.
>         * dbxout.c (dbxout_init): Likewise.
>         * doc/gty.texi: Don't mention variable_size attribute.
>         * dwarf2cfi.c (new_cfi): Adjust.
>         (new_cfi_row): Likewise.
>         (copy_cfi_row): Likewise.
>         (create_cie_data): Likewise.
>         * dwarf2out.c (dwarf2out_alloc_current_fde): Likewise.
>         (new_loc_descr): Likewise.
>         (find_AT_string_in_table): Likewise.
>         (add_addr_table_entry): Likewise.
>         (new_die): Likewise.
>         (add_var_loc_to_decl): Likewise.
>         (clone_die): Likewise.
>         (clone_as_declaration): Likewise.
>         (break_out_comdat_types): Likewise.
>         (new_loc_list): Likewise.
>         (add_loc_descr_to_each): Likewise.
>         (add_location_or_const_value_attribute): Likewise.
>         (add_linkage_name): Likewise.
>         (lookup_filename): Likewise.
>         (dwarf2out_var_location): Likewise.
>         (new_line_info_table): Likewise.
>         (dwarf2out_init): Likewise.
>         * emit-rtl.c (set_mem_attrs): Likewise.
>         (get_reg_attrs): Likewise.
>         (start_sequence): Likewise.
>         (init_emit): Likewise.
>         (init_emit_regs): Likewise.
>         * except.c (init_eh_for_function): Likewise.
>         (gen_eh_region): Likewise.
>         (gen_eh_region_catch): Likewise.
>         (gen_eh_landing_pad): Likewise.
>         (add_call_site): Likewise.
>         * function.c (add_frame_space): Likewise.
>         (insert_temp_slot_address): Likewise.
>         (assign_stack_temp_for_type): Likewise.
>         (get_hard_reg_initial_val): Likewise.
>         (allocate_struct_function): Likewise.
>         (prepare_function_start): Likewise.
>         (types_used_by_var_decl_insert): Likewise.
>         * gengtype.c (variable_size_p): Remove function.
>         (enum alloc_quantity): Remove enum.
>         (write_typed_alloc_def): Remove function.
>         (write_typed_struct_alloc_def): Likewise.
>         (write_typed_typedef_alloc_def): Likewise.
>         (write_typed_alloc_defns): Likewise.
>         (main): Adjust.
>         * ggc-common.c (ggc_cleared_alloc_htab_ignore_args): Adjust.
>         (ggc_cleared_alloc_ptr_array_two_args): Likewise.
>         * ggc.h (ggc_alloc): new function.
>         (ggc_cleared_alloc): Likewise.
>         (ggc_vec_alloc): Template on type of vector element, and remove
>         element size argument.
>         (ggc_cleared_vec_alloc): Likewise.
>         * gimple.c (gimple_build_omp_for): Adjust.
>         (gimple_copy): Likewise.
>         * ipa-cp.c (get_replacement_map): Likewise.
>         (find_aggregate_values_for_callers_subset): Likewise.
>         (known_aggs_to_agg_replacement_list): Likewise.
>         * ipa-devirt.c (get_odr_type): Likewise.
>         * ipa-prop.c (ipa_node_duplication_hook): Likewise.
>         (read_agg_replacement_chain): Likewise.
>         * loop-iv.c (get_simple_loop_desc): Likewise.
>         * lto-cgraph.c (input_node_opt_summary): Likewise.
>         * lto-section-in.c (lto_new_in_decl_state): Likewise.
>         * lto-streamer-in.c (lto_input_eh_catch_list): Likewise.
>         (input_eh_region): Likewise.
>         (input_eh_lp): Likewise.
>         (input_cfg): Likewise.
>         * optabs.c (set_optab_libfunc): Likewise.
>         (set_conv_libfunc): Likewise.
>         * passes.c (do_per_function_toporder): Likewise.
>         * rtl.h: Don't use variable_size gty attribute.
>         * sese.c (if_region_set_false_region): Adjust.
>         * stringpool.c (gt_pch_save_stringpool): Likewise.
>         * target-globals.c (save_target_globals): Likewise.
>         * toplev.c (general_init): Likewise.
>         * trans-mem.c (record_tm_replacement): Likewise.
>         (split_bb_make_tm_edge): Likewise.
>         * tree-cfg.c (move_sese_region_to_fn): Likewise.
>         * tree-data-ref.h (lambda_vector_new): Likewise.
>         * tree-eh.c (add_stmt_to_eh_lp_fn): Likewise.
>         * tree-iterator.c (tsi_link_before): Likewise.
>         (tsi_link_after): Likewise.
>         * tree-scalar-evolution.c (new_scev_info_str): Likewise.
>         * tree-ssa-loop-niter.c (record_estimate): Likewise.
>         * tree-ssa-operands.h: Don't use variable_size gty attribute.
>         * tree-ssa.c (init_tree_ssa): Adjust.
>         * tree-ssanames.c (set_range_info): Likewise.
>         (get_ptr_info): Likewise.
>         (duplicate_ssa_name_ptr_info): Likewise.
>         (duplicate_ssa_name_range_info): Likewise.
>         * tree-streamer-in.c (unpack_ts_real_cst_value_fields): Likewise.
>         (unpack_ts_fixed_cst_value_fields): Likewise.
>         * tree.c (build_fixed): Likewise.
>         (build_real): Likewise.
>         (build_string): Likewise.
>         (decl_priority_info): Likewise.
>         (decl_debug_expr_insert): Likewise.
>         (decl_value_expr_insert): Likewise.
>         (decl_debug_args_insert): Likewise.
>         (type_hash_add): Likewise.
>         (build_omp_clause): Likewise.
>         * ubsan.c (decl_for_type_insert): Likewise.
>         * varasm.c (get_unnamed_section): Likewise.
>         (get_noswitch_section): Likewise.
>         (get_section): Likewise.
>         (get_block_for_section): Likewise.
>         (create_block_symbol): Likewise.
>         (build_constant_desc): Likewise.
>         (create_constant_pool): Likewise.
>         (force_const_mem): Likewise.
>         (record_tm_clone_pair): Likewise.
>         * varpool.c (varpool_create_empty_node): Likewise.
>
> gcc/c-family/ChangeLog:
>
>         * c-common.h (sorted_fields_type): Remove variable_size GTY attribute.
>         * c-pragma.c (push_alignment): Adjust.
>         (handle_pragma_push_options): Likewise.
>
> gcc/fortran/ChangeLog:
>
>         * f95-lang.c (pushlevel): Adjust.
>         * trans-decl.c (gfc_allocate_lang_decl): Likewise.
>         (gfc_find_module): Likewise.
>         * trans-types.c (gfc_get_nodesc_array_type): Likewise.
>         (gfc_get_array_type_bounds): Likewise.
>         (gfc_nonrestricted_type): Likewise.
>         * trans.h: Don't use variable_size gty attribute.
>
> gcc/c/ChangeLog:
>
>         * c-decl.c (bind): Adjust.
>         (record_inline_static): Likewise.
>         (push_scope): Likewise.
>         (make_label): Likewise.
>         (lookup_label_for_goto): Likewise.
>         (finish_struct): Likewise.
>         (finish_enum): Likewise.
>         (store_parm_decls): Likewise.
>         (c_push_function_context): Likewise.
>         * c-lang.h: Remove usage of variable_size gty attribute.
>         * c-parser.c (c_parse_init): Adjust.
>         (c_parse_file): Likewise.
>
> gcc/lto/ChangeLog:
>
>         * lto-tree.h: Don't use variable_size gty attribute.
>         * lto.c (lto_read_in_decl_state): Adjust.
>         (create_subid_section_table): Likewise.
>         (lto_flatten_files): Likewise.
>         (read_cgraph_and_symbols): Likewise.
>
> gcc/java/ChangeLog:
>
>         * class.c (add_method_1): Adjust.
>         (java_treetreehash_new): Likewise.
>         * constants.c (set_constant_entry): Likewise.
>         (cpool_for_class): Likewise.
>         * decl.c (make_binding_level): Likewise.
>         (java_dup_lang_specific_decl): Likewise.
>         * expr.c (add_type_assertion): Likewise.
>         * java-tree.h (MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC): Likewise.
>         (lang_decl): don't use variable_size gty attribute.
>         (MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC): Adjust.
>         (lang_type): Don't use variable_size gty attribute.
>         * jcf-parse.c (java_parse_file): Adjust.
>         (process_zip_dir): Likewise.
>         * jcf.h: Remove usage of variable_size gty attribute.
> ---
>  gcc/ada/gcc-interface/ada-tree.h    |  10 +--
>  gcc/alias.c                         |   2 +-
>  gcc/bitmap.c                        |   4 +-
>  gcc/c-family/c-common.h             |   2 +-
>  gcc/c-family/c-pragma.c             |   7 +-
>  gcc/c/c-decl.c                      |  23 +++----
>  gcc/c/c-lang.h                      |   4 +-
>  gcc/c/c-parser.c                    |   4 +-
>  gcc/cfg.c                           |  10 +--
>  gcc/cfgloop.c                       |   8 +--
>  gcc/cfgrtl.c                        |   2 +-
>  gcc/cgraph.c                        |   8 +--
>  gcc/cgraphclones.c                  |   2 +-
>  gcc/cgraphunit.c                    |   4 +-
>  gcc/config/i386/i386.c              |   6 +-
>  gcc/coverage.c                      |   2 +-
>  gcc/cp/cp-cilkplus.c                |   2 +-
>  gcc/cp/cp-objcp-common.c            |   2 +-
>  gcc/cp/cp-tree.h                    |   4 +-
>  gcc/cp/decl.c                       |   8 +--
>  gcc/cp/lex.c                        |   2 +-
>  gcc/cp/name-lookup.c                |  14 ++--
>  gcc/cp/parser.c                     |  14 ++--
>  gcc/cp/pt.c                         |  10 +--
>  gcc/cp/semantics.c                  |   4 +-
>  gcc/cp/typeck2.c                    |   2 +-
>  gcc/dbxout.c                        |   2 +-
>  gcc/doc/gty.texi                    |  32 ---------
>  gcc/dwarf2cfi.c                     |   8 +--
>  gcc/dwarf2out.c                     |  44 ++++++-------
>  gcc/emit-rtl.c                      |  10 +--
>  gcc/except.c                        |  10 +--
>  gcc/fortran/f95-lang.c              |   2 +-
>  gcc/fortran/trans-decl.c            |   6 +-
>  gcc/fortran/trans-types.c           |  15 ++---
>  gcc/fortran/trans.h                 |   7 +-
>  gcc/function.c                      |  18 ++---
>  gcc/gengtype.c                      | 128 ------------------------------------
>  gcc/ggc-common.c                    |   4 +-
>  gcc/ggc.h                           |  31 +++++++--
>  gcc/gimple.c                        |   9 +--
>  gcc/go/go-lang.c                    |   2 +-
>  gcc/ipa-cp.c                        |   6 +-
>  gcc/ipa-devirt.c                    |   2 +-
>  gcc/ipa-prop.c                      |   4 +-
>  gcc/java/class.c                    |   6 +-
>  gcc/java/constants.c                |   9 +--
>  gcc/java/decl.c                     |   4 +-
>  gcc/java/expr.c                     |   2 +-
>  gcc/java/java-tree.h                |  15 ++---
>  gcc/java/jcf-parse.c                |   6 +-
>  gcc/java/jcf.h                      |   2 +-
>  gcc/loop-iv.c                       |   2 +-
>  gcc/lto-cgraph.c                    |   2 +-
>  gcc/lto-section-in.c                |   2 +-
>  gcc/lto-streamer-in.c               |   8 +--
>  gcc/lto/lto-tree.h                  |   4 +-
>  gcc/lto/lto.c                       |   8 +--
>  gcc/objc/objc-act.c                 |   4 +-
>  gcc/objc/objc-act.h                 |   4 +-
>  gcc/objc/objc-map.c                 |  10 +--
>  gcc/objc/objc-next-runtime-abi-02.c |   4 +-
>  gcc/optabs.c                        |   4 +-
>  gcc/passes.c                        |   2 +-
>  gcc/rtl.h                           |   4 +-
>  gcc/sese.c                          |   2 +-
>  gcc/stringpool.c                    |   4 +-
>  gcc/target-globals.c                |   4 +-
>  gcc/toplev.c                        |   2 +-
>  gcc/trans-mem.c                     |   4 +-
>  gcc/tree-cfg.c                      |   2 +-
>  gcc/tree-data-ref.h                 |   2 +-
>  gcc/tree-eh.c                       |   2 +-
>  gcc/tree-iterator.c                 |   4 +-
>  gcc/tree-scalar-evolution.c         |   2 +-
>  gcc/tree-ssa-loop-niter.c           |   2 +-
>  gcc/tree-ssa-operands.h             |   2 +-
>  gcc/tree-ssa.c                      |   2 +-
>  gcc/tree-ssanames.c                 |   8 +--
>  gcc/tree-streamer-in.c              |   4 +-
>  gcc/tree.c                          |  14 ++--
>  gcc/ubsan.c                         |   2 +-
>  gcc/varasm.c                        |  16 ++---
>  gcc/varpool.c                       |   2 +-
>  84 files changed, 250 insertions(+), 432 deletions(-)
>
> diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h
> index 5ea386f..30f8ec4 100644
> --- a/gcc/ada/gcc-interface/ada-tree.h
> +++ b/gcc/ada/gcc-interface/ada-tree.h
> @@ -32,13 +32,9 @@ union GTY((desc ("0"),
>                        desc ("tree_node_structure (&%h)"))) generic;
>  };
>
> -/* Ada uses the lang_decl and lang_type fields to hold a tree.
> -
> -   FIXME: the variable_size annotation here is needed because these types are
> -   variable-sized in some other front-ends.  Due to gengtype deficiency, the
> -   GTY options of such types have to agree across all front-ends.  */
> -struct GTY((variable_size)) lang_type { tree t; };
> -struct GTY((variable_size)) lang_decl { tree t; };
> +/* Ada uses the lang_decl and lang_type fields to hold a tree.  */
> +struct GTY(()) lang_type { tree t; };
> +struct GTY(()) lang_decl { tree t; };
>
>  /* Macros to get and set the tree in TYPE_LANG_SPECIFIC.  */
>  #define GET_TYPE_LANG_SPECIFIC(NODE) \
> diff --git a/gcc/alias.c b/gcc/alias.c
> index 5f37402..bd45fcc 100644
> --- a/gcc/alias.c
> +++ b/gcc/alias.c
> @@ -943,7 +943,7 @@ record_alias_subset (alias_set_type superset, alias_set_type subset)
>      {
>        /* Create an entry for the SUPERSET, so that we have a place to
>          attach the SUBSET.  */
> -      superset_entry = ggc_alloc_cleared_alias_set_entry_d ();
> +      superset_entry = ggc_cleared_alloc<alias_set_entry_d> ();
>        superset_entry->alias_set = superset;
>        superset_entry->children
>         = splay_tree_new_ggc (splay_tree_compare_ints,
> diff --git a/gcc/bitmap.c b/gcc/bitmap.c
> index 4855a66..b2914e1 100644
> --- a/gcc/bitmap.c
> +++ b/gcc/bitmap.c
> @@ -244,7 +244,7 @@ bitmap_element_allocate (bitmap head)
>           /*  Inner list was just a singleton.  */
>           bitmap_ggc_free = element->prev;
>        else
> -       element = ggc_alloc_bitmap_element ();
> +       element = ggc_alloc<bitmap_element> ();
>      }
>
>    if (GATHER_STATISTICS)
> @@ -388,7 +388,7 @@ bitmap_gc_alloc_stat (ALONE_MEM_STAT_DECL)
>  {
>    bitmap map;
>
> -  map = ggc_alloc_bitmap_head ();
> +  map = ggc_alloc<bitmap_head> ();
>    bitmap_initialize_stat (map, NULL PASS_MEM_STAT);
>
>    if (GATHER_STATISTICS)
> diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
> index 57b7dce..d3b1099 100644
> --- a/gcc/c-family/c-common.h
> +++ b/gcc/c-family/c-common.h
> @@ -440,7 +440,7 @@ extern GTY(()) tree c_global_trees[CTI_MAX];
>
>  /* In a RECORD_TYPE, a sorted array of the fields of the type, not a
>     tree for size reasons.  */
> -struct GTY((variable_size)) sorted_fields_type {
> +struct GTY(()) sorted_fields_type {
>    int len;
>    tree GTY((length ("%h.len"))) elts[1];
>  };
> diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
> index 9e2a00e..7b016ab 100644
> --- a/gcc/c-family/c-pragma.c
> +++ b/gcc/c-family/c-pragma.c
> @@ -74,9 +74,7 @@ static void pop_alignment (tree);
>  static void
>  push_alignment (int alignment, tree id)
>  {
> -  align_stack * entry;
> -
> -  entry = ggc_alloc_align_stack ();
> +  align_stack * entry = ggc_alloc<align_stack> ();
>
>    entry->alignment  = alignment;
>    entry->id        = id;
> @@ -911,7 +909,6 @@ handle_pragma_push_options (cpp_reader *ARG_UNUSED(dummy))
>  {
>    enum cpp_ttype token;
>    tree x = 0;
> -  opt_stack *p;
>
>    token = pragma_lex (&x);
>    if (token != CPP_EOF)
> @@ -920,7 +917,7 @@ handle_pragma_push_options (cpp_reader *ARG_UNUSED(dummy))
>        return;
>      }
>
> -  p = ggc_alloc_opt_stack ();
> +  opt_stack *p = ggc_alloc<opt_stack> ();
>    p->prev = options_stack;
>    options_stack = p;
>
> diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
> index e8b8166..2400849 100644
> --- a/gcc/c/c-decl.c
> +++ b/gcc/c/c-decl.c
> @@ -638,7 +638,7 @@ bind (tree name, tree decl, struct c_scope *scope, bool invisible,
>        binding_freelist = b->prev;
>      }
>    else
> -    b = ggc_alloc_c_binding ();
> +    b = ggc_alloc<c_binding> ();
>
>    b->shadowed = 0;
>    b->decl = decl;
> @@ -755,7 +755,7 @@ void
>  record_inline_static (location_t loc, tree func, tree decl,
>                       enum c_inline_static_type type)
>  {
> -  struct c_inline_static *csi = ggc_alloc_c_inline_static ();
> +  c_inline_static *csi = ggc_alloc<c_inline_static> ();
>    csi->location = loc;
>    csi->function = func;
>    csi->static_decl = decl;
> @@ -952,7 +952,7 @@ push_scope (void)
>           scope_freelist = scope->outer;
>         }
>        else
> -       scope = ggc_alloc_cleared_c_scope ();
> +       scope = ggc_cleared_alloc<c_scope> ();
>
>        /* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes.  */
>        if (current_scope)
> @@ -3084,12 +3084,10 @@ make_label (location_t location, tree name, bool defining,
>             struct c_label_vars **p_label_vars)
>  {
>    tree label = build_decl (location, LABEL_DECL, name, void_type_node);
> -  struct c_label_vars *label_vars;
> -
>    DECL_CONTEXT (label) = current_function_decl;
>    DECL_MODE (label) = VOIDmode;
>
> -  label_vars = ggc_alloc_c_label_vars ();
> +  c_label_vars *label_vars = ggc_alloc<c_label_vars> ();
>    label_vars->shadowed = NULL;
>    set_spot_bindings (&label_vars->label_bindings, defining);
>    label_vars->decls_in_scope = make_tree_vector ();
> @@ -3185,9 +3183,8 @@ lookup_label_for_goto (location_t loc, tree name)
>       list for possible later warnings.  */
>    if (label_vars->label_bindings.scope == NULL)
>      {
> -      struct c_goto_bindings *g;
> +      c_goto_bindings *g = ggc_alloc<c_goto_bindings> ();
>
> -      g = ggc_alloc_c_goto_bindings ();
>        g->loc = loc;
>        set_spot_bindings (&g->goto_bindings, true);
>        vec_safe_push (label_vars->gotos, g);
> @@ -7423,8 +7420,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
>           ensure that this lives as long as the rest of the struct decl.
>           All decls in an inline function need to be saved.  */
>
> -       space = (struct lang_type *) ggc_internal_cleared_alloc
> -         (sizeof (struct lang_type));
> +       space = ggc_cleared_alloc<struct lang_type> ();
>         space2 = (sorted_fields_type *) ggc_internal_alloc
>           (sizeof (struct sorted_fields_type) + len * sizeof (tree));
>
> @@ -7705,8 +7701,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
>
>    /* Record the min/max values so that we can warn about bit-field
>       enumerations that are too small for the values.  */
> -  lt = (struct lang_type *) ggc_internal_cleared_alloc
> -    (sizeof (struct lang_type));
> +  lt = ggc_cleared_alloc<struct lang_type> ();
>    lt->enum_min = minnode;
>    lt->enum_max = maxnode;
>    TYPE_LANG_SPECIFIC (enumtype) = lt;
> @@ -8477,7 +8472,7 @@ store_parm_decls (void)
>    allocate_struct_function (fndecl, false);
>
>    if (warn_unused_local_typedefs)
> -    cfun->language = ggc_alloc_cleared_language_function ();
> +    cfun->language = ggc_cleared_alloc<language_function> ();
>
>    /* Begin the statement tree for this function.  */
>    DECL_SAVED_TREE (fndecl) = push_stmt_list ();
> @@ -8801,7 +8796,7 @@ c_push_function_context (void)
>    /* cfun->language might have been already allocated by the use of
>       -Wunused-local-typedefs.  In that case, just re-use it.  */
>    if (p == NULL)
> -    cfun->language = p = ggc_alloc_cleared_language_function ();
> +    cfun->language = p = ggc_cleared_alloc<language_function> ();
>
>    p->base.x_stmt_tree = c_stmt_tree;
>    c_stmt_tree.x_cur_stmt_list = vec_safe_copy (c_stmt_tree.x_cur_stmt_list);
> diff --git a/gcc/c/c-lang.h b/gcc/c/c-lang.h
> index 7fcf333..e974906 100644
> --- a/gcc/c/c-lang.h
> +++ b/gcc/c/c-lang.h
> @@ -23,7 +23,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "c-family/c-common.h"
>  #include "ggc.h"
>
> -struct GTY((variable_size)) lang_type {
> +struct GTY(()) lang_type {
>    /* In a RECORD_TYPE, a sorted array of the fields of the type.  */
>    struct sorted_fields_type * GTY ((reorder ("resort_sorted_fields"))) s;
>    /* In an ENUMERAL_TYPE, the min and max values.  */
> @@ -35,7 +35,7 @@ struct GTY((variable_size)) lang_type {
>    tree objc_info;
>  };
>
> -struct GTY((variable_size)) lang_decl {
> +struct GTY(()) lang_decl {
>    char dummy;
>  };
>
> diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
> index 56f79f6..2843e9d 100644
> --- a/gcc/c/c-parser.c
> +++ b/gcc/c/c-parser.c
> @@ -90,7 +90,7 @@ c_parse_init (void)
>    if (!c_dialect_objc ())
>      mask |= D_OBJC | D_CXX_OBJC;
>
> -  ridpointers = ggc_alloc_cleared_vec_tree ((int) RID_MAX);
> +  ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX);
>    for (i = 0; i < num_c_common_reswords; i++)
>      {
>        /* If a keyword is disabled, do not enter it into the table
> @@ -14039,7 +14039,7 @@ c_parse_file (void)
>    if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
>      c_parser_pragma_pch_preprocess (&tparser);
>
> -  the_parser = ggc_alloc_c_parser ();
> +  the_parser = ggc_alloc<c_parser> ();
>    *the_parser = tparser;
>    if (tparser.tokens == &tparser.tokens_buf[0])
>      the_parser->tokens = &the_parser->tokens_buf[0];
> diff --git a/gcc/cfg.c b/gcc/cfg.c
> index 3b6349a..aef1145 100644
> --- a/gcc/cfg.c
> +++ b/gcc/cfg.c
> @@ -68,13 +68,13 @@ void
>  init_flow (struct function *the_fun)
>  {
>    if (!the_fun->cfg)
> -    the_fun->cfg = ggc_alloc_cleared_control_flow_graph ();
> +    the_fun->cfg = ggc_cleared_alloc<control_flow_graph> ();
>    n_edges_for_fn (the_fun) = 0;
>    ENTRY_BLOCK_PTR_FOR_FN (the_fun)
> -    = ggc_alloc_cleared_basic_block_def ();
> +    = ggc_cleared_alloc<basic_block_def> ();
>    ENTRY_BLOCK_PTR_FOR_FN (the_fun)->index = ENTRY_BLOCK;
>    EXIT_BLOCK_PTR_FOR_FN (the_fun)
> -    = ggc_alloc_cleared_basic_block_def ();
> +    = ggc_cleared_alloc<basic_block_def> ();
>    EXIT_BLOCK_PTR_FOR_FN (the_fun)->index = EXIT_BLOCK;
>    ENTRY_BLOCK_PTR_FOR_FN (the_fun)->next_bb
>      = EXIT_BLOCK_PTR_FOR_FN (the_fun);
> @@ -123,7 +123,7 @@ basic_block
>  alloc_block (void)
>  {
>    basic_block bb;
> -  bb = ggc_alloc_cleared_basic_block_def ();
> +  bb = ggc_cleared_alloc<basic_block_def> ();
>    return bb;
>  }
>
> @@ -261,7 +261,7 @@ edge
>  unchecked_make_edge (basic_block src, basic_block dst, int flags)
>  {
>    edge e;
> -  e = ggc_alloc_cleared_edge_def ();
> +  e = ggc_cleared_alloc<edge_def> ();
>    n_edges_for_fn (cfun)++;
>
>    e->src = src;
> diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
> index 70744d8..3ff5b6a 100644
> --- a/gcc/cfgloop.c
> +++ b/gcc/cfgloop.c
> @@ -331,9 +331,9 @@ flow_loop_tree_node_remove (struct loop *loop)
>  struct loop *
>  alloc_loop (void)
>  {
> -  struct loop *loop = ggc_alloc_cleared_loop ();
> +  struct loop *loop = ggc_cleared_alloc<struct loop> ();
>
> -  loop->exits = ggc_alloc_cleared_loop_exit ();
> +  loop->exits = ggc_cleared_alloc<loop_exit> ();
>    loop->exits->next = loop->exits->prev = loop->exits;
>    loop->can_be_parallel = false;
>
> @@ -414,7 +414,7 @@ flow_loops_find (struct loops *loops)
>
>    if (!loops)
>      {
> -      loops = ggc_alloc_cleared_loops ();
> +      loops = ggc_cleared_alloc<struct loops> ();
>        init_loops_structure (cfun, loops, 1);
>      }
>
> @@ -1028,7 +1028,7 @@ rescan_loop_exit (edge e, bool new_edge, bool removed)
>            aloop != cloop;
>            aloop = loop_outer (aloop))
>         {
> -         exit = ggc_alloc_loop_exit ();
> +         exit = ggc_alloc<loop_exit> ();
>           exit->e = e;
>
>           exit->next = aloop->exits->next;
> diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
> index 5dd27d2..06fc43e 100644
> --- a/gcc/cfgrtl.c
> +++ b/gcc/cfgrtl.c
> @@ -4954,7 +4954,7 @@ init_rtl_bb_info (basic_block bb)
>  {
>    gcc_assert (!bb->il.x.rtl);
>    bb->il.x.head_ = NULL;
> -  bb->il.x.rtl = ggc_alloc_cleared_rtl_bb_info ();
> +  bb->il.x.rtl = ggc_cleared_alloc<rtl_bb_info> ();
>  }
>
>  /* Returns true if it is possible to remove edge E by redirecting
> diff --git a/gcc/cgraph.c b/gcc/cgraph.c
> index ee192ed..f28492e 100644
> --- a/gcc/cgraph.c
> +++ b/gcc/cgraph.c
> @@ -198,7 +198,7 @@ insert_new_cgraph_node_version (struct cgraph_node *node)
>    void **slot;
>
>    version_info_node = NULL;
> -  version_info_node = ggc_alloc_cleared_cgraph_function_version_info ();
> +  version_info_node = ggc_cleared_alloc<cgraph_function_version_info> ();
>    version_info_node->this_node = node;
>
>    if (cgraph_fnver_htab == NULL)
> @@ -507,7 +507,7 @@ cgraph_allocate_node (void)
>      }
>    else
>      {
> -      node = ggc_alloc_cleared_cgraph_node ();
> +      node = ggc_cleared_alloc<cgraph_node> ();
>        node->uid = cgraph_max_uid++;
>      }
>
> @@ -866,7 +866,7 @@ cgraph_create_edge_1 (struct cgraph_node *caller, struct cgraph_node *callee,
>      }
>    else
>      {
> -      edge = ggc_alloc_cgraph_edge ();
> +      edge = ggc_alloc<struct cgraph_edge> ();
>        edge->uid = cgraph_edge_max_uid++;
>      }
>
> @@ -938,7 +938,7 @@ cgraph_allocate_init_indirect_info (void)
>  {
>    struct cgraph_indirect_call_info *ii;
>
> -  ii = ggc_alloc_cleared_cgraph_indirect_call_info ();
> +  ii = ggc_cleared_alloc<cgraph_indirect_call_info> ();
>    ii->param_index = -1;
>    return ii;
>  }
> diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
> index 48b5379..d61e0f7 100644
> --- a/gcc/cgraphclones.c
> +++ b/gcc/cgraphclones.c
> @@ -146,7 +146,7 @@ cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n,
>        if (e->indirect_info)
>         {
>           new_edge->indirect_info
> -           = ggc_alloc_cleared_cgraph_indirect_call_info ();
> +           = ggc_cleared_alloc<cgraph_indirect_call_info> ();
>           *new_edge->indirect_info = *e->indirect_info;
>         }
>      }
> diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
> index 7bf9a07..acb9a7a 100644
> --- a/gcc/cgraphunit.c
> +++ b/gcc/cgraphunit.c
> @@ -570,7 +570,7 @@ add_asm_node (tree asm_str)
>  {
>    struct asm_node *node;
>
> -  node = ggc_alloc_cleared_asm_node ();
> +  node = ggc_cleared_alloc<asm_node> ();
>    node->asm_str = asm_str;
>    node->order = symtab_order++;
>    node->next = NULL;
> @@ -1337,7 +1337,7 @@ init_lowered_empty_function (tree decl, bool in_ssa)
>    cfun->curr_properties |= (PROP_gimple_lcf | PROP_gimple_leh | PROP_gimple_any
>                             | PROP_cfg | PROP_loops);
>
> -  set_loops_for_fn (cfun, ggc_alloc_cleared_loops ());
> +  set_loops_for_fn (cfun, ggc_cleared_alloc<loops> ());
>    init_loops_structure (cfun, loops_for_fn (cfun), 1);
>    loops_for_fn (cfun)->state |= LOOPS_MAY_HAVE_MULTIPLE_LATCHES;
>
> diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> index 895ebbb..848788e 100644
> --- a/gcc/config/i386/i386.c
> +++ b/gcc/config/i386/i386.c
> @@ -13643,7 +13643,7 @@ get_dllimport_decl (tree decl, bool beimport)
>    if (h)
>      return h->to;
>
> -  *loc = h = ggc_alloc_tree_map ();
> +  *loc = h = ggc_alloc<tree_map> ();
>    h->hash = in.hash;
>    h->base.from = decl;
>    h->to = to = build_decl (DECL_SOURCE_LOCATION (decl),
> @@ -24990,7 +24990,7 @@ ix86_init_machine_status (void)
>  {
>    struct machine_function *f;
>
> -  f = ggc_alloc_cleared_machine_function ();
> +  f = ggc_cleared_alloc<machine_function> ();
>    f->use_fast_prologue_epilogue_nregs = -1;
>    f->call_abi = ix86_abi;
>
> @@ -25014,7 +25014,7 @@ assign_386_stack_local (enum machine_mode mode, enum ix86_stack_slot n)
>      if (s->mode == mode && s->n == n)
>        return validize_mem (copy_rtx (s->rtl));
>
> -  s = ggc_alloc_stack_local_entry ();
> +  s = ggc_alloc<stack_local_entry> ();
>    s->n = n;
>    s->mode = mode;
>    s->rtl = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
> diff --git a/gcc/coverage.c b/gcc/coverage.c
> index ff1e67d..5e9005e 100644
> --- a/gcc/coverage.c
> +++ b/gcc/coverage.c
> @@ -667,7 +667,7 @@ coverage_end_function (unsigned lineno_checksum, unsigned cfg_checksum)
>          list.  */
>        if (!DECL_EXTERNAL (current_function_decl))
>         {
> -         item = ggc_alloc_coverage_data ();
> +         item = ggc_alloc<coverage_data> ();
>
>           item->ident = current_function_funcdef_no + 1;
>           item->lineno_checksum = lineno_checksum;
> diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c
> index f3a2aff..daa9b8e 100644
> --- a/gcc/cp/cp-cilkplus.c
> +++ b/gcc/cp/cp-cilkplus.c
> @@ -118,7 +118,7 @@ cilk_install_body_with_frame_cleanup (tree fndecl, tree orig_body, void *wd)
>    tree dtor = create_cilk_function_exit (frame, false, false);
>    add_local_decl (cfun, frame);
>
> -  cfun->language = ggc_alloc_cleared_language_function ();
> +  cfun->language = ggc_cleared_alloc<language_function> ();
>
>    location_t loc = EXPR_LOCATION (orig_body);
>    tree list = alloc_stmt_list ();
> diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
> index aa0ff83..78dddef 100644
> --- a/gcc/cp/cp-objcp-common.c
> +++ b/gcc/cp/cp-objcp-common.c
> @@ -208,7 +208,7 @@ decl_shadowed_for_var_insert (tree from, tree to)
>    struct tree_decl_map *h;
>    void **loc;
>
> -  h = ggc_alloc_tree_decl_map ();
> +  h = ggc_alloc<tree_decl_map> ();
>    h->base.from = from;
>    h->to = to;
>    loc = htab_find_slot_with_hash (shadowed_var_for_decl, h, DECL_UID (from),
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 9fbc7f8..b76af3c 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -1482,7 +1482,7 @@ struct GTY(()) lang_type_ptrmem {
>    tree record;
>  };
>
> -struct GTY((variable_size)) lang_type {
> +struct GTY(()) lang_type {
>    union lang_type_u
>    {
>      struct lang_type_header GTY((skip (""))) h;
> @@ -2060,7 +2060,7 @@ struct GTY(()) lang_decl_parm {
>     union rather than a struct containing a union as its only field, but
>     tree.h declares it as a struct.  */
>
> -struct GTY((variable_size)) lang_decl {
> +struct GTY(()) lang_decl {
>    union GTY((desc ("%h.base.selector"))) lang_decl_u {
>      struct lang_decl_base GTY ((default)) base;
>      struct lang_decl_min GTY((tag ("0"))) min;
> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> index 7ce55c8..4ad6f16 100644
> --- a/gcc/cp/decl.c
> +++ b/gcc/cp/decl.c
> @@ -2700,7 +2700,7 @@ make_label_decl (tree id, int local_p)
>    /* Record this label on the list of labels used in this function.
>       We do this before calling make_label_decl so that we get the
>       IDENTIFIER_LABEL_VALUE before the new label is declared.  */
> -  ent = ggc_alloc_cleared_named_label_entry ();
> +  ent = ggc_cleared_alloc<named_label_entry> ();
>    ent->label_decl = decl;
>
>    slot = htab_find_slot (named_labels, ent, INSERT);
> @@ -2931,7 +2931,7 @@ check_goto (tree decl)
>           && ent->uses->names_in_scope == current_binding_level->names)
>         return;
>
> -      new_use = ggc_alloc_named_label_use_entry ();
> +      new_use = ggc_alloc<named_label_use_entry> ();
>        new_use->binding_level = current_binding_level;
>        new_use->names_in_scope = current_binding_level->names;
>        new_use->o_goto_locus = input_location;
> @@ -13301,7 +13301,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
>
>    /* Initialize the language data structures.  Whenever we start
>       a new function, we destroy temporaries in the usual way.  */
> -  cfun->language = ggc_alloc_cleared_language_function ();
> +  cfun->language = ggc_cleared_alloc<language_function> ();
>    current_stmt_tree ()->stmts_are_full_exprs_p = 1;
>    current_binding_level = bl;
>
> @@ -13603,7 +13603,7 @@ save_function_data (tree decl)
>    gcc_assert (!DECL_PENDING_INLINE_P (decl));
>
>    /* Make a copy.  */
> -  f = ggc_alloc_language_function ();
> +  f = ggc_alloc<language_function> ();
>    memcpy (f, cp_function_chain, sizeof (struct language_function));
>    DECL_SAVED_FUNCTION_DATA (decl) = f;
>
> diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
> index 46c28ae..57b779d 100644
> --- a/gcc/cp/lex.c
> +++ b/gcc/cp/lex.c
> @@ -182,7 +182,7 @@ init_reswords (void)
>    /* The Objective-C keywords are all context-dependent.  */
>    mask |= D_OBJC;
>
> -  ridpointers = ggc_alloc_cleared_vec_tree ((int) RID_MAX);
> +  ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX);
>    for (i = 0; i < num_c_common_reswords; i++)
>      {
>        if (c_common_reswords[i].disable & D_CONLY)
> diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
> index d900560..2baeeb7 100644
> --- a/gcc/cp/name-lookup.c
> +++ b/gcc/cp/name-lookup.c
> @@ -105,7 +105,7 @@ binding_entry_make (tree name, tree type)
>        free_binding_entry = entry->chain;
>      }
>    else
> -    entry = ggc_alloc_binding_entry_s ();
> +    entry = ggc_alloc<binding_entry_s> ();
>
>    entry->name = name;
>    entry->type = type;
> @@ -147,7 +147,7 @@ binding_table_construct (binding_table table, size_t chain_count)
>  {
>    table->chain_count = chain_count;
>    table->entry_count = 0;
> -  table->chain = ggc_alloc_cleared_vec_binding_entry (table->chain_count);
> +  table->chain = ggc_cleared_vec_alloc<binding_entry> (table->chain_count);
>  }
>
>  /* Make TABLE's entries ready for reuse.  */
> @@ -181,7 +181,7 @@ binding_table_free (binding_table table)
>  static inline binding_table
>  binding_table_new (size_t chain_count)
>  {
> -  binding_table table = ggc_alloc_binding_table_s ();
> +  binding_table table = ggc_alloc<binding_table_s> ();
>    table->chain = NULL;
>    binding_table_construct (table, chain_count);
>    return table;
> @@ -299,7 +299,7 @@ cxx_binding_make (tree value, tree type)
>        free_bindings = binding->previous;
>      }
>    else
> -    binding = ggc_alloc_cxx_binding ();
> +    binding = ggc_alloc<cxx_binding> ();
>
>    cxx_binding_init (binding, value, type);
>
> @@ -775,7 +775,7 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
>                       = htab_create_ggc (20, cxx_int_tree_map_hash,
>                                          cxx_int_tree_map_eq, NULL);
>
> -                 h = ggc_alloc_cxx_int_tree_map ();
> +                 h = ggc_alloc<cxx_int_tree_map> ();
>                   h->uid = DECL_UID (x);
>                   h->to = t;
>                   loc = htab_find_slot_with_hash
> @@ -1544,7 +1544,7 @@ begin_scope (scope_kind kind, tree entity)
>        free_binding_level = scope->level_chain;
>      }
>    else
> -    scope = ggc_alloc_cleared_cp_binding_level ();
> +    scope = ggc_cleared_alloc<cp_binding_level> ();
>
>    scope->this_entity = entity;
>    scope->more_cleanups_ok = true;
> @@ -6074,7 +6074,7 @@ push_to_top_level (void)
>    bool need_pop;
>
>    bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
> -  s = ggc_alloc_cleared_saved_scope ();
> +  s = ggc_cleared_alloc<saved_scope> ();
>
>    b = scope_chain ? current_binding_level : 0;
>
> diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> index c1d94ae..a2f9355 100644
> --- a/gcc/cp/parser.c
> +++ b/gcc/cp/parser.c
> @@ -602,7 +602,7 @@ cp_lexer_alloc (void)
>    c_common_no_more_pch ();
>
>    /* Allocate the memory.  */
> -  lexer = ggc_alloc_cleared_cp_lexer ();
> +  lexer = ggc_cleared_alloc<cp_lexer> ();
>
>    /* Initially we are not debugging.  */
>    lexer->debugging_p = false;
> @@ -665,7 +665,7 @@ cp_lexer_new_from_tokens (cp_token_cache *cache)
>  {
>    cp_token *first = cache->first;
>    cp_token *last = cache->last;
> -  cp_lexer *lexer = ggc_alloc_cleared_cp_lexer ();
> +  cp_lexer *lexer = ggc_cleared_alloc<cp_lexer> ();
>
>    /* We do not own the buffer.  */
>    lexer->buffer = NULL;
> @@ -1240,7 +1240,7 @@ cp_lexer_stop_debugging (cp_lexer* lexer)
>  static cp_token_cache *
>  cp_token_cache_new (cp_token *first, cp_token *last)
>  {
> -  cp_token_cache *cache = ggc_alloc_cp_token_cache ();
> +  cp_token_cache *cache = ggc_alloc<cp_token_cache> ();
>    cache->first = first;
>    cache->last = last;
>    return cache;
> @@ -1822,7 +1822,7 @@ cp_parser_context_new (cp_parser_context* next)
>        memset (context, 0, sizeof (*context));
>      }
>    else
> -    context = ggc_alloc_cleared_cp_parser_context ();
> +    context = ggc_cleared_alloc<cp_parser_context> ();
>
>    /* No errors have occurred yet in this context.  */
>    context->status = CP_PARSER_STATUS_KIND_NO_ERROR;
> @@ -3411,7 +3411,7 @@ cp_parser_new (void)
>    for (i = 0; i < sizeof (binops) / sizeof (binops[0]); i++)
>      binops_by_token[binops[i].token_type] = binops[i];
>
> -  parser = ggc_alloc_cleared_cp_parser ();
> +  parser = ggc_cleared_alloc<cp_parser> ();
>    parser->lexer = lexer;
>    parser->context = cp_parser_context_new (NULL);
>
> @@ -5425,7 +5425,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
>        token->type = CPP_NESTED_NAME_SPECIFIER;
>        /* Retrieve any deferred checks.  Do not pop this access checks yet
>          so the memory will not be reclaimed during token replacing below.  */
> -      token->u.tree_check_value = ggc_alloc_cleared_tree_check ();
> +      token->u.tree_check_value = ggc_cleared_alloc<struct tree_check> ();
>        token->u.tree_check_value->value = parser->scope;
>        token->u.tree_check_value->checks = get_deferred_access_checks ();
>        token->u.tree_check_value->qualifying_scope =
> @@ -13500,7 +13500,7 @@ cp_parser_template_id (cp_parser *parser,
>        token->type = CPP_TEMPLATE_ID;
>        /* Retrieve any deferred checks.  Do not pop this access checks yet
>          so the memory will not be reclaimed during token replacing below.  */
> -      token->u.tree_check_value = ggc_alloc_cleared_tree_check ();
> +      token->u.tree_check_value = ggc_cleared_alloc<struct tree_check> ();
>        token->u.tree_check_value->value = template_id;
>        token->u.tree_check_value->checks = get_deferred_access_checks ();
>        token->keyword = RID_MAX;
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index c74e7ae..b1e6c14 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -940,7 +940,7 @@ maybe_process_partial_specialization (tree type)
>                   elt.args = INNERMOST_TEMPLATE_ARGS (elt.args);
>
>                   slot = htab_find_slot (type_specializations, &elt, INSERT);
> -                 entry = ggc_alloc_spec_entry ();
> +                 entry = ggc_alloc<spec_entry> ();
>                   *entry = elt;
>                   *slot = entry;
>                 }
> @@ -1477,7 +1477,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
>
>    if (slot != NULL /* !optimize_specialization_lookup_p (tmpl) */)
>      {
> -      spec_entry *entry = ggc_alloc_spec_entry ();
> +      spec_entry *entry = ggc_alloc<spec_entry> ();
>        gcc_assert (tmpl && args && spec);
>        *entry = elt;
>        *slot = entry;
> @@ -7177,7 +7177,7 @@ add_pending_template (tree d)
>    if (level)
>      push_tinst_level (d);
>
> -  pt = ggc_alloc_pending_template ();
> +  pt = ggc_alloc<pending_template> ();
>    pt->next = NULL;
>    pt->tinst = current_tinst_level;
>    if (last_pending_template)
> @@ -7807,7 +7807,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
>        elt.spec = t;
>        slot = htab_find_slot_with_hash (type_specializations,
>                                        &elt, hash, INSERT);
> -      entry = ggc_alloc_spec_entry ();
> +      entry = ggc_alloc<spec_entry> ();
>        *entry = elt;
>        *slot = entry;
>
> @@ -8232,7 +8232,7 @@ push_tinst_level (tree d)
>    if (limit_bad_template_recursion (d))
>      return 0;
>
> -  new_level = ggc_alloc_tinst_level ();
> +  new_level = ggc_alloc<tinst_level> ();
>    new_level->decl = d;
>    new_level->locus = input_location;
>    new_level->errors = errorcount+sorrycount;
> diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
> index 3f8ca44..a8b8dab 100644
> --- a/gcc/cp/semantics.c
> +++ b/gcc/cp/semantics.c
> @@ -8024,7 +8024,7 @@ register_constexpr_fundef (tree fun, tree body)
>      htab_find_slot (constexpr_fundef_table, &entry, INSERT);
>
>    gcc_assert (*slot == NULL);
> -  *slot = ggc_alloc_constexpr_fundef ();
> +  *slot = ggc_alloc<constexpr_fundef> ();
>    **slot = entry;
>
>    return fun;
> @@ -8465,7 +8465,7 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
>      {
>        /* We need to keep a pointer to the entry, not just the slot, as the
>          slot can move in the call to cxx_eval_builtin_function_call.  */
> -      *slot = entry = ggc_alloc_constexpr_call ();
> +      *slot = entry = ggc_alloc<constexpr_call> ();
>        *entry = new_call;
>      }
>    /* Calls which are in progress have their result set to NULL
> diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
> index 68e518a..b7fa77b 100644
> --- a/gcc/cp/typeck2.c
> +++ b/gcc/cp/typeck2.c
> @@ -293,7 +293,7 @@ abstract_virtuals_error_sfinae (tree decl, tree type, abstract_class_use use,
>        slot = htab_find_slot_with_hash (abstract_pending_vars, type,
>                                       (hashval_t)TYPE_UID (type), INSERT);
>
> -      pat = ggc_alloc_pending_abstract_type ();
> +      pat = ggc_alloc<pending_abstract_type> ();
>        pat->type = type;
>        pat->decl = decl;
>        pat->use = use;
> diff --git a/gcc/dbxout.c b/gcc/dbxout.c
> index 5fbbdf6..0fe9bfe 100644
> --- a/gcc/dbxout.c
> +++ b/gcc/dbxout.c
> @@ -1025,7 +1025,7 @@ dbxout_init (const char *input_file_name)
>    const char *mapped_name;
>
>    typevec_len = 100;
> -  typevec = ggc_alloc_cleared_vec_typeinfo (typevec_len);
> +  typevec = ggc_cleared_vec_alloc<typeinfo> (typevec_len);
>
>    /* stabstr_ob contains one string, which will be just fine with
>       1-byte alignment.  */
> diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi
> index d32ac00..e50eef6 100644
> --- a/gcc/doc/gty.texi
> +++ b/gcc/doc/gty.texi
> @@ -382,38 +382,6 @@ of pointers.  @code{reorder} functions can be expensive.  When
>  possible, it is better to depend on properties of the data, like an ID
>  number or the hash of a string instead.
>
> -@findex variable_size
> -@item variable_size
> -
> -The type machinery expects the types to be of constant size.  When this
> -is not true, for example, with structs that have array fields or unions,
> -the type machinery cannot tell how many bytes need to be allocated at
> -each allocation.  The @code{variable_size} is used to mark such types.
> -The type machinery then provides allocators that take a parameter
> -indicating an exact size of object being allocated.  Note that the size
> -must be provided in bytes whereas the @code{length} option works with
> -array lengths in number of elements.
> -
> -For example,
> -@smallexample
> -struct GTY((variable_size)) sorted_fields_type @{
> -  int len;
> -  tree GTY((length ("%h.len"))) elts[1];
> -@};
> -@end smallexample
> -
> -Then the objects of @code{struct sorted_fields_type} are allocated in GC
> -memory as follows:
> -@smallexample
> -  field_vec = ggc_alloc_sorted_fields_type (size);
> -@end smallexample
> -
> -If @var{field_vec->elts} stores @var{n} elements, then @var{size}
> -could be calculated as follows:
> -@smallexample
> -  size_t size = sizeof (struct sorted_fields_type) + n * sizeof (tree);
> -@end smallexample
> -
>  @findex atomic
>  @item atomic
>
> diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
> index 4180890..47fd028 100644
> --- a/gcc/dwarf2cfi.c
> +++ b/gcc/dwarf2cfi.c
> @@ -356,7 +356,7 @@ need_data_align_sf_opcode (HOST_WIDE_INT off)
>  static inline dw_cfi_ref
>  new_cfi (void)
>  {
> -  dw_cfi_ref cfi = ggc_alloc_dw_cfi_node ();
> +  dw_cfi_ref cfi = ggc_alloc<dw_cfi_node> ();
>
>    cfi->dw_cfi_oprnd1.dw_cfi_reg_num = 0;
>    cfi->dw_cfi_oprnd2.dw_cfi_reg_num = 0;
> @@ -369,7 +369,7 @@ new_cfi (void)
>  static dw_cfi_row *
>  new_cfi_row (void)
>  {
> -  dw_cfi_row *row = ggc_alloc_cleared_dw_cfi_row ();
> +  dw_cfi_row *row = ggc_cleared_alloc<dw_cfi_row> ();
>
>    row->cfa.reg = INVALID_REGNUM;
>
> @@ -381,7 +381,7 @@ new_cfi_row (void)
>  static dw_cfi_row *
>  copy_cfi_row (dw_cfi_row *src)
>  {
> -  dw_cfi_row *dst = ggc_alloc_dw_cfi_row ();
> +  dw_cfi_row *dst = ggc_alloc<dw_cfi_row> ();
>
>    *dst = *src;
>    dst->reg_save = vec_safe_copy (src->reg_save);
> @@ -2892,7 +2892,7 @@ create_cie_data (void)
>         case 0:
>           break;
>         case 1:
> -         cie_return_save = ggc_alloc_reg_saved_in_data ();
> +         cie_return_save = ggc_alloc<reg_saved_in_data> ();
>           *cie_return_save = cie_trace.regs_saved_in_regs[0];
>           cie_trace.regs_saved_in_regs.release ();
>           break;
> diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
> index 6133fa3..9e99e46 100644
> --- a/gcc/dwarf2out.c
> +++ b/gcc/dwarf2out.c
> @@ -982,7 +982,7 @@ dwarf2out_alloc_current_fde (void)
>  {
>    dw_fde_ref fde;
>
> -  fde = ggc_alloc_cleared_dw_fde_node ();
> +  fde = ggc_cleared_alloc<dw_fde_node> ();
>    fde->decl = current_function_decl;
>    fde->funcdef_number = current_function_funcdef_no;
>    fde->fde_index = vec_safe_length (fde_vec);
> @@ -1305,7 +1305,7 @@ static inline dw_loc_descr_ref
>  new_loc_descr (enum dwarf_location_atom op, unsigned HOST_WIDE_INT oprnd1,
>                unsigned HOST_WIDE_INT oprnd2)
>  {
> -  dw_loc_descr_ref descr = ggc_alloc_cleared_dw_loc_descr_node ();
> +  dw_loc_descr_ref descr = ggc_cleared_alloc<dw_loc_descr_node> ();
>
>    descr->dw_loc_opc = op;
>    descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const;
> @@ -3872,7 +3872,7 @@ find_AT_string_in_table (const char *str, htab_t table)
>                                    htab_hash_string (str), INSERT);
>    if (*slot == NULL)
>      {
> -      node = ggc_alloc_cleared_indirect_string_node ();
> +      node = ggc_cleared_alloc<indirect_string_node> ();
>        node->str = ggc_strdup (str);
>        *slot = node;
>      }
> @@ -4203,7 +4203,7 @@ add_addr_table_entry (void *addr, enum ate_kind kind)
>
>    if (*slot == HTAB_EMPTY_ENTRY)
>      {
> -      node = ggc_alloc_cleared_addr_table_entry ();
> +      node = ggc_cleared_alloc<addr_table_entry> ();
>        init_addr_table_entry (node, kind, addr);
>        *slot = node;
>      }
> @@ -4779,7 +4779,7 @@ splice_child_die (dw_die_ref parent, dw_die_ref child)
>  static inline dw_die_ref
>  new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
>  {
> -  dw_die_ref die = ggc_alloc_cleared_die_node ();
> +  dw_die_ref die = ggc_cleared_alloc<die_node> ();
>
>    die->die_tag = tag_value;
>
> @@ -4789,7 +4789,7 @@ new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
>      {
>        limbo_die_node *limbo_node;
>
> -      limbo_node = ggc_alloc_cleared_limbo_die_node ();
> +      limbo_node = ggc_cleared_alloc<limbo_die_node> ();
>        limbo_node->die = die;
>        limbo_node->created_for = t;
>        limbo_node->next = limbo_die_list;
> @@ -5106,7 +5106,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
>    slot = htab_find_slot_with_hash (decl_loc_table, decl, decl_id, INSERT);
>    if (*slot == NULL)
>      {
> -      temp = ggc_alloc_cleared_var_loc_list ();
> +      temp = ggc_cleared_alloc<var_loc_list> ();
>        temp->decl_id = decl_id;
>        *slot = temp;
>      }
> @@ -5131,7 +5131,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
>           || (NOTE_VAR_LOCATION_STATUS (temp->first->loc)
>               != NOTE_VAR_LOCATION_STATUS (loc_note))))
>      {
> -      loc = ggc_alloc_cleared_var_loc_node ();
> +      loc = ggc_cleared_alloc<var_loc_node> ();
>        temp->first->next = loc;
>        temp->last = loc;
>        loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
> @@ -5221,7 +5221,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
>               memset (loc, '\0', sizeof (*loc));
>             }
>           else
> -           loc = ggc_alloc_cleared_var_loc_node ();
> +           loc = ggc_cleared_alloc<var_loc_node> ();
>           if (bitsize == -1 || piece_loc == NULL)
>             loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
>           else
> @@ -5238,7 +5238,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
>      }
>    else
>      {
> -      loc = ggc_alloc_cleared_var_loc_node ();
> +      loc = ggc_cleared_alloc<var_loc_node> ();
>        temp->first = loc;
>        temp->last = loc;
>        loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
> @@ -6868,7 +6868,7 @@ clone_die (dw_die_ref die)
>    dw_attr_ref a;
>    unsigned ix;
>
> -  clone = ggc_alloc_cleared_die_node ();
> +  clone = ggc_cleared_alloc<die_node> ();
>    clone->die_tag = die->die_tag;
>
>    FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
> @@ -6914,7 +6914,7 @@ clone_as_declaration (dw_die_ref die)
>        return clone;
>      }
>
> -  clone = ggc_alloc_cleared_die_node ();
> +  clone = ggc_cleared_alloc<die_node> ();
>    clone->die_tag = die->die_tag;
>
>    FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
> @@ -7274,7 +7274,7 @@ break_out_comdat_types (dw_die_ref die)
>          unit = new_die (DW_TAG_type_unit, NULL, NULL);
>          add_AT_unsigned (unit, DW_AT_language,
>                           get_AT_unsigned (comp_unit_die (), DW_AT_language));
> -        type_node = ggc_alloc_cleared_comdat_type_node ();
> +        type_node = ggc_cleared_alloc<comdat_type_node> ();
>          type_node->root_die = unit;
>          type_node->next = comdat_type_list;
>          comdat_type_list = type_node;
> @@ -8347,7 +8347,7 @@ static inline dw_loc_list_ref
>  new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end,
>               const char *section)
>  {
> -  dw_loc_list_ref retlist = ggc_alloc_cleared_dw_loc_list_node ();
> +  dw_loc_list_ref retlist = ggc_cleared_alloc<dw_loc_list_node> ();
>
>    retlist->begin = begin;
>    retlist->begin_entry = NULL;
> @@ -13891,12 +13891,12 @@ add_loc_descr_to_each (dw_loc_list_ref list, dw_loc_descr_ref ref)
>    list = list->dw_loc_next;
>    while (list)
>      {
> -      copy = ggc_alloc_dw_loc_descr_node ();
> +      copy = ggc_alloc<dw_loc_descr_node> ();
>        memcpy (copy, ref, sizeof (dw_loc_descr_node));
>        add_loc_descr (&list->expr, copy);
>        while (copy->dw_loc_next)
>         {
> -         dw_loc_descr_ref new_copy = ggc_alloc_dw_loc_descr_node ();
> +         dw_loc_descr_ref new_copy = ggc_alloc<dw_loc_descr_node> ();
>           memcpy (new_copy, copy->dw_loc_next, sizeof (dw_loc_descr_node));
>           copy->dw_loc_next = new_copy;
>           copy = new_copy;
> @@ -15678,7 +15678,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
>         {
>           slot = htab_find_slot_with_hash (cached_dw_loc_list_table, decl,
>                                            DECL_UID (decl), INSERT);
> -         cache = ggc_alloc_cleared_cached_dw_loc_list ();
> +         cache = ggc_cleared_alloc<cached_dw_loc_list> ();
>           cache->decl_id = DECL_UID (decl);
>           cache->loc_list = list;
>           *slot = cache;
> @@ -16639,7 +16639,7 @@ add_linkage_name (dw_die_ref die, tree decl)
>         {
>           limbo_die_node *asm_name;
>
> -         asm_name = ggc_alloc_cleared_limbo_die_node ();
> +         asm_name = ggc_cleared_alloc<limbo_die_node> ();
>           asm_name->die = die;
>           asm_name->created_for = decl;
>           asm_name->next = deferred_asm_name;
> @@ -20968,7 +20968,7 @@ lookup_filename (const char *file_name)
>    if (*slot)
>      return (struct dwarf_file_data *) *slot;
>
> -  created = ggc_alloc_dwarf_file_data ();
> +  created = ggc_alloc<dwarf_file_data> ();
>    created->filename = file_name;
>    created->emitted_number = 0;
>    *slot = created;
> @@ -21278,7 +21278,7 @@ dwarf2out_var_location (rtx loc_note)
>    if (!var_loc_p)
>      {
>        struct call_arg_loc_node *ca_loc
> -       = ggc_alloc_cleared_call_arg_loc_node ();
> +       = ggc_cleared_alloc<call_arg_loc_node> ();
>        rtx prev = prev_real_insn (loc_note), x;
>        ca_loc->call_arg_loc_note = loc_note;
>        ca_loc->next = NULL;
> @@ -21353,7 +21353,7 @@ new_line_info_table (void)
>  {
>    dw_line_info_table *table;
>
> -  table = ggc_alloc_cleared_dw_line_info_table_struct ();
> +  table = ggc_cleared_alloc<dw_line_info_table_struct> ();
>    table->file_num = 1;
>    table->line_num = 1;
>    table->is_stmt = DWARF_LINE_DEFAULT_IS_STMT_START;
> @@ -22122,7 +22122,7 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
>    vec_alloc (decl_scope_table, 256);
>
>    /* Allocate the initial hunk of the abbrev_die_table.  */
> -  abbrev_die_table = ggc_alloc_cleared_vec_dw_die_ref
> +  abbrev_die_table = ggc_cleared_vec_alloc<dw_die_ref>
>      (ABBREV_DIE_TABLE_INCREMENT);
>    abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT;
>    /* Zero-th entry is allocated, but unused.  */
> diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
> index e3fd0a5..2b64a9f 100644
> --- a/gcc/emit-rtl.c
> +++ b/gcc/emit-rtl.c
> @@ -275,7 +275,7 @@ set_mem_attrs (rtx mem, mem_attrs *attrs)
>    if (!MEM_ATTRS (mem)
>        || !mem_attrs_eq_p (attrs, MEM_ATTRS (mem)))
>      {
> -      MEM_ATTRS (mem) = ggc_alloc_mem_attrs ();
> +      MEM_ATTRS (mem) = ggc_alloc<mem_attrs> ();
>        memcpy (MEM_ATTRS (mem), attrs, sizeof (mem_attrs));
>      }
>  }
> @@ -322,7 +322,7 @@ get_reg_attrs (tree decl, int offset)
>    slot = htab_find_slot (reg_attrs_htab, &attrs, INSERT);
>    if (*slot == 0)
>      {
> -      *slot = ggc_alloc_reg_attrs ();
> +      *slot = ggc_alloc<reg_attrs> ();
>        memcpy (*slot, &attrs, sizeof (reg_attrs));
>      }
>
> @@ -5123,7 +5123,7 @@ start_sequence (void)
>        free_sequence_stack = tem->next;
>      }
>    else
> -    tem = ggc_alloc_sequence_stack ();
> +    tem = ggc_alloc<sequence_stack> ();
>
>    tem->next = seq_stack;
>    tem->first = get_insns ();
> @@ -5456,7 +5456,7 @@ init_emit (void)
>    crtl->emit.regno_pointer_align
>      = XCNEWVEC (unsigned char, crtl->emit.regno_pointer_align_length);
>
> -  regno_reg_rtx = ggc_alloc_vec_rtx (crtl->emit.regno_pointer_align_length);
> +  regno_reg_rtx = ggc_vec_alloc<rtx> (crtl->emit.regno_pointer_align_length);
>
>    /* Put copies of all the hard registers into regno_reg_rtx.  */
>    memcpy (regno_reg_rtx,
> @@ -5606,7 +5606,7 @@ init_emit_regs (void)
>    for (i = 0; i < (int) MAX_MACHINE_MODE; i++)
>      {
>        mode = (enum machine_mode) i;
> -      attrs = ggc_alloc_cleared_mem_attrs ();
> +      attrs = ggc_cleared_alloc<mem_attrs> ();
>        attrs->align = BITS_PER_UNIT;
>        attrs->addrspace = ADDR_SPACE_GENERIC;
>        if (mode != BLKmode)
> diff --git a/gcc/except.c b/gcc/except.c
> index 5b33c9c..3da0003 100644
> --- a/gcc/except.c
> +++ b/gcc/except.c
> @@ -333,7 +333,7 @@ init_eh (void)
>  void
>  init_eh_for_function (void)
>  {
> -  cfun->eh = ggc_alloc_cleared_eh_status ();
> +  cfun->eh = ggc_cleared_alloc<eh_status> ();
>
>    /* Make sure zero'th entries are used.  */
>    vec_safe_push (cfun->eh->region_array, (eh_region)0);
> @@ -350,7 +350,7 @@ gen_eh_region (enum eh_region_type type, eh_region outer)
>    eh_region new_eh;
>
>    /* Insert a new blank region as a leaf in the tree.  */
> -  new_eh = ggc_alloc_cleared_eh_region_d ();
> +  new_eh = ggc_cleared_alloc<eh_region_d> ();
>    new_eh->type = type;
>    new_eh->outer = outer;
>    if (outer)
> @@ -407,7 +407,7 @@ gen_eh_region_catch (eh_region t, tree type_or_list)
>         add_type_for_runtime (TREE_VALUE (type_node));
>      }
>
> -  c = ggc_alloc_cleared_eh_catch_d ();
> +  c = ggc_cleared_alloc<eh_catch_d> ();
>    c->type_list = type_list;
>    l = t->u.eh_try.last_catch;
>    c->prev_catch = l;
> @@ -441,7 +441,7 @@ gen_eh_region_must_not_throw (eh_region outer)
>  eh_landing_pad
>  gen_eh_landing_pad (eh_region region)
>  {
> -  eh_landing_pad lp = ggc_alloc_cleared_eh_landing_pad_d ();
> +  eh_landing_pad lp = ggc_cleared_alloc<eh_landing_pad_d> ();
>
>    lp->next_lp = region->landing_pads;
>    lp->region = region;
> @@ -2451,7 +2451,7 @@ add_call_site (rtx landing_pad, int action, int section)
>  {
>    call_site_record record;
>
> -  record = ggc_alloc_call_site_record_d ();
> +  record = ggc_alloc<call_site_record_d> ();
>    record->landing_pad = landing_pad;
>    record->action = action;
>
> diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
> index e25e92a..adee07c 100644
> --- a/gcc/fortran/f95-lang.c
> +++ b/gcc/fortran/f95-lang.c
> @@ -323,7 +323,7 @@ getdecls (void)
>  void
>  pushlevel (void)
>  {
> -  struct binding_level *newlevel = ggc_alloc_binding_level ();
> +  struct binding_level *newlevel = ggc_alloc<binding_level> ();
>
>    *newlevel = clear_binding_level;
>
> diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
> index beb99a6..a8882e7 100644
> --- a/gcc/fortran/trans-decl.c
> +++ b/gcc/fortran/trans-decl.c
> @@ -615,9 +615,7 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
>  void
>  gfc_allocate_lang_decl (tree decl)
>  {
> -  DECL_LANG_SPECIFIC (decl)
> -    = (struct lang_decl *) ggc_internal_cleared_alloc (sizeof
> -                                                      (struct lang_decl));
> +  DECL_LANG_SPECIFIC (decl) = ggc_cleared_alloc<struct lang_decl> ();
>  }
>
>  /* Remember a symbol to generate initialization/cleanup code at function
> @@ -4119,7 +4117,7 @@ gfc_find_module (const char *name)
>                                    htab_hash_string (name), INSERT);
>    if (*slot == NULL)
>      {
> -      struct module_htab_entry *entry = ggc_alloc_cleared_module_htab_entry ();
> +      module_htab_entry *entry = ggc_cleared_alloc<module_htab_entry> ();
>
>        entry->name = gfc_get_string (name);
>        entry->decls = htab_create_ggc (10, module_htab_decls_hash,
> diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
> index 84503ce..ab3d601 100644
> --- a/gcc/fortran/trans-types.c
> +++ b/gcc/fortran/trans-types.c
> @@ -1511,9 +1511,7 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, gfc_packed packed,
>      type = build_variant_type_copy (etype);
>
>    GFC_ARRAY_TYPE_P (type) = 1;
> -  TYPE_LANG_SPECIFIC (type)
> -      = (struct lang_type *) ggc_internal_cleared_alloc
> -      (sizeof (struct lang_type));
> +  TYPE_LANG_SPECIFIC (type) = ggc_cleared_alloc<struct lang_type> ();
>
>    known_stride = (packed != PACKED_NO);
>    known_offset = 1;
> @@ -1815,9 +1813,7 @@ gfc_get_array_type_bounds (tree etype, int dimen, int codimen, tree * lbound,
>    TYPE_NAMELESS (fat_type) = 1;
>
>    GFC_DESCRIPTOR_TYPE_P (fat_type) = 1;
> -  TYPE_LANG_SPECIFIC (fat_type)
> -    = (struct lang_type *) ggc_internal_cleared_alloc
> -    (sizeof (struct lang_type));
> +  TYPE_LANG_SPECIFIC (fat_type) = ggc_cleared_alloc<struct lang_type> ();
>
>    GFC_TYPE_ARRAY_RANK (fat_type) = dimen;
>    GFC_TYPE_ARRAY_CORANK (fat_type) = codimen;
> @@ -1991,9 +1987,7 @@ gfc_nonrestricted_type (tree t)
>      return t;
>
>    if (!TYPE_LANG_SPECIFIC (t))
> -    TYPE_LANG_SPECIFIC (t)
> -      = (struct lang_type *) ggc_internal_cleared_alloc
> -      (sizeof (struct lang_type));
> +    TYPE_LANG_SPECIFIC (t) = ggc_cleared_alloc<struct lang_type> ();
>    /* If we're dealing with this very node already further up
>       the call chain (recursion via pointers and struct members)
>       we haven't yet determined if we really need a new type node.
> @@ -2045,8 +2039,7 @@ gfc_nonrestricted_type (tree t)
>                   if (dataptr_type != GFC_TYPE_ARRAY_DATAPTR_TYPE (t))
>                     {
>                       TYPE_LANG_SPECIFIC (ret)
> -                       = (struct lang_type *) ggc_internal_cleared_alloc
> -                       (sizeof (struct lang_type));
> +                       = ggc_cleared_alloc<struct lang_type> ();
>                       *TYPE_LANG_SPECIFIC (ret) = *TYPE_LANG_SPECIFIC (t);
>                       GFC_TYPE_ARRAY_DATAPTR_TYPE (ret) = dataptr_type;
>                     }
> diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
> index f8d29ec..0345ca0 100644
> --- a/gcc/fortran/trans.h
> +++ b/gcc/fortran/trans.h
> @@ -792,10 +792,7 @@ enum gfc_array_kind
>  };
>
>  /* Array types only.  */
> -/* FIXME: the variable_size annotation here is needed because these types are
> -   variable-sized in some other frontends.  Due to gengtype deficiency the GTY
> -   options of such types have to agree across all frontends. */
> -struct GTY((variable_size))    lang_type        {
> +struct GTY(()) lang_type        {
>    int rank, corank;
>    enum gfc_array_kind akind;
>    tree lbound[GFC_MAX_DIMENSIONS];
> @@ -812,7 +809,7 @@ struct GTY((variable_size)) lang_type        {
>    tree caf_offset;
>  };
>
> -struct GTY((variable_size)) lang_decl {
> +struct GTY(()) lang_decl {
>    /* Dummy variables.  */
>    tree saved_descriptor;
>    /* Assigned integer nodes.  Stringlength is the IO format string's length.
> diff --git a/gcc/function.c b/gcc/function.c
> index 383a52a..4ebc255 100644
> --- a/gcc/function.c
> +++ b/gcc/function.c
> @@ -306,7 +306,7 @@ try_fit_stack_local (HOST_WIDE_INT start, HOST_WIDE_INT length,
>  static void
>  add_frame_space (HOST_WIDE_INT start, HOST_WIDE_INT end)
>  {
> -  struct frame_space *space = ggc_alloc_frame_space ();
> +  struct frame_space *space = ggc_alloc<frame_space> ();
>    space->next = crtl->frame_space_list;
>    crtl->frame_space_list = space;
>    space->start = start;
> @@ -654,7 +654,7 @@ static void
>  insert_temp_slot_address (rtx address, struct temp_slot *temp_slot)
>  {
>    void **slot;
> -  struct temp_slot_address_entry *t = ggc_alloc_temp_slot_address_entry ();
> +  struct temp_slot_address_entry *t = ggc_alloc<temp_slot_address_entry> ();
>    t->address = address;
>    t->temp_slot = temp_slot;
>    t->hash = temp_slot_address_compute_hash (t);
> @@ -801,7 +801,7 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
>
>           if (best_p->size - rounded_size >= alignment)
>             {
> -             p = ggc_alloc_temp_slot ();
> +             p = ggc_alloc<temp_slot> ();
>               p->in_use = 0;
>               p->size = best_p->size - rounded_size;
>               p->base_offset = best_p->base_offset + rounded_size;
> @@ -825,7 +825,7 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
>      {
>        HOST_WIDE_INT frame_offset_old = frame_offset;
>
> -      p = ggc_alloc_temp_slot ();
> +      p = ggc_alloc<temp_slot> ();
>
>        /* We are passing an explicit alignment request to assign_stack_local.
>          One side effect of that is assign_stack_local will not round SIZE
> @@ -1253,10 +1253,10 @@ get_hard_reg_initial_val (enum machine_mode mode, unsigned int regno)
>    ivs = crtl->hard_reg_initial_vals;
>    if (ivs == 0)
>      {
> -      ivs = ggc_alloc_initial_value_struct ();
> +      ivs = ggc_alloc<initial_value_struct> ();
>        ivs->num_entries = 0;
>        ivs->max_entries = 5;
> -      ivs->entries = ggc_alloc_vec_initial_value_pair (5);
> +      ivs->entries = ggc_vec_alloc<initial_value_pair> (5);
>        crtl->hard_reg_initial_vals = ivs;
>      }
>
> @@ -4498,7 +4498,7 @@ allocate_struct_function (tree fndecl, bool abstract_p)
>  {
>    tree fntype = fndecl ? TREE_TYPE (fndecl) : NULL_TREE;
>
> -  cfun = ggc_alloc_cleared_function ();
> +  cfun = ggc_cleared_alloc<function> ();
>
>    init_eh_for_function ();
>
> @@ -4572,7 +4572,7 @@ prepare_function_start (void)
>
>    if (flag_stack_usage_info)
>      {
> -      cfun->su = ggc_alloc_cleared_stack_usage ();
> +      cfun->su = ggc_cleared_alloc<stack_usage> ();
>        cfun->su->static_stack_size = -1;
>      }
>
> @@ -6936,7 +6936,7 @@ types_used_by_var_decl_insert (tree type, tree var_decl)
>        if (*slot == NULL)
>         {
>           struct types_used_by_vars_entry *entry;
> -         entry = ggc_alloc_types_used_by_vars_entry ();
> +         entry = ggc_alloc<types_used_by_vars_entry> ();
>           entry->type = type;
>           entry->var_decl = var_decl;
>           *slot = entry;
> diff --git a/gcc/gengtype.c b/gcc/gengtype.c
> index b3c966c..d85300b 100644
> --- a/gcc/gengtype.c
> +++ b/gcc/gengtype.c
> @@ -4938,133 +4938,6 @@ write_roots (pair_p variables, bool emit_pch)
>                      "gt_pch_scalar_rtab");
>  }
>
> -/* TRUE if type S has the GTY variable_size annotation.  */
> -
> -static bool
> -variable_size_p (const type_p s)
> -{
> -  options_p o;
> -  for (o = s->u.s.opt; o; o = o->next)
> -    if (strcmp (o->name, "variable_size") == 0)
> -      return true;
> -  return false;
> -}
> -
> -enum alloc_quantity
> -{ single, vector };
> -
> -/* Writes one typed allocator definition into output F for type
> -   identifier TYPE_NAME with optional type specifier TYPE_SPECIFIER.
> -   The allocator name will contain ALLOCATOR_TYPE.  If VARIABLE_SIZE
> -   is true, the allocator will have an extra parameter specifying
> -   number of bytes to allocate.  If QUANTITY is set to VECTOR, a
> -   vector allocator will be output.  */
> -
> -static void
> -write_typed_alloc_def (outf_p f,
> -                       bool variable_size, const char *type_specifier,
> -                       const char *type_name, const char *allocator_type,
> -                       enum alloc_quantity quantity)
> -{
> -  bool two_args = variable_size && (quantity == vector);
> -  if (variable_size)
> -    return;
> -
> -  gcc_assert (f != NULL);
> -  const char *type_name_as_id = filter_type_name (type_name);
> -  oprintf (f, "#define ggc_alloc_%s%s", allocator_type, type_name_as_id);
> -  oprintf (f, "(%s%s%s) ",
> -          (variable_size ? "SIZE" : ""),
> -          (two_args ? ", " : ""),
> -          (quantity == vector) ? "n" : "");
> -  oprintf (f, "((%s%s *)", type_specifier, type_name);
> -  oprintf (f, "(ggc_internal_%salloc (", allocator_type);
> -  if (variable_size)
> -    oprintf (f, "SIZE");
> -  else
> -    oprintf (f, "sizeof (%s%s)", type_specifier, type_name);
> -  if (quantity == vector)
> -    oprintf (f, ", n");
> -  oprintf (f, " MEM_STAT_INFO)))\n");
> -  if (type_name_as_id != type_name)
> -    free (CONST_CAST (char *, type_name_as_id));
> -}
> -
> -/* Writes a typed allocator definition into output F for a struct or
> -   union S, with a given ALLOCATOR_TYPE and QUANTITY for ZONE.  */
> -
> -static void
> -write_typed_struct_alloc_def (outf_p f,
> -                             const type_p s, const char *allocator_type,
> -                             enum alloc_quantity quantity)
> -{
> -  gcc_assert (union_or_struct_p (s));
> -  write_typed_alloc_def (f, variable_size_p (s), get_type_specifier (s),
> -                         s->u.s.tag, allocator_type, quantity);
> -}
> -
> -/* Writes a typed allocator definition into output F for a typedef P,
> -   with a given ALLOCATOR_TYPE and QUANTITY for ZONE.  */
> -
> -static void
> -write_typed_typedef_alloc_def (outf_p f,
> -                               const pair_p p, const char *allocator_type,
> -                               enum alloc_quantity quantity)
> -{
> -  write_typed_alloc_def (f, variable_size_p (p->type), "", p->name,
> -                         allocator_type, quantity);
> -}
> -
> -/* Writes typed allocator definitions into output F for the types in
> -   STRUCTURES and TYPEDEFS that are used by GC.  */
> -
> -static void
> -write_typed_alloc_defns (outf_p f,
> -                         const type_p structures, const pair_p typedefs)
> -{
> -  type_p s;
> -  pair_p p;
> -
> -  gcc_assert (f != NULL);
> -  oprintf (f,
> -          "\n/* Allocators for known structs and unions.  */\n\n");
> -  for (s = structures; s; s = s->next)
> -    {
> -      if (!USED_BY_TYPED_GC_P (s))
> -       continue;
> -      gcc_assert (union_or_struct_p (s));
> -      /* In plugin mode onput output ggc_alloc macro definitions
> -        relevant to plugin input files.  */
> -      if (nb_plugin_files > 0
> -         && ((s->u.s.line.file == NULL) || !s->u.s.line.file->inpisplugin))
> -       continue;
> -      write_typed_struct_alloc_def (f, s, "", single);
> -      write_typed_struct_alloc_def (f, s, "cleared_", single);
> -      write_typed_struct_alloc_def (f, s, "vec_", vector);
> -      write_typed_struct_alloc_def (f, s, "cleared_vec_", vector);
> -    }
> -
> -  oprintf (f, "\n/* Allocators for known typedefs.  */\n");
> -  for (p = typedefs; p; p = p->next)
> -    {
> -      s = p->type;
> -      if (!USED_BY_TYPED_GC_P (s) || (strcmp (p->name, s->u.s.tag) == 0))
> -       continue;
> -      /* In plugin mode onput output ggc_alloc macro definitions
> -        relevant to plugin input files.  */
> -      if (nb_plugin_files > 0)
> -       {
> -         struct fileloc* filoc = type_fileloc (s);
> -         if (!filoc || !filoc->file->inpisplugin)
> -           continue;
> -       };
> -      write_typed_typedef_alloc_def (f, p, "", single);
> -      write_typed_typedef_alloc_def (f, p, "cleared_", single);
> -      write_typed_typedef_alloc_def (f, p, "vec_", vector);
> -      write_typed_typedef_alloc_def (f, p, "cleared_vec_", vector);
> -    }
> -}
> -
>  /* Prints not-as-ugly version of a typename of T to OF.  Trades the uniquness
>     guaranteee for somewhat increased readability.  If name conflicts do happen,
>     this funcion will have to be adjusted to be more like
> @@ -5775,7 +5648,6 @@ main (int argc, char **argv)
>    open_base_files ();
>
>    output_header = plugin_output ? plugin_output : header_file;
> -  write_typed_alloc_defns (output_header, structures, typedefs);
>    DBGPRINT_COUNT_TYPE ("structures before write_types outputheader",
>                        structures);
>    DBGPRINT_COUNT_TYPE ("param_structs before write_types outputheader",
> diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
> index e1cc48e..e89cc64 100644
> --- a/gcc/ggc-common.c
> +++ b/gcc/ggc-common.c
> @@ -232,7 +232,7 @@ ggc_cleared_alloc_htab_ignore_args (size_t c ATTRIBUTE_UNUSED,
>                                     size_t n ATTRIBUTE_UNUSED)
>  {
>    gcc_assert (c * n == sizeof (struct htab));
> -  return ggc_alloc_cleared_htab ();
> +  return ggc_cleared_alloc<htab> ();
>  }
>
>  /* TODO: once we actually use type information in GGC, create a new tag
> @@ -241,7 +241,7 @@ void *
>  ggc_cleared_alloc_ptr_array_two_args (size_t c, size_t n)
>  {
>    gcc_assert (sizeof (PTR *) == n);
> -  return ggc_internal_cleared_vec_alloc (sizeof (PTR *), c);
> +  return ggc_cleared_vec_alloc<PTR *> (c);
>  }
>
>  /* These are for splay_tree_new_ggc.  */
> diff --git a/gcc/ggc.h b/gcc/ggc.h
> index 736305d..2c567de 100644
> --- a/gcc/ggc.h
> +++ b/gcc/ggc.h
> @@ -156,16 +156,35 @@ extern void dump_ggc_loc_statistics (bool);
>  #define GGC_RESIZEVEC(T, P, N) \
>      ((T *) ggc_realloc ((P), (N) * sizeof (T) MEM_STAT_INFO))
>
> -static inline void *
> -ggc_internal_vec_alloc (size_t s, size_t c MEM_STAT_DECL)
> +template<typename T>
> +static inline T *
> +ggc_alloc (ALONE_CXX_MEM_STAT_INFO)
>  {
> -    return ggc_internal_alloc (c * s PASS_MEM_STAT);
> +  return static_cast<T *> (ggc_internal_alloc (sizeof (T) PASS_MEM_STAT));
>  }
>
> -static inline void *
> -ggc_internal_cleared_vec_alloc (size_t s, size_t c CXX_MEM_STAT_INFO)
> +template<typename T>
> +static inline T *
> +ggc_cleared_alloc (ALONE_CXX_MEM_STAT_INFO)
> +{
> +  return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T)
> +                                                      PASS_MEM_STAT));
> +}
> +
> +template<typename T>
> +static inline T *
> +ggc_vec_alloc (size_t c CXX_MEM_STAT_INFO)
> +{
> +    return static_cast<T *> (ggc_internal_alloc (c * sizeof (T)
> +                                                PASS_MEM_STAT));
> +}
> +
> +template<typename T>
> +static inline T *
> +ggc_cleared_vec_alloc (size_t c CXX_MEM_STAT_INFO)
>  {
> -    return ggc_internal_cleared_alloc (c * s PASS_MEM_STAT);
> +    return static_cast<T *> (ggc_internal_cleared_alloc (c * sizeof (T)
> +                                                        PASS_MEM_STAT));
>  }
>
>  static inline void *
> diff --git a/gcc/gimple.c b/gcc/gimple.c
> index fc6ecb9..165a4bd 100644
> --- a/gcc/gimple.c
> +++ b/gcc/gimple.c
> @@ -835,8 +835,7 @@ gimple_build_omp_for (gimple_seq body, int kind, tree clauses, size_t collapse,
>    gimple_omp_for_set_clauses (p, clauses);
>    gimple_omp_for_set_kind (p, kind);
>    p->collapse = collapse;
> -  p->iter =  static_cast <struct gimple_omp_for_iter *> (
> -   ggc_internal_cleared_vec_alloc (sizeof (*p->iter), collapse));
> +  p->iter =  ggc_cleared_vec_alloc<gimple_omp_for_iter> (collapse);
>
>    if (pre_body)
>      gimple_omp_for_set_pre_body (p, pre_body);
> @@ -1664,10 +1663,8 @@ gimple_copy (gimple stmt)
>           {
>             gimple_statement_omp_for *omp_for_copy =
>               as_a <gimple_statement_omp_for *> (copy);
> -           omp_for_copy->iter =
> -             static_cast <struct gimple_omp_for_iter *> (
> -                 ggc_internal_vec_alloc (sizeof (struct gimple_omp_for_iter),
> -                                         gimple_omp_for_collapse (stmt)));
> +           omp_for_copy->iter = ggc_vec_alloc<gimple_omp_for_iter>
> +             ( gimple_omp_for_collapse (stmt));
>            }
>           for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
>             {
> diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c
> index c0f2f1f..7231b34 100644
> --- a/gcc/go/go-lang.c
> +++ b/gcc/go/go-lang.c
> @@ -51,7 +51,7 @@ struct GTY(()) lang_type
>
>  /* Language-dependent contents of a decl.  */
>
> -struct GTY((variable_size)) lang_decl
> +struct GTY(()) lang_decl
>  {
>    char dummy;
>  };
> diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
> index 479963c..d1f882a 100644
> --- a/gcc/ipa-cp.c
> +++ b/gcc/ipa-cp.c
> @@ -2599,7 +2599,7 @@ get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
>    struct ipa_replace_map *replace_map;
>
>
> -  replace_map = ggc_alloc_ipa_replace_map ();
> +  replace_map = ggc_alloc<ipa_replace_map> ();
>    if (dump_file)
>      {
>        fprintf (dump_file, "    replacing ");
> @@ -3182,7 +3182,7 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node,
>           if (!item->value)
>             continue;
>
> -         v = ggc_alloc_ipa_agg_replacement_value ();
> +         v = ggc_alloc<ipa_agg_replacement_value> ();
>           v->index = i;
>           v->offset = item->offset;
>           v->value = item->value;
> @@ -3212,7 +3212,7 @@ known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
>      FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
>        {
>         struct ipa_agg_replacement_value *v;
> -       v = ggc_alloc_ipa_agg_replacement_value ();
> +       v = ggc_alloc<ipa_agg_replacement_value> ();
>         v->index = i;
>         v->offset = item->offset;
>         v->value = item->value;
> diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
> index 4ff31fc..bacbeec 100644
> --- a/gcc/ipa-devirt.c
> +++ b/gcc/ipa-devirt.c
> @@ -491,7 +491,7 @@ get_odr_type (tree type, bool insert)
>        tree binfo = TYPE_BINFO (type);
>        unsigned int i;
>
> -      val = ggc_alloc_cleared_odr_type_d ();
> +      val = ggc_cleared_alloc<odr_type_d> ();
>        val->type = type;
>        val->bases = vNULL;
>        val->derived_types = vNULL;
> diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
> index 9f144fa..336dd97 100644
> --- a/gcc/ipa-prop.c
> +++ b/gcc/ipa-prop.c
> @@ -3311,7 +3311,7 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
>      {
>        struct ipa_agg_replacement_value *v;
>
> -      v = ggc_alloc_ipa_agg_replacement_value ();
> +      v = ggc_alloc<ipa_agg_replacement_value> ();
>        memcpy (v, old_av, sizeof (*v));
>        v->next = new_av;
>        new_av = v;
> @@ -4670,7 +4670,7 @@ read_agg_replacement_chain (struct lto_input_block *ib,
>        struct ipa_agg_replacement_value *av;
>        struct bitpack_d bp;
>
> -      av = ggc_alloc_ipa_agg_replacement_value ();
> +      av = ggc_alloc<ipa_agg_replacement_value> ();
>        av->offset = streamer_read_uhwi (ib);
>        av->index = streamer_read_uhwi (ib);
>        av->value = stream_read_tree (ib, data_in);
> diff --git a/gcc/java/class.c b/gcc/java/class.c
> index 94c2568..a1e4a86 100644
> --- a/gcc/java/class.c
> +++ b/gcc/java/class.c
> @@ -764,9 +764,7 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type)
>    fndecl = build_decl (input_location, FUNCTION_DECL, name, method_type);
>    DECL_CONTEXT (fndecl) = this_class;
>
> -  DECL_LANG_SPECIFIC (fndecl)
> -    = (struct lang_decl *) ggc_internal_cleared_alloc
> -    (sizeof (struct lang_decl));
> +  DECL_LANG_SPECIFIC (fndecl) = ggc_cleared_alloc<struct lang_decl> ();
>    DECL_LANG_SPECIFIC (fndecl)->desc = LANG_DECL_FUNC;
>
>    /* Initialize the static initializer test table.  */
> @@ -3195,7 +3193,7 @@ java_treetreehash_new (htab_t ht, tree t)
>    e = htab_find_slot_with_hash (ht, t, hv, INSERT);
>    if (*e == NULL)
>      {
> -      tthe = ggc_alloc_cleared_treetreehash_entry ();
> +      tthe = ggc_cleared_alloc<treetreehash_entry> ();
>        tthe->key = t;
>        *e = tthe;
>      }
> diff --git a/gcc/java/constants.c b/gcc/java/constants.c
> index 51449ef..2e317c9 100644
> --- a/gcc/java/constants.c
> +++ b/gcc/java/constants.c
> @@ -46,11 +46,8 @@ set_constant_entry (CPool *cpool, int index, int tag, jword value)
>    if (cpool->data == NULL)
>      {
>        cpool->capacity = 100;
> -      cpool->tags = (uint8 *) ggc_internal_cleared_alloc (sizeof (uint8)
> -                                                         * cpool->capacity);
> -      cpool->data = (cpool_entry *) ggc_internal_cleared_alloc (sizeof
> -                                                      (union cpool_entry)
> -                                                      * cpool->capacity);
> +      cpool->tags = ggc_cleared_vec_alloc<uint8> (cpool->capacity);
> +      cpool->data = ggc_cleared_vec_alloc<cpool_entry> (cpool->capacity);
>        cpool->count = 1;
>      }
>    if (index >= cpool->capacity)
> @@ -338,7 +335,7 @@ cpool_for_class (tree klass)
>
>    if (cpool == NULL)
>      {
> -      cpool = ggc_alloc_cleared_CPool ();
> +      cpool = ggc_cleared_alloc<CPool> ();
>        TYPE_CPOOL (klass) = cpool;
>      }
>    return cpool;
> diff --git a/gcc/java/decl.c b/gcc/java/decl.c
> index 9f2f0ca..841fb4c 100644
> --- a/gcc/java/decl.c
> +++ b/gcc/java/decl.c
> @@ -1307,7 +1307,7 @@ static struct binding_level *
>  make_binding_level (void)
>  {
>    /* NOSTRICT */
> -  return ggc_alloc_cleared_binding_level ();
> +  return ggc_cleared_alloc<binding_level> ();
>  }
>
>  void
> @@ -1646,7 +1646,7 @@ java_dup_lang_specific_decl (tree node)
>      return;
>
>    lang_decl_size = sizeof (struct lang_decl);
> -  x = (struct lang_decl *) ggc_internal_alloc (lang_decl_size);
> +  x = ggc_alloc<struct lang_decl> ();
>    memcpy (x, DECL_LANG_SPECIFIC (node), lang_decl_size);
>    DECL_LANG_SPECIFIC (node) = x;
>  }
> diff --git a/gcc/java/expr.c b/gcc/java/expr.c
> index 69f6819..0fa5724 100644
> --- a/gcc/java/expr.c
> +++ b/gcc/java/expr.c
> @@ -470,7 +470,7 @@ add_type_assertion (tree klass, int assertion_code, tree op1, tree op2)
>    if (*as_pp)
>      return;
>
> -  *as_pp = ggc_alloc_type_assertion ();
> +  *as_pp = ggc_alloc<type_assertion> ();
>    **(type_assertion **)as_pp = as;
>  }
>
> diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
> index 43a8258..e832f44 100644
> --- a/gcc/java/java-tree.h
> +++ b/gcc/java/java-tree.h
> @@ -699,9 +699,7 @@ union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
>  #define MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC(T)                       \
>    if (DECL_LANG_SPECIFIC (T) == NULL)                                \
>      {                                                                \
> -      DECL_LANG_SPECIFIC ((T))                                       \
> -        = (struct lang_decl *) ggc_internal_cleared_alloc            \
> -      (sizeof (struct lang_decl));                                   \
> +      DECL_LANG_SPECIFIC ((T)) = ggc_cleared_alloc<struct lang_decl> (); \
>        DECL_LANG_SPECIFIC (T)->desc = LANG_DECL_VAR;                  \
>      }
>
> @@ -809,7 +807,7 @@ struct GTY(()) lang_decl_var {
>
>  enum lang_decl_desc {LANG_DECL_FUNC, LANG_DECL_VAR};
>
> -struct GTY((variable_size)) lang_decl {
> +struct GTY(()) lang_decl {
>    enum lang_decl_desc desc;
>    union lang_decl_u
>      {
> @@ -826,9 +824,7 @@ struct GTY((variable_size)) lang_decl {
>  #define TYPE_CPOOL_DATA_REF(T) (TYPE_LANG_SPECIFIC (T)->cpool_data_ref)
>  #define MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC(T) \
>    if (TYPE_LANG_SPECIFIC ((T)) == NULL)                \
> -     TYPE_LANG_SPECIFIC ((T))                  \
> -       = (struct lang_type *) ggc_internal_cleared_alloc \
> -(sizeof (struct lang_type));     \
> +     TYPE_LANG_SPECIFIC ((T)) = ggc_cleared_alloc<struct lang_type> ();
>
>  #define TYPE_DUMMY(T)          (TYPE_LANG_SPECIFIC(T)->dummy_class)
>
> @@ -871,10 +867,7 @@ typedef struct GTY(()) method_entry_d {
>  } method_entry;
>
>
> -/* FIXME: the variable_size annotation here is needed because these types are
> -   variable-sized in some other frontends.  Due to gengtype deficiency the GTY
> -   options of such types have to agree across all frontends. */
> -struct GTY((variable_size)) lang_type {
> +struct GTY(()) lang_type {
>    tree signature;
>    struct JCF *jcf;
>    struct CPool *cpool;
> diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
> index afe35f0..e57a044 100644
> --- a/gcc/java/jcf-parse.c
> +++ b/gcc/java/jcf-parse.c
> @@ -1905,7 +1905,7 @@ java_parse_file (void)
>        if (magic == 0xcafebabe)
>         {
>           CLASS_FILE_P (node) = 1;
> -         current_jcf = ggc_alloc_cleared_JCF ();
> +         current_jcf = ggc_cleared_alloc<JCF> ();
>           current_jcf->read_state = finput;
>           current_jcf->filbuf = jcf_filbuf_from_stdio;
>           jcf_parse (current_jcf);
> @@ -1922,7 +1922,7 @@ java_parse_file (void)
>         }
>        else if (magic == (JCF_u4)ZIPMAGIC)
>         {
> -         main_jcf = ggc_alloc_cleared_JCF ();
> +         main_jcf = ggc_cleared_alloc<JCF> ();
>           main_jcf->read_state = finput;
>           main_jcf->filbuf = jcf_filbuf_from_stdio;
>           linemap_add (line_table, LC_ENTER, false, filename, 0);
> @@ -2178,7 +2178,7 @@ process_zip_dir (FILE *finput)
>
>        class_name = compute_class_name (zdir);
>        file_name  = XNEWVEC (char, zdir->filename_length+1);
> -      jcf = ggc_alloc_cleared_JCF ();
> +      jcf = ggc_cleared_alloc<JCF> ();
>
>        strncpy (file_name, class_name_in_zip_dir, zdir->filename_length);
>        file_name [zdir->filename_length] = '\0';
> diff --git a/gcc/java/jcf.h b/gcc/java/jcf.h
> index 8aa077e..0988d65 100644
> --- a/gcc/java/jcf.h
> +++ b/gcc/java/jcf.h
> @@ -65,7 +65,7 @@ jcf_open_exact_case (const char* filename, int oflag);
>  struct JCF;
>  typedef int (*jcf_filbuf_t) (struct JCF*, int needed);
>
> -union GTY((variable_size)) cpool_entry {
> +union GTY(()) cpool_entry {
>    jword GTY ((tag ("0"))) w;
>    tree GTY ((tag ("1"))) t;
>  };
> diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c
> index 42bcb75..6acc4c9 100644
> --- a/gcc/loop-iv.c
> +++ b/gcc/loop-iv.c
> @@ -3036,7 +3036,7 @@ get_simple_loop_desc (struct loop *loop)
>
>    /* At least desc->infinite is not always initialized by
>       find_simple_loop_exit.  */
> -  desc = ggc_alloc_cleared_niter_desc ();
> +  desc = ggc_cleared_alloc<niter_desc> ();
>    iv_analysis_loop_init (loop);
>    find_simple_exit (loop, desc);
>    loop->simple_loop_desc = desc;
> diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
> index 58084cd..d4a6d38 100644
> --- a/gcc/lto-cgraph.c
> +++ b/gcc/lto-cgraph.c
> @@ -1755,7 +1755,7 @@ input_node_opt_summary (struct cgraph_node *node,
>    count = streamer_read_uhwi (ib_main);
>    for (i = 0; i < count; i++)
>      {
> -      struct ipa_replace_map *map = ggc_alloc_ipa_replace_map ();
> +      struct ipa_replace_map *map = ggc_alloc<ipa_replace_map> ();
>
>        vec_safe_push (node->clone.tree_map, map);
>        map->parm_num = streamer_read_uhwi (ib_main);
> diff --git a/gcc/lto-section-in.c b/gcc/lto-section-in.c
> index 9aa7639..d887763 100644
> --- a/gcc/lto-section-in.c
> +++ b/gcc/lto-section-in.c
> @@ -364,7 +364,7 @@ lto_get_decl_name_mapping (struct lto_file_decl_data *decl_data,
>  struct lto_in_decl_state *
>  lto_new_in_decl_state (void)
>  {
> -  return ggc_alloc_cleared_lto_in_decl_state ();
> +  return ggc_cleared_alloc<lto_in_decl_state> ();
>  }
>
>  /* Delete STATE and its components. */
> diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
> index 20835f7..deb9b1c 100644
> --- a/gcc/lto-streamer-in.c
> +++ b/gcc/lto-streamer-in.c
> @@ -279,7 +279,7 @@ lto_input_eh_catch_list (struct lto_input_block *ib, struct data_in *data_in,
>        lto_tag_check_range (tag, LTO_eh_catch, LTO_eh_catch);
>
>        /* Read the catch node.  */
> -      n = ggc_alloc_cleared_eh_catch_d ();
> +      n = ggc_cleared_alloc<eh_catch_d> ();
>        n->type_list = stream_read_tree (ib, data_in);
>        n->filter_list = stream_read_tree (ib, data_in);
>        n->label = stream_read_tree (ib, data_in);
> @@ -319,7 +319,7 @@ input_eh_region (struct lto_input_block *ib, struct data_in *data_in, int ix)
>    if (tag == LTO_null)
>      return NULL;
>
> -  r = ggc_alloc_cleared_eh_region_d ();
> +  r = ggc_cleared_alloc<eh_region_d> ();
>    r->index = streamer_read_hwi (ib);
>
>    gcc_assert (r->index == ix);
> @@ -396,7 +396,7 @@ input_eh_lp (struct lto_input_block *ib, struct data_in *data_in, int ix)
>
>    lto_tag_check_range (tag, LTO_eh_landing_pad, LTO_eh_landing_pad);
>
> -  lp = ggc_alloc_cleared_eh_landing_pad_d ();
> +  lp = ggc_cleared_alloc<eh_landing_pad_d> ();
>    lp->index = streamer_read_hwi (ib);
>    gcc_assert (lp->index == ix);
>    lp->next_lp = (eh_landing_pad) (intptr_t) streamer_read_hwi (ib);
> @@ -682,7 +682,7 @@ input_cfg (struct lto_input_block *ib, struct data_in *data_in,
>    if (n_loops == 0)
>      return;
>
> -  struct loops *loops = ggc_alloc_cleared_loops ();
> +  struct loops *loops = ggc_cleared_alloc<struct loops> ();
>    init_loops_structure (fn, loops, n_loops);
>    set_loops_for_fn (fn, loops);
>
> diff --git a/gcc/lto/lto-tree.h b/gcc/lto/lto-tree.h
> index b1c3d2a..4e3f5d6 100644
> --- a/gcc/lto/lto-tree.h
> +++ b/gcc/lto/lto-tree.h
> @@ -28,12 +28,12 @@ struct GTY(()) lang_identifier
>    struct tree_identifier base;
>  };
>
> -struct GTY((variable_size)) lang_decl
> +struct GTY(()) lang_decl
>  {
>    int dummy;  /* Added because ggc does not like empty structs.  */
>  };
>
> -struct GTY((variable_size)) lang_type
> +struct GTY(()) lang_type
>  {
>    int dummy;  /* Added because ggc does not like empty structs.  */
>  };
> diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
> index 5f4478a..38e1149 100644
> --- a/gcc/lto/lto.c
> +++ b/gcc/lto/lto.c
> @@ -244,7 +244,7 @@ lto_read_in_decl_state (struct data_in *data_in, const uint32_t *data,
>    for (i = 0; i < LTO_N_DECL_STREAMS; i++)
>      {
>        uint32_t size = *data++;
> -      tree *decls = ggc_alloc_vec_tree (size);
> +      tree *decls = ggc_vec_alloc<tree> (size);
>
>        for (j = 0; j < size; j++)
>         decls[j] = streamer_tree_cache_get_tree (data_in->reader_cache, data[j]);
> @@ -2159,7 +2159,7 @@ create_subid_section_table (struct lto_section_slot *ls, splay_tree file_ids,
>      }
>    else
>      {
> -      file_data = ggc_alloc_lto_file_decl_data ();
> +      file_data = ggc_alloc<lto_file_decl_data> ();
>        memset(file_data, 0, sizeof (struct lto_file_decl_data));
>        file_data->id = id;
>        file_data->section_hash_table = lto_obj_create_section_hash_table ();;
> @@ -2860,7 +2860,7 @@ lto_flatten_files (struct lto_file_decl_data **orig, int count, int last_file_ix
>
>    lto_stats.num_input_files = count;
>    all_file_decl_data
> -    = ggc_alloc_cleared_vec_lto_file_decl_data_ptr (count + 1);
> +    = ggc_cleared_vec_alloc<lto_file_decl_data_ptr> (count + 1);
>    /* Set the hooks so that all of the ipa passes can read in their data.  */
>    lto_set_in_hooks (all_file_decl_data, get_section_data, free_section_data);
>    for (i = 0, k = 0; i < last_file_ix; i++)
> @@ -2903,7 +2903,7 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
>    timevar_push (TV_IPA_LTO_DECL_IN);
>
>    real_file_decl_data
> -    = decl_data = ggc_alloc_cleared_vec_lto_file_decl_data_ptr (nfiles + 1);
> +    = decl_data = ggc_cleared_vec_alloc<lto_file_decl_data_ptr> (nfiles + 1);
>    real_file_count = nfiles;
>
>    /* Read the resolution file.  */
> diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
> index cda345b..551325a 100644
> --- a/gcc/objc/objc-act.c
> +++ b/gcc/objc/objc-act.c
> @@ -3198,7 +3198,7 @@ objc_build_string_object (tree string)
>
>    if (!desc)
>      {
> -      *loc = desc = ggc_alloc_string_descriptor ();
> +      *loc = desc = ggc_alloc<string_descriptor> ();
>        desc->literal = string;
>        desc->constructor =
>         (*runtime.build_const_string_constructor) (input_location, string, length);
> @@ -7040,7 +7040,7 @@ continue_class (tree klass)
>         uprivate_record = CLASS_STATIC_TEMPLATE (implementation_template);
>         objc_instance_type = build_pointer_type (uprivate_record);
>
> -       imp_entry = ggc_alloc_imp_entry ();
> +       imp_entry = ggc_alloc<struct imp_entry> ();
>
>         imp_entry->next = imp_list;
>         imp_entry->imp_context = klass;
> diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
> index a050727..7e1e265 100644
> --- a/gcc/objc/objc-act.h
> +++ b/gcc/objc/objc-act.h
> @@ -192,9 +192,7 @@ typedef enum objc_property_assign_semantics {
>  #define SIZEOF_OBJC_TYPE_LANG_SPECIFIC sizeof (struct lang_type)
>  #define ALLOC_OBJC_TYPE_LANG_SPECIFIC(NODE)                            \
>    do {                                                                 \
> -    TYPE_LANG_SPECIFIC (NODE)                                          \
> -      = (struct lang_type *) ggc_internal_cleared_alloc     \
> -      (sizeof (struct lang_type));     \
> +      TYPE_LANG_SPECIFIC (NODE) = ggc_cleared_alloc<struct lang_type> (); \
>    } while (0)
>
>  #define TYPE_HAS_OBJC_INFO(TYPE)                               \
> diff --git a/gcc/objc/objc-map.c b/gcc/objc/objc-map.c
> index 386d2c5..aaee729 100644
> --- a/gcc/objc/objc-map.c
> +++ b/gcc/objc/objc-map.c
> @@ -56,7 +56,7 @@ next_power_of_two (size_t x)
>  objc_map_t
>  objc_map_alloc_ggc (size_t initial_capacity)
>  {
> -  objc_map_t map = (objc_map_t) ggc_internal_cleared_vec_alloc (1, sizeof (struct objc_map_private));
> +  objc_map_t map = ggc_cleared_alloc<objc_map_private> ();
>    if (map == NULL)
>      OUT_OF_MEMORY;
>
> @@ -67,8 +67,8 @@ objc_map_alloc_ggc (size_t initial_capacity)
>    map->maximum_load_factor = 70;
>    map->max_number_of_non_empty_slots = (initial_capacity * map->maximum_load_factor) / 100;
>
> -  map->slots = (tree *)ggc_internal_cleared_vec_alloc (initial_capacity, sizeof (tree));
> -  map->values = (tree *)ggc_internal_cleared_vec_alloc (initial_capacity, sizeof (tree));
> +  map->slots = ggc_cleared_vec_alloc<tree> (initial_capacity);
> +  map->values = ggc_cleared_vec_alloc<tree> (initial_capacity);
>
>    if (map->slots == NULL)
>      OUT_OF_MEMORY;
> @@ -112,8 +112,8 @@ objc_map_private_resize (objc_map_t map, size_t new_number_of_slots)
>    map->max_number_of_non_empty_slots = (map->number_of_slots * map->maximum_load_factor) / 100;
>
>
> -  map->slots = (tree *)ggc_internal_cleared_vec_alloc (map->number_of_slots, sizeof (tree));
> -  map->values = (tree *)ggc_internal_cleared_vec_alloc (map->number_of_slots, sizeof (tree));
> +  map->slots = ggc_cleared_vec_alloc<tree> (map->number_of_slots);
> +  map->values = ggc_cleared_vec_alloc<tree> (map->number_of_slots);
>
>    if (map->slots == NULL)
>      OUT_OF_MEMORY;
> diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
> index ee43d2d..85033a3 100644
> --- a/gcc/objc/objc-next-runtime-abi-02.c
> +++ b/gcc/objc/objc-next-runtime-abi-02.c
> @@ -238,7 +238,7 @@ static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
>  bool
>  objc_next_runtime_abi_02_init (objc_runtime_hooks *rthooks)
>  {
> -  extern_names = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
> +  extern_names = ggc_cleared_vec_alloc<hash> (SIZEHASHTABLE);
>
>    if (flag_objc_exceptions && flag_objc_sjlj_exceptions)
>      {
> @@ -857,7 +857,7 @@ hash_name_enter (hash *hashlist, tree id)
>    hash obj;
>    int slot = IDENTIFIER_HASH_VALUE (DECL_NAME (id)) % SIZEHASHTABLE;
>
> -  obj = ggc_alloc_hashed_entry ();
> +  obj = ggc_alloc<hashed_entry> ();
>    obj->list = 0;
>    obj->next = hashlist[slot];
>    obj->key = id;
> diff --git a/gcc/optabs.c b/gcc/optabs.c
> index 54f07ab..e465cbc 100644
> --- a/gcc/optabs.c
> +++ b/gcc/optabs.c
> @@ -6156,7 +6156,7 @@ set_optab_libfunc (optab op, enum machine_mode mode, const char *name)
>      val = 0;
>    slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
>    if (*slot == NULL)
> -    *slot = ggc_alloc_libfunc_entry ();
> +    *slot = ggc_alloc<libfunc_entry> ();
>    (*slot)->op = op;
>    (*slot)->mode1 = mode;
>    (*slot)->mode2 = VOIDmode;
> @@ -6184,7 +6184,7 @@ set_conv_libfunc (convert_optab optab, enum machine_mode tmode,
>      val = 0;
>    slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
>    if (*slot == NULL)
> -    *slot = ggc_alloc_libfunc_entry ();
> +    *slot = ggc_alloc<libfunc_entry> ();
>    (*slot)->op = optab;
>    (*slot)->mode1 = tmode;
>    (*slot)->mode2 = fmode;
> diff --git a/gcc/passes.c b/gcc/passes.c
> index fb60fc8..78277a2 100644
> --- a/gcc/passes.c
> +++ b/gcc/passes.c
> @@ -1542,7 +1542,7 @@ do_per_function_toporder (void (*callback) (void *data), void *data)
>    else
>      {
>        gcc_assert (!order);
> -      order = ggc_alloc_vec_cgraph_node_ptr (cgraph_n_nodes);
> +      order = ggc_vec_alloc<cgraph_node_ptr> (cgraph_n_nodes);
>        nnodes = ipa_reverse_postorder (order);
>        for (i = nnodes - 1; i >= 0; i--)
>          order[i]->process = 1;
> diff --git a/gcc/rtl.h b/gcc/rtl.h
> index 595b699..d8dca30 100644
> --- a/gcc/rtl.h
> +++ b/gcc/rtl.h
> @@ -251,7 +251,7 @@ struct GTY(()) object_block {
>  /* RTL expression ("rtx").  */
>
>  struct GTY((chain_next ("RTX_NEXT (&%h)"),
> -           chain_prev ("RTX_PREV (&%h)"), variable_size)) rtx_def {
> +           chain_prev ("RTX_PREV (&%h)"))) rtx_def {
>    /* The kind of expression this is.  */
>    ENUM_BITFIELD(rtx_code) code: 16;
>
> @@ -382,7 +382,7 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"),
>     for a variable number of things.  The principle use is inside
>     PARALLEL expressions.  */
>
> -struct GTY((variable_size)) rtvec_def {
> +struct GTY(()) rtvec_def {
>    int num_elem;                /* number of elements */
>    rtx GTY ((length ("%h.num_elem"))) elem[1];
>  };
> diff --git a/gcc/sese.c b/gcc/sese.c
> index 342c5e8..a0b0899 100644
> --- a/gcc/sese.c
> +++ b/gcc/sese.c
> @@ -698,7 +698,7 @@ if_region_set_false_region (ifsese if_region, sese region)
>
>    if (slot)
>      {
> -      struct loop_exit *loop_exit = ggc_alloc_cleared_loop_exit ();
> +      struct loop_exit *loop_exit = ggc_cleared_alloc<struct loop_exit> ();
>
>        memcpy (loop_exit, *((struct loop_exit **) slot), sizeof (struct loop_exit));
>        htab_clear_slot (current_loops->exits, slot);
> diff --git a/gcc/stringpool.c b/gcc/stringpool.c
> index e317525..c880cb1 100644
> --- a/gcc/stringpool.c
> +++ b/gcc/stringpool.c
> @@ -258,10 +258,10 @@ static GTY(()) struct string_pool_data * spd;
>  void
>  gt_pch_save_stringpool (void)
>  {
> -  spd = ggc_alloc_string_pool_data ();
> +  spd = ggc_alloc<string_pool_data> ();
>    spd->nslots = ident_hash->nslots;
>    spd->nelements = ident_hash->nelements;
> -  spd->entries = ggc_alloc_vec_ht_identifier_ptr (spd->nslots);
> +  spd->entries = ggc_vec_alloc<ht_identifier_ptr> (spd->nslots);
>    memcpy (spd->entries, ident_hash->entries,
>           spd->nslots * sizeof (spd->entries[0]));
>  }
> diff --git a/gcc/target-globals.c b/gcc/target-globals.c
> index 7cf95ae..5f1a208 100644
> --- a/gcc/target-globals.c
> +++ b/gcc/target-globals.c
> @@ -83,13 +83,13 @@ save_target_globals (void)
>    g = (struct target_globals *) p;
>    g->flag_state = &p->flag_state;
>    g->regs = ggc_internal_cleared_alloc (sizeof (struct target_regs));
> -  g->rtl = ggc_alloc_cleared_target_rtl ();
> +  g->rtl = ggc_cleared_alloc<target_rtl> ();
>    g->hard_regs
>      = ggc_internal_cleared_alloc (sizeof (struct target_hard_regs));
>    g->reload = ggc_internal_cleared_alloc (sizeof (struct target_reload));
>    g->expmed =  ggc_internal_cleared_alloc (sizeof (struct target_expmed));
>    g->optabs = &p->optabs;
> -  g->libfuncs = ggc_alloc_cleared_target_libfuncs ();
> +  g->libfuncs = ggc_cleared_alloc<target_libfuncs> ();
>    g->cfgloop = &p->cfgloop;
>    g->ira = ggc_internal_cleared_alloc (sizeof (struct target_ira));
>    g->ira_int = ggc_internal_cleared_alloc (sizeof (struct target_ira_int));
> diff --git a/gcc/toplev.c b/gcc/toplev.c
> index 9535bd0..2f9c9f5 100644
> --- a/gcc/toplev.c
> +++ b/gcc/toplev.c
> @@ -1156,7 +1156,7 @@ general_init (const char *argv0)
>       table.  */
>    init_ggc ();
>    init_stringpool ();
> -  line_table = ggc_alloc_line_maps ();
> +  line_table = ggc_alloc<line_maps> ();
>    linemap_init (line_table);
>    line_table->reallocator = realloc_for_line_map;
>    line_table->round_alloc_size = ggc_round_alloc_size;
> diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
> index 417ca8a..52777d5 100644
> --- a/gcc/trans-mem.c
> +++ b/gcc/trans-mem.c
> @@ -479,7 +479,7 @@ record_tm_replacement (tree from, tree to)
>    if (tm_wrap_map == NULL)
>      tm_wrap_map = htab_create_ggc (32, tree_map_hash, tree_map_eq, 0);
>
> -  h = ggc_alloc_tree_map ();
> +  h = ggc_alloc<tree_map> ();
>    h->hash = htab_hash_pointer (from);
>    h->base.from = from;
>    h->to = to;
> @@ -3070,7 +3070,7 @@ split_bb_make_tm_edge (gimple stmt, basic_block dest_bb,
>    struct tm_restart_node *n = (struct tm_restart_node *) *slot;
>    if (n == NULL)
>      {
> -      n = ggc_alloc_tm_restart_node ();
> +      n = ggc_alloc<tm_restart_node> ();
>        *n = dummy;
>      }
>    else
> diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
> index 0fb2681..446e0f2 100644
> --- a/gcc/tree-cfg.c
> +++ b/gcc/tree-cfg.c
> @@ -6893,7 +6893,7 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
>      }
>
>    /* Initialize an empty loop tree.  */
> -  struct loops *loops = ggc_alloc_cleared_loops ();
> +  struct loops *loops = ggc_cleared_alloc<struct loops> ();
>    init_loops_structure (dest_cfun, loops, 1);
>    loops->state = LOOPS_MAY_HAVE_MULTIPLE_LATCHES;
>    set_loops_for_fn (dest_cfun, loops);
> diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h
> index 8810a3e..f4075fc 100644
> --- a/gcc/tree-data-ref.h
> +++ b/gcc/tree-data-ref.h
> @@ -565,7 +565,7 @@ lambda_vector_gcd (lambda_vector vector, int size)
>  static inline lambda_vector
>  lambda_vector_new (int size)
>  {
> -  return (lambda_vector) ggc_internal_cleared_alloc (sizeof (int) * size);
> +  return ggc_cleared_vec_alloc<int> (size);
>  }
>
>  /* Clear out vector VEC1 of length SIZE.  */
> diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
> index 960c04a..914ef68 100644
> --- a/gcc/tree-eh.c
> +++ b/gcc/tree-eh.c
> @@ -82,7 +82,7 @@ add_stmt_to_eh_lp_fn (struct function *ifun, gimple t, int num)
>
>    gcc_assert (num != 0);
>
> -  n = ggc_alloc_throw_stmt_node ();
> +  n = ggc_alloc<throw_stmt_node> ();
>    n->stmt = t;
>    n->lp_nr = num;
>
> diff --git a/gcc/tree-iterator.c b/gcc/tree-iterator.c
> index 37ee752..c4412ba 100644
> --- a/gcc/tree-iterator.c
> +++ b/gcc/tree-iterator.c
> @@ -131,7 +131,7 @@ tsi_link_before (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
>      }
>    else
>      {
> -      head = ggc_alloc_tree_statement_list_node ();
> +      head = ggc_alloc<tree_statement_list_node> ();
>        head->prev = NULL;
>        head->next = NULL;
>        head->stmt = t;
> @@ -207,7 +207,7 @@ tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
>      }
>    else
>      {
> -      head = ggc_alloc_tree_statement_list_node ();
> +      head = ggc_alloc<tree_statement_list_node> ();
>        head->prev = NULL;
>        head->next = NULL;
>        head->stmt = t;
> diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
> index f1ddc24..fc0b0d1 100644
> --- a/gcc/tree-scalar-evolution.c
> +++ b/gcc/tree-scalar-evolution.c
> @@ -332,7 +332,7 @@ new_scev_info_str (basic_block instantiated_below, tree var)
>  {
>    struct scev_info_str *res;
>
> -  res = ggc_alloc_scev_info_str ();
> +  res = ggc_alloc<scev_info_str> ();
>    res->name_version = SSA_NAME_VERSION (var);
>    res->chrec = chrec_not_analyzed_yet;
>    res->instantiated_below = instantiated_below->index;
> diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
> index 7628363..04effab 100644
> --- a/gcc/tree-ssa-loop-niter.c
> +++ b/gcc/tree-ssa-loop-niter.c
> @@ -2678,7 +2678,7 @@ record_estimate (struct loop *loop, tree bound, double_int i_bound,
>           || loop->nb_iterations == NULL_TREE
>           || TREE_CODE (loop->nb_iterations) != INTEGER_CST))
>      {
> -      struct nb_iter_bound *elt = ggc_alloc_nb_iter_bound ();
> +      struct nb_iter_bound *elt = ggc_alloc<nb_iter_bound> ();
>
>        elt->bound = i_bound;
>        elt->stmt = at_stmt;
> diff --git a/gcc/tree-ssa-operands.h b/gcc/tree-ssa-operands.h
> index 5f9edd4..42fe5a7 100644
> --- a/gcc/tree-ssa-operands.h
> +++ b/gcc/tree-ssa-operands.h
> @@ -45,7 +45,7 @@ typedef struct use_optype_d *use_optype_p;
>     operand memory manager.  Operands are suballocated out of this block.  The
>     MEM array varies in size.  */
>
> -struct GTY((chain_next("%h.next"), variable_size)) ssa_operand_memory_d {
> +struct GTY((chain_next("%h.next"))) ssa_operand_memory_d {
>    struct ssa_operand_memory_d *next;
>    char mem[1];
>  };
> diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
> index 1ea639d..f6f9dc9 100644
> --- a/gcc/tree-ssa.c
> +++ b/gcc/tree-ssa.c
> @@ -1120,7 +1120,7 @@ uid_ssaname_map_hash (const void *item)
>  void
>  init_tree_ssa (struct function *fn)
>  {
> -  fn->gimple_df = ggc_alloc_cleared_gimple_df ();
> +  fn->gimple_df = ggc_cleared_alloc<gimple_df> ();
>    fn->gimple_df->default_defs = htab_create_ggc (20, uid_ssaname_map_hash,
>                                                  uid_ssaname_map_eq, NULL);
>    pt_solution_reset (&fn->gimple_df->escaped);
> diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
> index 02db6a5..b013149 100644
> --- a/gcc/tree-ssanames.c
> +++ b/gcc/tree-ssanames.c
> @@ -196,7 +196,7 @@ set_range_info (tree name, enum value_range_type range_type, double_int min,
>    /* Allocate if not available.  */
>    if (ri == NULL)
>      {
> -      ri = ggc_alloc_cleared_range_info_def ();
> +      ri = ggc_cleared_alloc<range_info_def> ();
>        SSA_NAME_RANGE_INFO (name) = ri;
>        ri->nonzero_bits = double_int::mask (TYPE_PRECISION (TREE_TYPE (name)));
>      }
> @@ -437,7 +437,7 @@ get_ptr_info (tree t)
>    pi = SSA_NAME_PTR_INFO (t);
>    if (pi == NULL)
>      {
> -      pi = ggc_alloc_cleared_ptr_info_def ();
> +      pi = ggc_cleared_alloc<ptr_info_def> ();
>        pt_solution_reset (&pi->pt);
>        mark_ptr_info_alignment_unknown (pi);
>        SSA_NAME_PTR_INFO (t) = pi;
> @@ -481,7 +481,7 @@ duplicate_ssa_name_ptr_info (tree name, struct ptr_info_def *ptr_info)
>    if (!ptr_info)
>      return;
>
> -  new_ptr_info = ggc_alloc_ptr_info_def ();
> +  new_ptr_info = ggc_alloc<ptr_info_def> ();
>    *new_ptr_info = *ptr_info;
>
>    SSA_NAME_PTR_INFO (name) = new_ptr_info;
> @@ -502,7 +502,7 @@ duplicate_ssa_name_range_info (tree name, enum value_range_type range_type,
>    if (!range_info)
>      return;
>
> -  new_range_info = ggc_alloc_range_info_def ();
> +  new_range_info = ggc_alloc<range_info_def> ();
>    *new_range_info = *range_info;
>
>    gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE);
> diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
> index b02bb6b..aa61187 100644
> --- a/gcc/tree-streamer-in.c
> +++ b/gcc/tree-streamer-in.c
> @@ -176,7 +176,7 @@ unpack_ts_real_cst_value_fields (struct bitpack_d *bp, tree expr)
>    for (i = 0; i < SIGSZ; i++)
>      r.sig[i] = (unsigned long) bp_unpack_value (bp, HOST_BITS_PER_LONG);
>
> -  rp = ggc_alloc_real_value ();
> +  rp = ggc_alloc<real_value> ();
>    memcpy (rp, &r, sizeof (REAL_VALUE_TYPE));
>    TREE_REAL_CST_PTR (expr) = rp;
>  }
> @@ -188,7 +188,7 @@ unpack_ts_real_cst_value_fields (struct bitpack_d *bp, tree expr)
>  static void
>  unpack_ts_fixed_cst_value_fields (struct bitpack_d *bp, tree expr)
>  {
> -  FIXED_VALUE_TYPE *fp = ggc_alloc_fixed_value ();
> +  FIXED_VALUE_TYPE *fp = ggc_alloc<fixed_value> ();
>    fp->mode = bp_unpack_enum (bp, machine_mode, MAX_MACHINE_MODE);
>    fp->data.low = bp_unpack_var_len_int (bp);
>    fp->data.high = bp_unpack_var_len_int (bp);
> diff --git a/gcc/tree.c b/gcc/tree.c
> index 365faf2..9a3e7e9 100644
> --- a/gcc/tree.c
> +++ b/gcc/tree.c
> @@ -1577,7 +1577,7 @@ build_fixed (tree type, FIXED_VALUE_TYPE f)
>    FIXED_VALUE_TYPE *fp;
>
>    v = make_node (FIXED_CST);
> -  fp = ggc_alloc_fixed_value ();
> +  fp = ggc_alloc<fixed_value> ();
>    memcpy (fp, &f, sizeof (FIXED_VALUE_TYPE));
>
>    TREE_TYPE (v) = type;
> @@ -1598,7 +1598,7 @@ build_real (tree type, REAL_VALUE_TYPE d)
>       Consider doing it via real_convert now.  */
>
>    v = make_node (REAL_CST);
> -  dp = ggc_alloc_real_value ();
> +  dp = ggc_alloc<real_value> ();
>    memcpy (dp, &d, sizeof (REAL_VALUE_TYPE));
>
>    TREE_TYPE (v) = type;
> @@ -6390,7 +6390,7 @@ decl_priority_info (tree decl)
>    h = (struct tree_priority_map *) *loc;
>    if (!h)
>      {
> -      h = ggc_alloc_cleared_tree_priority_map ();
> +      h = ggc_cleared_alloc<tree_priority_map> ();
>        *loc = h;
>        h->base.from = decl;
>        h->init = DEFAULT_INIT_PRIORITY;
> @@ -6473,7 +6473,7 @@ decl_debug_expr_insert (tree from, tree to)
>    struct tree_decl_map *h;
>    void **loc;
>
> -  h = ggc_alloc_tree_decl_map ();
> +  h = ggc_alloc<tree_decl_map> ();
>    h->base.from = from;
>    h->to = to;
>    loc = htab_find_slot_with_hash (debug_expr_for_decl, h, DECL_UID (from),
> @@ -6504,7 +6504,7 @@ decl_value_expr_insert (tree from, tree to)
>    struct tree_decl_map *h;
>    void **loc;
>
> -  h = ggc_alloc_tree_decl_map ();
> +  h = ggc_alloc<tree_decl_map> ();
>    h->base.from = from;
>    h->to = to;
>    loc = htab_find_slot_with_hash (value_expr_for_decl, h, DECL_UID (from),
> @@ -6545,7 +6545,7 @@ decl_debug_args_insert (tree from)
>    if (debug_args_for_decl == NULL)
>      debug_args_for_decl = htab_create_ggc (64, tree_vec_map_hash,
>                                            tree_vec_map_eq, 0);
> -  h = ggc_alloc_tree_vec_map ();
> +  h = ggc_alloc<tree_vec_map> ();
>    h->base.from = from;
>    h->to = NULL;
>    loc = htab_find_slot_with_hash (debug_args_for_decl, h, DECL_UID (from),
> @@ -6728,7 +6728,7 @@ type_hash_add (hashval_t hashcode, tree type)
>    struct type_hash *h;
>    void **loc;
>
> -  h = ggc_alloc_type_hash ();
> +  h = ggc_alloc<type_hash> ();
>    h->hash = hashcode;
>    h->type = type;
>    loc = htab_find_slot_with_hash (type_hash_table, h, hashcode, INSERT);
> diff --git a/gcc/ubsan.c b/gcc/ubsan.c
> index d9d740c..11461d0 100644
> --- a/gcc/ubsan.c
> +++ b/gcc/ubsan.c
> @@ -99,7 +99,7 @@ decl_for_type_insert (tree type, tree decl)
>    struct tree_type_map *h;
>    void **slot;
>
> -  h = ggc_alloc_tree_type_map ();
> +  h = ggc_alloc<tree_type_map> ();
>    h->type.from = type;
>    h->decl = decl;
>    slot = htab_find_slot_with_hash (decl_tree_for_type, h, TYPE_UID (type),
> diff --git a/gcc/varasm.c b/gcc/varasm.c
> index 3b42faa..4c59d35 100644
> --- a/gcc/varasm.c
> +++ b/gcc/varasm.c
> @@ -242,7 +242,7 @@ get_unnamed_section (unsigned int flags, void (*callback) (const void *),
>  {
>    section *sect;
>
> -  sect = ggc_alloc_section ();
> +  sect = ggc_alloc<section> ();
>    sect->unnamed.common.flags = flags | SECTION_UNNAMED;
>    sect->unnamed.callback = callback;
>    sect->unnamed.data = data;
> @@ -259,7 +259,7 @@ get_noswitch_section (unsigned int flags, noswitch_section_callback callback)
>  {
>    section *sect;
>
> -  sect = ggc_alloc_section ();
> +  sect = ggc_alloc<section> ();
>    sect->noswitch.common.flags = flags | SECTION_NOSWITCH;
>    sect->noswitch.callback = callback;
>
> @@ -280,7 +280,7 @@ get_section (const char *name, unsigned int flags, tree decl)
>    flags |= SECTION_NAMED;
>    if (*slot == NULL)
>      {
> -      sect = ggc_alloc_section ();
> +      sect = ggc_alloc<section> ();
>        sect->named.common.flags = flags;
>        sect->named.name = ggc_strdup (name);
>        sect->named.decl = decl;
> @@ -361,7 +361,7 @@ get_block_for_section (section *sect)
>    block = (struct object_block *) *slot;
>    if (block == NULL)
>      {
> -      block = ggc_alloc_cleared_object_block ();
> +      block = ggc_cleared_alloc<object_block> ();
>        block->sect = sect;
>        *slot = block;
>      }
> @@ -3203,7 +3203,7 @@ build_constant_desc (tree exp)
>    int labelno;
>    tree decl;
>
> -  desc = ggc_alloc_constant_descriptor_tree ();
> +  desc = ggc_alloc<constant_descriptor_tree> ();
>    desc->value = copy_constant (exp);
>
>    /* Create a string containing the label name, in LABEL.  */
> @@ -3607,7 +3607,7 @@ create_constant_pool (void)
>  {
>    struct rtx_constant_pool *pool;
>
> -  pool = ggc_alloc_rtx_constant_pool ();
> +  pool = ggc_alloc<rtx_constant_pool> ();
>    pool->const_rtx_htab = htab_create_ggc (31, const_desc_rtx_hash,
>                                           const_desc_rtx_eq, NULL);
>    pool->first = NULL;
> @@ -3673,7 +3673,7 @@ force_const_mem (enum machine_mode mode, rtx x)
>      return copy_rtx (desc->mem);
>
>    /* Otherwise, create a new descriptor.  */
> -  desc = ggc_alloc_constant_descriptor_rtx ();
> +  desc = ggc_alloc<constant_descriptor_rtx> ();
>    *slot = desc;
>
>    /* Align the location counter as required by EXP's data type.  */
> @@ -5721,7 +5721,7 @@ record_tm_clone_pair (tree o, tree n)
>    if (tm_clone_hash == NULL)
>      tm_clone_hash = htab_create_ggc (32, tree_map_hash, tree_map_eq, 0);
>
> -  h = ggc_alloc_tree_map ();
> +  h = ggc_alloc<tree_map> ();
>    h->hash = htab_hash_pointer (o);
>    h->base.from = o;
>    h->to = n;
> diff --git a/gcc/varpool.c b/gcc/varpool.c
> index 69172c6..45ff88d 100644
> --- a/gcc/varpool.c
> +++ b/gcc/varpool.c
> @@ -135,7 +135,7 @@ varpool_call_variable_insertion_hooks (varpool_node *node)
>  varpool_node *
>  varpool_create_empty_node (void)
>  {
> -  varpool_node *node = ggc_alloc_cleared_varpool_node ();
> +  varpool_node *node = ggc_cleared_alloc<varpool_node> ();
>    node->type = SYMTAB_VARIABLE;
>    return node;
>  }
> --
> 2.0.0.rc0
>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/6] add finalizers to ggc
  2014-04-29 11:59 ` [PATCH 5/6] add finalizers to ggc tsaunders
@ 2014-04-29 13:00   ` Richard Biener
  2014-04-29 13:26     ` Trevor Saunders
  0 siblings, 1 reply; 18+ messages in thread
From: Richard Biener @ 2014-04-29 13:00 UTC (permalink / raw)
  To: tsaunders; +Cc: GCC Patches

On Tue, Apr 29, 2014 at 1:08 PM,  <tsaunders@mozilla.com> wrote:
> From: Trevor Saunders <tsaunders@mozilla.com>
>
> Hi,
>
> This implements finalizers by keeping a list of registered finalizers
> and after every mark but before sweeping check to see if any of them are
> for unmarked blocks.
>
> bootstrapped + regtested on x86_64-unknown-linux-gnu, ok?
>
> Trev
>
> gcc/ChangeLog:
>
>         * ggc-common.c (ggc_internal_cleared_alloc): Adjust.
>         * ggc-none.c (ggc_internal_alloc): Assert if a finalizer is passed.
>         (ggc_internal_cleared_alloc): Likewise.
>         * ggc-page.c (finalizer): New class.
>         (globals::finalizer_lists): New member.
>         (ggc_internal_alloc): Record the finalizer if any for the block being
>         allocated.
>         (ggc_handle_finalizers): New function.
>         (ggc_collect): Call ggc_handle_finalizers.
>         * ggc.h (ggc_internal_alloc):Add arguments to allow installing a
>         finalizer.
>         (ggc_internal_cleared_alloc): Likewise.
>         (finalize): New function.
>         (need_finalization_p): Likewise.
>         (ggc_alloc): Install the type's destructor as the finalizer if it
>         might do something.
>         (ggc_cleared_alloc): Likewise.
>         (ggc_vec_alloc): Likewise.
>         (ggc_cleared_vec_alloc): Likewise.
> ---
>  gcc/ggc-common.c |  5 +++--
>  gcc/ggc-none.c   |  8 ++++++--
>  gcc/ggc-page.c   | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
>  gcc/ggc.h        | 52 ++++++++++++++++++++++++++++++++++++++++++++++------
>  4 files changed, 104 insertions(+), 11 deletions(-)
>
> diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
> index e89cc64..b11a10c 100644
> --- a/gcc/ggc-common.c
> +++ b/gcc/ggc-common.c
> @@ -174,9 +174,10 @@ ggc_mark_roots (void)
>
>  /* Allocate a block of memory, then clear it.  */
>  void *
> -ggc_internal_cleared_alloc (size_t size MEM_STAT_DECL)
> +ggc_internal_cleared_alloc (size_t size, void (*f)(void *), size_t s, size_t n
> +                           MEM_STAT_DECL)
>  {
> -  void *buf = ggc_internal_alloc (size PASS_MEM_STAT);
> +  void *buf = ggc_internal_alloc (size, f, s, n PASS_MEM_STAT);
>    memset (buf, 0, size);
>    return buf;
>  }
> diff --git a/gcc/ggc-none.c b/gcc/ggc-none.c
> index aad89bf..97d3566 100644
> --- a/gcc/ggc-none.c
> +++ b/gcc/ggc-none.c
> @@ -41,14 +41,18 @@ ggc_round_alloc_size (size_t requested_size)
>  }
>
>  void *
> -ggc_internal_alloc (size_t size MEM_STAT_DECL)
> +ggc_internal_alloc (size_t size, void (*f)(void *), size_t, size_t
> +                   MEM_STAT_DECL)
>  {
> +  gcc_assert (!f); // ggc-none doesn't support finalizers
>    return xmalloc (size);
>  }
>
>  void *
> -ggc_internal_cleared_alloc (size_t size MEM_STAT_DECL)
> +ggc_internal_cleared_alloc (size_t size, void (*f)(void *), size_t, size_t
> +                           MEM_STAT_DECL)
>  {
> +  gcc_assert (!f); // ggc-none doesn't support finalizers
>    return xcalloc (size, 1);
>  }
>
> diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
> index ae5e88a..208b526 100644
> --- a/gcc/ggc-page.c
> +++ b/gcc/ggc-page.c
> @@ -332,6 +332,27 @@ typedef struct page_table_chain
>
>  #endif
>
> +class finalizer
> +{
> +public:
> +  finalizer (uintptr_t addr, void (*f)(void *), size_t s, size_t n) :
> +    m_addr (addr), m_function (f), m_object_size (s), m_n_objects (n) {}
> +
> +  void call () const
> +    {
> +      for (size_t i = 0; i < m_n_objects; i++)
> +       m_function (reinterpret_cast<void *> (m_addr + (i * m_object_size)));
> +    }
> +
> +  uintptr_t addr () const { return m_addr; }
> +
> +private:
> +  uintptr_t m_addr;
> +  void (*m_function)(void *);
> +  size_t m_object_size;
> +  size_t m_n_objects;
> +};
> +
>  #ifdef ENABLE_GC_ALWAYS_COLLECT
>  /* List of free objects to be verified as actually free on the
>     next collection.  */
> @@ -425,6 +446,9 @@ static struct globals
>       better runtime data access pattern.  */
>    unsigned long **save_in_use;
>
> +  /* finalizer_lists[i] is the list of finalizers for blocks of order i.  */
> +  vec<finalizer> finalizer_lists[NUM_ORDERS];
> +
>  #ifdef ENABLE_GC_ALWAYS_COLLECT
>    /* List of free objects to be verified as actually free on the
>       next collection.  */
> @@ -1202,7 +1226,8 @@ ggc_round_alloc_size (size_t requested_size)
>  /* Allocate a chunk of memory of SIZE bytes.  Its contents are undefined.  */
>
>  void *
> -ggc_internal_alloc (size_t size MEM_STAT_DECL)
> +ggc_internal_alloc (size_t size, void (*f)(void *), size_t s, size_t n
> +                   MEM_STAT_DECL)
>  {
>    size_t order, word, bit, object_offset, object_size;
>    struct page_entry *entry;
> @@ -1345,6 +1370,10 @@ ggc_internal_alloc (size_t size MEM_STAT_DECL)
>    /* For timevar statistics.  */
>    timevar_ggc_mem_total += object_size;
>
> +  if (f)
> +    G.finalizer_lists[order]
> +      .safe_push (finalizer (reinterpret_cast<uintptr_t> (result), f, s, n));
> +
>    if (GATHER_STATISTICS)
>      {
>        size_t overhead = object_size - size;
> @@ -1811,6 +1840,24 @@ clear_marks (void)
>      }
>  }
>
> +static void
> +ggc_handle_finalizers ()
> +{
> +  for (unsigned int order = 2; order < NUM_ORDERS; order++)
> +    {
> +      unsigned int length = G.finalizer_lists[order].length ();
> +      for (unsigned int i = length - 1; i < length; i--)

I suppose you are walking backwards here to handle dependences
properly.

But it doesn't address dependencies across different allocation
orders (what's the reason to even have one vector per order?).

> +       {
> +         finalizer &f = G.finalizer_lists[order][i];
> +         if (!ggc_marked_p (reinterpret_cast<void *> (f.addr ())))
> +           {
> +             f.call ();
> +             G.finalizer_lists[order].ordered_remove (i);

But this clearly will be an efficiency issue.  Can you delay
removing the element from the list and instead do it in
a second forward run over all finalizers of that order (if there
were any finalizers run in the first)?

I suppose that the overall complexity of walking the finalizers isn't
that bad as we walked all reachable ggc memory anyway.

So the only issue would be memory inefficiencies for a lot
of small individual objects that need finalization.  Thus,

> +private:
> +  uintptr_t m_addr;
> +  void (*m_function)(void *);
> +  size_t m_object_size;
> +  size_t m_n_objects;

could be improved by noting that m_function and m_object_size
are somewhat redundant (and m_object_size and m_n_objects
are unused for non-vectors).  So, instead of m_function and
m_object_size you could store an index into a global vector
of m_function/m_object_size pairs (eventually even statically
compute it by gengtype.c to avoid some kind of lookup
at allocation time).

As finalization order is currently broken (see above) you could
also have two vectors of finalizers, one for the vector case
and one for the non-vector case.

An optimization would also be to look at the last added
finalizer and see if the current object is adjacent to it
and only adjust m_n_objects.   (not sure if that would trigger
often)

I suppose given we don't have many uses of finalizers (yet)
this all isn't much of an issue.  Still please eventually
reduce to a single finalizer vector and avoid the ordered remove.

Thanks,
Richard.

> +           }
> +       }
> +    }
> +}
> +
>  /* Free all empty pages.  Partially empty pages need no attention
>     because the `mark' bit doubles as an `unused' bit.  */
>
> @@ -2075,6 +2122,7 @@ ggc_collect (void)
>
>    clear_marks ();
>    ggc_mark_roots ();
> +  ggc_handle_finalizers ();
>
>    if (GATHER_STATISTICS)
>      ggc_prune_overhead_list ();
> diff --git a/gcc/ggc.h b/gcc/ggc.h
> index 50fb199..4c59597 100644
> --- a/gcc/ggc.h
> +++ b/gcc/ggc.h
> @@ -136,13 +136,16 @@ extern void gt_pch_save (FILE *f);
>  /* Allocation.  */
>
>  /* The internal primitive.  */
> -extern void *ggc_internal_alloc (size_t CXX_MEM_STAT_INFO) ATTRIBUTE_MALLOC;
> +extern void *ggc_internal_alloc (size_t, void (*)(void *) = NULL, size_t = 0,
> +                                size_t = 1 CXX_MEM_STAT_INFO)
> +     ATTRIBUTE_MALLOC;
>
>  extern size_t ggc_round_alloc_size (size_t requested_size);
>
>  /* Allocates cleared memory.  */
> -extern void *ggc_internal_cleared_alloc (size_t CXX_MEM_STAT_INFO)
> -  ATTRIBUTE_MALLOC;
> +extern void *ggc_internal_cleared_alloc (size_t, void (*)(void *) = NULL,
> +                                        size_t = 0, size_t = 1
> +                                        CXX_MEM_STAT_INFO) ATTRIBUTE_MALLOC;
>
>  /* Resize a block.  */
>  extern void *ggc_realloc (void *, size_t CXX_MEM_STAT_INFO);
> @@ -157,24 +160,55 @@ extern void dump_ggc_loc_statistics (bool);
>      ((T *) ggc_realloc ((P), (N) * sizeof (T) MEM_STAT_INFO))
>
>  template<typename T>
> +void
> +finalize (void *p)
> +{
> +  static_cast<T *> (p)->~T ();
> +}
> +
> +template<typename T>
> +static inline bool
> +need_finalization_p ()
> +{
> +#if GCC_VERSION >= 4003
> +  return !__has_trivial_destructor (T);
> +#else
> +  return true;
> +#endif
> +}
> +
> +template<typename T>
>  static inline T *
>  ggc_alloc (ALONE_CXX_MEM_STAT_INFO)
>  {
> -  return static_cast<T *> (ggc_internal_alloc (sizeof (T) PASS_MEM_STAT));
> +  if (need_finalization_p<T> ())
> +    return static_cast<T *> (ggc_internal_alloc (sizeof (T), finalize<T>
> +                                                PASS_MEM_STAT));
> +  else
> +    return static_cast<T *> (ggc_internal_alloc (sizeof (T) PASS_MEM_STAT));
>  }
>
>  template<typename T>
>  static inline T *
>  ggc_cleared_alloc (ALONE_CXX_MEM_STAT_INFO)
>  {
> -  return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T)
> -                                                      PASS_MEM_STAT));
> +  if (need_finalization_p<T> ())
> +    return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T),
> +                                                        finalize<T>
> +                                                        PASS_MEM_STAT));
> +  else
> +    return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T)
> +                                                        PASS_MEM_STAT));
>  }
>
>  template<typename T>
>  static inline T *
>  ggc_vec_alloc (size_t c CXX_MEM_STAT_INFO)
>  {
> +  if (need_finalization_p<T> ())
> +    return static_cast<T *> (ggc_internal_alloc (c * sizeof (T), finalize<T>,
> +                                                sizeof (T), c PASS_MEM_STAT));
> +  else
>      return static_cast<T *> (ggc_internal_alloc (c * sizeof (T)
>                                                  PASS_MEM_STAT));
>  }
> @@ -183,6 +217,12 @@ template<typename T>
>  static inline T *
>  ggc_cleared_vec_alloc (size_t c CXX_MEM_STAT_INFO)
>  {
> +  if (need_finalization_p<T> ())
> +    return static_cast<T *> (ggc_internal_cleared_alloc (c * sizeof (T),
> +                                                        finalize<T>,
> +                                                        sizeof (T), c
> +                                                        PASS_MEM_STAT));
> +  else
>      return static_cast<T *> (ggc_internal_cleared_alloc (c * sizeof (T)
>                                                          PASS_MEM_STAT));
>  }
> --
> 2.0.0.rc0
>

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 3/6] use templates instead of gengtype for typed allocation functions
  2014-04-29 12:41   ` Richard Biener
@ 2014-04-29 13:08     ` Trevor Saunders
  2014-04-29 13:15       ` Richard Biener
  0 siblings, 1 reply; 18+ messages in thread
From: Trevor Saunders @ 2014-04-29 13:08 UTC (permalink / raw)
  To: Richard Biener; +Cc: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 124727 bytes --]

On Tue, Apr 29, 2014 at 02:32:23PM +0200, Richard Biener wrote:
> On Tue, Apr 29, 2014 at 1:08 PM,  <tsaunders@mozilla.com> wrote:
> > From: Trevor Saunders <tsaunders@mozilla.com>
> >
> > Hi,
> >
> > much less code to accomplish the same thing.
> 
> Agreed.  Does that fix the comment on the last patch about
> dropping typed allocations of variable lengths, as I see you
> introduce ggc_vec_alloc () here?

in some cases yes, for example the c front end used to have to deal with
ggc thinking lang_decl was variably sized because c++ makes it that way.
So after this patch the C front end can now just write
ld = ggc_alloc<lang_decl> ();
And for free we get that dwarf2out.c can do
unsigned char *vec = ggc_cleared_vec_alloc<unsigned char> (n);
 (I didn't go looking for places where I could do that cleanup, but I
 could).  On the other hand these functions don't help with things like
 allocating lang_decls in the C++ front end where they basically want to
 write
 ld = (struct x*) ggc_internal_alloc (sizeof (struct y));
There's about 10 places that do something like that or get the length
from someplace else.  We could add some sort of macro like
GGC_NEW(type, size)
if you think it would be better than calling ggc_internal_alloc and
casting, but given the number of sites and it not being much better in
my mind I didn't bother.

thanks!

Trev

> 
> > bootstrapped + regtested on x86_64-unknown-linux-gnu ok?
> 
> If so, then ok.
> 
> Thanks,
> Richard.
> 
> > Trev
> >
> > gcc/ada/ChangeLog:
> >
> >         * gcc-interface/ada-tree.h: Remove usage of variable_size gty
> >         annotation.
> >
> > gcc/cp/ChangeLog:
> >
> >         * cp-cilkplus.c (cilk_install_body_with_frame_cleanup): Adjust.
> >         * cp-objcp-common.c (decl_shadowed_for_var_insert): Adjust.
> >         * cp-tree.h: Remove usage of variable_size gty attribute.
> >         * decl.c (make_label_decl): Adjust.
> >         (check_goto): Likewise.
> >         (start_preparsed_function): Likewise.
> >         (save_function_data): Likewise.
> >         * lex.c (init_reswords): Likewise.
> >         (retrofit_lang_decl): Likewise.
> >         (cxx_dup_lang_specific_decl): Likewise.
> >         (copy_lang_type): Likewise.
> >         (cxx_make_type): Likewise.
> >         * name-lookup.c (binding_entry_make): Likewise.
> >         (binding_table_construct): Likewise.
> >         (binding_table_new): Likewise.
> >         (cxx_binding_make): Likewise.
> >         (pushdecl_maybe_friend_1): Likewise.
> >         (begin_scope): Likewise.
> >         (push_to_top_level): Likewise.
> >         * parser.c (cp_lexer_alloc): Likewise.
> >         (cp_lexer_new_from_tokens): Likewise.
> >         (cp_token_cache_new): Likewise.
> >         (cp_parser_context_new): Likewise.
> >         (cp_parser_new): Likewise.
> >         (cp_parser_nested_name_specifier_opt): Likewise.
> >         (cp_parser_template_id): Likewise.
> >         * pt.c (maybe_process_partial_specialization): Likewise.
> >         (register_specialization): Likewise.
> >         (add_pending_template): Likewise.
> >         (lookup_template_class_1): Likewise.
> >         (push_tinst_level): Likewise.
> >         * semantics.c (register_constexpr_fundef): Likewise.
> >         (cxx_eval_call_expression): Likewise.
> >         * typeck2.c (abstract_virtuals_error_sfinae): Likewise.
> >
> > gcc/objc/ChangeLog:
> >
> >         * objc-act.c (objc_build_string_object): Adjust.
> >         (continue_class): Likewise.
> >         * objc-act.h (ALLOC_OBJC_TYPE_LANG_SPECIFIC): Likewise.
> >         * objc-map.c (objc_map_alloc_ggc): Likewise.
> >         (objc_map_private_resize): Likewise.
> >         * objc-next-runtime-abi-02.c (objc_next_runtime_abi_02_init):
> >         Likewise.
> >         (hash_name_enter): Likewise.
> >
> > gcc/go/ChangeLog:
> >
> >         * go-lang.c (struct GTY): Don't use variable_size gty attribute.
> >
> > gcc/ChangeLog:
> >
> >         * alias.c (record_alias_subset): Adjust.
> >         * bitmap.c (bitmap_element_allocate): Likewise.
> >         (bitmap_gc_alloc_stat): Likewise.
> >         * cfg.c (init_flow): Likewise.
> >         (alloc_block): Likewise.
> >         (unchecked_make_edge): Likewise.
> >         * cfgloop.c (alloc_loop): Likewise.
> >         (flow_loops_find): Likewise.
> >         (rescan_loop_exit): Likewise.
> >         * cfgrtl.c (init_rtl_bb_info): Likewise.
> >         * cgraph.c (insert_new_cgraph_node_version): Likewise.
> >         (cgraph_allocate_node): Likewise.
> >         (cgraph_create_edge_1): Likewise.
> >         (cgraph_allocate_init_indirect_info): Likewise.
> >         * cgraphclones.c (cgraph_clone_edge): Likewise.
> >         * cgraphunit.c (add_asm_node): Likewise.
> >         (init_lowered_empty_function): Likewise.
> >         * config/i386/i386.c (get_dllimport_decl): Likewise.
> >         (ix86_init_machine_status): Likewise.
> >         (assign_386_stack_local): Likewise.
> >         * coverage.c (coverage_end_function): Likewise.
> >         * dbxout.c (dbxout_init): Likewise.
> >         * doc/gty.texi: Don't mention variable_size attribute.
> >         * dwarf2cfi.c (new_cfi): Adjust.
> >         (new_cfi_row): Likewise.
> >         (copy_cfi_row): Likewise.
> >         (create_cie_data): Likewise.
> >         * dwarf2out.c (dwarf2out_alloc_current_fde): Likewise.
> >         (new_loc_descr): Likewise.
> >         (find_AT_string_in_table): Likewise.
> >         (add_addr_table_entry): Likewise.
> >         (new_die): Likewise.
> >         (add_var_loc_to_decl): Likewise.
> >         (clone_die): Likewise.
> >         (clone_as_declaration): Likewise.
> >         (break_out_comdat_types): Likewise.
> >         (new_loc_list): Likewise.
> >         (add_loc_descr_to_each): Likewise.
> >         (add_location_or_const_value_attribute): Likewise.
> >         (add_linkage_name): Likewise.
> >         (lookup_filename): Likewise.
> >         (dwarf2out_var_location): Likewise.
> >         (new_line_info_table): Likewise.
> >         (dwarf2out_init): Likewise.
> >         * emit-rtl.c (set_mem_attrs): Likewise.
> >         (get_reg_attrs): Likewise.
> >         (start_sequence): Likewise.
> >         (init_emit): Likewise.
> >         (init_emit_regs): Likewise.
> >         * except.c (init_eh_for_function): Likewise.
> >         (gen_eh_region): Likewise.
> >         (gen_eh_region_catch): Likewise.
> >         (gen_eh_landing_pad): Likewise.
> >         (add_call_site): Likewise.
> >         * function.c (add_frame_space): Likewise.
> >         (insert_temp_slot_address): Likewise.
> >         (assign_stack_temp_for_type): Likewise.
> >         (get_hard_reg_initial_val): Likewise.
> >         (allocate_struct_function): Likewise.
> >         (prepare_function_start): Likewise.
> >         (types_used_by_var_decl_insert): Likewise.
> >         * gengtype.c (variable_size_p): Remove function.
> >         (enum alloc_quantity): Remove enum.
> >         (write_typed_alloc_def): Remove function.
> >         (write_typed_struct_alloc_def): Likewise.
> >         (write_typed_typedef_alloc_def): Likewise.
> >         (write_typed_alloc_defns): Likewise.
> >         (main): Adjust.
> >         * ggc-common.c (ggc_cleared_alloc_htab_ignore_args): Adjust.
> >         (ggc_cleared_alloc_ptr_array_two_args): Likewise.
> >         * ggc.h (ggc_alloc): new function.
> >         (ggc_cleared_alloc): Likewise.
> >         (ggc_vec_alloc): Template on type of vector element, and remove
> >         element size argument.
> >         (ggc_cleared_vec_alloc): Likewise.
> >         * gimple.c (gimple_build_omp_for): Adjust.
> >         (gimple_copy): Likewise.
> >         * ipa-cp.c (get_replacement_map): Likewise.
> >         (find_aggregate_values_for_callers_subset): Likewise.
> >         (known_aggs_to_agg_replacement_list): Likewise.
> >         * ipa-devirt.c (get_odr_type): Likewise.
> >         * ipa-prop.c (ipa_node_duplication_hook): Likewise.
> >         (read_agg_replacement_chain): Likewise.
> >         * loop-iv.c (get_simple_loop_desc): Likewise.
> >         * lto-cgraph.c (input_node_opt_summary): Likewise.
> >         * lto-section-in.c (lto_new_in_decl_state): Likewise.
> >         * lto-streamer-in.c (lto_input_eh_catch_list): Likewise.
> >         (input_eh_region): Likewise.
> >         (input_eh_lp): Likewise.
> >         (input_cfg): Likewise.
> >         * optabs.c (set_optab_libfunc): Likewise.
> >         (set_conv_libfunc): Likewise.
> >         * passes.c (do_per_function_toporder): Likewise.
> >         * rtl.h: Don't use variable_size gty attribute.
> >         * sese.c (if_region_set_false_region): Adjust.
> >         * stringpool.c (gt_pch_save_stringpool): Likewise.
> >         * target-globals.c (save_target_globals): Likewise.
> >         * toplev.c (general_init): Likewise.
> >         * trans-mem.c (record_tm_replacement): Likewise.
> >         (split_bb_make_tm_edge): Likewise.
> >         * tree-cfg.c (move_sese_region_to_fn): Likewise.
> >         * tree-data-ref.h (lambda_vector_new): Likewise.
> >         * tree-eh.c (add_stmt_to_eh_lp_fn): Likewise.
> >         * tree-iterator.c (tsi_link_before): Likewise.
> >         (tsi_link_after): Likewise.
> >         * tree-scalar-evolution.c (new_scev_info_str): Likewise.
> >         * tree-ssa-loop-niter.c (record_estimate): Likewise.
> >         * tree-ssa-operands.h: Don't use variable_size gty attribute.
> >         * tree-ssa.c (init_tree_ssa): Adjust.
> >         * tree-ssanames.c (set_range_info): Likewise.
> >         (get_ptr_info): Likewise.
> >         (duplicate_ssa_name_ptr_info): Likewise.
> >         (duplicate_ssa_name_range_info): Likewise.
> >         * tree-streamer-in.c (unpack_ts_real_cst_value_fields): Likewise.
> >         (unpack_ts_fixed_cst_value_fields): Likewise.
> >         * tree.c (build_fixed): Likewise.
> >         (build_real): Likewise.
> >         (build_string): Likewise.
> >         (decl_priority_info): Likewise.
> >         (decl_debug_expr_insert): Likewise.
> >         (decl_value_expr_insert): Likewise.
> >         (decl_debug_args_insert): Likewise.
> >         (type_hash_add): Likewise.
> >         (build_omp_clause): Likewise.
> >         * ubsan.c (decl_for_type_insert): Likewise.
> >         * varasm.c (get_unnamed_section): Likewise.
> >         (get_noswitch_section): Likewise.
> >         (get_section): Likewise.
> >         (get_block_for_section): Likewise.
> >         (create_block_symbol): Likewise.
> >         (build_constant_desc): Likewise.
> >         (create_constant_pool): Likewise.
> >         (force_const_mem): Likewise.
> >         (record_tm_clone_pair): Likewise.
> >         * varpool.c (varpool_create_empty_node): Likewise.
> >
> > gcc/c-family/ChangeLog:
> >
> >         * c-common.h (sorted_fields_type): Remove variable_size GTY attribute.
> >         * c-pragma.c (push_alignment): Adjust.
> >         (handle_pragma_push_options): Likewise.
> >
> > gcc/fortran/ChangeLog:
> >
> >         * f95-lang.c (pushlevel): Adjust.
> >         * trans-decl.c (gfc_allocate_lang_decl): Likewise.
> >         (gfc_find_module): Likewise.
> >         * trans-types.c (gfc_get_nodesc_array_type): Likewise.
> >         (gfc_get_array_type_bounds): Likewise.
> >         (gfc_nonrestricted_type): Likewise.
> >         * trans.h: Don't use variable_size gty attribute.
> >
> > gcc/c/ChangeLog:
> >
> >         * c-decl.c (bind): Adjust.
> >         (record_inline_static): Likewise.
> >         (push_scope): Likewise.
> >         (make_label): Likewise.
> >         (lookup_label_for_goto): Likewise.
> >         (finish_struct): Likewise.
> >         (finish_enum): Likewise.
> >         (store_parm_decls): Likewise.
> >         (c_push_function_context): Likewise.
> >         * c-lang.h: Remove usage of variable_size gty attribute.
> >         * c-parser.c (c_parse_init): Adjust.
> >         (c_parse_file): Likewise.
> >
> > gcc/lto/ChangeLog:
> >
> >         * lto-tree.h: Don't use variable_size gty attribute.
> >         * lto.c (lto_read_in_decl_state): Adjust.
> >         (create_subid_section_table): Likewise.
> >         (lto_flatten_files): Likewise.
> >         (read_cgraph_and_symbols): Likewise.
> >
> > gcc/java/ChangeLog:
> >
> >         * class.c (add_method_1): Adjust.
> >         (java_treetreehash_new): Likewise.
> >         * constants.c (set_constant_entry): Likewise.
> >         (cpool_for_class): Likewise.
> >         * decl.c (make_binding_level): Likewise.
> >         (java_dup_lang_specific_decl): Likewise.
> >         * expr.c (add_type_assertion): Likewise.
> >         * java-tree.h (MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC): Likewise.
> >         (lang_decl): don't use variable_size gty attribute.
> >         (MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC): Adjust.
> >         (lang_type): Don't use variable_size gty attribute.
> >         * jcf-parse.c (java_parse_file): Adjust.
> >         (process_zip_dir): Likewise.
> >         * jcf.h: Remove usage of variable_size gty attribute.
> > ---
> >  gcc/ada/gcc-interface/ada-tree.h    |  10 +--
> >  gcc/alias.c                         |   2 +-
> >  gcc/bitmap.c                        |   4 +-
> >  gcc/c-family/c-common.h             |   2 +-
> >  gcc/c-family/c-pragma.c             |   7 +-
> >  gcc/c/c-decl.c                      |  23 +++----
> >  gcc/c/c-lang.h                      |   4 +-
> >  gcc/c/c-parser.c                    |   4 +-
> >  gcc/cfg.c                           |  10 +--
> >  gcc/cfgloop.c                       |   8 +--
> >  gcc/cfgrtl.c                        |   2 +-
> >  gcc/cgraph.c                        |   8 +--
> >  gcc/cgraphclones.c                  |   2 +-
> >  gcc/cgraphunit.c                    |   4 +-
> >  gcc/config/i386/i386.c              |   6 +-
> >  gcc/coverage.c                      |   2 +-
> >  gcc/cp/cp-cilkplus.c                |   2 +-
> >  gcc/cp/cp-objcp-common.c            |   2 +-
> >  gcc/cp/cp-tree.h                    |   4 +-
> >  gcc/cp/decl.c                       |   8 +--
> >  gcc/cp/lex.c                        |   2 +-
> >  gcc/cp/name-lookup.c                |  14 ++--
> >  gcc/cp/parser.c                     |  14 ++--
> >  gcc/cp/pt.c                         |  10 +--
> >  gcc/cp/semantics.c                  |   4 +-
> >  gcc/cp/typeck2.c                    |   2 +-
> >  gcc/dbxout.c                        |   2 +-
> >  gcc/doc/gty.texi                    |  32 ---------
> >  gcc/dwarf2cfi.c                     |   8 +--
> >  gcc/dwarf2out.c                     |  44 ++++++-------
> >  gcc/emit-rtl.c                      |  10 +--
> >  gcc/except.c                        |  10 +--
> >  gcc/fortran/f95-lang.c              |   2 +-
> >  gcc/fortran/trans-decl.c            |   6 +-
> >  gcc/fortran/trans-types.c           |  15 ++---
> >  gcc/fortran/trans.h                 |   7 +-
> >  gcc/function.c                      |  18 ++---
> >  gcc/gengtype.c                      | 128 ------------------------------------
> >  gcc/ggc-common.c                    |   4 +-
> >  gcc/ggc.h                           |  31 +++++++--
> >  gcc/gimple.c                        |   9 +--
> >  gcc/go/go-lang.c                    |   2 +-
> >  gcc/ipa-cp.c                        |   6 +-
> >  gcc/ipa-devirt.c                    |   2 +-
> >  gcc/ipa-prop.c                      |   4 +-
> >  gcc/java/class.c                    |   6 +-
> >  gcc/java/constants.c                |   9 +--
> >  gcc/java/decl.c                     |   4 +-
> >  gcc/java/expr.c                     |   2 +-
> >  gcc/java/java-tree.h                |  15 ++---
> >  gcc/java/jcf-parse.c                |   6 +-
> >  gcc/java/jcf.h                      |   2 +-
> >  gcc/loop-iv.c                       |   2 +-
> >  gcc/lto-cgraph.c                    |   2 +-
> >  gcc/lto-section-in.c                |   2 +-
> >  gcc/lto-streamer-in.c               |   8 +--
> >  gcc/lto/lto-tree.h                  |   4 +-
> >  gcc/lto/lto.c                       |   8 +--
> >  gcc/objc/objc-act.c                 |   4 +-
> >  gcc/objc/objc-act.h                 |   4 +-
> >  gcc/objc/objc-map.c                 |  10 +--
> >  gcc/objc/objc-next-runtime-abi-02.c |   4 +-
> >  gcc/optabs.c                        |   4 +-
> >  gcc/passes.c                        |   2 +-
> >  gcc/rtl.h                           |   4 +-
> >  gcc/sese.c                          |   2 +-
> >  gcc/stringpool.c                    |   4 +-
> >  gcc/target-globals.c                |   4 +-
> >  gcc/toplev.c                        |   2 +-
> >  gcc/trans-mem.c                     |   4 +-
> >  gcc/tree-cfg.c                      |   2 +-
> >  gcc/tree-data-ref.h                 |   2 +-
> >  gcc/tree-eh.c                       |   2 +-
> >  gcc/tree-iterator.c                 |   4 +-
> >  gcc/tree-scalar-evolution.c         |   2 +-
> >  gcc/tree-ssa-loop-niter.c           |   2 +-
> >  gcc/tree-ssa-operands.h             |   2 +-
> >  gcc/tree-ssa.c                      |   2 +-
> >  gcc/tree-ssanames.c                 |   8 +--
> >  gcc/tree-streamer-in.c              |   4 +-
> >  gcc/tree.c                          |  14 ++--
> >  gcc/ubsan.c                         |   2 +-
> >  gcc/varasm.c                        |  16 ++---
> >  gcc/varpool.c                       |   2 +-
> >  84 files changed, 250 insertions(+), 432 deletions(-)
> >
> > diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h
> > index 5ea386f..30f8ec4 100644
> > --- a/gcc/ada/gcc-interface/ada-tree.h
> > +++ b/gcc/ada/gcc-interface/ada-tree.h
> > @@ -32,13 +32,9 @@ union GTY((desc ("0"),
> >                        desc ("tree_node_structure (&%h)"))) generic;
> >  };
> >
> > -/* Ada uses the lang_decl and lang_type fields to hold a tree.
> > -
> > -   FIXME: the variable_size annotation here is needed because these types are
> > -   variable-sized in some other front-ends.  Due to gengtype deficiency, the
> > -   GTY options of such types have to agree across all front-ends.  */
> > -struct GTY((variable_size)) lang_type { tree t; };
> > -struct GTY((variable_size)) lang_decl { tree t; };
> > +/* Ada uses the lang_decl and lang_type fields to hold a tree.  */
> > +struct GTY(()) lang_type { tree t; };
> > +struct GTY(()) lang_decl { tree t; };
> >
> >  /* Macros to get and set the tree in TYPE_LANG_SPECIFIC.  */
> >  #define GET_TYPE_LANG_SPECIFIC(NODE) \
> > diff --git a/gcc/alias.c b/gcc/alias.c
> > index 5f37402..bd45fcc 100644
> > --- a/gcc/alias.c
> > +++ b/gcc/alias.c
> > @@ -943,7 +943,7 @@ record_alias_subset (alias_set_type superset, alias_set_type subset)
> >      {
> >        /* Create an entry for the SUPERSET, so that we have a place to
> >          attach the SUBSET.  */
> > -      superset_entry = ggc_alloc_cleared_alias_set_entry_d ();
> > +      superset_entry = ggc_cleared_alloc<alias_set_entry_d> ();
> >        superset_entry->alias_set = superset;
> >        superset_entry->children
> >         = splay_tree_new_ggc (splay_tree_compare_ints,
> > diff --git a/gcc/bitmap.c b/gcc/bitmap.c
> > index 4855a66..b2914e1 100644
> > --- a/gcc/bitmap.c
> > +++ b/gcc/bitmap.c
> > @@ -244,7 +244,7 @@ bitmap_element_allocate (bitmap head)
> >           /*  Inner list was just a singleton.  */
> >           bitmap_ggc_free = element->prev;
> >        else
> > -       element = ggc_alloc_bitmap_element ();
> > +       element = ggc_alloc<bitmap_element> ();
> >      }
> >
> >    if (GATHER_STATISTICS)
> > @@ -388,7 +388,7 @@ bitmap_gc_alloc_stat (ALONE_MEM_STAT_DECL)
> >  {
> >    bitmap map;
> >
> > -  map = ggc_alloc_bitmap_head ();
> > +  map = ggc_alloc<bitmap_head> ();
> >    bitmap_initialize_stat (map, NULL PASS_MEM_STAT);
> >
> >    if (GATHER_STATISTICS)
> > diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
> > index 57b7dce..d3b1099 100644
> > --- a/gcc/c-family/c-common.h
> > +++ b/gcc/c-family/c-common.h
> > @@ -440,7 +440,7 @@ extern GTY(()) tree c_global_trees[CTI_MAX];
> >
> >  /* In a RECORD_TYPE, a sorted array of the fields of the type, not a
> >     tree for size reasons.  */
> > -struct GTY((variable_size)) sorted_fields_type {
> > +struct GTY(()) sorted_fields_type {
> >    int len;
> >    tree GTY((length ("%h.len"))) elts[1];
> >  };
> > diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
> > index 9e2a00e..7b016ab 100644
> > --- a/gcc/c-family/c-pragma.c
> > +++ b/gcc/c-family/c-pragma.c
> > @@ -74,9 +74,7 @@ static void pop_alignment (tree);
> >  static void
> >  push_alignment (int alignment, tree id)
> >  {
> > -  align_stack * entry;
> > -
> > -  entry = ggc_alloc_align_stack ();
> > +  align_stack * entry = ggc_alloc<align_stack> ();
> >
> >    entry->alignment  = alignment;
> >    entry->id        = id;
> > @@ -911,7 +909,6 @@ handle_pragma_push_options (cpp_reader *ARG_UNUSED(dummy))
> >  {
> >    enum cpp_ttype token;
> >    tree x = 0;
> > -  opt_stack *p;
> >
> >    token = pragma_lex (&x);
> >    if (token != CPP_EOF)
> > @@ -920,7 +917,7 @@ handle_pragma_push_options (cpp_reader *ARG_UNUSED(dummy))
> >        return;
> >      }
> >
> > -  p = ggc_alloc_opt_stack ();
> > +  opt_stack *p = ggc_alloc<opt_stack> ();
> >    p->prev = options_stack;
> >    options_stack = p;
> >
> > diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
> > index e8b8166..2400849 100644
> > --- a/gcc/c/c-decl.c
> > +++ b/gcc/c/c-decl.c
> > @@ -638,7 +638,7 @@ bind (tree name, tree decl, struct c_scope *scope, bool invisible,
> >        binding_freelist = b->prev;
> >      }
> >    else
> > -    b = ggc_alloc_c_binding ();
> > +    b = ggc_alloc<c_binding> ();
> >
> >    b->shadowed = 0;
> >    b->decl = decl;
> > @@ -755,7 +755,7 @@ void
> >  record_inline_static (location_t loc, tree func, tree decl,
> >                       enum c_inline_static_type type)
> >  {
> > -  struct c_inline_static *csi = ggc_alloc_c_inline_static ();
> > +  c_inline_static *csi = ggc_alloc<c_inline_static> ();
> >    csi->location = loc;
> >    csi->function = func;
> >    csi->static_decl = decl;
> > @@ -952,7 +952,7 @@ push_scope (void)
> >           scope_freelist = scope->outer;
> >         }
> >        else
> > -       scope = ggc_alloc_cleared_c_scope ();
> > +       scope = ggc_cleared_alloc<c_scope> ();
> >
> >        /* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes.  */
> >        if (current_scope)
> > @@ -3084,12 +3084,10 @@ make_label (location_t location, tree name, bool defining,
> >             struct c_label_vars **p_label_vars)
> >  {
> >    tree label = build_decl (location, LABEL_DECL, name, void_type_node);
> > -  struct c_label_vars *label_vars;
> > -
> >    DECL_CONTEXT (label) = current_function_decl;
> >    DECL_MODE (label) = VOIDmode;
> >
> > -  label_vars = ggc_alloc_c_label_vars ();
> > +  c_label_vars *label_vars = ggc_alloc<c_label_vars> ();
> >    label_vars->shadowed = NULL;
> >    set_spot_bindings (&label_vars->label_bindings, defining);
> >    label_vars->decls_in_scope = make_tree_vector ();
> > @@ -3185,9 +3183,8 @@ lookup_label_for_goto (location_t loc, tree name)
> >       list for possible later warnings.  */
> >    if (label_vars->label_bindings.scope == NULL)
> >      {
> > -      struct c_goto_bindings *g;
> > +      c_goto_bindings *g = ggc_alloc<c_goto_bindings> ();
> >
> > -      g = ggc_alloc_c_goto_bindings ();
> >        g->loc = loc;
> >        set_spot_bindings (&g->goto_bindings, true);
> >        vec_safe_push (label_vars->gotos, g);
> > @@ -7423,8 +7420,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
> >           ensure that this lives as long as the rest of the struct decl.
> >           All decls in an inline function need to be saved.  */
> >
> > -       space = (struct lang_type *) ggc_internal_cleared_alloc
> > -         (sizeof (struct lang_type));
> > +       space = ggc_cleared_alloc<struct lang_type> ();
> >         space2 = (sorted_fields_type *) ggc_internal_alloc
> >           (sizeof (struct sorted_fields_type) + len * sizeof (tree));
> >
> > @@ -7705,8 +7701,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
> >
> >    /* Record the min/max values so that we can warn about bit-field
> >       enumerations that are too small for the values.  */
> > -  lt = (struct lang_type *) ggc_internal_cleared_alloc
> > -    (sizeof (struct lang_type));
> > +  lt = ggc_cleared_alloc<struct lang_type> ();
> >    lt->enum_min = minnode;
> >    lt->enum_max = maxnode;
> >    TYPE_LANG_SPECIFIC (enumtype) = lt;
> > @@ -8477,7 +8472,7 @@ store_parm_decls (void)
> >    allocate_struct_function (fndecl, false);
> >
> >    if (warn_unused_local_typedefs)
> > -    cfun->language = ggc_alloc_cleared_language_function ();
> > +    cfun->language = ggc_cleared_alloc<language_function> ();
> >
> >    /* Begin the statement tree for this function.  */
> >    DECL_SAVED_TREE (fndecl) = push_stmt_list ();
> > @@ -8801,7 +8796,7 @@ c_push_function_context (void)
> >    /* cfun->language might have been already allocated by the use of
> >       -Wunused-local-typedefs.  In that case, just re-use it.  */
> >    if (p == NULL)
> > -    cfun->language = p = ggc_alloc_cleared_language_function ();
> > +    cfun->language = p = ggc_cleared_alloc<language_function> ();
> >
> >    p->base.x_stmt_tree = c_stmt_tree;
> >    c_stmt_tree.x_cur_stmt_list = vec_safe_copy (c_stmt_tree.x_cur_stmt_list);
> > diff --git a/gcc/c/c-lang.h b/gcc/c/c-lang.h
> > index 7fcf333..e974906 100644
> > --- a/gcc/c/c-lang.h
> > +++ b/gcc/c/c-lang.h
> > @@ -23,7 +23,7 @@ along with GCC; see the file COPYING3.  If not see
> >  #include "c-family/c-common.h"
> >  #include "ggc.h"
> >
> > -struct GTY((variable_size)) lang_type {
> > +struct GTY(()) lang_type {
> >    /* In a RECORD_TYPE, a sorted array of the fields of the type.  */
> >    struct sorted_fields_type * GTY ((reorder ("resort_sorted_fields"))) s;
> >    /* In an ENUMERAL_TYPE, the min and max values.  */
> > @@ -35,7 +35,7 @@ struct GTY((variable_size)) lang_type {
> >    tree objc_info;
> >  };
> >
> > -struct GTY((variable_size)) lang_decl {
> > +struct GTY(()) lang_decl {
> >    char dummy;
> >  };
> >
> > diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
> > index 56f79f6..2843e9d 100644
> > --- a/gcc/c/c-parser.c
> > +++ b/gcc/c/c-parser.c
> > @@ -90,7 +90,7 @@ c_parse_init (void)
> >    if (!c_dialect_objc ())
> >      mask |= D_OBJC | D_CXX_OBJC;
> >
> > -  ridpointers = ggc_alloc_cleared_vec_tree ((int) RID_MAX);
> > +  ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX);
> >    for (i = 0; i < num_c_common_reswords; i++)
> >      {
> >        /* If a keyword is disabled, do not enter it into the table
> > @@ -14039,7 +14039,7 @@ c_parse_file (void)
> >    if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
> >      c_parser_pragma_pch_preprocess (&tparser);
> >
> > -  the_parser = ggc_alloc_c_parser ();
> > +  the_parser = ggc_alloc<c_parser> ();
> >    *the_parser = tparser;
> >    if (tparser.tokens == &tparser.tokens_buf[0])
> >      the_parser->tokens = &the_parser->tokens_buf[0];
> > diff --git a/gcc/cfg.c b/gcc/cfg.c
> > index 3b6349a..aef1145 100644
> > --- a/gcc/cfg.c
> > +++ b/gcc/cfg.c
> > @@ -68,13 +68,13 @@ void
> >  init_flow (struct function *the_fun)
> >  {
> >    if (!the_fun->cfg)
> > -    the_fun->cfg = ggc_alloc_cleared_control_flow_graph ();
> > +    the_fun->cfg = ggc_cleared_alloc<control_flow_graph> ();
> >    n_edges_for_fn (the_fun) = 0;
> >    ENTRY_BLOCK_PTR_FOR_FN (the_fun)
> > -    = ggc_alloc_cleared_basic_block_def ();
> > +    = ggc_cleared_alloc<basic_block_def> ();
> >    ENTRY_BLOCK_PTR_FOR_FN (the_fun)->index = ENTRY_BLOCK;
> >    EXIT_BLOCK_PTR_FOR_FN (the_fun)
> > -    = ggc_alloc_cleared_basic_block_def ();
> > +    = ggc_cleared_alloc<basic_block_def> ();
> >    EXIT_BLOCK_PTR_FOR_FN (the_fun)->index = EXIT_BLOCK;
> >    ENTRY_BLOCK_PTR_FOR_FN (the_fun)->next_bb
> >      = EXIT_BLOCK_PTR_FOR_FN (the_fun);
> > @@ -123,7 +123,7 @@ basic_block
> >  alloc_block (void)
> >  {
> >    basic_block bb;
> > -  bb = ggc_alloc_cleared_basic_block_def ();
> > +  bb = ggc_cleared_alloc<basic_block_def> ();
> >    return bb;
> >  }
> >
> > @@ -261,7 +261,7 @@ edge
> >  unchecked_make_edge (basic_block src, basic_block dst, int flags)
> >  {
> >    edge e;
> > -  e = ggc_alloc_cleared_edge_def ();
> > +  e = ggc_cleared_alloc<edge_def> ();
> >    n_edges_for_fn (cfun)++;
> >
> >    e->src = src;
> > diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
> > index 70744d8..3ff5b6a 100644
> > --- a/gcc/cfgloop.c
> > +++ b/gcc/cfgloop.c
> > @@ -331,9 +331,9 @@ flow_loop_tree_node_remove (struct loop *loop)
> >  struct loop *
> >  alloc_loop (void)
> >  {
> > -  struct loop *loop = ggc_alloc_cleared_loop ();
> > +  struct loop *loop = ggc_cleared_alloc<struct loop> ();
> >
> > -  loop->exits = ggc_alloc_cleared_loop_exit ();
> > +  loop->exits = ggc_cleared_alloc<loop_exit> ();
> >    loop->exits->next = loop->exits->prev = loop->exits;
> >    loop->can_be_parallel = false;
> >
> > @@ -414,7 +414,7 @@ flow_loops_find (struct loops *loops)
> >
> >    if (!loops)
> >      {
> > -      loops = ggc_alloc_cleared_loops ();
> > +      loops = ggc_cleared_alloc<struct loops> ();
> >        init_loops_structure (cfun, loops, 1);
> >      }
> >
> > @@ -1028,7 +1028,7 @@ rescan_loop_exit (edge e, bool new_edge, bool removed)
> >            aloop != cloop;
> >            aloop = loop_outer (aloop))
> >         {
> > -         exit = ggc_alloc_loop_exit ();
> > +         exit = ggc_alloc<loop_exit> ();
> >           exit->e = e;
> >
> >           exit->next = aloop->exits->next;
> > diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
> > index 5dd27d2..06fc43e 100644
> > --- a/gcc/cfgrtl.c
> > +++ b/gcc/cfgrtl.c
> > @@ -4954,7 +4954,7 @@ init_rtl_bb_info (basic_block bb)
> >  {
> >    gcc_assert (!bb->il.x.rtl);
> >    bb->il.x.head_ = NULL;
> > -  bb->il.x.rtl = ggc_alloc_cleared_rtl_bb_info ();
> > +  bb->il.x.rtl = ggc_cleared_alloc<rtl_bb_info> ();
> >  }
> >
> >  /* Returns true if it is possible to remove edge E by redirecting
> > diff --git a/gcc/cgraph.c b/gcc/cgraph.c
> > index ee192ed..f28492e 100644
> > --- a/gcc/cgraph.c
> > +++ b/gcc/cgraph.c
> > @@ -198,7 +198,7 @@ insert_new_cgraph_node_version (struct cgraph_node *node)
> >    void **slot;
> >
> >    version_info_node = NULL;
> > -  version_info_node = ggc_alloc_cleared_cgraph_function_version_info ();
> > +  version_info_node = ggc_cleared_alloc<cgraph_function_version_info> ();
> >    version_info_node->this_node = node;
> >
> >    if (cgraph_fnver_htab == NULL)
> > @@ -507,7 +507,7 @@ cgraph_allocate_node (void)
> >      }
> >    else
> >      {
> > -      node = ggc_alloc_cleared_cgraph_node ();
> > +      node = ggc_cleared_alloc<cgraph_node> ();
> >        node->uid = cgraph_max_uid++;
> >      }
> >
> > @@ -866,7 +866,7 @@ cgraph_create_edge_1 (struct cgraph_node *caller, struct cgraph_node *callee,
> >      }
> >    else
> >      {
> > -      edge = ggc_alloc_cgraph_edge ();
> > +      edge = ggc_alloc<struct cgraph_edge> ();
> >        edge->uid = cgraph_edge_max_uid++;
> >      }
> >
> > @@ -938,7 +938,7 @@ cgraph_allocate_init_indirect_info (void)
> >  {
> >    struct cgraph_indirect_call_info *ii;
> >
> > -  ii = ggc_alloc_cleared_cgraph_indirect_call_info ();
> > +  ii = ggc_cleared_alloc<cgraph_indirect_call_info> ();
> >    ii->param_index = -1;
> >    return ii;
> >  }
> > diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
> > index 48b5379..d61e0f7 100644
> > --- a/gcc/cgraphclones.c
> > +++ b/gcc/cgraphclones.c
> > @@ -146,7 +146,7 @@ cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n,
> >        if (e->indirect_info)
> >         {
> >           new_edge->indirect_info
> > -           = ggc_alloc_cleared_cgraph_indirect_call_info ();
> > +           = ggc_cleared_alloc<cgraph_indirect_call_info> ();
> >           *new_edge->indirect_info = *e->indirect_info;
> >         }
> >      }
> > diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
> > index 7bf9a07..acb9a7a 100644
> > --- a/gcc/cgraphunit.c
> > +++ b/gcc/cgraphunit.c
> > @@ -570,7 +570,7 @@ add_asm_node (tree asm_str)
> >  {
> >    struct asm_node *node;
> >
> > -  node = ggc_alloc_cleared_asm_node ();
> > +  node = ggc_cleared_alloc<asm_node> ();
> >    node->asm_str = asm_str;
> >    node->order = symtab_order++;
> >    node->next = NULL;
> > @@ -1337,7 +1337,7 @@ init_lowered_empty_function (tree decl, bool in_ssa)
> >    cfun->curr_properties |= (PROP_gimple_lcf | PROP_gimple_leh | PROP_gimple_any
> >                             | PROP_cfg | PROP_loops);
> >
> > -  set_loops_for_fn (cfun, ggc_alloc_cleared_loops ());
> > +  set_loops_for_fn (cfun, ggc_cleared_alloc<loops> ());
> >    init_loops_structure (cfun, loops_for_fn (cfun), 1);
> >    loops_for_fn (cfun)->state |= LOOPS_MAY_HAVE_MULTIPLE_LATCHES;
> >
> > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
> > index 895ebbb..848788e 100644
> > --- a/gcc/config/i386/i386.c
> > +++ b/gcc/config/i386/i386.c
> > @@ -13643,7 +13643,7 @@ get_dllimport_decl (tree decl, bool beimport)
> >    if (h)
> >      return h->to;
> >
> > -  *loc = h = ggc_alloc_tree_map ();
> > +  *loc = h = ggc_alloc<tree_map> ();
> >    h->hash = in.hash;
> >    h->base.from = decl;
> >    h->to = to = build_decl (DECL_SOURCE_LOCATION (decl),
> > @@ -24990,7 +24990,7 @@ ix86_init_machine_status (void)
> >  {
> >    struct machine_function *f;
> >
> > -  f = ggc_alloc_cleared_machine_function ();
> > +  f = ggc_cleared_alloc<machine_function> ();
> >    f->use_fast_prologue_epilogue_nregs = -1;
> >    f->call_abi = ix86_abi;
> >
> > @@ -25014,7 +25014,7 @@ assign_386_stack_local (enum machine_mode mode, enum ix86_stack_slot n)
> >      if (s->mode == mode && s->n == n)
> >        return validize_mem (copy_rtx (s->rtl));
> >
> > -  s = ggc_alloc_stack_local_entry ();
> > +  s = ggc_alloc<stack_local_entry> ();
> >    s->n = n;
> >    s->mode = mode;
> >    s->rtl = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
> > diff --git a/gcc/coverage.c b/gcc/coverage.c
> > index ff1e67d..5e9005e 100644
> > --- a/gcc/coverage.c
> > +++ b/gcc/coverage.c
> > @@ -667,7 +667,7 @@ coverage_end_function (unsigned lineno_checksum, unsigned cfg_checksum)
> >          list.  */
> >        if (!DECL_EXTERNAL (current_function_decl))
> >         {
> > -         item = ggc_alloc_coverage_data ();
> > +         item = ggc_alloc<coverage_data> ();
> >
> >           item->ident = current_function_funcdef_no + 1;
> >           item->lineno_checksum = lineno_checksum;
> > diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c
> > index f3a2aff..daa9b8e 100644
> > --- a/gcc/cp/cp-cilkplus.c
> > +++ b/gcc/cp/cp-cilkplus.c
> > @@ -118,7 +118,7 @@ cilk_install_body_with_frame_cleanup (tree fndecl, tree orig_body, void *wd)
> >    tree dtor = create_cilk_function_exit (frame, false, false);
> >    add_local_decl (cfun, frame);
> >
> > -  cfun->language = ggc_alloc_cleared_language_function ();
> > +  cfun->language = ggc_cleared_alloc<language_function> ();
> >
> >    location_t loc = EXPR_LOCATION (orig_body);
> >    tree list = alloc_stmt_list ();
> > diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
> > index aa0ff83..78dddef 100644
> > --- a/gcc/cp/cp-objcp-common.c
> > +++ b/gcc/cp/cp-objcp-common.c
> > @@ -208,7 +208,7 @@ decl_shadowed_for_var_insert (tree from, tree to)
> >    struct tree_decl_map *h;
> >    void **loc;
> >
> > -  h = ggc_alloc_tree_decl_map ();
> > +  h = ggc_alloc<tree_decl_map> ();
> >    h->base.from = from;
> >    h->to = to;
> >    loc = htab_find_slot_with_hash (shadowed_var_for_decl, h, DECL_UID (from),
> > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> > index 9fbc7f8..b76af3c 100644
> > --- a/gcc/cp/cp-tree.h
> > +++ b/gcc/cp/cp-tree.h
> > @@ -1482,7 +1482,7 @@ struct GTY(()) lang_type_ptrmem {
> >    tree record;
> >  };
> >
> > -struct GTY((variable_size)) lang_type {
> > +struct GTY(()) lang_type {
> >    union lang_type_u
> >    {
> >      struct lang_type_header GTY((skip (""))) h;
> > @@ -2060,7 +2060,7 @@ struct GTY(()) lang_decl_parm {
> >     union rather than a struct containing a union as its only field, but
> >     tree.h declares it as a struct.  */
> >
> > -struct GTY((variable_size)) lang_decl {
> > +struct GTY(()) lang_decl {
> >    union GTY((desc ("%h.base.selector"))) lang_decl_u {
> >      struct lang_decl_base GTY ((default)) base;
> >      struct lang_decl_min GTY((tag ("0"))) min;
> > diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> > index 7ce55c8..4ad6f16 100644
> > --- a/gcc/cp/decl.c
> > +++ b/gcc/cp/decl.c
> > @@ -2700,7 +2700,7 @@ make_label_decl (tree id, int local_p)
> >    /* Record this label on the list of labels used in this function.
> >       We do this before calling make_label_decl so that we get the
> >       IDENTIFIER_LABEL_VALUE before the new label is declared.  */
> > -  ent = ggc_alloc_cleared_named_label_entry ();
> > +  ent = ggc_cleared_alloc<named_label_entry> ();
> >    ent->label_decl = decl;
> >
> >    slot = htab_find_slot (named_labels, ent, INSERT);
> > @@ -2931,7 +2931,7 @@ check_goto (tree decl)
> >           && ent->uses->names_in_scope == current_binding_level->names)
> >         return;
> >
> > -      new_use = ggc_alloc_named_label_use_entry ();
> > +      new_use = ggc_alloc<named_label_use_entry> ();
> >        new_use->binding_level = current_binding_level;
> >        new_use->names_in_scope = current_binding_level->names;
> >        new_use->o_goto_locus = input_location;
> > @@ -13301,7 +13301,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
> >
> >    /* Initialize the language data structures.  Whenever we start
> >       a new function, we destroy temporaries in the usual way.  */
> > -  cfun->language = ggc_alloc_cleared_language_function ();
> > +  cfun->language = ggc_cleared_alloc<language_function> ();
> >    current_stmt_tree ()->stmts_are_full_exprs_p = 1;
> >    current_binding_level = bl;
> >
> > @@ -13603,7 +13603,7 @@ save_function_data (tree decl)
> >    gcc_assert (!DECL_PENDING_INLINE_P (decl));
> >
> >    /* Make a copy.  */
> > -  f = ggc_alloc_language_function ();
> > +  f = ggc_alloc<language_function> ();
> >    memcpy (f, cp_function_chain, sizeof (struct language_function));
> >    DECL_SAVED_FUNCTION_DATA (decl) = f;
> >
> > diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
> > index 46c28ae..57b779d 100644
> > --- a/gcc/cp/lex.c
> > +++ b/gcc/cp/lex.c
> > @@ -182,7 +182,7 @@ init_reswords (void)
> >    /* The Objective-C keywords are all context-dependent.  */
> >    mask |= D_OBJC;
> >
> > -  ridpointers = ggc_alloc_cleared_vec_tree ((int) RID_MAX);
> > +  ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX);
> >    for (i = 0; i < num_c_common_reswords; i++)
> >      {
> >        if (c_common_reswords[i].disable & D_CONLY)
> > diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
> > index d900560..2baeeb7 100644
> > --- a/gcc/cp/name-lookup.c
> > +++ b/gcc/cp/name-lookup.c
> > @@ -105,7 +105,7 @@ binding_entry_make (tree name, tree type)
> >        free_binding_entry = entry->chain;
> >      }
> >    else
> > -    entry = ggc_alloc_binding_entry_s ();
> > +    entry = ggc_alloc<binding_entry_s> ();
> >
> >    entry->name = name;
> >    entry->type = type;
> > @@ -147,7 +147,7 @@ binding_table_construct (binding_table table, size_t chain_count)
> >  {
> >    table->chain_count = chain_count;
> >    table->entry_count = 0;
> > -  table->chain = ggc_alloc_cleared_vec_binding_entry (table->chain_count);
> > +  table->chain = ggc_cleared_vec_alloc<binding_entry> (table->chain_count);
> >  }
> >
> >  /* Make TABLE's entries ready for reuse.  */
> > @@ -181,7 +181,7 @@ binding_table_free (binding_table table)
> >  static inline binding_table
> >  binding_table_new (size_t chain_count)
> >  {
> > -  binding_table table = ggc_alloc_binding_table_s ();
> > +  binding_table table = ggc_alloc<binding_table_s> ();
> >    table->chain = NULL;
> >    binding_table_construct (table, chain_count);
> >    return table;
> > @@ -299,7 +299,7 @@ cxx_binding_make (tree value, tree type)
> >        free_bindings = binding->previous;
> >      }
> >    else
> > -    binding = ggc_alloc_cxx_binding ();
> > +    binding = ggc_alloc<cxx_binding> ();
> >
> >    cxx_binding_init (binding, value, type);
> >
> > @@ -775,7 +775,7 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
> >                       = htab_create_ggc (20, cxx_int_tree_map_hash,
> >                                          cxx_int_tree_map_eq, NULL);
> >
> > -                 h = ggc_alloc_cxx_int_tree_map ();
> > +                 h = ggc_alloc<cxx_int_tree_map> ();
> >                   h->uid = DECL_UID (x);
> >                   h->to = t;
> >                   loc = htab_find_slot_with_hash
> > @@ -1544,7 +1544,7 @@ begin_scope (scope_kind kind, tree entity)
> >        free_binding_level = scope->level_chain;
> >      }
> >    else
> > -    scope = ggc_alloc_cleared_cp_binding_level ();
> > +    scope = ggc_cleared_alloc<cp_binding_level> ();
> >
> >    scope->this_entity = entity;
> >    scope->more_cleanups_ok = true;
> > @@ -6074,7 +6074,7 @@ push_to_top_level (void)
> >    bool need_pop;
> >
> >    bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
> > -  s = ggc_alloc_cleared_saved_scope ();
> > +  s = ggc_cleared_alloc<saved_scope> ();
> >
> >    b = scope_chain ? current_binding_level : 0;
> >
> > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
> > index c1d94ae..a2f9355 100644
> > --- a/gcc/cp/parser.c
> > +++ b/gcc/cp/parser.c
> > @@ -602,7 +602,7 @@ cp_lexer_alloc (void)
> >    c_common_no_more_pch ();
> >
> >    /* Allocate the memory.  */
> > -  lexer = ggc_alloc_cleared_cp_lexer ();
> > +  lexer = ggc_cleared_alloc<cp_lexer> ();
> >
> >    /* Initially we are not debugging.  */
> >    lexer->debugging_p = false;
> > @@ -665,7 +665,7 @@ cp_lexer_new_from_tokens (cp_token_cache *cache)
> >  {
> >    cp_token *first = cache->first;
> >    cp_token *last = cache->last;
> > -  cp_lexer *lexer = ggc_alloc_cleared_cp_lexer ();
> > +  cp_lexer *lexer = ggc_cleared_alloc<cp_lexer> ();
> >
> >    /* We do not own the buffer.  */
> >    lexer->buffer = NULL;
> > @@ -1240,7 +1240,7 @@ cp_lexer_stop_debugging (cp_lexer* lexer)
> >  static cp_token_cache *
> >  cp_token_cache_new (cp_token *first, cp_token *last)
> >  {
> > -  cp_token_cache *cache = ggc_alloc_cp_token_cache ();
> > +  cp_token_cache *cache = ggc_alloc<cp_token_cache> ();
> >    cache->first = first;
> >    cache->last = last;
> >    return cache;
> > @@ -1822,7 +1822,7 @@ cp_parser_context_new (cp_parser_context* next)
> >        memset (context, 0, sizeof (*context));
> >      }
> >    else
> > -    context = ggc_alloc_cleared_cp_parser_context ();
> > +    context = ggc_cleared_alloc<cp_parser_context> ();
> >
> >    /* No errors have occurred yet in this context.  */
> >    context->status = CP_PARSER_STATUS_KIND_NO_ERROR;
> > @@ -3411,7 +3411,7 @@ cp_parser_new (void)
> >    for (i = 0; i < sizeof (binops) / sizeof (binops[0]); i++)
> >      binops_by_token[binops[i].token_type] = binops[i];
> >
> > -  parser = ggc_alloc_cleared_cp_parser ();
> > +  parser = ggc_cleared_alloc<cp_parser> ();
> >    parser->lexer = lexer;
> >    parser->context = cp_parser_context_new (NULL);
> >
> > @@ -5425,7 +5425,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
> >        token->type = CPP_NESTED_NAME_SPECIFIER;
> >        /* Retrieve any deferred checks.  Do not pop this access checks yet
> >          so the memory will not be reclaimed during token replacing below.  */
> > -      token->u.tree_check_value = ggc_alloc_cleared_tree_check ();
> > +      token->u.tree_check_value = ggc_cleared_alloc<struct tree_check> ();
> >        token->u.tree_check_value->value = parser->scope;
> >        token->u.tree_check_value->checks = get_deferred_access_checks ();
> >        token->u.tree_check_value->qualifying_scope =
> > @@ -13500,7 +13500,7 @@ cp_parser_template_id (cp_parser *parser,
> >        token->type = CPP_TEMPLATE_ID;
> >        /* Retrieve any deferred checks.  Do not pop this access checks yet
> >          so the memory will not be reclaimed during token replacing below.  */
> > -      token->u.tree_check_value = ggc_alloc_cleared_tree_check ();
> > +      token->u.tree_check_value = ggc_cleared_alloc<struct tree_check> ();
> >        token->u.tree_check_value->value = template_id;
> >        token->u.tree_check_value->checks = get_deferred_access_checks ();
> >        token->keyword = RID_MAX;
> > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> > index c74e7ae..b1e6c14 100644
> > --- a/gcc/cp/pt.c
> > +++ b/gcc/cp/pt.c
> > @@ -940,7 +940,7 @@ maybe_process_partial_specialization (tree type)
> >                   elt.args = INNERMOST_TEMPLATE_ARGS (elt.args);
> >
> >                   slot = htab_find_slot (type_specializations, &elt, INSERT);
> > -                 entry = ggc_alloc_spec_entry ();
> > +                 entry = ggc_alloc<spec_entry> ();
> >                   *entry = elt;
> >                   *slot = entry;
> >                 }
> > @@ -1477,7 +1477,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
> >
> >    if (slot != NULL /* !optimize_specialization_lookup_p (tmpl) */)
> >      {
> > -      spec_entry *entry = ggc_alloc_spec_entry ();
> > +      spec_entry *entry = ggc_alloc<spec_entry> ();
> >        gcc_assert (tmpl && args && spec);
> >        *entry = elt;
> >        *slot = entry;
> > @@ -7177,7 +7177,7 @@ add_pending_template (tree d)
> >    if (level)
> >      push_tinst_level (d);
> >
> > -  pt = ggc_alloc_pending_template ();
> > +  pt = ggc_alloc<pending_template> ();
> >    pt->next = NULL;
> >    pt->tinst = current_tinst_level;
> >    if (last_pending_template)
> > @@ -7807,7 +7807,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
> >        elt.spec = t;
> >        slot = htab_find_slot_with_hash (type_specializations,
> >                                        &elt, hash, INSERT);
> > -      entry = ggc_alloc_spec_entry ();
> > +      entry = ggc_alloc<spec_entry> ();
> >        *entry = elt;
> >        *slot = entry;
> >
> > @@ -8232,7 +8232,7 @@ push_tinst_level (tree d)
> >    if (limit_bad_template_recursion (d))
> >      return 0;
> >
> > -  new_level = ggc_alloc_tinst_level ();
> > +  new_level = ggc_alloc<tinst_level> ();
> >    new_level->decl = d;
> >    new_level->locus = input_location;
> >    new_level->errors = errorcount+sorrycount;
> > diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
> > index 3f8ca44..a8b8dab 100644
> > --- a/gcc/cp/semantics.c
> > +++ b/gcc/cp/semantics.c
> > @@ -8024,7 +8024,7 @@ register_constexpr_fundef (tree fun, tree body)
> >      htab_find_slot (constexpr_fundef_table, &entry, INSERT);
> >
> >    gcc_assert (*slot == NULL);
> > -  *slot = ggc_alloc_constexpr_fundef ();
> > +  *slot = ggc_alloc<constexpr_fundef> ();
> >    **slot = entry;
> >
> >    return fun;
> > @@ -8465,7 +8465,7 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
> >      {
> >        /* We need to keep a pointer to the entry, not just the slot, as the
> >          slot can move in the call to cxx_eval_builtin_function_call.  */
> > -      *slot = entry = ggc_alloc_constexpr_call ();
> > +      *slot = entry = ggc_alloc<constexpr_call> ();
> >        *entry = new_call;
> >      }
> >    /* Calls which are in progress have their result set to NULL
> > diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
> > index 68e518a..b7fa77b 100644
> > --- a/gcc/cp/typeck2.c
> > +++ b/gcc/cp/typeck2.c
> > @@ -293,7 +293,7 @@ abstract_virtuals_error_sfinae (tree decl, tree type, abstract_class_use use,
> >        slot = htab_find_slot_with_hash (abstract_pending_vars, type,
> >                                       (hashval_t)TYPE_UID (type), INSERT);
> >
> > -      pat = ggc_alloc_pending_abstract_type ();
> > +      pat = ggc_alloc<pending_abstract_type> ();
> >        pat->type = type;
> >        pat->decl = decl;
> >        pat->use = use;
> > diff --git a/gcc/dbxout.c b/gcc/dbxout.c
> > index 5fbbdf6..0fe9bfe 100644
> > --- a/gcc/dbxout.c
> > +++ b/gcc/dbxout.c
> > @@ -1025,7 +1025,7 @@ dbxout_init (const char *input_file_name)
> >    const char *mapped_name;
> >
> >    typevec_len = 100;
> > -  typevec = ggc_alloc_cleared_vec_typeinfo (typevec_len);
> > +  typevec = ggc_cleared_vec_alloc<typeinfo> (typevec_len);
> >
> >    /* stabstr_ob contains one string, which will be just fine with
> >       1-byte alignment.  */
> > diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi
> > index d32ac00..e50eef6 100644
> > --- a/gcc/doc/gty.texi
> > +++ b/gcc/doc/gty.texi
> > @@ -382,38 +382,6 @@ of pointers.  @code{reorder} functions can be expensive.  When
> >  possible, it is better to depend on properties of the data, like an ID
> >  number or the hash of a string instead.
> >
> > -@findex variable_size
> > -@item variable_size
> > -
> > -The type machinery expects the types to be of constant size.  When this
> > -is not true, for example, with structs that have array fields or unions,
> > -the type machinery cannot tell how many bytes need to be allocated at
> > -each allocation.  The @code{variable_size} is used to mark such types.
> > -The type machinery then provides allocators that take a parameter
> > -indicating an exact size of object being allocated.  Note that the size
> > -must be provided in bytes whereas the @code{length} option works with
> > -array lengths in number of elements.
> > -
> > -For example,
> > -@smallexample
> > -struct GTY((variable_size)) sorted_fields_type @{
> > -  int len;
> > -  tree GTY((length ("%h.len"))) elts[1];
> > -@};
> > -@end smallexample
> > -
> > -Then the objects of @code{struct sorted_fields_type} are allocated in GC
> > -memory as follows:
> > -@smallexample
> > -  field_vec = ggc_alloc_sorted_fields_type (size);
> > -@end smallexample
> > -
> > -If @var{field_vec->elts} stores @var{n} elements, then @var{size}
> > -could be calculated as follows:
> > -@smallexample
> > -  size_t size = sizeof (struct sorted_fields_type) + n * sizeof (tree);
> > -@end smallexample
> > -
> >  @findex atomic
> >  @item atomic
> >
> > diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
> > index 4180890..47fd028 100644
> > --- a/gcc/dwarf2cfi.c
> > +++ b/gcc/dwarf2cfi.c
> > @@ -356,7 +356,7 @@ need_data_align_sf_opcode (HOST_WIDE_INT off)
> >  static inline dw_cfi_ref
> >  new_cfi (void)
> >  {
> > -  dw_cfi_ref cfi = ggc_alloc_dw_cfi_node ();
> > +  dw_cfi_ref cfi = ggc_alloc<dw_cfi_node> ();
> >
> >    cfi->dw_cfi_oprnd1.dw_cfi_reg_num = 0;
> >    cfi->dw_cfi_oprnd2.dw_cfi_reg_num = 0;
> > @@ -369,7 +369,7 @@ new_cfi (void)
> >  static dw_cfi_row *
> >  new_cfi_row (void)
> >  {
> > -  dw_cfi_row *row = ggc_alloc_cleared_dw_cfi_row ();
> > +  dw_cfi_row *row = ggc_cleared_alloc<dw_cfi_row> ();
> >
> >    row->cfa.reg = INVALID_REGNUM;
> >
> > @@ -381,7 +381,7 @@ new_cfi_row (void)
> >  static dw_cfi_row *
> >  copy_cfi_row (dw_cfi_row *src)
> >  {
> > -  dw_cfi_row *dst = ggc_alloc_dw_cfi_row ();
> > +  dw_cfi_row *dst = ggc_alloc<dw_cfi_row> ();
> >
> >    *dst = *src;
> >    dst->reg_save = vec_safe_copy (src->reg_save);
> > @@ -2892,7 +2892,7 @@ create_cie_data (void)
> >         case 0:
> >           break;
> >         case 1:
> > -         cie_return_save = ggc_alloc_reg_saved_in_data ();
> > +         cie_return_save = ggc_alloc<reg_saved_in_data> ();
> >           *cie_return_save = cie_trace.regs_saved_in_regs[0];
> >           cie_trace.regs_saved_in_regs.release ();
> >           break;
> > diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
> > index 6133fa3..9e99e46 100644
> > --- a/gcc/dwarf2out.c
> > +++ b/gcc/dwarf2out.c
> > @@ -982,7 +982,7 @@ dwarf2out_alloc_current_fde (void)
> >  {
> >    dw_fde_ref fde;
> >
> > -  fde = ggc_alloc_cleared_dw_fde_node ();
> > +  fde = ggc_cleared_alloc<dw_fde_node> ();
> >    fde->decl = current_function_decl;
> >    fde->funcdef_number = current_function_funcdef_no;
> >    fde->fde_index = vec_safe_length (fde_vec);
> > @@ -1305,7 +1305,7 @@ static inline dw_loc_descr_ref
> >  new_loc_descr (enum dwarf_location_atom op, unsigned HOST_WIDE_INT oprnd1,
> >                unsigned HOST_WIDE_INT oprnd2)
> >  {
> > -  dw_loc_descr_ref descr = ggc_alloc_cleared_dw_loc_descr_node ();
> > +  dw_loc_descr_ref descr = ggc_cleared_alloc<dw_loc_descr_node> ();
> >
> >    descr->dw_loc_opc = op;
> >    descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const;
> > @@ -3872,7 +3872,7 @@ find_AT_string_in_table (const char *str, htab_t table)
> >                                    htab_hash_string (str), INSERT);
> >    if (*slot == NULL)
> >      {
> > -      node = ggc_alloc_cleared_indirect_string_node ();
> > +      node = ggc_cleared_alloc<indirect_string_node> ();
> >        node->str = ggc_strdup (str);
> >        *slot = node;
> >      }
> > @@ -4203,7 +4203,7 @@ add_addr_table_entry (void *addr, enum ate_kind kind)
> >
> >    if (*slot == HTAB_EMPTY_ENTRY)
> >      {
> > -      node = ggc_alloc_cleared_addr_table_entry ();
> > +      node = ggc_cleared_alloc<addr_table_entry> ();
> >        init_addr_table_entry (node, kind, addr);
> >        *slot = node;
> >      }
> > @@ -4779,7 +4779,7 @@ splice_child_die (dw_die_ref parent, dw_die_ref child)
> >  static inline dw_die_ref
> >  new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
> >  {
> > -  dw_die_ref die = ggc_alloc_cleared_die_node ();
> > +  dw_die_ref die = ggc_cleared_alloc<die_node> ();
> >
> >    die->die_tag = tag_value;
> >
> > @@ -4789,7 +4789,7 @@ new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
> >      {
> >        limbo_die_node *limbo_node;
> >
> > -      limbo_node = ggc_alloc_cleared_limbo_die_node ();
> > +      limbo_node = ggc_cleared_alloc<limbo_die_node> ();
> >        limbo_node->die = die;
> >        limbo_node->created_for = t;
> >        limbo_node->next = limbo_die_list;
> > @@ -5106,7 +5106,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
> >    slot = htab_find_slot_with_hash (decl_loc_table, decl, decl_id, INSERT);
> >    if (*slot == NULL)
> >      {
> > -      temp = ggc_alloc_cleared_var_loc_list ();
> > +      temp = ggc_cleared_alloc<var_loc_list> ();
> >        temp->decl_id = decl_id;
> >        *slot = temp;
> >      }
> > @@ -5131,7 +5131,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
> >           || (NOTE_VAR_LOCATION_STATUS (temp->first->loc)
> >               != NOTE_VAR_LOCATION_STATUS (loc_note))))
> >      {
> > -      loc = ggc_alloc_cleared_var_loc_node ();
> > +      loc = ggc_cleared_alloc<var_loc_node> ();
> >        temp->first->next = loc;
> >        temp->last = loc;
> >        loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
> > @@ -5221,7 +5221,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
> >               memset (loc, '\0', sizeof (*loc));
> >             }
> >           else
> > -           loc = ggc_alloc_cleared_var_loc_node ();
> > +           loc = ggc_cleared_alloc<var_loc_node> ();
> >           if (bitsize == -1 || piece_loc == NULL)
> >             loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
> >           else
> > @@ -5238,7 +5238,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
> >      }
> >    else
> >      {
> > -      loc = ggc_alloc_cleared_var_loc_node ();
> > +      loc = ggc_cleared_alloc<var_loc_node> ();
> >        temp->first = loc;
> >        temp->last = loc;
> >        loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
> > @@ -6868,7 +6868,7 @@ clone_die (dw_die_ref die)
> >    dw_attr_ref a;
> >    unsigned ix;
> >
> > -  clone = ggc_alloc_cleared_die_node ();
> > +  clone = ggc_cleared_alloc<die_node> ();
> >    clone->die_tag = die->die_tag;
> >
> >    FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
> > @@ -6914,7 +6914,7 @@ clone_as_declaration (dw_die_ref die)
> >        return clone;
> >      }
> >
> > -  clone = ggc_alloc_cleared_die_node ();
> > +  clone = ggc_cleared_alloc<die_node> ();
> >    clone->die_tag = die->die_tag;
> >
> >    FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
> > @@ -7274,7 +7274,7 @@ break_out_comdat_types (dw_die_ref die)
> >          unit = new_die (DW_TAG_type_unit, NULL, NULL);
> >          add_AT_unsigned (unit, DW_AT_language,
> >                           get_AT_unsigned (comp_unit_die (), DW_AT_language));
> > -        type_node = ggc_alloc_cleared_comdat_type_node ();
> > +        type_node = ggc_cleared_alloc<comdat_type_node> ();
> >          type_node->root_die = unit;
> >          type_node->next = comdat_type_list;
> >          comdat_type_list = type_node;
> > @@ -8347,7 +8347,7 @@ static inline dw_loc_list_ref
> >  new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end,
> >               const char *section)
> >  {
> > -  dw_loc_list_ref retlist = ggc_alloc_cleared_dw_loc_list_node ();
> > +  dw_loc_list_ref retlist = ggc_cleared_alloc<dw_loc_list_node> ();
> >
> >    retlist->begin = begin;
> >    retlist->begin_entry = NULL;
> > @@ -13891,12 +13891,12 @@ add_loc_descr_to_each (dw_loc_list_ref list, dw_loc_descr_ref ref)
> >    list = list->dw_loc_next;
> >    while (list)
> >      {
> > -      copy = ggc_alloc_dw_loc_descr_node ();
> > +      copy = ggc_alloc<dw_loc_descr_node> ();
> >        memcpy (copy, ref, sizeof (dw_loc_descr_node));
> >        add_loc_descr (&list->expr, copy);
> >        while (copy->dw_loc_next)
> >         {
> > -         dw_loc_descr_ref new_copy = ggc_alloc_dw_loc_descr_node ();
> > +         dw_loc_descr_ref new_copy = ggc_alloc<dw_loc_descr_node> ();
> >           memcpy (new_copy, copy->dw_loc_next, sizeof (dw_loc_descr_node));
> >           copy->dw_loc_next = new_copy;
> >           copy = new_copy;
> > @@ -15678,7 +15678,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
> >         {
> >           slot = htab_find_slot_with_hash (cached_dw_loc_list_table, decl,
> >                                            DECL_UID (decl), INSERT);
> > -         cache = ggc_alloc_cleared_cached_dw_loc_list ();
> > +         cache = ggc_cleared_alloc<cached_dw_loc_list> ();
> >           cache->decl_id = DECL_UID (decl);
> >           cache->loc_list = list;
> >           *slot = cache;
> > @@ -16639,7 +16639,7 @@ add_linkage_name (dw_die_ref die, tree decl)
> >         {
> >           limbo_die_node *asm_name;
> >
> > -         asm_name = ggc_alloc_cleared_limbo_die_node ();
> > +         asm_name = ggc_cleared_alloc<limbo_die_node> ();
> >           asm_name->die = die;
> >           asm_name->created_for = decl;
> >           asm_name->next = deferred_asm_name;
> > @@ -20968,7 +20968,7 @@ lookup_filename (const char *file_name)
> >    if (*slot)
> >      return (struct dwarf_file_data *) *slot;
> >
> > -  created = ggc_alloc_dwarf_file_data ();
> > +  created = ggc_alloc<dwarf_file_data> ();
> >    created->filename = file_name;
> >    created->emitted_number = 0;
> >    *slot = created;
> > @@ -21278,7 +21278,7 @@ dwarf2out_var_location (rtx loc_note)
> >    if (!var_loc_p)
> >      {
> >        struct call_arg_loc_node *ca_loc
> > -       = ggc_alloc_cleared_call_arg_loc_node ();
> > +       = ggc_cleared_alloc<call_arg_loc_node> ();
> >        rtx prev = prev_real_insn (loc_note), x;
> >        ca_loc->call_arg_loc_note = loc_note;
> >        ca_loc->next = NULL;
> > @@ -21353,7 +21353,7 @@ new_line_info_table (void)
> >  {
> >    dw_line_info_table *table;
> >
> > -  table = ggc_alloc_cleared_dw_line_info_table_struct ();
> > +  table = ggc_cleared_alloc<dw_line_info_table_struct> ();
> >    table->file_num = 1;
> >    table->line_num = 1;
> >    table->is_stmt = DWARF_LINE_DEFAULT_IS_STMT_START;
> > @@ -22122,7 +22122,7 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
> >    vec_alloc (decl_scope_table, 256);
> >
> >    /* Allocate the initial hunk of the abbrev_die_table.  */
> > -  abbrev_die_table = ggc_alloc_cleared_vec_dw_die_ref
> > +  abbrev_die_table = ggc_cleared_vec_alloc<dw_die_ref>
> >      (ABBREV_DIE_TABLE_INCREMENT);
> >    abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT;
> >    /* Zero-th entry is allocated, but unused.  */
> > diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
> > index e3fd0a5..2b64a9f 100644
> > --- a/gcc/emit-rtl.c
> > +++ b/gcc/emit-rtl.c
> > @@ -275,7 +275,7 @@ set_mem_attrs (rtx mem, mem_attrs *attrs)
> >    if (!MEM_ATTRS (mem)
> >        || !mem_attrs_eq_p (attrs, MEM_ATTRS (mem)))
> >      {
> > -      MEM_ATTRS (mem) = ggc_alloc_mem_attrs ();
> > +      MEM_ATTRS (mem) = ggc_alloc<mem_attrs> ();
> >        memcpy (MEM_ATTRS (mem), attrs, sizeof (mem_attrs));
> >      }
> >  }
> > @@ -322,7 +322,7 @@ get_reg_attrs (tree decl, int offset)
> >    slot = htab_find_slot (reg_attrs_htab, &attrs, INSERT);
> >    if (*slot == 0)
> >      {
> > -      *slot = ggc_alloc_reg_attrs ();
> > +      *slot = ggc_alloc<reg_attrs> ();
> >        memcpy (*slot, &attrs, sizeof (reg_attrs));
> >      }
> >
> > @@ -5123,7 +5123,7 @@ start_sequence (void)
> >        free_sequence_stack = tem->next;
> >      }
> >    else
> > -    tem = ggc_alloc_sequence_stack ();
> > +    tem = ggc_alloc<sequence_stack> ();
> >
> >    tem->next = seq_stack;
> >    tem->first = get_insns ();
> > @@ -5456,7 +5456,7 @@ init_emit (void)
> >    crtl->emit.regno_pointer_align
> >      = XCNEWVEC (unsigned char, crtl->emit.regno_pointer_align_length);
> >
> > -  regno_reg_rtx = ggc_alloc_vec_rtx (crtl->emit.regno_pointer_align_length);
> > +  regno_reg_rtx = ggc_vec_alloc<rtx> (crtl->emit.regno_pointer_align_length);
> >
> >    /* Put copies of all the hard registers into regno_reg_rtx.  */
> >    memcpy (regno_reg_rtx,
> > @@ -5606,7 +5606,7 @@ init_emit_regs (void)
> >    for (i = 0; i < (int) MAX_MACHINE_MODE; i++)
> >      {
> >        mode = (enum machine_mode) i;
> > -      attrs = ggc_alloc_cleared_mem_attrs ();
> > +      attrs = ggc_cleared_alloc<mem_attrs> ();
> >        attrs->align = BITS_PER_UNIT;
> >        attrs->addrspace = ADDR_SPACE_GENERIC;
> >        if (mode != BLKmode)
> > diff --git a/gcc/except.c b/gcc/except.c
> > index 5b33c9c..3da0003 100644
> > --- a/gcc/except.c
> > +++ b/gcc/except.c
> > @@ -333,7 +333,7 @@ init_eh (void)
> >  void
> >  init_eh_for_function (void)
> >  {
> > -  cfun->eh = ggc_alloc_cleared_eh_status ();
> > +  cfun->eh = ggc_cleared_alloc<eh_status> ();
> >
> >    /* Make sure zero'th entries are used.  */
> >    vec_safe_push (cfun->eh->region_array, (eh_region)0);
> > @@ -350,7 +350,7 @@ gen_eh_region (enum eh_region_type type, eh_region outer)
> >    eh_region new_eh;
> >
> >    /* Insert a new blank region as a leaf in the tree.  */
> > -  new_eh = ggc_alloc_cleared_eh_region_d ();
> > +  new_eh = ggc_cleared_alloc<eh_region_d> ();
> >    new_eh->type = type;
> >    new_eh->outer = outer;
> >    if (outer)
> > @@ -407,7 +407,7 @@ gen_eh_region_catch (eh_region t, tree type_or_list)
> >         add_type_for_runtime (TREE_VALUE (type_node));
> >      }
> >
> > -  c = ggc_alloc_cleared_eh_catch_d ();
> > +  c = ggc_cleared_alloc<eh_catch_d> ();
> >    c->type_list = type_list;
> >    l = t->u.eh_try.last_catch;
> >    c->prev_catch = l;
> > @@ -441,7 +441,7 @@ gen_eh_region_must_not_throw (eh_region outer)
> >  eh_landing_pad
> >  gen_eh_landing_pad (eh_region region)
> >  {
> > -  eh_landing_pad lp = ggc_alloc_cleared_eh_landing_pad_d ();
> > +  eh_landing_pad lp = ggc_cleared_alloc<eh_landing_pad_d> ();
> >
> >    lp->next_lp = region->landing_pads;
> >    lp->region = region;
> > @@ -2451,7 +2451,7 @@ add_call_site (rtx landing_pad, int action, int section)
> >  {
> >    call_site_record record;
> >
> > -  record = ggc_alloc_call_site_record_d ();
> > +  record = ggc_alloc<call_site_record_d> ();
> >    record->landing_pad = landing_pad;
> >    record->action = action;
> >
> > diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
> > index e25e92a..adee07c 100644
> > --- a/gcc/fortran/f95-lang.c
> > +++ b/gcc/fortran/f95-lang.c
> > @@ -323,7 +323,7 @@ getdecls (void)
> >  void
> >  pushlevel (void)
> >  {
> > -  struct binding_level *newlevel = ggc_alloc_binding_level ();
> > +  struct binding_level *newlevel = ggc_alloc<binding_level> ();
> >
> >    *newlevel = clear_binding_level;
> >
> > diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
> > index beb99a6..a8882e7 100644
> > --- a/gcc/fortran/trans-decl.c
> > +++ b/gcc/fortran/trans-decl.c
> > @@ -615,9 +615,7 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
> >  void
> >  gfc_allocate_lang_decl (tree decl)
> >  {
> > -  DECL_LANG_SPECIFIC (decl)
> > -    = (struct lang_decl *) ggc_internal_cleared_alloc (sizeof
> > -                                                      (struct lang_decl));
> > +  DECL_LANG_SPECIFIC (decl) = ggc_cleared_alloc<struct lang_decl> ();
> >  }
> >
> >  /* Remember a symbol to generate initialization/cleanup code at function
> > @@ -4119,7 +4117,7 @@ gfc_find_module (const char *name)
> >                                    htab_hash_string (name), INSERT);
> >    if (*slot == NULL)
> >      {
> > -      struct module_htab_entry *entry = ggc_alloc_cleared_module_htab_entry ();
> > +      module_htab_entry *entry = ggc_cleared_alloc<module_htab_entry> ();
> >
> >        entry->name = gfc_get_string (name);
> >        entry->decls = htab_create_ggc (10, module_htab_decls_hash,
> > diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
> > index 84503ce..ab3d601 100644
> > --- a/gcc/fortran/trans-types.c
> > +++ b/gcc/fortran/trans-types.c
> > @@ -1511,9 +1511,7 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, gfc_packed packed,
> >      type = build_variant_type_copy (etype);
> >
> >    GFC_ARRAY_TYPE_P (type) = 1;
> > -  TYPE_LANG_SPECIFIC (type)
> > -      = (struct lang_type *) ggc_internal_cleared_alloc
> > -      (sizeof (struct lang_type));
> > +  TYPE_LANG_SPECIFIC (type) = ggc_cleared_alloc<struct lang_type> ();
> >
> >    known_stride = (packed != PACKED_NO);
> >    known_offset = 1;
> > @@ -1815,9 +1813,7 @@ gfc_get_array_type_bounds (tree etype, int dimen, int codimen, tree * lbound,
> >    TYPE_NAMELESS (fat_type) = 1;
> >
> >    GFC_DESCRIPTOR_TYPE_P (fat_type) = 1;
> > -  TYPE_LANG_SPECIFIC (fat_type)
> > -    = (struct lang_type *) ggc_internal_cleared_alloc
> > -    (sizeof (struct lang_type));
> > +  TYPE_LANG_SPECIFIC (fat_type) = ggc_cleared_alloc<struct lang_type> ();
> >
> >    GFC_TYPE_ARRAY_RANK (fat_type) = dimen;
> >    GFC_TYPE_ARRAY_CORANK (fat_type) = codimen;
> > @@ -1991,9 +1987,7 @@ gfc_nonrestricted_type (tree t)
> >      return t;
> >
> >    if (!TYPE_LANG_SPECIFIC (t))
> > -    TYPE_LANG_SPECIFIC (t)
> > -      = (struct lang_type *) ggc_internal_cleared_alloc
> > -      (sizeof (struct lang_type));
> > +    TYPE_LANG_SPECIFIC (t) = ggc_cleared_alloc<struct lang_type> ();
> >    /* If we're dealing with this very node already further up
> >       the call chain (recursion via pointers and struct members)
> >       we haven't yet determined if we really need a new type node.
> > @@ -2045,8 +2039,7 @@ gfc_nonrestricted_type (tree t)
> >                   if (dataptr_type != GFC_TYPE_ARRAY_DATAPTR_TYPE (t))
> >                     {
> >                       TYPE_LANG_SPECIFIC (ret)
> > -                       = (struct lang_type *) ggc_internal_cleared_alloc
> > -                       (sizeof (struct lang_type));
> > +                       = ggc_cleared_alloc<struct lang_type> ();
> >                       *TYPE_LANG_SPECIFIC (ret) = *TYPE_LANG_SPECIFIC (t);
> >                       GFC_TYPE_ARRAY_DATAPTR_TYPE (ret) = dataptr_type;
> >                     }
> > diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
> > index f8d29ec..0345ca0 100644
> > --- a/gcc/fortran/trans.h
> > +++ b/gcc/fortran/trans.h
> > @@ -792,10 +792,7 @@ enum gfc_array_kind
> >  };
> >
> >  /* Array types only.  */
> > -/* FIXME: the variable_size annotation here is needed because these types are
> > -   variable-sized in some other frontends.  Due to gengtype deficiency the GTY
> > -   options of such types have to agree across all frontends. */
> > -struct GTY((variable_size))    lang_type        {
> > +struct GTY(()) lang_type        {
> >    int rank, corank;
> >    enum gfc_array_kind akind;
> >    tree lbound[GFC_MAX_DIMENSIONS];
> > @@ -812,7 +809,7 @@ struct GTY((variable_size)) lang_type        {
> >    tree caf_offset;
> >  };
> >
> > -struct GTY((variable_size)) lang_decl {
> > +struct GTY(()) lang_decl {
> >    /* Dummy variables.  */
> >    tree saved_descriptor;
> >    /* Assigned integer nodes.  Stringlength is the IO format string's length.
> > diff --git a/gcc/function.c b/gcc/function.c
> > index 383a52a..4ebc255 100644
> > --- a/gcc/function.c
> > +++ b/gcc/function.c
> > @@ -306,7 +306,7 @@ try_fit_stack_local (HOST_WIDE_INT start, HOST_WIDE_INT length,
> >  static void
> >  add_frame_space (HOST_WIDE_INT start, HOST_WIDE_INT end)
> >  {
> > -  struct frame_space *space = ggc_alloc_frame_space ();
> > +  struct frame_space *space = ggc_alloc<frame_space> ();
> >    space->next = crtl->frame_space_list;
> >    crtl->frame_space_list = space;
> >    space->start = start;
> > @@ -654,7 +654,7 @@ static void
> >  insert_temp_slot_address (rtx address, struct temp_slot *temp_slot)
> >  {
> >    void **slot;
> > -  struct temp_slot_address_entry *t = ggc_alloc_temp_slot_address_entry ();
> > +  struct temp_slot_address_entry *t = ggc_alloc<temp_slot_address_entry> ();
> >    t->address = address;
> >    t->temp_slot = temp_slot;
> >    t->hash = temp_slot_address_compute_hash (t);
> > @@ -801,7 +801,7 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
> >
> >           if (best_p->size - rounded_size >= alignment)
> >             {
> > -             p = ggc_alloc_temp_slot ();
> > +             p = ggc_alloc<temp_slot> ();
> >               p->in_use = 0;
> >               p->size = best_p->size - rounded_size;
> >               p->base_offset = best_p->base_offset + rounded_size;
> > @@ -825,7 +825,7 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
> >      {
> >        HOST_WIDE_INT frame_offset_old = frame_offset;
> >
> > -      p = ggc_alloc_temp_slot ();
> > +      p = ggc_alloc<temp_slot> ();
> >
> >        /* We are passing an explicit alignment request to assign_stack_local.
> >          One side effect of that is assign_stack_local will not round SIZE
> > @@ -1253,10 +1253,10 @@ get_hard_reg_initial_val (enum machine_mode mode, unsigned int regno)
> >    ivs = crtl->hard_reg_initial_vals;
> >    if (ivs == 0)
> >      {
> > -      ivs = ggc_alloc_initial_value_struct ();
> > +      ivs = ggc_alloc<initial_value_struct> ();
> >        ivs->num_entries = 0;
> >        ivs->max_entries = 5;
> > -      ivs->entries = ggc_alloc_vec_initial_value_pair (5);
> > +      ivs->entries = ggc_vec_alloc<initial_value_pair> (5);
> >        crtl->hard_reg_initial_vals = ivs;
> >      }
> >
> > @@ -4498,7 +4498,7 @@ allocate_struct_function (tree fndecl, bool abstract_p)
> >  {
> >    tree fntype = fndecl ? TREE_TYPE (fndecl) : NULL_TREE;
> >
> > -  cfun = ggc_alloc_cleared_function ();
> > +  cfun = ggc_cleared_alloc<function> ();
> >
> >    init_eh_for_function ();
> >
> > @@ -4572,7 +4572,7 @@ prepare_function_start (void)
> >
> >    if (flag_stack_usage_info)
> >      {
> > -      cfun->su = ggc_alloc_cleared_stack_usage ();
> > +      cfun->su = ggc_cleared_alloc<stack_usage> ();
> >        cfun->su->static_stack_size = -1;
> >      }
> >
> > @@ -6936,7 +6936,7 @@ types_used_by_var_decl_insert (tree type, tree var_decl)
> >        if (*slot == NULL)
> >         {
> >           struct types_used_by_vars_entry *entry;
> > -         entry = ggc_alloc_types_used_by_vars_entry ();
> > +         entry = ggc_alloc<types_used_by_vars_entry> ();
> >           entry->type = type;
> >           entry->var_decl = var_decl;
> >           *slot = entry;
> > diff --git a/gcc/gengtype.c b/gcc/gengtype.c
> > index b3c966c..d85300b 100644
> > --- a/gcc/gengtype.c
> > +++ b/gcc/gengtype.c
> > @@ -4938,133 +4938,6 @@ write_roots (pair_p variables, bool emit_pch)
> >                      "gt_pch_scalar_rtab");
> >  }
> >
> > -/* TRUE if type S has the GTY variable_size annotation.  */
> > -
> > -static bool
> > -variable_size_p (const type_p s)
> > -{
> > -  options_p o;
> > -  for (o = s->u.s.opt; o; o = o->next)
> > -    if (strcmp (o->name, "variable_size") == 0)
> > -      return true;
> > -  return false;
> > -}
> > -
> > -enum alloc_quantity
> > -{ single, vector };
> > -
> > -/* Writes one typed allocator definition into output F for type
> > -   identifier TYPE_NAME with optional type specifier TYPE_SPECIFIER.
> > -   The allocator name will contain ALLOCATOR_TYPE.  If VARIABLE_SIZE
> > -   is true, the allocator will have an extra parameter specifying
> > -   number of bytes to allocate.  If QUANTITY is set to VECTOR, a
> > -   vector allocator will be output.  */
> > -
> > -static void
> > -write_typed_alloc_def (outf_p f,
> > -                       bool variable_size, const char *type_specifier,
> > -                       const char *type_name, const char *allocator_type,
> > -                       enum alloc_quantity quantity)
> > -{
> > -  bool two_args = variable_size && (quantity == vector);
> > -  if (variable_size)
> > -    return;
> > -
> > -  gcc_assert (f != NULL);
> > -  const char *type_name_as_id = filter_type_name (type_name);
> > -  oprintf (f, "#define ggc_alloc_%s%s", allocator_type, type_name_as_id);
> > -  oprintf (f, "(%s%s%s) ",
> > -          (variable_size ? "SIZE" : ""),
> > -          (two_args ? ", " : ""),
> > -          (quantity == vector) ? "n" : "");
> > -  oprintf (f, "((%s%s *)", type_specifier, type_name);
> > -  oprintf (f, "(ggc_internal_%salloc (", allocator_type);
> > -  if (variable_size)
> > -    oprintf (f, "SIZE");
> > -  else
> > -    oprintf (f, "sizeof (%s%s)", type_specifier, type_name);
> > -  if (quantity == vector)
> > -    oprintf (f, ", n");
> > -  oprintf (f, " MEM_STAT_INFO)))\n");
> > -  if (type_name_as_id != type_name)
> > -    free (CONST_CAST (char *, type_name_as_id));
> > -}
> > -
> > -/* Writes a typed allocator definition into output F for a struct or
> > -   union S, with a given ALLOCATOR_TYPE and QUANTITY for ZONE.  */
> > -
> > -static void
> > -write_typed_struct_alloc_def (outf_p f,
> > -                             const type_p s, const char *allocator_type,
> > -                             enum alloc_quantity quantity)
> > -{
> > -  gcc_assert (union_or_struct_p (s));
> > -  write_typed_alloc_def (f, variable_size_p (s), get_type_specifier (s),
> > -                         s->u.s.tag, allocator_type, quantity);
> > -}
> > -
> > -/* Writes a typed allocator definition into output F for a typedef P,
> > -   with a given ALLOCATOR_TYPE and QUANTITY for ZONE.  */
> > -
> > -static void
> > -write_typed_typedef_alloc_def (outf_p f,
> > -                               const pair_p p, const char *allocator_type,
> > -                               enum alloc_quantity quantity)
> > -{
> > -  write_typed_alloc_def (f, variable_size_p (p->type), "", p->name,
> > -                         allocator_type, quantity);
> > -}
> > -
> > -/* Writes typed allocator definitions into output F for the types in
> > -   STRUCTURES and TYPEDEFS that are used by GC.  */
> > -
> > -static void
> > -write_typed_alloc_defns (outf_p f,
> > -                         const type_p structures, const pair_p typedefs)
> > -{
> > -  type_p s;
> > -  pair_p p;
> > -
> > -  gcc_assert (f != NULL);
> > -  oprintf (f,
> > -          "\n/* Allocators for known structs and unions.  */\n\n");
> > -  for (s = structures; s; s = s->next)
> > -    {
> > -      if (!USED_BY_TYPED_GC_P (s))
> > -       continue;
> > -      gcc_assert (union_or_struct_p (s));
> > -      /* In plugin mode onput output ggc_alloc macro definitions
> > -        relevant to plugin input files.  */
> > -      if (nb_plugin_files > 0
> > -         && ((s->u.s.line.file == NULL) || !s->u.s.line.file->inpisplugin))
> > -       continue;
> > -      write_typed_struct_alloc_def (f, s, "", single);
> > -      write_typed_struct_alloc_def (f, s, "cleared_", single);
> > -      write_typed_struct_alloc_def (f, s, "vec_", vector);
> > -      write_typed_struct_alloc_def (f, s, "cleared_vec_", vector);
> > -    }
> > -
> > -  oprintf (f, "\n/* Allocators for known typedefs.  */\n");
> > -  for (p = typedefs; p; p = p->next)
> > -    {
> > -      s = p->type;
> > -      if (!USED_BY_TYPED_GC_P (s) || (strcmp (p->name, s->u.s.tag) == 0))
> > -       continue;
> > -      /* In plugin mode onput output ggc_alloc macro definitions
> > -        relevant to plugin input files.  */
> > -      if (nb_plugin_files > 0)
> > -       {
> > -         struct fileloc* filoc = type_fileloc (s);
> > -         if (!filoc || !filoc->file->inpisplugin)
> > -           continue;
> > -       };
> > -      write_typed_typedef_alloc_def (f, p, "", single);
> > -      write_typed_typedef_alloc_def (f, p, "cleared_", single);
> > -      write_typed_typedef_alloc_def (f, p, "vec_", vector);
> > -      write_typed_typedef_alloc_def (f, p, "cleared_vec_", vector);
> > -    }
> > -}
> > -
> >  /* Prints not-as-ugly version of a typename of T to OF.  Trades the uniquness
> >     guaranteee for somewhat increased readability.  If name conflicts do happen,
> >     this funcion will have to be adjusted to be more like
> > @@ -5775,7 +5648,6 @@ main (int argc, char **argv)
> >    open_base_files ();
> >
> >    output_header = plugin_output ? plugin_output : header_file;
> > -  write_typed_alloc_defns (output_header, structures, typedefs);
> >    DBGPRINT_COUNT_TYPE ("structures before write_types outputheader",
> >                        structures);
> >    DBGPRINT_COUNT_TYPE ("param_structs before write_types outputheader",
> > diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
> > index e1cc48e..e89cc64 100644
> > --- a/gcc/ggc-common.c
> > +++ b/gcc/ggc-common.c
> > @@ -232,7 +232,7 @@ ggc_cleared_alloc_htab_ignore_args (size_t c ATTRIBUTE_UNUSED,
> >                                     size_t n ATTRIBUTE_UNUSED)
> >  {
> >    gcc_assert (c * n == sizeof (struct htab));
> > -  return ggc_alloc_cleared_htab ();
> > +  return ggc_cleared_alloc<htab> ();
> >  }
> >
> >  /* TODO: once we actually use type information in GGC, create a new tag
> > @@ -241,7 +241,7 @@ void *
> >  ggc_cleared_alloc_ptr_array_two_args (size_t c, size_t n)
> >  {
> >    gcc_assert (sizeof (PTR *) == n);
> > -  return ggc_internal_cleared_vec_alloc (sizeof (PTR *), c);
> > +  return ggc_cleared_vec_alloc<PTR *> (c);
> >  }
> >
> >  /* These are for splay_tree_new_ggc.  */
> > diff --git a/gcc/ggc.h b/gcc/ggc.h
> > index 736305d..2c567de 100644
> > --- a/gcc/ggc.h
> > +++ b/gcc/ggc.h
> > @@ -156,16 +156,35 @@ extern void dump_ggc_loc_statistics (bool);
> >  #define GGC_RESIZEVEC(T, P, N) \
> >      ((T *) ggc_realloc ((P), (N) * sizeof (T) MEM_STAT_INFO))
> >
> > -static inline void *
> > -ggc_internal_vec_alloc (size_t s, size_t c MEM_STAT_DECL)
> > +template<typename T>
> > +static inline T *
> > +ggc_alloc (ALONE_CXX_MEM_STAT_INFO)
> >  {
> > -    return ggc_internal_alloc (c * s PASS_MEM_STAT);
> > +  return static_cast<T *> (ggc_internal_alloc (sizeof (T) PASS_MEM_STAT));
> >  }
> >
> > -static inline void *
> > -ggc_internal_cleared_vec_alloc (size_t s, size_t c CXX_MEM_STAT_INFO)
> > +template<typename T>
> > +static inline T *
> > +ggc_cleared_alloc (ALONE_CXX_MEM_STAT_INFO)
> > +{
> > +  return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T)
> > +                                                      PASS_MEM_STAT));
> > +}
> > +
> > +template<typename T>
> > +static inline T *
> > +ggc_vec_alloc (size_t c CXX_MEM_STAT_INFO)
> > +{
> > +    return static_cast<T *> (ggc_internal_alloc (c * sizeof (T)
> > +                                                PASS_MEM_STAT));
> > +}
> > +
> > +template<typename T>
> > +static inline T *
> > +ggc_cleared_vec_alloc (size_t c CXX_MEM_STAT_INFO)
> >  {
> > -    return ggc_internal_cleared_alloc (c * s PASS_MEM_STAT);
> > +    return static_cast<T *> (ggc_internal_cleared_alloc (c * sizeof (T)
> > +                                                        PASS_MEM_STAT));
> >  }
> >
> >  static inline void *
> > diff --git a/gcc/gimple.c b/gcc/gimple.c
> > index fc6ecb9..165a4bd 100644
> > --- a/gcc/gimple.c
> > +++ b/gcc/gimple.c
> > @@ -835,8 +835,7 @@ gimple_build_omp_for (gimple_seq body, int kind, tree clauses, size_t collapse,
> >    gimple_omp_for_set_clauses (p, clauses);
> >    gimple_omp_for_set_kind (p, kind);
> >    p->collapse = collapse;
> > -  p->iter =  static_cast <struct gimple_omp_for_iter *> (
> > -   ggc_internal_cleared_vec_alloc (sizeof (*p->iter), collapse));
> > +  p->iter =  ggc_cleared_vec_alloc<gimple_omp_for_iter> (collapse);
> >
> >    if (pre_body)
> >      gimple_omp_for_set_pre_body (p, pre_body);
> > @@ -1664,10 +1663,8 @@ gimple_copy (gimple stmt)
> >           {
> >             gimple_statement_omp_for *omp_for_copy =
> >               as_a <gimple_statement_omp_for *> (copy);
> > -           omp_for_copy->iter =
> > -             static_cast <struct gimple_omp_for_iter *> (
> > -                 ggc_internal_vec_alloc (sizeof (struct gimple_omp_for_iter),
> > -                                         gimple_omp_for_collapse (stmt)));
> > +           omp_for_copy->iter = ggc_vec_alloc<gimple_omp_for_iter>
> > +             ( gimple_omp_for_collapse (stmt));
> >            }
> >           for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
> >             {
> > diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c
> > index c0f2f1f..7231b34 100644
> > --- a/gcc/go/go-lang.c
> > +++ b/gcc/go/go-lang.c
> > @@ -51,7 +51,7 @@ struct GTY(()) lang_type
> >
> >  /* Language-dependent contents of a decl.  */
> >
> > -struct GTY((variable_size)) lang_decl
> > +struct GTY(()) lang_decl
> >  {
> >    char dummy;
> >  };
> > diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
> > index 479963c..d1f882a 100644
> > --- a/gcc/ipa-cp.c
> > +++ b/gcc/ipa-cp.c
> > @@ -2599,7 +2599,7 @@ get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
> >    struct ipa_replace_map *replace_map;
> >
> >
> > -  replace_map = ggc_alloc_ipa_replace_map ();
> > +  replace_map = ggc_alloc<ipa_replace_map> ();
> >    if (dump_file)
> >      {
> >        fprintf (dump_file, "    replacing ");
> > @@ -3182,7 +3182,7 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node,
> >           if (!item->value)
> >             continue;
> >
> > -         v = ggc_alloc_ipa_agg_replacement_value ();
> > +         v = ggc_alloc<ipa_agg_replacement_value> ();
> >           v->index = i;
> >           v->offset = item->offset;
> >           v->value = item->value;
> > @@ -3212,7 +3212,7 @@ known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
> >      FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
> >        {
> >         struct ipa_agg_replacement_value *v;
> > -       v = ggc_alloc_ipa_agg_replacement_value ();
> > +       v = ggc_alloc<ipa_agg_replacement_value> ();
> >         v->index = i;
> >         v->offset = item->offset;
> >         v->value = item->value;
> > diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
> > index 4ff31fc..bacbeec 100644
> > --- a/gcc/ipa-devirt.c
> > +++ b/gcc/ipa-devirt.c
> > @@ -491,7 +491,7 @@ get_odr_type (tree type, bool insert)
> >        tree binfo = TYPE_BINFO (type);
> >        unsigned int i;
> >
> > -      val = ggc_alloc_cleared_odr_type_d ();
> > +      val = ggc_cleared_alloc<odr_type_d> ();
> >        val->type = type;
> >        val->bases = vNULL;
> >        val->derived_types = vNULL;
> > diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
> > index 9f144fa..336dd97 100644
> > --- a/gcc/ipa-prop.c
> > +++ b/gcc/ipa-prop.c
> > @@ -3311,7 +3311,7 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
> >      {
> >        struct ipa_agg_replacement_value *v;
> >
> > -      v = ggc_alloc_ipa_agg_replacement_value ();
> > +      v = ggc_alloc<ipa_agg_replacement_value> ();
> >        memcpy (v, old_av, sizeof (*v));
> >        v->next = new_av;
> >        new_av = v;
> > @@ -4670,7 +4670,7 @@ read_agg_replacement_chain (struct lto_input_block *ib,
> >        struct ipa_agg_replacement_value *av;
> >        struct bitpack_d bp;
> >
> > -      av = ggc_alloc_ipa_agg_replacement_value ();
> > +      av = ggc_alloc<ipa_agg_replacement_value> ();
> >        av->offset = streamer_read_uhwi (ib);
> >        av->index = streamer_read_uhwi (ib);
> >        av->value = stream_read_tree (ib, data_in);
> > diff --git a/gcc/java/class.c b/gcc/java/class.c
> > index 94c2568..a1e4a86 100644
> > --- a/gcc/java/class.c
> > +++ b/gcc/java/class.c
> > @@ -764,9 +764,7 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type)
> >    fndecl = build_decl (input_location, FUNCTION_DECL, name, method_type);
> >    DECL_CONTEXT (fndecl) = this_class;
> >
> > -  DECL_LANG_SPECIFIC (fndecl)
> > -    = (struct lang_decl *) ggc_internal_cleared_alloc
> > -    (sizeof (struct lang_decl));
> > +  DECL_LANG_SPECIFIC (fndecl) = ggc_cleared_alloc<struct lang_decl> ();
> >    DECL_LANG_SPECIFIC (fndecl)->desc = LANG_DECL_FUNC;
> >
> >    /* Initialize the static initializer test table.  */
> > @@ -3195,7 +3193,7 @@ java_treetreehash_new (htab_t ht, tree t)
> >    e = htab_find_slot_with_hash (ht, t, hv, INSERT);
> >    if (*e == NULL)
> >      {
> > -      tthe = ggc_alloc_cleared_treetreehash_entry ();
> > +      tthe = ggc_cleared_alloc<treetreehash_entry> ();
> >        tthe->key = t;
> >        *e = tthe;
> >      }
> > diff --git a/gcc/java/constants.c b/gcc/java/constants.c
> > index 51449ef..2e317c9 100644
> > --- a/gcc/java/constants.c
> > +++ b/gcc/java/constants.c
> > @@ -46,11 +46,8 @@ set_constant_entry (CPool *cpool, int index, int tag, jword value)
> >    if (cpool->data == NULL)
> >      {
> >        cpool->capacity = 100;
> > -      cpool->tags = (uint8 *) ggc_internal_cleared_alloc (sizeof (uint8)
> > -                                                         * cpool->capacity);
> > -      cpool->data = (cpool_entry *) ggc_internal_cleared_alloc (sizeof
> > -                                                      (union cpool_entry)
> > -                                                      * cpool->capacity);
> > +      cpool->tags = ggc_cleared_vec_alloc<uint8> (cpool->capacity);
> > +      cpool->data = ggc_cleared_vec_alloc<cpool_entry> (cpool->capacity);
> >        cpool->count = 1;
> >      }
> >    if (index >= cpool->capacity)
> > @@ -338,7 +335,7 @@ cpool_for_class (tree klass)
> >
> >    if (cpool == NULL)
> >      {
> > -      cpool = ggc_alloc_cleared_CPool ();
> > +      cpool = ggc_cleared_alloc<CPool> ();
> >        TYPE_CPOOL (klass) = cpool;
> >      }
> >    return cpool;
> > diff --git a/gcc/java/decl.c b/gcc/java/decl.c
> > index 9f2f0ca..841fb4c 100644
> > --- a/gcc/java/decl.c
> > +++ b/gcc/java/decl.c
> > @@ -1307,7 +1307,7 @@ static struct binding_level *
> >  make_binding_level (void)
> >  {
> >    /* NOSTRICT */
> > -  return ggc_alloc_cleared_binding_level ();
> > +  return ggc_cleared_alloc<binding_level> ();
> >  }
> >
> >  void
> > @@ -1646,7 +1646,7 @@ java_dup_lang_specific_decl (tree node)
> >      return;
> >
> >    lang_decl_size = sizeof (struct lang_decl);
> > -  x = (struct lang_decl *) ggc_internal_alloc (lang_decl_size);
> > +  x = ggc_alloc<struct lang_decl> ();
> >    memcpy (x, DECL_LANG_SPECIFIC (node), lang_decl_size);
> >    DECL_LANG_SPECIFIC (node) = x;
> >  }
> > diff --git a/gcc/java/expr.c b/gcc/java/expr.c
> > index 69f6819..0fa5724 100644
> > --- a/gcc/java/expr.c
> > +++ b/gcc/java/expr.c
> > @@ -470,7 +470,7 @@ add_type_assertion (tree klass, int assertion_code, tree op1, tree op2)
> >    if (*as_pp)
> >      return;
> >
> > -  *as_pp = ggc_alloc_type_assertion ();
> > +  *as_pp = ggc_alloc<type_assertion> ();
> >    **(type_assertion **)as_pp = as;
> >  }
> >
> > diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
> > index 43a8258..e832f44 100644
> > --- a/gcc/java/java-tree.h
> > +++ b/gcc/java/java-tree.h
> > @@ -699,9 +699,7 @@ union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
> >  #define MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC(T)                       \
> >    if (DECL_LANG_SPECIFIC (T) == NULL)                                \
> >      {                                                                \
> > -      DECL_LANG_SPECIFIC ((T))                                       \
> > -        = (struct lang_decl *) ggc_internal_cleared_alloc            \
> > -      (sizeof (struct lang_decl));                                   \
> > +      DECL_LANG_SPECIFIC ((T)) = ggc_cleared_alloc<struct lang_decl> (); \
> >        DECL_LANG_SPECIFIC (T)->desc = LANG_DECL_VAR;                  \
> >      }
> >
> > @@ -809,7 +807,7 @@ struct GTY(()) lang_decl_var {
> >
> >  enum lang_decl_desc {LANG_DECL_FUNC, LANG_DECL_VAR};
> >
> > -struct GTY((variable_size)) lang_decl {
> > +struct GTY(()) lang_decl {
> >    enum lang_decl_desc desc;
> >    union lang_decl_u
> >      {
> > @@ -826,9 +824,7 @@ struct GTY((variable_size)) lang_decl {
> >  #define TYPE_CPOOL_DATA_REF(T) (TYPE_LANG_SPECIFIC (T)->cpool_data_ref)
> >  #define MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC(T) \
> >    if (TYPE_LANG_SPECIFIC ((T)) == NULL)                \
> > -     TYPE_LANG_SPECIFIC ((T))                  \
> > -       = (struct lang_type *) ggc_internal_cleared_alloc \
> > -(sizeof (struct lang_type));     \
> > +     TYPE_LANG_SPECIFIC ((T)) = ggc_cleared_alloc<struct lang_type> ();
> >
> >  #define TYPE_DUMMY(T)          (TYPE_LANG_SPECIFIC(T)->dummy_class)
> >
> > @@ -871,10 +867,7 @@ typedef struct GTY(()) method_entry_d {
> >  } method_entry;
> >
> >
> > -/* FIXME: the variable_size annotation here is needed because these types are
> > -   variable-sized in some other frontends.  Due to gengtype deficiency the GTY
> > -   options of such types have to agree across all frontends. */
> > -struct GTY((variable_size)) lang_type {
> > +struct GTY(()) lang_type {
> >    tree signature;
> >    struct JCF *jcf;
> >    struct CPool *cpool;
> > diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
> > index afe35f0..e57a044 100644
> > --- a/gcc/java/jcf-parse.c
> > +++ b/gcc/java/jcf-parse.c
> > @@ -1905,7 +1905,7 @@ java_parse_file (void)
> >        if (magic == 0xcafebabe)
> >         {
> >           CLASS_FILE_P (node) = 1;
> > -         current_jcf = ggc_alloc_cleared_JCF ();
> > +         current_jcf = ggc_cleared_alloc<JCF> ();
> >           current_jcf->read_state = finput;
> >           current_jcf->filbuf = jcf_filbuf_from_stdio;
> >           jcf_parse (current_jcf);
> > @@ -1922,7 +1922,7 @@ java_parse_file (void)
> >         }
> >        else if (magic == (JCF_u4)ZIPMAGIC)
> >         {
> > -         main_jcf = ggc_alloc_cleared_JCF ();
> > +         main_jcf = ggc_cleared_alloc<JCF> ();
> >           main_jcf->read_state = finput;
> >           main_jcf->filbuf = jcf_filbuf_from_stdio;
> >           linemap_add (line_table, LC_ENTER, false, filename, 0);
> > @@ -2178,7 +2178,7 @@ process_zip_dir (FILE *finput)
> >
> >        class_name = compute_class_name (zdir);
> >        file_name  = XNEWVEC (char, zdir->filename_length+1);
> > -      jcf = ggc_alloc_cleared_JCF ();
> > +      jcf = ggc_cleared_alloc<JCF> ();
> >
> >        strncpy (file_name, class_name_in_zip_dir, zdir->filename_length);
> >        file_name [zdir->filename_length] = '\0';
> > diff --git a/gcc/java/jcf.h b/gcc/java/jcf.h
> > index 8aa077e..0988d65 100644
> > --- a/gcc/java/jcf.h
> > +++ b/gcc/java/jcf.h
> > @@ -65,7 +65,7 @@ jcf_open_exact_case (const char* filename, int oflag);
> >  struct JCF;
> >  typedef int (*jcf_filbuf_t) (struct JCF*, int needed);
> >
> > -union GTY((variable_size)) cpool_entry {
> > +union GTY(()) cpool_entry {
> >    jword GTY ((tag ("0"))) w;
> >    tree GTY ((tag ("1"))) t;
> >  };
> > diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c
> > index 42bcb75..6acc4c9 100644
> > --- a/gcc/loop-iv.c
> > +++ b/gcc/loop-iv.c
> > @@ -3036,7 +3036,7 @@ get_simple_loop_desc (struct loop *loop)
> >
> >    /* At least desc->infinite is not always initialized by
> >       find_simple_loop_exit.  */
> > -  desc = ggc_alloc_cleared_niter_desc ();
> > +  desc = ggc_cleared_alloc<niter_desc> ();
> >    iv_analysis_loop_init (loop);
> >    find_simple_exit (loop, desc);
> >    loop->simple_loop_desc = desc;
> > diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
> > index 58084cd..d4a6d38 100644
> > --- a/gcc/lto-cgraph.c
> > +++ b/gcc/lto-cgraph.c
> > @@ -1755,7 +1755,7 @@ input_node_opt_summary (struct cgraph_node *node,
> >    count = streamer_read_uhwi (ib_main);
> >    for (i = 0; i < count; i++)
> >      {
> > -      struct ipa_replace_map *map = ggc_alloc_ipa_replace_map ();
> > +      struct ipa_replace_map *map = ggc_alloc<ipa_replace_map> ();
> >
> >        vec_safe_push (node->clone.tree_map, map);
> >        map->parm_num = streamer_read_uhwi (ib_main);
> > diff --git a/gcc/lto-section-in.c b/gcc/lto-section-in.c
> > index 9aa7639..d887763 100644
> > --- a/gcc/lto-section-in.c
> > +++ b/gcc/lto-section-in.c
> > @@ -364,7 +364,7 @@ lto_get_decl_name_mapping (struct lto_file_decl_data *decl_data,
> >  struct lto_in_decl_state *
> >  lto_new_in_decl_state (void)
> >  {
> > -  return ggc_alloc_cleared_lto_in_decl_state ();
> > +  return ggc_cleared_alloc<lto_in_decl_state> ();
> >  }
> >
> >  /* Delete STATE and its components. */
> > diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
> > index 20835f7..deb9b1c 100644
> > --- a/gcc/lto-streamer-in.c
> > +++ b/gcc/lto-streamer-in.c
> > @@ -279,7 +279,7 @@ lto_input_eh_catch_list (struct lto_input_block *ib, struct data_in *data_in,
> >        lto_tag_check_range (tag, LTO_eh_catch, LTO_eh_catch);
> >
> >        /* Read the catch node.  */
> > -      n = ggc_alloc_cleared_eh_catch_d ();
> > +      n = ggc_cleared_alloc<eh_catch_d> ();
> >        n->type_list = stream_read_tree (ib, data_in);
> >        n->filter_list = stream_read_tree (ib, data_in);
> >        n->label = stream_read_tree (ib, data_in);
> > @@ -319,7 +319,7 @@ input_eh_region (struct lto_input_block *ib, struct data_in *data_in, int ix)
> >    if (tag == LTO_null)
> >      return NULL;
> >
> > -  r = ggc_alloc_cleared_eh_region_d ();
> > +  r = ggc_cleared_alloc<eh_region_d> ();
> >    r->index = streamer_read_hwi (ib);
> >
> >    gcc_assert (r->index == ix);
> > @@ -396,7 +396,7 @@ input_eh_lp (struct lto_input_block *ib, struct data_in *data_in, int ix)
> >
> >    lto_tag_check_range (tag, LTO_eh_landing_pad, LTO_eh_landing_pad);
> >
> > -  lp = ggc_alloc_cleared_eh_landing_pad_d ();
> > +  lp = ggc_cleared_alloc<eh_landing_pad_d> ();
> >    lp->index = streamer_read_hwi (ib);
> >    gcc_assert (lp->index == ix);
> >    lp->next_lp = (eh_landing_pad) (intptr_t) streamer_read_hwi (ib);
> > @@ -682,7 +682,7 @@ input_cfg (struct lto_input_block *ib, struct data_in *data_in,
> >    if (n_loops == 0)
> >      return;
> >
> > -  struct loops *loops = ggc_alloc_cleared_loops ();
> > +  struct loops *loops = ggc_cleared_alloc<struct loops> ();
> >    init_loops_structure (fn, loops, n_loops);
> >    set_loops_for_fn (fn, loops);
> >
> > diff --git a/gcc/lto/lto-tree.h b/gcc/lto/lto-tree.h
> > index b1c3d2a..4e3f5d6 100644
> > --- a/gcc/lto/lto-tree.h
> > +++ b/gcc/lto/lto-tree.h
> > @@ -28,12 +28,12 @@ struct GTY(()) lang_identifier
> >    struct tree_identifier base;
> >  };
> >
> > -struct GTY((variable_size)) lang_decl
> > +struct GTY(()) lang_decl
> >  {
> >    int dummy;  /* Added because ggc does not like empty structs.  */
> >  };
> >
> > -struct GTY((variable_size)) lang_type
> > +struct GTY(()) lang_type
> >  {
> >    int dummy;  /* Added because ggc does not like empty structs.  */
> >  };
> > diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
> > index 5f4478a..38e1149 100644
> > --- a/gcc/lto/lto.c
> > +++ b/gcc/lto/lto.c
> > @@ -244,7 +244,7 @@ lto_read_in_decl_state (struct data_in *data_in, const uint32_t *data,
> >    for (i = 0; i < LTO_N_DECL_STREAMS; i++)
> >      {
> >        uint32_t size = *data++;
> > -      tree *decls = ggc_alloc_vec_tree (size);
> > +      tree *decls = ggc_vec_alloc<tree> (size);
> >
> >        for (j = 0; j < size; j++)
> >         decls[j] = streamer_tree_cache_get_tree (data_in->reader_cache, data[j]);
> > @@ -2159,7 +2159,7 @@ create_subid_section_table (struct lto_section_slot *ls, splay_tree file_ids,
> >      }
> >    else
> >      {
> > -      file_data = ggc_alloc_lto_file_decl_data ();
> > +      file_data = ggc_alloc<lto_file_decl_data> ();
> >        memset(file_data, 0, sizeof (struct lto_file_decl_data));
> >        file_data->id = id;
> >        file_data->section_hash_table = lto_obj_create_section_hash_table ();;
> > @@ -2860,7 +2860,7 @@ lto_flatten_files (struct lto_file_decl_data **orig, int count, int last_file_ix
> >
> >    lto_stats.num_input_files = count;
> >    all_file_decl_data
> > -    = ggc_alloc_cleared_vec_lto_file_decl_data_ptr (count + 1);
> > +    = ggc_cleared_vec_alloc<lto_file_decl_data_ptr> (count + 1);
> >    /* Set the hooks so that all of the ipa passes can read in their data.  */
> >    lto_set_in_hooks (all_file_decl_data, get_section_data, free_section_data);
> >    for (i = 0, k = 0; i < last_file_ix; i++)
> > @@ -2903,7 +2903,7 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
> >    timevar_push (TV_IPA_LTO_DECL_IN);
> >
> >    real_file_decl_data
> > -    = decl_data = ggc_alloc_cleared_vec_lto_file_decl_data_ptr (nfiles + 1);
> > +    = decl_data = ggc_cleared_vec_alloc<lto_file_decl_data_ptr> (nfiles + 1);
> >    real_file_count = nfiles;
> >
> >    /* Read the resolution file.  */
> > diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
> > index cda345b..551325a 100644
> > --- a/gcc/objc/objc-act.c
> > +++ b/gcc/objc/objc-act.c
> > @@ -3198,7 +3198,7 @@ objc_build_string_object (tree string)
> >
> >    if (!desc)
> >      {
> > -      *loc = desc = ggc_alloc_string_descriptor ();
> > +      *loc = desc = ggc_alloc<string_descriptor> ();
> >        desc->literal = string;
> >        desc->constructor =
> >         (*runtime.build_const_string_constructor) (input_location, string, length);
> > @@ -7040,7 +7040,7 @@ continue_class (tree klass)
> >         uprivate_record = CLASS_STATIC_TEMPLATE (implementation_template);
> >         objc_instance_type = build_pointer_type (uprivate_record);
> >
> > -       imp_entry = ggc_alloc_imp_entry ();
> > +       imp_entry = ggc_alloc<struct imp_entry> ();
> >
> >         imp_entry->next = imp_list;
> >         imp_entry->imp_context = klass;
> > diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
> > index a050727..7e1e265 100644
> > --- a/gcc/objc/objc-act.h
> > +++ b/gcc/objc/objc-act.h
> > @@ -192,9 +192,7 @@ typedef enum objc_property_assign_semantics {
> >  #define SIZEOF_OBJC_TYPE_LANG_SPECIFIC sizeof (struct lang_type)
> >  #define ALLOC_OBJC_TYPE_LANG_SPECIFIC(NODE)                            \
> >    do {                                                                 \
> > -    TYPE_LANG_SPECIFIC (NODE)                                          \
> > -      = (struct lang_type *) ggc_internal_cleared_alloc     \
> > -      (sizeof (struct lang_type));     \
> > +      TYPE_LANG_SPECIFIC (NODE) = ggc_cleared_alloc<struct lang_type> (); \
> >    } while (0)
> >
> >  #define TYPE_HAS_OBJC_INFO(TYPE)                               \
> > diff --git a/gcc/objc/objc-map.c b/gcc/objc/objc-map.c
> > index 386d2c5..aaee729 100644
> > --- a/gcc/objc/objc-map.c
> > +++ b/gcc/objc/objc-map.c
> > @@ -56,7 +56,7 @@ next_power_of_two (size_t x)
> >  objc_map_t
> >  objc_map_alloc_ggc (size_t initial_capacity)
> >  {
> > -  objc_map_t map = (objc_map_t) ggc_internal_cleared_vec_alloc (1, sizeof (struct objc_map_private));
> > +  objc_map_t map = ggc_cleared_alloc<objc_map_private> ();
> >    if (map == NULL)
> >      OUT_OF_MEMORY;
> >
> > @@ -67,8 +67,8 @@ objc_map_alloc_ggc (size_t initial_capacity)
> >    map->maximum_load_factor = 70;
> >    map->max_number_of_non_empty_slots = (initial_capacity * map->maximum_load_factor) / 100;
> >
> > -  map->slots = (tree *)ggc_internal_cleared_vec_alloc (initial_capacity, sizeof (tree));
> > -  map->values = (tree *)ggc_internal_cleared_vec_alloc (initial_capacity, sizeof (tree));
> > +  map->slots = ggc_cleared_vec_alloc<tree> (initial_capacity);
> > +  map->values = ggc_cleared_vec_alloc<tree> (initial_capacity);
> >
> >    if (map->slots == NULL)
> >      OUT_OF_MEMORY;
> > @@ -112,8 +112,8 @@ objc_map_private_resize (objc_map_t map, size_t new_number_of_slots)
> >    map->max_number_of_non_empty_slots = (map->number_of_slots * map->maximum_load_factor) / 100;
> >
> >
> > -  map->slots = (tree *)ggc_internal_cleared_vec_alloc (map->number_of_slots, sizeof (tree));
> > -  map->values = (tree *)ggc_internal_cleared_vec_alloc (map->number_of_slots, sizeof (tree));
> > +  map->slots = ggc_cleared_vec_alloc<tree> (map->number_of_slots);
> > +  map->values = ggc_cleared_vec_alloc<tree> (map->number_of_slots);
> >
> >    if (map->slots == NULL)
> >      OUT_OF_MEMORY;
> > diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
> > index ee43d2d..85033a3 100644
> > --- a/gcc/objc/objc-next-runtime-abi-02.c
> > +++ b/gcc/objc/objc-next-runtime-abi-02.c
> > @@ -238,7 +238,7 @@ static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
> >  bool
> >  objc_next_runtime_abi_02_init (objc_runtime_hooks *rthooks)
> >  {
> > -  extern_names = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
> > +  extern_names = ggc_cleared_vec_alloc<hash> (SIZEHASHTABLE);
> >
> >    if (flag_objc_exceptions && flag_objc_sjlj_exceptions)
> >      {
> > @@ -857,7 +857,7 @@ hash_name_enter (hash *hashlist, tree id)
> >    hash obj;
> >    int slot = IDENTIFIER_HASH_VALUE (DECL_NAME (id)) % SIZEHASHTABLE;
> >
> > -  obj = ggc_alloc_hashed_entry ();
> > +  obj = ggc_alloc<hashed_entry> ();
> >    obj->list = 0;
> >    obj->next = hashlist[slot];
> >    obj->key = id;
> > diff --git a/gcc/optabs.c b/gcc/optabs.c
> > index 54f07ab..e465cbc 100644
> > --- a/gcc/optabs.c
> > +++ b/gcc/optabs.c
> > @@ -6156,7 +6156,7 @@ set_optab_libfunc (optab op, enum machine_mode mode, const char *name)
> >      val = 0;
> >    slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
> >    if (*slot == NULL)
> > -    *slot = ggc_alloc_libfunc_entry ();
> > +    *slot = ggc_alloc<libfunc_entry> ();
> >    (*slot)->op = op;
> >    (*slot)->mode1 = mode;
> >    (*slot)->mode2 = VOIDmode;
> > @@ -6184,7 +6184,7 @@ set_conv_libfunc (convert_optab optab, enum machine_mode tmode,
> >      val = 0;
> >    slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
> >    if (*slot == NULL)
> > -    *slot = ggc_alloc_libfunc_entry ();
> > +    *slot = ggc_alloc<libfunc_entry> ();
> >    (*slot)->op = optab;
> >    (*slot)->mode1 = tmode;
> >    (*slot)->mode2 = fmode;
> > diff --git a/gcc/passes.c b/gcc/passes.c
> > index fb60fc8..78277a2 100644
> > --- a/gcc/passes.c
> > +++ b/gcc/passes.c
> > @@ -1542,7 +1542,7 @@ do_per_function_toporder (void (*callback) (void *data), void *data)
> >    else
> >      {
> >        gcc_assert (!order);
> > -      order = ggc_alloc_vec_cgraph_node_ptr (cgraph_n_nodes);
> > +      order = ggc_vec_alloc<cgraph_node_ptr> (cgraph_n_nodes);
> >        nnodes = ipa_reverse_postorder (order);
> >        for (i = nnodes - 1; i >= 0; i--)
> >          order[i]->process = 1;
> > diff --git a/gcc/rtl.h b/gcc/rtl.h
> > index 595b699..d8dca30 100644
> > --- a/gcc/rtl.h
> > +++ b/gcc/rtl.h
> > @@ -251,7 +251,7 @@ struct GTY(()) object_block {
> >  /* RTL expression ("rtx").  */
> >
> >  struct GTY((chain_next ("RTX_NEXT (&%h)"),
> > -           chain_prev ("RTX_PREV (&%h)"), variable_size)) rtx_def {
> > +           chain_prev ("RTX_PREV (&%h)"))) rtx_def {
> >    /* The kind of expression this is.  */
> >    ENUM_BITFIELD(rtx_code) code: 16;
> >
> > @@ -382,7 +382,7 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"),
> >     for a variable number of things.  The principle use is inside
> >     PARALLEL expressions.  */
> >
> > -struct GTY((variable_size)) rtvec_def {
> > +struct GTY(()) rtvec_def {
> >    int num_elem;                /* number of elements */
> >    rtx GTY ((length ("%h.num_elem"))) elem[1];
> >  };
> > diff --git a/gcc/sese.c b/gcc/sese.c
> > index 342c5e8..a0b0899 100644
> > --- a/gcc/sese.c
> > +++ b/gcc/sese.c
> > @@ -698,7 +698,7 @@ if_region_set_false_region (ifsese if_region, sese region)
> >
> >    if (slot)
> >      {
> > -      struct loop_exit *loop_exit = ggc_alloc_cleared_loop_exit ();
> > +      struct loop_exit *loop_exit = ggc_cleared_alloc<struct loop_exit> ();
> >
> >        memcpy (loop_exit, *((struct loop_exit **) slot), sizeof (struct loop_exit));
> >        htab_clear_slot (current_loops->exits, slot);
> > diff --git a/gcc/stringpool.c b/gcc/stringpool.c
> > index e317525..c880cb1 100644
> > --- a/gcc/stringpool.c
> > +++ b/gcc/stringpool.c
> > @@ -258,10 +258,10 @@ static GTY(()) struct string_pool_data * spd;
> >  void
> >  gt_pch_save_stringpool (void)
> >  {
> > -  spd = ggc_alloc_string_pool_data ();
> > +  spd = ggc_alloc<string_pool_data> ();
> >    spd->nslots = ident_hash->nslots;
> >    spd->nelements = ident_hash->nelements;
> > -  spd->entries = ggc_alloc_vec_ht_identifier_ptr (spd->nslots);
> > +  spd->entries = ggc_vec_alloc<ht_identifier_ptr> (spd->nslots);
> >    memcpy (spd->entries, ident_hash->entries,
> >           spd->nslots * sizeof (spd->entries[0]));
> >  }
> > diff --git a/gcc/target-globals.c b/gcc/target-globals.c
> > index 7cf95ae..5f1a208 100644
> > --- a/gcc/target-globals.c
> > +++ b/gcc/target-globals.c
> > @@ -83,13 +83,13 @@ save_target_globals (void)
> >    g = (struct target_globals *) p;
> >    g->flag_state = &p->flag_state;
> >    g->regs = ggc_internal_cleared_alloc (sizeof (struct target_regs));
> > -  g->rtl = ggc_alloc_cleared_target_rtl ();
> > +  g->rtl = ggc_cleared_alloc<target_rtl> ();
> >    g->hard_regs
> >      = ggc_internal_cleared_alloc (sizeof (struct target_hard_regs));
> >    g->reload = ggc_internal_cleared_alloc (sizeof (struct target_reload));
> >    g->expmed =  ggc_internal_cleared_alloc (sizeof (struct target_expmed));
> >    g->optabs = &p->optabs;
> > -  g->libfuncs = ggc_alloc_cleared_target_libfuncs ();
> > +  g->libfuncs = ggc_cleared_alloc<target_libfuncs> ();
> >    g->cfgloop = &p->cfgloop;
> >    g->ira = ggc_internal_cleared_alloc (sizeof (struct target_ira));
> >    g->ira_int = ggc_internal_cleared_alloc (sizeof (struct target_ira_int));
> > diff --git a/gcc/toplev.c b/gcc/toplev.c
> > index 9535bd0..2f9c9f5 100644
> > --- a/gcc/toplev.c
> > +++ b/gcc/toplev.c
> > @@ -1156,7 +1156,7 @@ general_init (const char *argv0)
> >       table.  */
> >    init_ggc ();
> >    init_stringpool ();
> > -  line_table = ggc_alloc_line_maps ();
> > +  line_table = ggc_alloc<line_maps> ();
> >    linemap_init (line_table);
> >    line_table->reallocator = realloc_for_line_map;
> >    line_table->round_alloc_size = ggc_round_alloc_size;
> > diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
> > index 417ca8a..52777d5 100644
> > --- a/gcc/trans-mem.c
> > +++ b/gcc/trans-mem.c
> > @@ -479,7 +479,7 @@ record_tm_replacement (tree from, tree to)
> >    if (tm_wrap_map == NULL)
> >      tm_wrap_map = htab_create_ggc (32, tree_map_hash, tree_map_eq, 0);
> >
> > -  h = ggc_alloc_tree_map ();
> > +  h = ggc_alloc<tree_map> ();
> >    h->hash = htab_hash_pointer (from);
> >    h->base.from = from;
> >    h->to = to;
> > @@ -3070,7 +3070,7 @@ split_bb_make_tm_edge (gimple stmt, basic_block dest_bb,
> >    struct tm_restart_node *n = (struct tm_restart_node *) *slot;
> >    if (n == NULL)
> >      {
> > -      n = ggc_alloc_tm_restart_node ();
> > +      n = ggc_alloc<tm_restart_node> ();
> >        *n = dummy;
> >      }
> >    else
> > diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
> > index 0fb2681..446e0f2 100644
> > --- a/gcc/tree-cfg.c
> > +++ b/gcc/tree-cfg.c
> > @@ -6893,7 +6893,7 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
> >      }
> >
> >    /* Initialize an empty loop tree.  */
> > -  struct loops *loops = ggc_alloc_cleared_loops ();
> > +  struct loops *loops = ggc_cleared_alloc<struct loops> ();
> >    init_loops_structure (dest_cfun, loops, 1);
> >    loops->state = LOOPS_MAY_HAVE_MULTIPLE_LATCHES;
> >    set_loops_for_fn (dest_cfun, loops);
> > diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h
> > index 8810a3e..f4075fc 100644
> > --- a/gcc/tree-data-ref.h
> > +++ b/gcc/tree-data-ref.h
> > @@ -565,7 +565,7 @@ lambda_vector_gcd (lambda_vector vector, int size)
> >  static inline lambda_vector
> >  lambda_vector_new (int size)
> >  {
> > -  return (lambda_vector) ggc_internal_cleared_alloc (sizeof (int) * size);
> > +  return ggc_cleared_vec_alloc<int> (size);
> >  }
> >
> >  /* Clear out vector VEC1 of length SIZE.  */
> > diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
> > index 960c04a..914ef68 100644
> > --- a/gcc/tree-eh.c
> > +++ b/gcc/tree-eh.c
> > @@ -82,7 +82,7 @@ add_stmt_to_eh_lp_fn (struct function *ifun, gimple t, int num)
> >
> >    gcc_assert (num != 0);
> >
> > -  n = ggc_alloc_throw_stmt_node ();
> > +  n = ggc_alloc<throw_stmt_node> ();
> >    n->stmt = t;
> >    n->lp_nr = num;
> >
> > diff --git a/gcc/tree-iterator.c b/gcc/tree-iterator.c
> > index 37ee752..c4412ba 100644
> > --- a/gcc/tree-iterator.c
> > +++ b/gcc/tree-iterator.c
> > @@ -131,7 +131,7 @@ tsi_link_before (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
> >      }
> >    else
> >      {
> > -      head = ggc_alloc_tree_statement_list_node ();
> > +      head = ggc_alloc<tree_statement_list_node> ();
> >        head->prev = NULL;
> >        head->next = NULL;
> >        head->stmt = t;
> > @@ -207,7 +207,7 @@ tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
> >      }
> >    else
> >      {
> > -      head = ggc_alloc_tree_statement_list_node ();
> > +      head = ggc_alloc<tree_statement_list_node> ();
> >        head->prev = NULL;
> >        head->next = NULL;
> >        head->stmt = t;
> > diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
> > index f1ddc24..fc0b0d1 100644
> > --- a/gcc/tree-scalar-evolution.c
> > +++ b/gcc/tree-scalar-evolution.c
> > @@ -332,7 +332,7 @@ new_scev_info_str (basic_block instantiated_below, tree var)
> >  {
> >    struct scev_info_str *res;
> >
> > -  res = ggc_alloc_scev_info_str ();
> > +  res = ggc_alloc<scev_info_str> ();
> >    res->name_version = SSA_NAME_VERSION (var);
> >    res->chrec = chrec_not_analyzed_yet;
> >    res->instantiated_below = instantiated_below->index;
> > diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
> > index 7628363..04effab 100644
> > --- a/gcc/tree-ssa-loop-niter.c
> > +++ b/gcc/tree-ssa-loop-niter.c
> > @@ -2678,7 +2678,7 @@ record_estimate (struct loop *loop, tree bound, double_int i_bound,
> >           || loop->nb_iterations == NULL_TREE
> >           || TREE_CODE (loop->nb_iterations) != INTEGER_CST))
> >      {
> > -      struct nb_iter_bound *elt = ggc_alloc_nb_iter_bound ();
> > +      struct nb_iter_bound *elt = ggc_alloc<nb_iter_bound> ();
> >
> >        elt->bound = i_bound;
> >        elt->stmt = at_stmt;
> > diff --git a/gcc/tree-ssa-operands.h b/gcc/tree-ssa-operands.h
> > index 5f9edd4..42fe5a7 100644
> > --- a/gcc/tree-ssa-operands.h
> > +++ b/gcc/tree-ssa-operands.h
> > @@ -45,7 +45,7 @@ typedef struct use_optype_d *use_optype_p;
> >     operand memory manager.  Operands are suballocated out of this block.  The
> >     MEM array varies in size.  */
> >
> > -struct GTY((chain_next("%h.next"), variable_size)) ssa_operand_memory_d {
> > +struct GTY((chain_next("%h.next"))) ssa_operand_memory_d {
> >    struct ssa_operand_memory_d *next;
> >    char mem[1];
> >  };
> > diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
> > index 1ea639d..f6f9dc9 100644
> > --- a/gcc/tree-ssa.c
> > +++ b/gcc/tree-ssa.c
> > @@ -1120,7 +1120,7 @@ uid_ssaname_map_hash (const void *item)
> >  void
> >  init_tree_ssa (struct function *fn)
> >  {
> > -  fn->gimple_df = ggc_alloc_cleared_gimple_df ();
> > +  fn->gimple_df = ggc_cleared_alloc<gimple_df> ();
> >    fn->gimple_df->default_defs = htab_create_ggc (20, uid_ssaname_map_hash,
> >                                                  uid_ssaname_map_eq, NULL);
> >    pt_solution_reset (&fn->gimple_df->escaped);
> > diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
> > index 02db6a5..b013149 100644
> > --- a/gcc/tree-ssanames.c
> > +++ b/gcc/tree-ssanames.c
> > @@ -196,7 +196,7 @@ set_range_info (tree name, enum value_range_type range_type, double_int min,
> >    /* Allocate if not available.  */
> >    if (ri == NULL)
> >      {
> > -      ri = ggc_alloc_cleared_range_info_def ();
> > +      ri = ggc_cleared_alloc<range_info_def> ();
> >        SSA_NAME_RANGE_INFO (name) = ri;
> >        ri->nonzero_bits = double_int::mask (TYPE_PRECISION (TREE_TYPE (name)));
> >      }
> > @@ -437,7 +437,7 @@ get_ptr_info (tree t)
> >    pi = SSA_NAME_PTR_INFO (t);
> >    if (pi == NULL)
> >      {
> > -      pi = ggc_alloc_cleared_ptr_info_def ();
> > +      pi = ggc_cleared_alloc<ptr_info_def> ();
> >        pt_solution_reset (&pi->pt);
> >        mark_ptr_info_alignment_unknown (pi);
> >        SSA_NAME_PTR_INFO (t) = pi;
> > @@ -481,7 +481,7 @@ duplicate_ssa_name_ptr_info (tree name, struct ptr_info_def *ptr_info)
> >    if (!ptr_info)
> >      return;
> >
> > -  new_ptr_info = ggc_alloc_ptr_info_def ();
> > +  new_ptr_info = ggc_alloc<ptr_info_def> ();
> >    *new_ptr_info = *ptr_info;
> >
> >    SSA_NAME_PTR_INFO (name) = new_ptr_info;
> > @@ -502,7 +502,7 @@ duplicate_ssa_name_range_info (tree name, enum value_range_type range_type,
> >    if (!range_info)
> >      return;
> >
> > -  new_range_info = ggc_alloc_range_info_def ();
> > +  new_range_info = ggc_alloc<range_info_def> ();
> >    *new_range_info = *range_info;
> >
> >    gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE);
> > diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
> > index b02bb6b..aa61187 100644
> > --- a/gcc/tree-streamer-in.c
> > +++ b/gcc/tree-streamer-in.c
> > @@ -176,7 +176,7 @@ unpack_ts_real_cst_value_fields (struct bitpack_d *bp, tree expr)
> >    for (i = 0; i < SIGSZ; i++)
> >      r.sig[i] = (unsigned long) bp_unpack_value (bp, HOST_BITS_PER_LONG);
> >
> > -  rp = ggc_alloc_real_value ();
> > +  rp = ggc_alloc<real_value> ();
> >    memcpy (rp, &r, sizeof (REAL_VALUE_TYPE));
> >    TREE_REAL_CST_PTR (expr) = rp;
> >  }
> > @@ -188,7 +188,7 @@ unpack_ts_real_cst_value_fields (struct bitpack_d *bp, tree expr)
> >  static void
> >  unpack_ts_fixed_cst_value_fields (struct bitpack_d *bp, tree expr)
> >  {
> > -  FIXED_VALUE_TYPE *fp = ggc_alloc_fixed_value ();
> > +  FIXED_VALUE_TYPE *fp = ggc_alloc<fixed_value> ();
> >    fp->mode = bp_unpack_enum (bp, machine_mode, MAX_MACHINE_MODE);
> >    fp->data.low = bp_unpack_var_len_int (bp);
> >    fp->data.high = bp_unpack_var_len_int (bp);
> > diff --git a/gcc/tree.c b/gcc/tree.c
> > index 365faf2..9a3e7e9 100644
> > --- a/gcc/tree.c
> > +++ b/gcc/tree.c
> > @@ -1577,7 +1577,7 @@ build_fixed (tree type, FIXED_VALUE_TYPE f)
> >    FIXED_VALUE_TYPE *fp;
> >
> >    v = make_node (FIXED_CST);
> > -  fp = ggc_alloc_fixed_value ();
> > +  fp = ggc_alloc<fixed_value> ();
> >    memcpy (fp, &f, sizeof (FIXED_VALUE_TYPE));
> >
> >    TREE_TYPE (v) = type;
> > @@ -1598,7 +1598,7 @@ build_real (tree type, REAL_VALUE_TYPE d)
> >       Consider doing it via real_convert now.  */
> >
> >    v = make_node (REAL_CST);
> > -  dp = ggc_alloc_real_value ();
> > +  dp = ggc_alloc<real_value> ();
> >    memcpy (dp, &d, sizeof (REAL_VALUE_TYPE));
> >
> >    TREE_TYPE (v) = type;
> > @@ -6390,7 +6390,7 @@ decl_priority_info (tree decl)
> >    h = (struct tree_priority_map *) *loc;
> >    if (!h)
> >      {
> > -      h = ggc_alloc_cleared_tree_priority_map ();
> > +      h = ggc_cleared_alloc<tree_priority_map> ();
> >        *loc = h;
> >        h->base.from = decl;
> >        h->init = DEFAULT_INIT_PRIORITY;
> > @@ -6473,7 +6473,7 @@ decl_debug_expr_insert (tree from, tree to)
> >    struct tree_decl_map *h;
> >    void **loc;
> >
> > -  h = ggc_alloc_tree_decl_map ();
> > +  h = ggc_alloc<tree_decl_map> ();
> >    h->base.from = from;
> >    h->to = to;
> >    loc = htab_find_slot_with_hash (debug_expr_for_decl, h, DECL_UID (from),
> > @@ -6504,7 +6504,7 @@ decl_value_expr_insert (tree from, tree to)
> >    struct tree_decl_map *h;
> >    void **loc;
> >
> > -  h = ggc_alloc_tree_decl_map ();
> > +  h = ggc_alloc<tree_decl_map> ();
> >    h->base.from = from;
> >    h->to = to;
> >    loc = htab_find_slot_with_hash (value_expr_for_decl, h, DECL_UID (from),
> > @@ -6545,7 +6545,7 @@ decl_debug_args_insert (tree from)
> >    if (debug_args_for_decl == NULL)
> >      debug_args_for_decl = htab_create_ggc (64, tree_vec_map_hash,
> >                                            tree_vec_map_eq, 0);
> > -  h = ggc_alloc_tree_vec_map ();
> > +  h = ggc_alloc<tree_vec_map> ();
> >    h->base.from = from;
> >    h->to = NULL;
> >    loc = htab_find_slot_with_hash (debug_args_for_decl, h, DECL_UID (from),
> > @@ -6728,7 +6728,7 @@ type_hash_add (hashval_t hashcode, tree type)
> >    struct type_hash *h;
> >    void **loc;
> >
> > -  h = ggc_alloc_type_hash ();
> > +  h = ggc_alloc<type_hash> ();
> >    h->hash = hashcode;
> >    h->type = type;
> >    loc = htab_find_slot_with_hash (type_hash_table, h, hashcode, INSERT);
> > diff --git a/gcc/ubsan.c b/gcc/ubsan.c
> > index d9d740c..11461d0 100644
> > --- a/gcc/ubsan.c
> > +++ b/gcc/ubsan.c
> > @@ -99,7 +99,7 @@ decl_for_type_insert (tree type, tree decl)
> >    struct tree_type_map *h;
> >    void **slot;
> >
> > -  h = ggc_alloc_tree_type_map ();
> > +  h = ggc_alloc<tree_type_map> ();
> >    h->type.from = type;
> >    h->decl = decl;
> >    slot = htab_find_slot_with_hash (decl_tree_for_type, h, TYPE_UID (type),
> > diff --git a/gcc/varasm.c b/gcc/varasm.c
> > index 3b42faa..4c59d35 100644
> > --- a/gcc/varasm.c
> > +++ b/gcc/varasm.c
> > @@ -242,7 +242,7 @@ get_unnamed_section (unsigned int flags, void (*callback) (const void *),
> >  {
> >    section *sect;
> >
> > -  sect = ggc_alloc_section ();
> > +  sect = ggc_alloc<section> ();
> >    sect->unnamed.common.flags = flags | SECTION_UNNAMED;
> >    sect->unnamed.callback = callback;
> >    sect->unnamed.data = data;
> > @@ -259,7 +259,7 @@ get_noswitch_section (unsigned int flags, noswitch_section_callback callback)
> >  {
> >    section *sect;
> >
> > -  sect = ggc_alloc_section ();
> > +  sect = ggc_alloc<section> ();
> >    sect->noswitch.common.flags = flags | SECTION_NOSWITCH;
> >    sect->noswitch.callback = callback;
> >
> > @@ -280,7 +280,7 @@ get_section (const char *name, unsigned int flags, tree decl)
> >    flags |= SECTION_NAMED;
> >    if (*slot == NULL)
> >      {
> > -      sect = ggc_alloc_section ();
> > +      sect = ggc_alloc<section> ();
> >        sect->named.common.flags = flags;
> >        sect->named.name = ggc_strdup (name);
> >        sect->named.decl = decl;
> > @@ -361,7 +361,7 @@ get_block_for_section (section *sect)
> >    block = (struct object_block *) *slot;
> >    if (block == NULL)
> >      {
> > -      block = ggc_alloc_cleared_object_block ();
> > +      block = ggc_cleared_alloc<object_block> ();
> >        block->sect = sect;
> >        *slot = block;
> >      }
> > @@ -3203,7 +3203,7 @@ build_constant_desc (tree exp)
> >    int labelno;
> >    tree decl;
> >
> > -  desc = ggc_alloc_constant_descriptor_tree ();
> > +  desc = ggc_alloc<constant_descriptor_tree> ();
> >    desc->value = copy_constant (exp);
> >
> >    /* Create a string containing the label name, in LABEL.  */
> > @@ -3607,7 +3607,7 @@ create_constant_pool (void)
> >  {
> >    struct rtx_constant_pool *pool;
> >
> > -  pool = ggc_alloc_rtx_constant_pool ();
> > +  pool = ggc_alloc<rtx_constant_pool> ();
> >    pool->const_rtx_htab = htab_create_ggc (31, const_desc_rtx_hash,
> >                                           const_desc_rtx_eq, NULL);
> >    pool->first = NULL;
> > @@ -3673,7 +3673,7 @@ force_const_mem (enum machine_mode mode, rtx x)
> >      return copy_rtx (desc->mem);
> >
> >    /* Otherwise, create a new descriptor.  */
> > -  desc = ggc_alloc_constant_descriptor_rtx ();
> > +  desc = ggc_alloc<constant_descriptor_rtx> ();
> >    *slot = desc;
> >
> >    /* Align the location counter as required by EXP's data type.  */
> > @@ -5721,7 +5721,7 @@ record_tm_clone_pair (tree o, tree n)
> >    if (tm_clone_hash == NULL)
> >      tm_clone_hash = htab_create_ggc (32, tree_map_hash, tree_map_eq, 0);
> >
> > -  h = ggc_alloc_tree_map ();
> > +  h = ggc_alloc<tree_map> ();
> >    h->hash = htab_hash_pointer (o);
> >    h->base.from = o;
> >    h->to = n;
> > diff --git a/gcc/varpool.c b/gcc/varpool.c
> > index 69172c6..45ff88d 100644
> > --- a/gcc/varpool.c
> > +++ b/gcc/varpool.c
> > @@ -135,7 +135,7 @@ varpool_call_variable_insertion_hooks (varpool_node *node)
> >  varpool_node *
> >  varpool_create_empty_node (void)
> >  {
> > -  varpool_node *node = ggc_alloc_cleared_varpool_node ();
> > +  varpool_node *node = ggc_cleared_alloc<varpool_node> ();
> >    node->type = SYMTAB_VARIABLE;
> >    return node;
> >  }
> > --
> > 2.0.0.rc0
> >

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 3/6] use templates instead of gengtype for typed allocation functions
  2014-04-29 13:08     ` Trevor Saunders
@ 2014-04-29 13:15       ` Richard Biener
  0 siblings, 0 replies; 18+ messages in thread
From: Richard Biener @ 2014-04-29 13:15 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: GCC Patches

On Tue, Apr 29, 2014 at 3:01 PM, Trevor Saunders <tsaunders@mozilla.com> wrote:
> On Tue, Apr 29, 2014 at 02:32:23PM +0200, Richard Biener wrote:
>> On Tue, Apr 29, 2014 at 1:08 PM,  <tsaunders@mozilla.com> wrote:
>> > From: Trevor Saunders <tsaunders@mozilla.com>
>> >
>> > Hi,
>> >
>> > much less code to accomplish the same thing.
>>
>> Agreed.  Does that fix the comment on the last patch about
>> dropping typed allocations of variable lengths, as I see you
>> introduce ggc_vec_alloc () here?
>
> in some cases yes, for example the c front end used to have to deal with
> ggc thinking lang_decl was variably sized because c++ makes it that way.
> So after this patch the C front end can now just write
> ld = ggc_alloc<lang_decl> ();
> And for free we get that dwarf2out.c can do
> unsigned char *vec = ggc_cleared_vec_alloc<unsigned char> (n);
>  (I didn't go looking for places where I could do that cleanup, but I
>  could).  On the other hand these functions don't help with things like
>  allocating lang_decls in the C++ front end where they basically want to
>  write
>  ld = (struct x*) ggc_internal_alloc (sizeof (struct y));
> There's about 10 places that do something like that or get the length
> from someplace else.  We could add some sort of macro like
> GGC_NEW(type, size)
> if you think it would be better than calling ggc_internal_alloc and
> casting, but given the number of sites and it not being much better in
> my mind I didn't bother.

No, if the target type and the type that specifies the size are different
then it's not worth doing.

Thanks,
Richard.

> thanks!
>
> Trev
>
>>
>> > bootstrapped + regtested on x86_64-unknown-linux-gnu ok?
>>
>> If so, then ok.
>>
>> Thanks,
>> Richard.
>>
>> > Trev
>> >
>> > gcc/ada/ChangeLog:
>> >
>> >         * gcc-interface/ada-tree.h: Remove usage of variable_size gty
>> >         annotation.
>> >
>> > gcc/cp/ChangeLog:
>> >
>> >         * cp-cilkplus.c (cilk_install_body_with_frame_cleanup): Adjust.
>> >         * cp-objcp-common.c (decl_shadowed_for_var_insert): Adjust.
>> >         * cp-tree.h: Remove usage of variable_size gty attribute.
>> >         * decl.c (make_label_decl): Adjust.
>> >         (check_goto): Likewise.
>> >         (start_preparsed_function): Likewise.
>> >         (save_function_data): Likewise.
>> >         * lex.c (init_reswords): Likewise.
>> >         (retrofit_lang_decl): Likewise.
>> >         (cxx_dup_lang_specific_decl): Likewise.
>> >         (copy_lang_type): Likewise.
>> >         (cxx_make_type): Likewise.
>> >         * name-lookup.c (binding_entry_make): Likewise.
>> >         (binding_table_construct): Likewise.
>> >         (binding_table_new): Likewise.
>> >         (cxx_binding_make): Likewise.
>> >         (pushdecl_maybe_friend_1): Likewise.
>> >         (begin_scope): Likewise.
>> >         (push_to_top_level): Likewise.
>> >         * parser.c (cp_lexer_alloc): Likewise.
>> >         (cp_lexer_new_from_tokens): Likewise.
>> >         (cp_token_cache_new): Likewise.
>> >         (cp_parser_context_new): Likewise.
>> >         (cp_parser_new): Likewise.
>> >         (cp_parser_nested_name_specifier_opt): Likewise.
>> >         (cp_parser_template_id): Likewise.
>> >         * pt.c (maybe_process_partial_specialization): Likewise.
>> >         (register_specialization): Likewise.
>> >         (add_pending_template): Likewise.
>> >         (lookup_template_class_1): Likewise.
>> >         (push_tinst_level): Likewise.
>> >         * semantics.c (register_constexpr_fundef): Likewise.
>> >         (cxx_eval_call_expression): Likewise.
>> >         * typeck2.c (abstract_virtuals_error_sfinae): Likewise.
>> >
>> > gcc/objc/ChangeLog:
>> >
>> >         * objc-act.c (objc_build_string_object): Adjust.
>> >         (continue_class): Likewise.
>> >         * objc-act.h (ALLOC_OBJC_TYPE_LANG_SPECIFIC): Likewise.
>> >         * objc-map.c (objc_map_alloc_ggc): Likewise.
>> >         (objc_map_private_resize): Likewise.
>> >         * objc-next-runtime-abi-02.c (objc_next_runtime_abi_02_init):
>> >         Likewise.
>> >         (hash_name_enter): Likewise.
>> >
>> > gcc/go/ChangeLog:
>> >
>> >         * go-lang.c (struct GTY): Don't use variable_size gty attribute.
>> >
>> > gcc/ChangeLog:
>> >
>> >         * alias.c (record_alias_subset): Adjust.
>> >         * bitmap.c (bitmap_element_allocate): Likewise.
>> >         (bitmap_gc_alloc_stat): Likewise.
>> >         * cfg.c (init_flow): Likewise.
>> >         (alloc_block): Likewise.
>> >         (unchecked_make_edge): Likewise.
>> >         * cfgloop.c (alloc_loop): Likewise.
>> >         (flow_loops_find): Likewise.
>> >         (rescan_loop_exit): Likewise.
>> >         * cfgrtl.c (init_rtl_bb_info): Likewise.
>> >         * cgraph.c (insert_new_cgraph_node_version): Likewise.
>> >         (cgraph_allocate_node): Likewise.
>> >         (cgraph_create_edge_1): Likewise.
>> >         (cgraph_allocate_init_indirect_info): Likewise.
>> >         * cgraphclones.c (cgraph_clone_edge): Likewise.
>> >         * cgraphunit.c (add_asm_node): Likewise.
>> >         (init_lowered_empty_function): Likewise.
>> >         * config/i386/i386.c (get_dllimport_decl): Likewise.
>> >         (ix86_init_machine_status): Likewise.
>> >         (assign_386_stack_local): Likewise.
>> >         * coverage.c (coverage_end_function): Likewise.
>> >         * dbxout.c (dbxout_init): Likewise.
>> >         * doc/gty.texi: Don't mention variable_size attribute.
>> >         * dwarf2cfi.c (new_cfi): Adjust.
>> >         (new_cfi_row): Likewise.
>> >         (copy_cfi_row): Likewise.
>> >         (create_cie_data): Likewise.
>> >         * dwarf2out.c (dwarf2out_alloc_current_fde): Likewise.
>> >         (new_loc_descr): Likewise.
>> >         (find_AT_string_in_table): Likewise.
>> >         (add_addr_table_entry): Likewise.
>> >         (new_die): Likewise.
>> >         (add_var_loc_to_decl): Likewise.
>> >         (clone_die): Likewise.
>> >         (clone_as_declaration): Likewise.
>> >         (break_out_comdat_types): Likewise.
>> >         (new_loc_list): Likewise.
>> >         (add_loc_descr_to_each): Likewise.
>> >         (add_location_or_const_value_attribute): Likewise.
>> >         (add_linkage_name): Likewise.
>> >         (lookup_filename): Likewise.
>> >         (dwarf2out_var_location): Likewise.
>> >         (new_line_info_table): Likewise.
>> >         (dwarf2out_init): Likewise.
>> >         * emit-rtl.c (set_mem_attrs): Likewise.
>> >         (get_reg_attrs): Likewise.
>> >         (start_sequence): Likewise.
>> >         (init_emit): Likewise.
>> >         (init_emit_regs): Likewise.
>> >         * except.c (init_eh_for_function): Likewise.
>> >         (gen_eh_region): Likewise.
>> >         (gen_eh_region_catch): Likewise.
>> >         (gen_eh_landing_pad): Likewise.
>> >         (add_call_site): Likewise.
>> >         * function.c (add_frame_space): Likewise.
>> >         (insert_temp_slot_address): Likewise.
>> >         (assign_stack_temp_for_type): Likewise.
>> >         (get_hard_reg_initial_val): Likewise.
>> >         (allocate_struct_function): Likewise.
>> >         (prepare_function_start): Likewise.
>> >         (types_used_by_var_decl_insert): Likewise.
>> >         * gengtype.c (variable_size_p): Remove function.
>> >         (enum alloc_quantity): Remove enum.
>> >         (write_typed_alloc_def): Remove function.
>> >         (write_typed_struct_alloc_def): Likewise.
>> >         (write_typed_typedef_alloc_def): Likewise.
>> >         (write_typed_alloc_defns): Likewise.
>> >         (main): Adjust.
>> >         * ggc-common.c (ggc_cleared_alloc_htab_ignore_args): Adjust.
>> >         (ggc_cleared_alloc_ptr_array_two_args): Likewise.
>> >         * ggc.h (ggc_alloc): new function.
>> >         (ggc_cleared_alloc): Likewise.
>> >         (ggc_vec_alloc): Template on type of vector element, and remove
>> >         element size argument.
>> >         (ggc_cleared_vec_alloc): Likewise.
>> >         * gimple.c (gimple_build_omp_for): Adjust.
>> >         (gimple_copy): Likewise.
>> >         * ipa-cp.c (get_replacement_map): Likewise.
>> >         (find_aggregate_values_for_callers_subset): Likewise.
>> >         (known_aggs_to_agg_replacement_list): Likewise.
>> >         * ipa-devirt.c (get_odr_type): Likewise.
>> >         * ipa-prop.c (ipa_node_duplication_hook): Likewise.
>> >         (read_agg_replacement_chain): Likewise.
>> >         * loop-iv.c (get_simple_loop_desc): Likewise.
>> >         * lto-cgraph.c (input_node_opt_summary): Likewise.
>> >         * lto-section-in.c (lto_new_in_decl_state): Likewise.
>> >         * lto-streamer-in.c (lto_input_eh_catch_list): Likewise.
>> >         (input_eh_region): Likewise.
>> >         (input_eh_lp): Likewise.
>> >         (input_cfg): Likewise.
>> >         * optabs.c (set_optab_libfunc): Likewise.
>> >         (set_conv_libfunc): Likewise.
>> >         * passes.c (do_per_function_toporder): Likewise.
>> >         * rtl.h: Don't use variable_size gty attribute.
>> >         * sese.c (if_region_set_false_region): Adjust.
>> >         * stringpool.c (gt_pch_save_stringpool): Likewise.
>> >         * target-globals.c (save_target_globals): Likewise.
>> >         * toplev.c (general_init): Likewise.
>> >         * trans-mem.c (record_tm_replacement): Likewise.
>> >         (split_bb_make_tm_edge): Likewise.
>> >         * tree-cfg.c (move_sese_region_to_fn): Likewise.
>> >         * tree-data-ref.h (lambda_vector_new): Likewise.
>> >         * tree-eh.c (add_stmt_to_eh_lp_fn): Likewise.
>> >         * tree-iterator.c (tsi_link_before): Likewise.
>> >         (tsi_link_after): Likewise.
>> >         * tree-scalar-evolution.c (new_scev_info_str): Likewise.
>> >         * tree-ssa-loop-niter.c (record_estimate): Likewise.
>> >         * tree-ssa-operands.h: Don't use variable_size gty attribute.
>> >         * tree-ssa.c (init_tree_ssa): Adjust.
>> >         * tree-ssanames.c (set_range_info): Likewise.
>> >         (get_ptr_info): Likewise.
>> >         (duplicate_ssa_name_ptr_info): Likewise.
>> >         (duplicate_ssa_name_range_info): Likewise.
>> >         * tree-streamer-in.c (unpack_ts_real_cst_value_fields): Likewise.
>> >         (unpack_ts_fixed_cst_value_fields): Likewise.
>> >         * tree.c (build_fixed): Likewise.
>> >         (build_real): Likewise.
>> >         (build_string): Likewise.
>> >         (decl_priority_info): Likewise.
>> >         (decl_debug_expr_insert): Likewise.
>> >         (decl_value_expr_insert): Likewise.
>> >         (decl_debug_args_insert): Likewise.
>> >         (type_hash_add): Likewise.
>> >         (build_omp_clause): Likewise.
>> >         * ubsan.c (decl_for_type_insert): Likewise.
>> >         * varasm.c (get_unnamed_section): Likewise.
>> >         (get_noswitch_section): Likewise.
>> >         (get_section): Likewise.
>> >         (get_block_for_section): Likewise.
>> >         (create_block_symbol): Likewise.
>> >         (build_constant_desc): Likewise.
>> >         (create_constant_pool): Likewise.
>> >         (force_const_mem): Likewise.
>> >         (record_tm_clone_pair): Likewise.
>> >         * varpool.c (varpool_create_empty_node): Likewise.
>> >
>> > gcc/c-family/ChangeLog:
>> >
>> >         * c-common.h (sorted_fields_type): Remove variable_size GTY attribute.
>> >         * c-pragma.c (push_alignment): Adjust.
>> >         (handle_pragma_push_options): Likewise.
>> >
>> > gcc/fortran/ChangeLog:
>> >
>> >         * f95-lang.c (pushlevel): Adjust.
>> >         * trans-decl.c (gfc_allocate_lang_decl): Likewise.
>> >         (gfc_find_module): Likewise.
>> >         * trans-types.c (gfc_get_nodesc_array_type): Likewise.
>> >         (gfc_get_array_type_bounds): Likewise.
>> >         (gfc_nonrestricted_type): Likewise.
>> >         * trans.h: Don't use variable_size gty attribute.
>> >
>> > gcc/c/ChangeLog:
>> >
>> >         * c-decl.c (bind): Adjust.
>> >         (record_inline_static): Likewise.
>> >         (push_scope): Likewise.
>> >         (make_label): Likewise.
>> >         (lookup_label_for_goto): Likewise.
>> >         (finish_struct): Likewise.
>> >         (finish_enum): Likewise.
>> >         (store_parm_decls): Likewise.
>> >         (c_push_function_context): Likewise.
>> >         * c-lang.h: Remove usage of variable_size gty attribute.
>> >         * c-parser.c (c_parse_init): Adjust.
>> >         (c_parse_file): Likewise.
>> >
>> > gcc/lto/ChangeLog:
>> >
>> >         * lto-tree.h: Don't use variable_size gty attribute.
>> >         * lto.c (lto_read_in_decl_state): Adjust.
>> >         (create_subid_section_table): Likewise.
>> >         (lto_flatten_files): Likewise.
>> >         (read_cgraph_and_symbols): Likewise.
>> >
>> > gcc/java/ChangeLog:
>> >
>> >         * class.c (add_method_1): Adjust.
>> >         (java_treetreehash_new): Likewise.
>> >         * constants.c (set_constant_entry): Likewise.
>> >         (cpool_for_class): Likewise.
>> >         * decl.c (make_binding_level): Likewise.
>> >         (java_dup_lang_specific_decl): Likewise.
>> >         * expr.c (add_type_assertion): Likewise.
>> >         * java-tree.h (MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC): Likewise.
>> >         (lang_decl): don't use variable_size gty attribute.
>> >         (MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC): Adjust.
>> >         (lang_type): Don't use variable_size gty attribute.
>> >         * jcf-parse.c (java_parse_file): Adjust.
>> >         (process_zip_dir): Likewise.
>> >         * jcf.h: Remove usage of variable_size gty attribute.
>> > ---
>> >  gcc/ada/gcc-interface/ada-tree.h    |  10 +--
>> >  gcc/alias.c                         |   2 +-
>> >  gcc/bitmap.c                        |   4 +-
>> >  gcc/c-family/c-common.h             |   2 +-
>> >  gcc/c-family/c-pragma.c             |   7 +-
>> >  gcc/c/c-decl.c                      |  23 +++----
>> >  gcc/c/c-lang.h                      |   4 +-
>> >  gcc/c/c-parser.c                    |   4 +-
>> >  gcc/cfg.c                           |  10 +--
>> >  gcc/cfgloop.c                       |   8 +--
>> >  gcc/cfgrtl.c                        |   2 +-
>> >  gcc/cgraph.c                        |   8 +--
>> >  gcc/cgraphclones.c                  |   2 +-
>> >  gcc/cgraphunit.c                    |   4 +-
>> >  gcc/config/i386/i386.c              |   6 +-
>> >  gcc/coverage.c                      |   2 +-
>> >  gcc/cp/cp-cilkplus.c                |   2 +-
>> >  gcc/cp/cp-objcp-common.c            |   2 +-
>> >  gcc/cp/cp-tree.h                    |   4 +-
>> >  gcc/cp/decl.c                       |   8 +--
>> >  gcc/cp/lex.c                        |   2 +-
>> >  gcc/cp/name-lookup.c                |  14 ++--
>> >  gcc/cp/parser.c                     |  14 ++--
>> >  gcc/cp/pt.c                         |  10 +--
>> >  gcc/cp/semantics.c                  |   4 +-
>> >  gcc/cp/typeck2.c                    |   2 +-
>> >  gcc/dbxout.c                        |   2 +-
>> >  gcc/doc/gty.texi                    |  32 ---------
>> >  gcc/dwarf2cfi.c                     |   8 +--
>> >  gcc/dwarf2out.c                     |  44 ++++++-------
>> >  gcc/emit-rtl.c                      |  10 +--
>> >  gcc/except.c                        |  10 +--
>> >  gcc/fortran/f95-lang.c              |   2 +-
>> >  gcc/fortran/trans-decl.c            |   6 +-
>> >  gcc/fortran/trans-types.c           |  15 ++---
>> >  gcc/fortran/trans.h                 |   7 +-
>> >  gcc/function.c                      |  18 ++---
>> >  gcc/gengtype.c                      | 128 ------------------------------------
>> >  gcc/ggc-common.c                    |   4 +-
>> >  gcc/ggc.h                           |  31 +++++++--
>> >  gcc/gimple.c                        |   9 +--
>> >  gcc/go/go-lang.c                    |   2 +-
>> >  gcc/ipa-cp.c                        |   6 +-
>> >  gcc/ipa-devirt.c                    |   2 +-
>> >  gcc/ipa-prop.c                      |   4 +-
>> >  gcc/java/class.c                    |   6 +-
>> >  gcc/java/constants.c                |   9 +--
>> >  gcc/java/decl.c                     |   4 +-
>> >  gcc/java/expr.c                     |   2 +-
>> >  gcc/java/java-tree.h                |  15 ++---
>> >  gcc/java/jcf-parse.c                |   6 +-
>> >  gcc/java/jcf.h                      |   2 +-
>> >  gcc/loop-iv.c                       |   2 +-
>> >  gcc/lto-cgraph.c                    |   2 +-
>> >  gcc/lto-section-in.c                |   2 +-
>> >  gcc/lto-streamer-in.c               |   8 +--
>> >  gcc/lto/lto-tree.h                  |   4 +-
>> >  gcc/lto/lto.c                       |   8 +--
>> >  gcc/objc/objc-act.c                 |   4 +-
>> >  gcc/objc/objc-act.h                 |   4 +-
>> >  gcc/objc/objc-map.c                 |  10 +--
>> >  gcc/objc/objc-next-runtime-abi-02.c |   4 +-
>> >  gcc/optabs.c                        |   4 +-
>> >  gcc/passes.c                        |   2 +-
>> >  gcc/rtl.h                           |   4 +-
>> >  gcc/sese.c                          |   2 +-
>> >  gcc/stringpool.c                    |   4 +-
>> >  gcc/target-globals.c                |   4 +-
>> >  gcc/toplev.c                        |   2 +-
>> >  gcc/trans-mem.c                     |   4 +-
>> >  gcc/tree-cfg.c                      |   2 +-
>> >  gcc/tree-data-ref.h                 |   2 +-
>> >  gcc/tree-eh.c                       |   2 +-
>> >  gcc/tree-iterator.c                 |   4 +-
>> >  gcc/tree-scalar-evolution.c         |   2 +-
>> >  gcc/tree-ssa-loop-niter.c           |   2 +-
>> >  gcc/tree-ssa-operands.h             |   2 +-
>> >  gcc/tree-ssa.c                      |   2 +-
>> >  gcc/tree-ssanames.c                 |   8 +--
>> >  gcc/tree-streamer-in.c              |   4 +-
>> >  gcc/tree.c                          |  14 ++--
>> >  gcc/ubsan.c                         |   2 +-
>> >  gcc/varasm.c                        |  16 ++---
>> >  gcc/varpool.c                       |   2 +-
>> >  84 files changed, 250 insertions(+), 432 deletions(-)
>> >
>> > diff --git a/gcc/ada/gcc-interface/ada-tree.h b/gcc/ada/gcc-interface/ada-tree.h
>> > index 5ea386f..30f8ec4 100644
>> > --- a/gcc/ada/gcc-interface/ada-tree.h
>> > +++ b/gcc/ada/gcc-interface/ada-tree.h
>> > @@ -32,13 +32,9 @@ union GTY((desc ("0"),
>> >                        desc ("tree_node_structure (&%h)"))) generic;
>> >  };
>> >
>> > -/* Ada uses the lang_decl and lang_type fields to hold a tree.
>> > -
>> > -   FIXME: the variable_size annotation here is needed because these types are
>> > -   variable-sized in some other front-ends.  Due to gengtype deficiency, the
>> > -   GTY options of such types have to agree across all front-ends.  */
>> > -struct GTY((variable_size)) lang_type { tree t; };
>> > -struct GTY((variable_size)) lang_decl { tree t; };
>> > +/* Ada uses the lang_decl and lang_type fields to hold a tree.  */
>> > +struct GTY(()) lang_type { tree t; };
>> > +struct GTY(()) lang_decl { tree t; };
>> >
>> >  /* Macros to get and set the tree in TYPE_LANG_SPECIFIC.  */
>> >  #define GET_TYPE_LANG_SPECIFIC(NODE) \
>> > diff --git a/gcc/alias.c b/gcc/alias.c
>> > index 5f37402..bd45fcc 100644
>> > --- a/gcc/alias.c
>> > +++ b/gcc/alias.c
>> > @@ -943,7 +943,7 @@ record_alias_subset (alias_set_type superset, alias_set_type subset)
>> >      {
>> >        /* Create an entry for the SUPERSET, so that we have a place to
>> >          attach the SUBSET.  */
>> > -      superset_entry = ggc_alloc_cleared_alias_set_entry_d ();
>> > +      superset_entry = ggc_cleared_alloc<alias_set_entry_d> ();
>> >        superset_entry->alias_set = superset;
>> >        superset_entry->children
>> >         = splay_tree_new_ggc (splay_tree_compare_ints,
>> > diff --git a/gcc/bitmap.c b/gcc/bitmap.c
>> > index 4855a66..b2914e1 100644
>> > --- a/gcc/bitmap.c
>> > +++ b/gcc/bitmap.c
>> > @@ -244,7 +244,7 @@ bitmap_element_allocate (bitmap head)
>> >           /*  Inner list was just a singleton.  */
>> >           bitmap_ggc_free = element->prev;
>> >        else
>> > -       element = ggc_alloc_bitmap_element ();
>> > +       element = ggc_alloc<bitmap_element> ();
>> >      }
>> >
>> >    if (GATHER_STATISTICS)
>> > @@ -388,7 +388,7 @@ bitmap_gc_alloc_stat (ALONE_MEM_STAT_DECL)
>> >  {
>> >    bitmap map;
>> >
>> > -  map = ggc_alloc_bitmap_head ();
>> > +  map = ggc_alloc<bitmap_head> ();
>> >    bitmap_initialize_stat (map, NULL PASS_MEM_STAT);
>> >
>> >    if (GATHER_STATISTICS)
>> > diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
>> > index 57b7dce..d3b1099 100644
>> > --- a/gcc/c-family/c-common.h
>> > +++ b/gcc/c-family/c-common.h
>> > @@ -440,7 +440,7 @@ extern GTY(()) tree c_global_trees[CTI_MAX];
>> >
>> >  /* In a RECORD_TYPE, a sorted array of the fields of the type, not a
>> >     tree for size reasons.  */
>> > -struct GTY((variable_size)) sorted_fields_type {
>> > +struct GTY(()) sorted_fields_type {
>> >    int len;
>> >    tree GTY((length ("%h.len"))) elts[1];
>> >  };
>> > diff --git a/gcc/c-family/c-pragma.c b/gcc/c-family/c-pragma.c
>> > index 9e2a00e..7b016ab 100644
>> > --- a/gcc/c-family/c-pragma.c
>> > +++ b/gcc/c-family/c-pragma.c
>> > @@ -74,9 +74,7 @@ static void pop_alignment (tree);
>> >  static void
>> >  push_alignment (int alignment, tree id)
>> >  {
>> > -  align_stack * entry;
>> > -
>> > -  entry = ggc_alloc_align_stack ();
>> > +  align_stack * entry = ggc_alloc<align_stack> ();
>> >
>> >    entry->alignment  = alignment;
>> >    entry->id        = id;
>> > @@ -911,7 +909,6 @@ handle_pragma_push_options (cpp_reader *ARG_UNUSED(dummy))
>> >  {
>> >    enum cpp_ttype token;
>> >    tree x = 0;
>> > -  opt_stack *p;
>> >
>> >    token = pragma_lex (&x);
>> >    if (token != CPP_EOF)
>> > @@ -920,7 +917,7 @@ handle_pragma_push_options (cpp_reader *ARG_UNUSED(dummy))
>> >        return;
>> >      }
>> >
>> > -  p = ggc_alloc_opt_stack ();
>> > +  opt_stack *p = ggc_alloc<opt_stack> ();
>> >    p->prev = options_stack;
>> >    options_stack = p;
>> >
>> > diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
>> > index e8b8166..2400849 100644
>> > --- a/gcc/c/c-decl.c
>> > +++ b/gcc/c/c-decl.c
>> > @@ -638,7 +638,7 @@ bind (tree name, tree decl, struct c_scope *scope, bool invisible,
>> >        binding_freelist = b->prev;
>> >      }
>> >    else
>> > -    b = ggc_alloc_c_binding ();
>> > +    b = ggc_alloc<c_binding> ();
>> >
>> >    b->shadowed = 0;
>> >    b->decl = decl;
>> > @@ -755,7 +755,7 @@ void
>> >  record_inline_static (location_t loc, tree func, tree decl,
>> >                       enum c_inline_static_type type)
>> >  {
>> > -  struct c_inline_static *csi = ggc_alloc_c_inline_static ();
>> > +  c_inline_static *csi = ggc_alloc<c_inline_static> ();
>> >    csi->location = loc;
>> >    csi->function = func;
>> >    csi->static_decl = decl;
>> > @@ -952,7 +952,7 @@ push_scope (void)
>> >           scope_freelist = scope->outer;
>> >         }
>> >        else
>> > -       scope = ggc_alloc_cleared_c_scope ();
>> > +       scope = ggc_cleared_alloc<c_scope> ();
>> >
>> >        /* The FLOAT_CONST_DECIMAL64 pragma applies to nested scopes.  */
>> >        if (current_scope)
>> > @@ -3084,12 +3084,10 @@ make_label (location_t location, tree name, bool defining,
>> >             struct c_label_vars **p_label_vars)
>> >  {
>> >    tree label = build_decl (location, LABEL_DECL, name, void_type_node);
>> > -  struct c_label_vars *label_vars;
>> > -
>> >    DECL_CONTEXT (label) = current_function_decl;
>> >    DECL_MODE (label) = VOIDmode;
>> >
>> > -  label_vars = ggc_alloc_c_label_vars ();
>> > +  c_label_vars *label_vars = ggc_alloc<c_label_vars> ();
>> >    label_vars->shadowed = NULL;
>> >    set_spot_bindings (&label_vars->label_bindings, defining);
>> >    label_vars->decls_in_scope = make_tree_vector ();
>> > @@ -3185,9 +3183,8 @@ lookup_label_for_goto (location_t loc, tree name)
>> >       list for possible later warnings.  */
>> >    if (label_vars->label_bindings.scope == NULL)
>> >      {
>> > -      struct c_goto_bindings *g;
>> > +      c_goto_bindings *g = ggc_alloc<c_goto_bindings> ();
>> >
>> > -      g = ggc_alloc_c_goto_bindings ();
>> >        g->loc = loc;
>> >        set_spot_bindings (&g->goto_bindings, true);
>> >        vec_safe_push (label_vars->gotos, g);
>> > @@ -7423,8 +7420,7 @@ finish_struct (location_t loc, tree t, tree fieldlist, tree attributes,
>> >           ensure that this lives as long as the rest of the struct decl.
>> >           All decls in an inline function need to be saved.  */
>> >
>> > -       space = (struct lang_type *) ggc_internal_cleared_alloc
>> > -         (sizeof (struct lang_type));
>> > +       space = ggc_cleared_alloc<struct lang_type> ();
>> >         space2 = (sorted_fields_type *) ggc_internal_alloc
>> >           (sizeof (struct sorted_fields_type) + len * sizeof (tree));
>> >
>> > @@ -7705,8 +7701,7 @@ finish_enum (tree enumtype, tree values, tree attributes)
>> >
>> >    /* Record the min/max values so that we can warn about bit-field
>> >       enumerations that are too small for the values.  */
>> > -  lt = (struct lang_type *) ggc_internal_cleared_alloc
>> > -    (sizeof (struct lang_type));
>> > +  lt = ggc_cleared_alloc<struct lang_type> ();
>> >    lt->enum_min = minnode;
>> >    lt->enum_max = maxnode;
>> >    TYPE_LANG_SPECIFIC (enumtype) = lt;
>> > @@ -8477,7 +8472,7 @@ store_parm_decls (void)
>> >    allocate_struct_function (fndecl, false);
>> >
>> >    if (warn_unused_local_typedefs)
>> > -    cfun->language = ggc_alloc_cleared_language_function ();
>> > +    cfun->language = ggc_cleared_alloc<language_function> ();
>> >
>> >    /* Begin the statement tree for this function.  */
>> >    DECL_SAVED_TREE (fndecl) = push_stmt_list ();
>> > @@ -8801,7 +8796,7 @@ c_push_function_context (void)
>> >    /* cfun->language might have been already allocated by the use of
>> >       -Wunused-local-typedefs.  In that case, just re-use it.  */
>> >    if (p == NULL)
>> > -    cfun->language = p = ggc_alloc_cleared_language_function ();
>> > +    cfun->language = p = ggc_cleared_alloc<language_function> ();
>> >
>> >    p->base.x_stmt_tree = c_stmt_tree;
>> >    c_stmt_tree.x_cur_stmt_list = vec_safe_copy (c_stmt_tree.x_cur_stmt_list);
>> > diff --git a/gcc/c/c-lang.h b/gcc/c/c-lang.h
>> > index 7fcf333..e974906 100644
>> > --- a/gcc/c/c-lang.h
>> > +++ b/gcc/c/c-lang.h
>> > @@ -23,7 +23,7 @@ along with GCC; see the file COPYING3.  If not see
>> >  #include "c-family/c-common.h"
>> >  #include "ggc.h"
>> >
>> > -struct GTY((variable_size)) lang_type {
>> > +struct GTY(()) lang_type {
>> >    /* In a RECORD_TYPE, a sorted array of the fields of the type.  */
>> >    struct sorted_fields_type * GTY ((reorder ("resort_sorted_fields"))) s;
>> >    /* In an ENUMERAL_TYPE, the min and max values.  */
>> > @@ -35,7 +35,7 @@ struct GTY((variable_size)) lang_type {
>> >    tree objc_info;
>> >  };
>> >
>> > -struct GTY((variable_size)) lang_decl {
>> > +struct GTY(()) lang_decl {
>> >    char dummy;
>> >  };
>> >
>> > diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
>> > index 56f79f6..2843e9d 100644
>> > --- a/gcc/c/c-parser.c
>> > +++ b/gcc/c/c-parser.c
>> > @@ -90,7 +90,7 @@ c_parse_init (void)
>> >    if (!c_dialect_objc ())
>> >      mask |= D_OBJC | D_CXX_OBJC;
>> >
>> > -  ridpointers = ggc_alloc_cleared_vec_tree ((int) RID_MAX);
>> > +  ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX);
>> >    for (i = 0; i < num_c_common_reswords; i++)
>> >      {
>> >        /* If a keyword is disabled, do not enter it into the table
>> > @@ -14039,7 +14039,7 @@ c_parse_file (void)
>> >    if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
>> >      c_parser_pragma_pch_preprocess (&tparser);
>> >
>> > -  the_parser = ggc_alloc_c_parser ();
>> > +  the_parser = ggc_alloc<c_parser> ();
>> >    *the_parser = tparser;
>> >    if (tparser.tokens == &tparser.tokens_buf[0])
>> >      the_parser->tokens = &the_parser->tokens_buf[0];
>> > diff --git a/gcc/cfg.c b/gcc/cfg.c
>> > index 3b6349a..aef1145 100644
>> > --- a/gcc/cfg.c
>> > +++ b/gcc/cfg.c
>> > @@ -68,13 +68,13 @@ void
>> >  init_flow (struct function *the_fun)
>> >  {
>> >    if (!the_fun->cfg)
>> > -    the_fun->cfg = ggc_alloc_cleared_control_flow_graph ();
>> > +    the_fun->cfg = ggc_cleared_alloc<control_flow_graph> ();
>> >    n_edges_for_fn (the_fun) = 0;
>> >    ENTRY_BLOCK_PTR_FOR_FN (the_fun)
>> > -    = ggc_alloc_cleared_basic_block_def ();
>> > +    = ggc_cleared_alloc<basic_block_def> ();
>> >    ENTRY_BLOCK_PTR_FOR_FN (the_fun)->index = ENTRY_BLOCK;
>> >    EXIT_BLOCK_PTR_FOR_FN (the_fun)
>> > -    = ggc_alloc_cleared_basic_block_def ();
>> > +    = ggc_cleared_alloc<basic_block_def> ();
>> >    EXIT_BLOCK_PTR_FOR_FN (the_fun)->index = EXIT_BLOCK;
>> >    ENTRY_BLOCK_PTR_FOR_FN (the_fun)->next_bb
>> >      = EXIT_BLOCK_PTR_FOR_FN (the_fun);
>> > @@ -123,7 +123,7 @@ basic_block
>> >  alloc_block (void)
>> >  {
>> >    basic_block bb;
>> > -  bb = ggc_alloc_cleared_basic_block_def ();
>> > +  bb = ggc_cleared_alloc<basic_block_def> ();
>> >    return bb;
>> >  }
>> >
>> > @@ -261,7 +261,7 @@ edge
>> >  unchecked_make_edge (basic_block src, basic_block dst, int flags)
>> >  {
>> >    edge e;
>> > -  e = ggc_alloc_cleared_edge_def ();
>> > +  e = ggc_cleared_alloc<edge_def> ();
>> >    n_edges_for_fn (cfun)++;
>> >
>> >    e->src = src;
>> > diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c
>> > index 70744d8..3ff5b6a 100644
>> > --- a/gcc/cfgloop.c
>> > +++ b/gcc/cfgloop.c
>> > @@ -331,9 +331,9 @@ flow_loop_tree_node_remove (struct loop *loop)
>> >  struct loop *
>> >  alloc_loop (void)
>> >  {
>> > -  struct loop *loop = ggc_alloc_cleared_loop ();
>> > +  struct loop *loop = ggc_cleared_alloc<struct loop> ();
>> >
>> > -  loop->exits = ggc_alloc_cleared_loop_exit ();
>> > +  loop->exits = ggc_cleared_alloc<loop_exit> ();
>> >    loop->exits->next = loop->exits->prev = loop->exits;
>> >    loop->can_be_parallel = false;
>> >
>> > @@ -414,7 +414,7 @@ flow_loops_find (struct loops *loops)
>> >
>> >    if (!loops)
>> >      {
>> > -      loops = ggc_alloc_cleared_loops ();
>> > +      loops = ggc_cleared_alloc<struct loops> ();
>> >        init_loops_structure (cfun, loops, 1);
>> >      }
>> >
>> > @@ -1028,7 +1028,7 @@ rescan_loop_exit (edge e, bool new_edge, bool removed)
>> >            aloop != cloop;
>> >            aloop = loop_outer (aloop))
>> >         {
>> > -         exit = ggc_alloc_loop_exit ();
>> > +         exit = ggc_alloc<loop_exit> ();
>> >           exit->e = e;
>> >
>> >           exit->next = aloop->exits->next;
>> > diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
>> > index 5dd27d2..06fc43e 100644
>> > --- a/gcc/cfgrtl.c
>> > +++ b/gcc/cfgrtl.c
>> > @@ -4954,7 +4954,7 @@ init_rtl_bb_info (basic_block bb)
>> >  {
>> >    gcc_assert (!bb->il.x.rtl);
>> >    bb->il.x.head_ = NULL;
>> > -  bb->il.x.rtl = ggc_alloc_cleared_rtl_bb_info ();
>> > +  bb->il.x.rtl = ggc_cleared_alloc<rtl_bb_info> ();
>> >  }
>> >
>> >  /* Returns true if it is possible to remove edge E by redirecting
>> > diff --git a/gcc/cgraph.c b/gcc/cgraph.c
>> > index ee192ed..f28492e 100644
>> > --- a/gcc/cgraph.c
>> > +++ b/gcc/cgraph.c
>> > @@ -198,7 +198,7 @@ insert_new_cgraph_node_version (struct cgraph_node *node)
>> >    void **slot;
>> >
>> >    version_info_node = NULL;
>> > -  version_info_node = ggc_alloc_cleared_cgraph_function_version_info ();
>> > +  version_info_node = ggc_cleared_alloc<cgraph_function_version_info> ();
>> >    version_info_node->this_node = node;
>> >
>> >    if (cgraph_fnver_htab == NULL)
>> > @@ -507,7 +507,7 @@ cgraph_allocate_node (void)
>> >      }
>> >    else
>> >      {
>> > -      node = ggc_alloc_cleared_cgraph_node ();
>> > +      node = ggc_cleared_alloc<cgraph_node> ();
>> >        node->uid = cgraph_max_uid++;
>> >      }
>> >
>> > @@ -866,7 +866,7 @@ cgraph_create_edge_1 (struct cgraph_node *caller, struct cgraph_node *callee,
>> >      }
>> >    else
>> >      {
>> > -      edge = ggc_alloc_cgraph_edge ();
>> > +      edge = ggc_alloc<struct cgraph_edge> ();
>> >        edge->uid = cgraph_edge_max_uid++;
>> >      }
>> >
>> > @@ -938,7 +938,7 @@ cgraph_allocate_init_indirect_info (void)
>> >  {
>> >    struct cgraph_indirect_call_info *ii;
>> >
>> > -  ii = ggc_alloc_cleared_cgraph_indirect_call_info ();
>> > +  ii = ggc_cleared_alloc<cgraph_indirect_call_info> ();
>> >    ii->param_index = -1;
>> >    return ii;
>> >  }
>> > diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
>> > index 48b5379..d61e0f7 100644
>> > --- a/gcc/cgraphclones.c
>> > +++ b/gcc/cgraphclones.c
>> > @@ -146,7 +146,7 @@ cgraph_clone_edge (struct cgraph_edge *e, struct cgraph_node *n,
>> >        if (e->indirect_info)
>> >         {
>> >           new_edge->indirect_info
>> > -           = ggc_alloc_cleared_cgraph_indirect_call_info ();
>> > +           = ggc_cleared_alloc<cgraph_indirect_call_info> ();
>> >           *new_edge->indirect_info = *e->indirect_info;
>> >         }
>> >      }
>> > diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
>> > index 7bf9a07..acb9a7a 100644
>> > --- a/gcc/cgraphunit.c
>> > +++ b/gcc/cgraphunit.c
>> > @@ -570,7 +570,7 @@ add_asm_node (tree asm_str)
>> >  {
>> >    struct asm_node *node;
>> >
>> > -  node = ggc_alloc_cleared_asm_node ();
>> > +  node = ggc_cleared_alloc<asm_node> ();
>> >    node->asm_str = asm_str;
>> >    node->order = symtab_order++;
>> >    node->next = NULL;
>> > @@ -1337,7 +1337,7 @@ init_lowered_empty_function (tree decl, bool in_ssa)
>> >    cfun->curr_properties |= (PROP_gimple_lcf | PROP_gimple_leh | PROP_gimple_any
>> >                             | PROP_cfg | PROP_loops);
>> >
>> > -  set_loops_for_fn (cfun, ggc_alloc_cleared_loops ());
>> > +  set_loops_for_fn (cfun, ggc_cleared_alloc<loops> ());
>> >    init_loops_structure (cfun, loops_for_fn (cfun), 1);
>> >    loops_for_fn (cfun)->state |= LOOPS_MAY_HAVE_MULTIPLE_LATCHES;
>> >
>> > diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
>> > index 895ebbb..848788e 100644
>> > --- a/gcc/config/i386/i386.c
>> > +++ b/gcc/config/i386/i386.c
>> > @@ -13643,7 +13643,7 @@ get_dllimport_decl (tree decl, bool beimport)
>> >    if (h)
>> >      return h->to;
>> >
>> > -  *loc = h = ggc_alloc_tree_map ();
>> > +  *loc = h = ggc_alloc<tree_map> ();
>> >    h->hash = in.hash;
>> >    h->base.from = decl;
>> >    h->to = to = build_decl (DECL_SOURCE_LOCATION (decl),
>> > @@ -24990,7 +24990,7 @@ ix86_init_machine_status (void)
>> >  {
>> >    struct machine_function *f;
>> >
>> > -  f = ggc_alloc_cleared_machine_function ();
>> > +  f = ggc_cleared_alloc<machine_function> ();
>> >    f->use_fast_prologue_epilogue_nregs = -1;
>> >    f->call_abi = ix86_abi;
>> >
>> > @@ -25014,7 +25014,7 @@ assign_386_stack_local (enum machine_mode mode, enum ix86_stack_slot n)
>> >      if (s->mode == mode && s->n == n)
>> >        return validize_mem (copy_rtx (s->rtl));
>> >
>> > -  s = ggc_alloc_stack_local_entry ();
>> > +  s = ggc_alloc<stack_local_entry> ();
>> >    s->n = n;
>> >    s->mode = mode;
>> >    s->rtl = assign_stack_local (mode, GET_MODE_SIZE (mode), 0);
>> > diff --git a/gcc/coverage.c b/gcc/coverage.c
>> > index ff1e67d..5e9005e 100644
>> > --- a/gcc/coverage.c
>> > +++ b/gcc/coverage.c
>> > @@ -667,7 +667,7 @@ coverage_end_function (unsigned lineno_checksum, unsigned cfg_checksum)
>> >          list.  */
>> >        if (!DECL_EXTERNAL (current_function_decl))
>> >         {
>> > -         item = ggc_alloc_coverage_data ();
>> > +         item = ggc_alloc<coverage_data> ();
>> >
>> >           item->ident = current_function_funcdef_no + 1;
>> >           item->lineno_checksum = lineno_checksum;
>> > diff --git a/gcc/cp/cp-cilkplus.c b/gcc/cp/cp-cilkplus.c
>> > index f3a2aff..daa9b8e 100644
>> > --- a/gcc/cp/cp-cilkplus.c
>> > +++ b/gcc/cp/cp-cilkplus.c
>> > @@ -118,7 +118,7 @@ cilk_install_body_with_frame_cleanup (tree fndecl, tree orig_body, void *wd)
>> >    tree dtor = create_cilk_function_exit (frame, false, false);
>> >    add_local_decl (cfun, frame);
>> >
>> > -  cfun->language = ggc_alloc_cleared_language_function ();
>> > +  cfun->language = ggc_cleared_alloc<language_function> ();
>> >
>> >    location_t loc = EXPR_LOCATION (orig_body);
>> >    tree list = alloc_stmt_list ();
>> > diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
>> > index aa0ff83..78dddef 100644
>> > --- a/gcc/cp/cp-objcp-common.c
>> > +++ b/gcc/cp/cp-objcp-common.c
>> > @@ -208,7 +208,7 @@ decl_shadowed_for_var_insert (tree from, tree to)
>> >    struct tree_decl_map *h;
>> >    void **loc;
>> >
>> > -  h = ggc_alloc_tree_decl_map ();
>> > +  h = ggc_alloc<tree_decl_map> ();
>> >    h->base.from = from;
>> >    h->to = to;
>> >    loc = htab_find_slot_with_hash (shadowed_var_for_decl, h, DECL_UID (from),
>> > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
>> > index 9fbc7f8..b76af3c 100644
>> > --- a/gcc/cp/cp-tree.h
>> > +++ b/gcc/cp/cp-tree.h
>> > @@ -1482,7 +1482,7 @@ struct GTY(()) lang_type_ptrmem {
>> >    tree record;
>> >  };
>> >
>> > -struct GTY((variable_size)) lang_type {
>> > +struct GTY(()) lang_type {
>> >    union lang_type_u
>> >    {
>> >      struct lang_type_header GTY((skip (""))) h;
>> > @@ -2060,7 +2060,7 @@ struct GTY(()) lang_decl_parm {
>> >     union rather than a struct containing a union as its only field, but
>> >     tree.h declares it as a struct.  */
>> >
>> > -struct GTY((variable_size)) lang_decl {
>> > +struct GTY(()) lang_decl {
>> >    union GTY((desc ("%h.base.selector"))) lang_decl_u {
>> >      struct lang_decl_base GTY ((default)) base;
>> >      struct lang_decl_min GTY((tag ("0"))) min;
>> > diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
>> > index 7ce55c8..4ad6f16 100644
>> > --- a/gcc/cp/decl.c
>> > +++ b/gcc/cp/decl.c
>> > @@ -2700,7 +2700,7 @@ make_label_decl (tree id, int local_p)
>> >    /* Record this label on the list of labels used in this function.
>> >       We do this before calling make_label_decl so that we get the
>> >       IDENTIFIER_LABEL_VALUE before the new label is declared.  */
>> > -  ent = ggc_alloc_cleared_named_label_entry ();
>> > +  ent = ggc_cleared_alloc<named_label_entry> ();
>> >    ent->label_decl = decl;
>> >
>> >    slot = htab_find_slot (named_labels, ent, INSERT);
>> > @@ -2931,7 +2931,7 @@ check_goto (tree decl)
>> >           && ent->uses->names_in_scope == current_binding_level->names)
>> >         return;
>> >
>> > -      new_use = ggc_alloc_named_label_use_entry ();
>> > +      new_use = ggc_alloc<named_label_use_entry> ();
>> >        new_use->binding_level = current_binding_level;
>> >        new_use->names_in_scope = current_binding_level->names;
>> >        new_use->o_goto_locus = input_location;
>> > @@ -13301,7 +13301,7 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
>> >
>> >    /* Initialize the language data structures.  Whenever we start
>> >       a new function, we destroy temporaries in the usual way.  */
>> > -  cfun->language = ggc_alloc_cleared_language_function ();
>> > +  cfun->language = ggc_cleared_alloc<language_function> ();
>> >    current_stmt_tree ()->stmts_are_full_exprs_p = 1;
>> >    current_binding_level = bl;
>> >
>> > @@ -13603,7 +13603,7 @@ save_function_data (tree decl)
>> >    gcc_assert (!DECL_PENDING_INLINE_P (decl));
>> >
>> >    /* Make a copy.  */
>> > -  f = ggc_alloc_language_function ();
>> > +  f = ggc_alloc<language_function> ();
>> >    memcpy (f, cp_function_chain, sizeof (struct language_function));
>> >    DECL_SAVED_FUNCTION_DATA (decl) = f;
>> >
>> > diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c
>> > index 46c28ae..57b779d 100644
>> > --- a/gcc/cp/lex.c
>> > +++ b/gcc/cp/lex.c
>> > @@ -182,7 +182,7 @@ init_reswords (void)
>> >    /* The Objective-C keywords are all context-dependent.  */
>> >    mask |= D_OBJC;
>> >
>> > -  ridpointers = ggc_alloc_cleared_vec_tree ((int) RID_MAX);
>> > +  ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX);
>> >    for (i = 0; i < num_c_common_reswords; i++)
>> >      {
>> >        if (c_common_reswords[i].disable & D_CONLY)
>> > diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
>> > index d900560..2baeeb7 100644
>> > --- a/gcc/cp/name-lookup.c
>> > +++ b/gcc/cp/name-lookup.c
>> > @@ -105,7 +105,7 @@ binding_entry_make (tree name, tree type)
>> >        free_binding_entry = entry->chain;
>> >      }
>> >    else
>> > -    entry = ggc_alloc_binding_entry_s ();
>> > +    entry = ggc_alloc<binding_entry_s> ();
>> >
>> >    entry->name = name;
>> >    entry->type = type;
>> > @@ -147,7 +147,7 @@ binding_table_construct (binding_table table, size_t chain_count)
>> >  {
>> >    table->chain_count = chain_count;
>> >    table->entry_count = 0;
>> > -  table->chain = ggc_alloc_cleared_vec_binding_entry (table->chain_count);
>> > +  table->chain = ggc_cleared_vec_alloc<binding_entry> (table->chain_count);
>> >  }
>> >
>> >  /* Make TABLE's entries ready for reuse.  */
>> > @@ -181,7 +181,7 @@ binding_table_free (binding_table table)
>> >  static inline binding_table
>> >  binding_table_new (size_t chain_count)
>> >  {
>> > -  binding_table table = ggc_alloc_binding_table_s ();
>> > +  binding_table table = ggc_alloc<binding_table_s> ();
>> >    table->chain = NULL;
>> >    binding_table_construct (table, chain_count);
>> >    return table;
>> > @@ -299,7 +299,7 @@ cxx_binding_make (tree value, tree type)
>> >        free_bindings = binding->previous;
>> >      }
>> >    else
>> > -    binding = ggc_alloc_cxx_binding ();
>> > +    binding = ggc_alloc<cxx_binding> ();
>> >
>> >    cxx_binding_init (binding, value, type);
>> >
>> > @@ -775,7 +775,7 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
>> >                       = htab_create_ggc (20, cxx_int_tree_map_hash,
>> >                                          cxx_int_tree_map_eq, NULL);
>> >
>> > -                 h = ggc_alloc_cxx_int_tree_map ();
>> > +                 h = ggc_alloc<cxx_int_tree_map> ();
>> >                   h->uid = DECL_UID (x);
>> >                   h->to = t;
>> >                   loc = htab_find_slot_with_hash
>> > @@ -1544,7 +1544,7 @@ begin_scope (scope_kind kind, tree entity)
>> >        free_binding_level = scope->level_chain;
>> >      }
>> >    else
>> > -    scope = ggc_alloc_cleared_cp_binding_level ();
>> > +    scope = ggc_cleared_alloc<cp_binding_level> ();
>> >
>> >    scope->this_entity = entity;
>> >    scope->more_cleanups_ok = true;
>> > @@ -6074,7 +6074,7 @@ push_to_top_level (void)
>> >    bool need_pop;
>> >
>> >    bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
>> > -  s = ggc_alloc_cleared_saved_scope ();
>> > +  s = ggc_cleared_alloc<saved_scope> ();
>> >
>> >    b = scope_chain ? current_binding_level : 0;
>> >
>> > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
>> > index c1d94ae..a2f9355 100644
>> > --- a/gcc/cp/parser.c
>> > +++ b/gcc/cp/parser.c
>> > @@ -602,7 +602,7 @@ cp_lexer_alloc (void)
>> >    c_common_no_more_pch ();
>> >
>> >    /* Allocate the memory.  */
>> > -  lexer = ggc_alloc_cleared_cp_lexer ();
>> > +  lexer = ggc_cleared_alloc<cp_lexer> ();
>> >
>> >    /* Initially we are not debugging.  */
>> >    lexer->debugging_p = false;
>> > @@ -665,7 +665,7 @@ cp_lexer_new_from_tokens (cp_token_cache *cache)
>> >  {
>> >    cp_token *first = cache->first;
>> >    cp_token *last = cache->last;
>> > -  cp_lexer *lexer = ggc_alloc_cleared_cp_lexer ();
>> > +  cp_lexer *lexer = ggc_cleared_alloc<cp_lexer> ();
>> >
>> >    /* We do not own the buffer.  */
>> >    lexer->buffer = NULL;
>> > @@ -1240,7 +1240,7 @@ cp_lexer_stop_debugging (cp_lexer* lexer)
>> >  static cp_token_cache *
>> >  cp_token_cache_new (cp_token *first, cp_token *last)
>> >  {
>> > -  cp_token_cache *cache = ggc_alloc_cp_token_cache ();
>> > +  cp_token_cache *cache = ggc_alloc<cp_token_cache> ();
>> >    cache->first = first;
>> >    cache->last = last;
>> >    return cache;
>> > @@ -1822,7 +1822,7 @@ cp_parser_context_new (cp_parser_context* next)
>> >        memset (context, 0, sizeof (*context));
>> >      }
>> >    else
>> > -    context = ggc_alloc_cleared_cp_parser_context ();
>> > +    context = ggc_cleared_alloc<cp_parser_context> ();
>> >
>> >    /* No errors have occurred yet in this context.  */
>> >    context->status = CP_PARSER_STATUS_KIND_NO_ERROR;
>> > @@ -3411,7 +3411,7 @@ cp_parser_new (void)
>> >    for (i = 0; i < sizeof (binops) / sizeof (binops[0]); i++)
>> >      binops_by_token[binops[i].token_type] = binops[i];
>> >
>> > -  parser = ggc_alloc_cleared_cp_parser ();
>> > +  parser = ggc_cleared_alloc<cp_parser> ();
>> >    parser->lexer = lexer;
>> >    parser->context = cp_parser_context_new (NULL);
>> >
>> > @@ -5425,7 +5425,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
>> >        token->type = CPP_NESTED_NAME_SPECIFIER;
>> >        /* Retrieve any deferred checks.  Do not pop this access checks yet
>> >          so the memory will not be reclaimed during token replacing below.  */
>> > -      token->u.tree_check_value = ggc_alloc_cleared_tree_check ();
>> > +      token->u.tree_check_value = ggc_cleared_alloc<struct tree_check> ();
>> >        token->u.tree_check_value->value = parser->scope;
>> >        token->u.tree_check_value->checks = get_deferred_access_checks ();
>> >        token->u.tree_check_value->qualifying_scope =
>> > @@ -13500,7 +13500,7 @@ cp_parser_template_id (cp_parser *parser,
>> >        token->type = CPP_TEMPLATE_ID;
>> >        /* Retrieve any deferred checks.  Do not pop this access checks yet
>> >          so the memory will not be reclaimed during token replacing below.  */
>> > -      token->u.tree_check_value = ggc_alloc_cleared_tree_check ();
>> > +      token->u.tree_check_value = ggc_cleared_alloc<struct tree_check> ();
>> >        token->u.tree_check_value->value = template_id;
>> >        token->u.tree_check_value->checks = get_deferred_access_checks ();
>> >        token->keyword = RID_MAX;
>> > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
>> > index c74e7ae..b1e6c14 100644
>> > --- a/gcc/cp/pt.c
>> > +++ b/gcc/cp/pt.c
>> > @@ -940,7 +940,7 @@ maybe_process_partial_specialization (tree type)
>> >                   elt.args = INNERMOST_TEMPLATE_ARGS (elt.args);
>> >
>> >                   slot = htab_find_slot (type_specializations, &elt, INSERT);
>> > -                 entry = ggc_alloc_spec_entry ();
>> > +                 entry = ggc_alloc<spec_entry> ();
>> >                   *entry = elt;
>> >                   *slot = entry;
>> >                 }
>> > @@ -1477,7 +1477,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
>> >
>> >    if (slot != NULL /* !optimize_specialization_lookup_p (tmpl) */)
>> >      {
>> > -      spec_entry *entry = ggc_alloc_spec_entry ();
>> > +      spec_entry *entry = ggc_alloc<spec_entry> ();
>> >        gcc_assert (tmpl && args && spec);
>> >        *entry = elt;
>> >        *slot = entry;
>> > @@ -7177,7 +7177,7 @@ add_pending_template (tree d)
>> >    if (level)
>> >      push_tinst_level (d);
>> >
>> > -  pt = ggc_alloc_pending_template ();
>> > +  pt = ggc_alloc<pending_template> ();
>> >    pt->next = NULL;
>> >    pt->tinst = current_tinst_level;
>> >    if (last_pending_template)
>> > @@ -7807,7 +7807,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
>> >        elt.spec = t;
>> >        slot = htab_find_slot_with_hash (type_specializations,
>> >                                        &elt, hash, INSERT);
>> > -      entry = ggc_alloc_spec_entry ();
>> > +      entry = ggc_alloc<spec_entry> ();
>> >        *entry = elt;
>> >        *slot = entry;
>> >
>> > @@ -8232,7 +8232,7 @@ push_tinst_level (tree d)
>> >    if (limit_bad_template_recursion (d))
>> >      return 0;
>> >
>> > -  new_level = ggc_alloc_tinst_level ();
>> > +  new_level = ggc_alloc<tinst_level> ();
>> >    new_level->decl = d;
>> >    new_level->locus = input_location;
>> >    new_level->errors = errorcount+sorrycount;
>> > diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
>> > index 3f8ca44..a8b8dab 100644
>> > --- a/gcc/cp/semantics.c
>> > +++ b/gcc/cp/semantics.c
>> > @@ -8024,7 +8024,7 @@ register_constexpr_fundef (tree fun, tree body)
>> >      htab_find_slot (constexpr_fundef_table, &entry, INSERT);
>> >
>> >    gcc_assert (*slot == NULL);
>> > -  *slot = ggc_alloc_constexpr_fundef ();
>> > +  *slot = ggc_alloc<constexpr_fundef> ();
>> >    **slot = entry;
>> >
>> >    return fun;
>> > @@ -8465,7 +8465,7 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
>> >      {
>> >        /* We need to keep a pointer to the entry, not just the slot, as the
>> >          slot can move in the call to cxx_eval_builtin_function_call.  */
>> > -      *slot = entry = ggc_alloc_constexpr_call ();
>> > +      *slot = entry = ggc_alloc<constexpr_call> ();
>> >        *entry = new_call;
>> >      }
>> >    /* Calls which are in progress have their result set to NULL
>> > diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
>> > index 68e518a..b7fa77b 100644
>> > --- a/gcc/cp/typeck2.c
>> > +++ b/gcc/cp/typeck2.c
>> > @@ -293,7 +293,7 @@ abstract_virtuals_error_sfinae (tree decl, tree type, abstract_class_use use,
>> >        slot = htab_find_slot_with_hash (abstract_pending_vars, type,
>> >                                       (hashval_t)TYPE_UID (type), INSERT);
>> >
>> > -      pat = ggc_alloc_pending_abstract_type ();
>> > +      pat = ggc_alloc<pending_abstract_type> ();
>> >        pat->type = type;
>> >        pat->decl = decl;
>> >        pat->use = use;
>> > diff --git a/gcc/dbxout.c b/gcc/dbxout.c
>> > index 5fbbdf6..0fe9bfe 100644
>> > --- a/gcc/dbxout.c
>> > +++ b/gcc/dbxout.c
>> > @@ -1025,7 +1025,7 @@ dbxout_init (const char *input_file_name)
>> >    const char *mapped_name;
>> >
>> >    typevec_len = 100;
>> > -  typevec = ggc_alloc_cleared_vec_typeinfo (typevec_len);
>> > +  typevec = ggc_cleared_vec_alloc<typeinfo> (typevec_len);
>> >
>> >    /* stabstr_ob contains one string, which will be just fine with
>> >       1-byte alignment.  */
>> > diff --git a/gcc/doc/gty.texi b/gcc/doc/gty.texi
>> > index d32ac00..e50eef6 100644
>> > --- a/gcc/doc/gty.texi
>> > +++ b/gcc/doc/gty.texi
>> > @@ -382,38 +382,6 @@ of pointers.  @code{reorder} functions can be expensive.  When
>> >  possible, it is better to depend on properties of the data, like an ID
>> >  number or the hash of a string instead.
>> >
>> > -@findex variable_size
>> > -@item variable_size
>> > -
>> > -The type machinery expects the types to be of constant size.  When this
>> > -is not true, for example, with structs that have array fields or unions,
>> > -the type machinery cannot tell how many bytes need to be allocated at
>> > -each allocation.  The @code{variable_size} is used to mark such types.
>> > -The type machinery then provides allocators that take a parameter
>> > -indicating an exact size of object being allocated.  Note that the size
>> > -must be provided in bytes whereas the @code{length} option works with
>> > -array lengths in number of elements.
>> > -
>> > -For example,
>> > -@smallexample
>> > -struct GTY((variable_size)) sorted_fields_type @{
>> > -  int len;
>> > -  tree GTY((length ("%h.len"))) elts[1];
>> > -@};
>> > -@end smallexample
>> > -
>> > -Then the objects of @code{struct sorted_fields_type} are allocated in GC
>> > -memory as follows:
>> > -@smallexample
>> > -  field_vec = ggc_alloc_sorted_fields_type (size);
>> > -@end smallexample
>> > -
>> > -If @var{field_vec->elts} stores @var{n} elements, then @var{size}
>> > -could be calculated as follows:
>> > -@smallexample
>> > -  size_t size = sizeof (struct sorted_fields_type) + n * sizeof (tree);
>> > -@end smallexample
>> > -
>> >  @findex atomic
>> >  @item atomic
>> >
>> > diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
>> > index 4180890..47fd028 100644
>> > --- a/gcc/dwarf2cfi.c
>> > +++ b/gcc/dwarf2cfi.c
>> > @@ -356,7 +356,7 @@ need_data_align_sf_opcode (HOST_WIDE_INT off)
>> >  static inline dw_cfi_ref
>> >  new_cfi (void)
>> >  {
>> > -  dw_cfi_ref cfi = ggc_alloc_dw_cfi_node ();
>> > +  dw_cfi_ref cfi = ggc_alloc<dw_cfi_node> ();
>> >
>> >    cfi->dw_cfi_oprnd1.dw_cfi_reg_num = 0;
>> >    cfi->dw_cfi_oprnd2.dw_cfi_reg_num = 0;
>> > @@ -369,7 +369,7 @@ new_cfi (void)
>> >  static dw_cfi_row *
>> >  new_cfi_row (void)
>> >  {
>> > -  dw_cfi_row *row = ggc_alloc_cleared_dw_cfi_row ();
>> > +  dw_cfi_row *row = ggc_cleared_alloc<dw_cfi_row> ();
>> >
>> >    row->cfa.reg = INVALID_REGNUM;
>> >
>> > @@ -381,7 +381,7 @@ new_cfi_row (void)
>> >  static dw_cfi_row *
>> >  copy_cfi_row (dw_cfi_row *src)
>> >  {
>> > -  dw_cfi_row *dst = ggc_alloc_dw_cfi_row ();
>> > +  dw_cfi_row *dst = ggc_alloc<dw_cfi_row> ();
>> >
>> >    *dst = *src;
>> >    dst->reg_save = vec_safe_copy (src->reg_save);
>> > @@ -2892,7 +2892,7 @@ create_cie_data (void)
>> >         case 0:
>> >           break;
>> >         case 1:
>> > -         cie_return_save = ggc_alloc_reg_saved_in_data ();
>> > +         cie_return_save = ggc_alloc<reg_saved_in_data> ();
>> >           *cie_return_save = cie_trace.regs_saved_in_regs[0];
>> >           cie_trace.regs_saved_in_regs.release ();
>> >           break;
>> > diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
>> > index 6133fa3..9e99e46 100644
>> > --- a/gcc/dwarf2out.c
>> > +++ b/gcc/dwarf2out.c
>> > @@ -982,7 +982,7 @@ dwarf2out_alloc_current_fde (void)
>> >  {
>> >    dw_fde_ref fde;
>> >
>> > -  fde = ggc_alloc_cleared_dw_fde_node ();
>> > +  fde = ggc_cleared_alloc<dw_fde_node> ();
>> >    fde->decl = current_function_decl;
>> >    fde->funcdef_number = current_function_funcdef_no;
>> >    fde->fde_index = vec_safe_length (fde_vec);
>> > @@ -1305,7 +1305,7 @@ static inline dw_loc_descr_ref
>> >  new_loc_descr (enum dwarf_location_atom op, unsigned HOST_WIDE_INT oprnd1,
>> >                unsigned HOST_WIDE_INT oprnd2)
>> >  {
>> > -  dw_loc_descr_ref descr = ggc_alloc_cleared_dw_loc_descr_node ();
>> > +  dw_loc_descr_ref descr = ggc_cleared_alloc<dw_loc_descr_node> ();
>> >
>> >    descr->dw_loc_opc = op;
>> >    descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const;
>> > @@ -3872,7 +3872,7 @@ find_AT_string_in_table (const char *str, htab_t table)
>> >                                    htab_hash_string (str), INSERT);
>> >    if (*slot == NULL)
>> >      {
>> > -      node = ggc_alloc_cleared_indirect_string_node ();
>> > +      node = ggc_cleared_alloc<indirect_string_node> ();
>> >        node->str = ggc_strdup (str);
>> >        *slot = node;
>> >      }
>> > @@ -4203,7 +4203,7 @@ add_addr_table_entry (void *addr, enum ate_kind kind)
>> >
>> >    if (*slot == HTAB_EMPTY_ENTRY)
>> >      {
>> > -      node = ggc_alloc_cleared_addr_table_entry ();
>> > +      node = ggc_cleared_alloc<addr_table_entry> ();
>> >        init_addr_table_entry (node, kind, addr);
>> >        *slot = node;
>> >      }
>> > @@ -4779,7 +4779,7 @@ splice_child_die (dw_die_ref parent, dw_die_ref child)
>> >  static inline dw_die_ref
>> >  new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
>> >  {
>> > -  dw_die_ref die = ggc_alloc_cleared_die_node ();
>> > +  dw_die_ref die = ggc_cleared_alloc<die_node> ();
>> >
>> >    die->die_tag = tag_value;
>> >
>> > @@ -4789,7 +4789,7 @@ new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
>> >      {
>> >        limbo_die_node *limbo_node;
>> >
>> > -      limbo_node = ggc_alloc_cleared_limbo_die_node ();
>> > +      limbo_node = ggc_cleared_alloc<limbo_die_node> ();
>> >        limbo_node->die = die;
>> >        limbo_node->created_for = t;
>> >        limbo_node->next = limbo_die_list;
>> > @@ -5106,7 +5106,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
>> >    slot = htab_find_slot_with_hash (decl_loc_table, decl, decl_id, INSERT);
>> >    if (*slot == NULL)
>> >      {
>> > -      temp = ggc_alloc_cleared_var_loc_list ();
>> > +      temp = ggc_cleared_alloc<var_loc_list> ();
>> >        temp->decl_id = decl_id;
>> >        *slot = temp;
>> >      }
>> > @@ -5131,7 +5131,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
>> >           || (NOTE_VAR_LOCATION_STATUS (temp->first->loc)
>> >               != NOTE_VAR_LOCATION_STATUS (loc_note))))
>> >      {
>> > -      loc = ggc_alloc_cleared_var_loc_node ();
>> > +      loc = ggc_cleared_alloc<var_loc_node> ();
>> >        temp->first->next = loc;
>> >        temp->last = loc;
>> >        loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
>> > @@ -5221,7 +5221,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
>> >               memset (loc, '\0', sizeof (*loc));
>> >             }
>> >           else
>> > -           loc = ggc_alloc_cleared_var_loc_node ();
>> > +           loc = ggc_cleared_alloc<var_loc_node> ();
>> >           if (bitsize == -1 || piece_loc == NULL)
>> >             loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
>> >           else
>> > @@ -5238,7 +5238,7 @@ add_var_loc_to_decl (tree decl, rtx loc_note, const char *label)
>> >      }
>> >    else
>> >      {
>> > -      loc = ggc_alloc_cleared_var_loc_node ();
>> > +      loc = ggc_cleared_alloc<var_loc_node> ();
>> >        temp->first = loc;
>> >        temp->last = loc;
>> >        loc->loc = construct_piece_list (loc_note, bitpos, bitsize);
>> > @@ -6868,7 +6868,7 @@ clone_die (dw_die_ref die)
>> >    dw_attr_ref a;
>> >    unsigned ix;
>> >
>> > -  clone = ggc_alloc_cleared_die_node ();
>> > +  clone = ggc_cleared_alloc<die_node> ();
>> >    clone->die_tag = die->die_tag;
>> >
>> >    FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
>> > @@ -6914,7 +6914,7 @@ clone_as_declaration (dw_die_ref die)
>> >        return clone;
>> >      }
>> >
>> > -  clone = ggc_alloc_cleared_die_node ();
>> > +  clone = ggc_cleared_alloc<die_node> ();
>> >    clone->die_tag = die->die_tag;
>> >
>> >    FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
>> > @@ -7274,7 +7274,7 @@ break_out_comdat_types (dw_die_ref die)
>> >          unit = new_die (DW_TAG_type_unit, NULL, NULL);
>> >          add_AT_unsigned (unit, DW_AT_language,
>> >                           get_AT_unsigned (comp_unit_die (), DW_AT_language));
>> > -        type_node = ggc_alloc_cleared_comdat_type_node ();
>> > +        type_node = ggc_cleared_alloc<comdat_type_node> ();
>> >          type_node->root_die = unit;
>> >          type_node->next = comdat_type_list;
>> >          comdat_type_list = type_node;
>> > @@ -8347,7 +8347,7 @@ static inline dw_loc_list_ref
>> >  new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end,
>> >               const char *section)
>> >  {
>> > -  dw_loc_list_ref retlist = ggc_alloc_cleared_dw_loc_list_node ();
>> > +  dw_loc_list_ref retlist = ggc_cleared_alloc<dw_loc_list_node> ();
>> >
>> >    retlist->begin = begin;
>> >    retlist->begin_entry = NULL;
>> > @@ -13891,12 +13891,12 @@ add_loc_descr_to_each (dw_loc_list_ref list, dw_loc_descr_ref ref)
>> >    list = list->dw_loc_next;
>> >    while (list)
>> >      {
>> > -      copy = ggc_alloc_dw_loc_descr_node ();
>> > +      copy = ggc_alloc<dw_loc_descr_node> ();
>> >        memcpy (copy, ref, sizeof (dw_loc_descr_node));
>> >        add_loc_descr (&list->expr, copy);
>> >        while (copy->dw_loc_next)
>> >         {
>> > -         dw_loc_descr_ref new_copy = ggc_alloc_dw_loc_descr_node ();
>> > +         dw_loc_descr_ref new_copy = ggc_alloc<dw_loc_descr_node> ();
>> >           memcpy (new_copy, copy->dw_loc_next, sizeof (dw_loc_descr_node));
>> >           copy->dw_loc_next = new_copy;
>> >           copy = new_copy;
>> > @@ -15678,7 +15678,7 @@ add_location_or_const_value_attribute (dw_die_ref die, tree decl, bool cache_p,
>> >         {
>> >           slot = htab_find_slot_with_hash (cached_dw_loc_list_table, decl,
>> >                                            DECL_UID (decl), INSERT);
>> > -         cache = ggc_alloc_cleared_cached_dw_loc_list ();
>> > +         cache = ggc_cleared_alloc<cached_dw_loc_list> ();
>> >           cache->decl_id = DECL_UID (decl);
>> >           cache->loc_list = list;
>> >           *slot = cache;
>> > @@ -16639,7 +16639,7 @@ add_linkage_name (dw_die_ref die, tree decl)
>> >         {
>> >           limbo_die_node *asm_name;
>> >
>> > -         asm_name = ggc_alloc_cleared_limbo_die_node ();
>> > +         asm_name = ggc_cleared_alloc<limbo_die_node> ();
>> >           asm_name->die = die;
>> >           asm_name->created_for = decl;
>> >           asm_name->next = deferred_asm_name;
>> > @@ -20968,7 +20968,7 @@ lookup_filename (const char *file_name)
>> >    if (*slot)
>> >      return (struct dwarf_file_data *) *slot;
>> >
>> > -  created = ggc_alloc_dwarf_file_data ();
>> > +  created = ggc_alloc<dwarf_file_data> ();
>> >    created->filename = file_name;
>> >    created->emitted_number = 0;
>> >    *slot = created;
>> > @@ -21278,7 +21278,7 @@ dwarf2out_var_location (rtx loc_note)
>> >    if (!var_loc_p)
>> >      {
>> >        struct call_arg_loc_node *ca_loc
>> > -       = ggc_alloc_cleared_call_arg_loc_node ();
>> > +       = ggc_cleared_alloc<call_arg_loc_node> ();
>> >        rtx prev = prev_real_insn (loc_note), x;
>> >        ca_loc->call_arg_loc_note = loc_note;
>> >        ca_loc->next = NULL;
>> > @@ -21353,7 +21353,7 @@ new_line_info_table (void)
>> >  {
>> >    dw_line_info_table *table;
>> >
>> > -  table = ggc_alloc_cleared_dw_line_info_table_struct ();
>> > +  table = ggc_cleared_alloc<dw_line_info_table_struct> ();
>> >    table->file_num = 1;
>> >    table->line_num = 1;
>> >    table->is_stmt = DWARF_LINE_DEFAULT_IS_STMT_START;
>> > @@ -22122,7 +22122,7 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
>> >    vec_alloc (decl_scope_table, 256);
>> >
>> >    /* Allocate the initial hunk of the abbrev_die_table.  */
>> > -  abbrev_die_table = ggc_alloc_cleared_vec_dw_die_ref
>> > +  abbrev_die_table = ggc_cleared_vec_alloc<dw_die_ref>
>> >      (ABBREV_DIE_TABLE_INCREMENT);
>> >    abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT;
>> >    /* Zero-th entry is allocated, but unused.  */
>> > diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
>> > index e3fd0a5..2b64a9f 100644
>> > --- a/gcc/emit-rtl.c
>> > +++ b/gcc/emit-rtl.c
>> > @@ -275,7 +275,7 @@ set_mem_attrs (rtx mem, mem_attrs *attrs)
>> >    if (!MEM_ATTRS (mem)
>> >        || !mem_attrs_eq_p (attrs, MEM_ATTRS (mem)))
>> >      {
>> > -      MEM_ATTRS (mem) = ggc_alloc_mem_attrs ();
>> > +      MEM_ATTRS (mem) = ggc_alloc<mem_attrs> ();
>> >        memcpy (MEM_ATTRS (mem), attrs, sizeof (mem_attrs));
>> >      }
>> >  }
>> > @@ -322,7 +322,7 @@ get_reg_attrs (tree decl, int offset)
>> >    slot = htab_find_slot (reg_attrs_htab, &attrs, INSERT);
>> >    if (*slot == 0)
>> >      {
>> > -      *slot = ggc_alloc_reg_attrs ();
>> > +      *slot = ggc_alloc<reg_attrs> ();
>> >        memcpy (*slot, &attrs, sizeof (reg_attrs));
>> >      }
>> >
>> > @@ -5123,7 +5123,7 @@ start_sequence (void)
>> >        free_sequence_stack = tem->next;
>> >      }
>> >    else
>> > -    tem = ggc_alloc_sequence_stack ();
>> > +    tem = ggc_alloc<sequence_stack> ();
>> >
>> >    tem->next = seq_stack;
>> >    tem->first = get_insns ();
>> > @@ -5456,7 +5456,7 @@ init_emit (void)
>> >    crtl->emit.regno_pointer_align
>> >      = XCNEWVEC (unsigned char, crtl->emit.regno_pointer_align_length);
>> >
>> > -  regno_reg_rtx = ggc_alloc_vec_rtx (crtl->emit.regno_pointer_align_length);
>> > +  regno_reg_rtx = ggc_vec_alloc<rtx> (crtl->emit.regno_pointer_align_length);
>> >
>> >    /* Put copies of all the hard registers into regno_reg_rtx.  */
>> >    memcpy (regno_reg_rtx,
>> > @@ -5606,7 +5606,7 @@ init_emit_regs (void)
>> >    for (i = 0; i < (int) MAX_MACHINE_MODE; i++)
>> >      {
>> >        mode = (enum machine_mode) i;
>> > -      attrs = ggc_alloc_cleared_mem_attrs ();
>> > +      attrs = ggc_cleared_alloc<mem_attrs> ();
>> >        attrs->align = BITS_PER_UNIT;
>> >        attrs->addrspace = ADDR_SPACE_GENERIC;
>> >        if (mode != BLKmode)
>> > diff --git a/gcc/except.c b/gcc/except.c
>> > index 5b33c9c..3da0003 100644
>> > --- a/gcc/except.c
>> > +++ b/gcc/except.c
>> > @@ -333,7 +333,7 @@ init_eh (void)
>> >  void
>> >  init_eh_for_function (void)
>> >  {
>> > -  cfun->eh = ggc_alloc_cleared_eh_status ();
>> > +  cfun->eh = ggc_cleared_alloc<eh_status> ();
>> >
>> >    /* Make sure zero'th entries are used.  */
>> >    vec_safe_push (cfun->eh->region_array, (eh_region)0);
>> > @@ -350,7 +350,7 @@ gen_eh_region (enum eh_region_type type, eh_region outer)
>> >    eh_region new_eh;
>> >
>> >    /* Insert a new blank region as a leaf in the tree.  */
>> > -  new_eh = ggc_alloc_cleared_eh_region_d ();
>> > +  new_eh = ggc_cleared_alloc<eh_region_d> ();
>> >    new_eh->type = type;
>> >    new_eh->outer = outer;
>> >    if (outer)
>> > @@ -407,7 +407,7 @@ gen_eh_region_catch (eh_region t, tree type_or_list)
>> >         add_type_for_runtime (TREE_VALUE (type_node));
>> >      }
>> >
>> > -  c = ggc_alloc_cleared_eh_catch_d ();
>> > +  c = ggc_cleared_alloc<eh_catch_d> ();
>> >    c->type_list = type_list;
>> >    l = t->u.eh_try.last_catch;
>> >    c->prev_catch = l;
>> > @@ -441,7 +441,7 @@ gen_eh_region_must_not_throw (eh_region outer)
>> >  eh_landing_pad
>> >  gen_eh_landing_pad (eh_region region)
>> >  {
>> > -  eh_landing_pad lp = ggc_alloc_cleared_eh_landing_pad_d ();
>> > +  eh_landing_pad lp = ggc_cleared_alloc<eh_landing_pad_d> ();
>> >
>> >    lp->next_lp = region->landing_pads;
>> >    lp->region = region;
>> > @@ -2451,7 +2451,7 @@ add_call_site (rtx landing_pad, int action, int section)
>> >  {
>> >    call_site_record record;
>> >
>> > -  record = ggc_alloc_call_site_record_d ();
>> > +  record = ggc_alloc<call_site_record_d> ();
>> >    record->landing_pad = landing_pad;
>> >    record->action = action;
>> >
>> > diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c
>> > index e25e92a..adee07c 100644
>> > --- a/gcc/fortran/f95-lang.c
>> > +++ b/gcc/fortran/f95-lang.c
>> > @@ -323,7 +323,7 @@ getdecls (void)
>> >  void
>> >  pushlevel (void)
>> >  {
>> > -  struct binding_level *newlevel = ggc_alloc_binding_level ();
>> > +  struct binding_level *newlevel = ggc_alloc<binding_level> ();
>> >
>> >    *newlevel = clear_binding_level;
>> >
>> > diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
>> > index beb99a6..a8882e7 100644
>> > --- a/gcc/fortran/trans-decl.c
>> > +++ b/gcc/fortran/trans-decl.c
>> > @@ -615,9 +615,7 @@ gfc_finish_var_decl (tree decl, gfc_symbol * sym)
>> >  void
>> >  gfc_allocate_lang_decl (tree decl)
>> >  {
>> > -  DECL_LANG_SPECIFIC (decl)
>> > -    = (struct lang_decl *) ggc_internal_cleared_alloc (sizeof
>> > -                                                      (struct lang_decl));
>> > +  DECL_LANG_SPECIFIC (decl) = ggc_cleared_alloc<struct lang_decl> ();
>> >  }
>> >
>> >  /* Remember a symbol to generate initialization/cleanup code at function
>> > @@ -4119,7 +4117,7 @@ gfc_find_module (const char *name)
>> >                                    htab_hash_string (name), INSERT);
>> >    if (*slot == NULL)
>> >      {
>> > -      struct module_htab_entry *entry = ggc_alloc_cleared_module_htab_entry ();
>> > +      module_htab_entry *entry = ggc_cleared_alloc<module_htab_entry> ();
>> >
>> >        entry->name = gfc_get_string (name);
>> >        entry->decls = htab_create_ggc (10, module_htab_decls_hash,
>> > diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
>> > index 84503ce..ab3d601 100644
>> > --- a/gcc/fortran/trans-types.c
>> > +++ b/gcc/fortran/trans-types.c
>> > @@ -1511,9 +1511,7 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * as, gfc_packed packed,
>> >      type = build_variant_type_copy (etype);
>> >
>> >    GFC_ARRAY_TYPE_P (type) = 1;
>> > -  TYPE_LANG_SPECIFIC (type)
>> > -      = (struct lang_type *) ggc_internal_cleared_alloc
>> > -      (sizeof (struct lang_type));
>> > +  TYPE_LANG_SPECIFIC (type) = ggc_cleared_alloc<struct lang_type> ();
>> >
>> >    known_stride = (packed != PACKED_NO);
>> >    known_offset = 1;
>> > @@ -1815,9 +1813,7 @@ gfc_get_array_type_bounds (tree etype, int dimen, int codimen, tree * lbound,
>> >    TYPE_NAMELESS (fat_type) = 1;
>> >
>> >    GFC_DESCRIPTOR_TYPE_P (fat_type) = 1;
>> > -  TYPE_LANG_SPECIFIC (fat_type)
>> > -    = (struct lang_type *) ggc_internal_cleared_alloc
>> > -    (sizeof (struct lang_type));
>> > +  TYPE_LANG_SPECIFIC (fat_type) = ggc_cleared_alloc<struct lang_type> ();
>> >
>> >    GFC_TYPE_ARRAY_RANK (fat_type) = dimen;
>> >    GFC_TYPE_ARRAY_CORANK (fat_type) = codimen;
>> > @@ -1991,9 +1987,7 @@ gfc_nonrestricted_type (tree t)
>> >      return t;
>> >
>> >    if (!TYPE_LANG_SPECIFIC (t))
>> > -    TYPE_LANG_SPECIFIC (t)
>> > -      = (struct lang_type *) ggc_internal_cleared_alloc
>> > -      (sizeof (struct lang_type));
>> > +    TYPE_LANG_SPECIFIC (t) = ggc_cleared_alloc<struct lang_type> ();
>> >    /* If we're dealing with this very node already further up
>> >       the call chain (recursion via pointers and struct members)
>> >       we haven't yet determined if we really need a new type node.
>> > @@ -2045,8 +2039,7 @@ gfc_nonrestricted_type (tree t)
>> >                   if (dataptr_type != GFC_TYPE_ARRAY_DATAPTR_TYPE (t))
>> >                     {
>> >                       TYPE_LANG_SPECIFIC (ret)
>> > -                       = (struct lang_type *) ggc_internal_cleared_alloc
>> > -                       (sizeof (struct lang_type));
>> > +                       = ggc_cleared_alloc<struct lang_type> ();
>> >                       *TYPE_LANG_SPECIFIC (ret) = *TYPE_LANG_SPECIFIC (t);
>> >                       GFC_TYPE_ARRAY_DATAPTR_TYPE (ret) = dataptr_type;
>> >                     }
>> > diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
>> > index f8d29ec..0345ca0 100644
>> > --- a/gcc/fortran/trans.h
>> > +++ b/gcc/fortran/trans.h
>> > @@ -792,10 +792,7 @@ enum gfc_array_kind
>> >  };
>> >
>> >  /* Array types only.  */
>> > -/* FIXME: the variable_size annotation here is needed because these types are
>> > -   variable-sized in some other frontends.  Due to gengtype deficiency the GTY
>> > -   options of such types have to agree across all frontends. */
>> > -struct GTY((variable_size))    lang_type        {
>> > +struct GTY(()) lang_type        {
>> >    int rank, corank;
>> >    enum gfc_array_kind akind;
>> >    tree lbound[GFC_MAX_DIMENSIONS];
>> > @@ -812,7 +809,7 @@ struct GTY((variable_size)) lang_type        {
>> >    tree caf_offset;
>> >  };
>> >
>> > -struct GTY((variable_size)) lang_decl {
>> > +struct GTY(()) lang_decl {
>> >    /* Dummy variables.  */
>> >    tree saved_descriptor;
>> >    /* Assigned integer nodes.  Stringlength is the IO format string's length.
>> > diff --git a/gcc/function.c b/gcc/function.c
>> > index 383a52a..4ebc255 100644
>> > --- a/gcc/function.c
>> > +++ b/gcc/function.c
>> > @@ -306,7 +306,7 @@ try_fit_stack_local (HOST_WIDE_INT start, HOST_WIDE_INT length,
>> >  static void
>> >  add_frame_space (HOST_WIDE_INT start, HOST_WIDE_INT end)
>> >  {
>> > -  struct frame_space *space = ggc_alloc_frame_space ();
>> > +  struct frame_space *space = ggc_alloc<frame_space> ();
>> >    space->next = crtl->frame_space_list;
>> >    crtl->frame_space_list = space;
>> >    space->start = start;
>> > @@ -654,7 +654,7 @@ static void
>> >  insert_temp_slot_address (rtx address, struct temp_slot *temp_slot)
>> >  {
>> >    void **slot;
>> > -  struct temp_slot_address_entry *t = ggc_alloc_temp_slot_address_entry ();
>> > +  struct temp_slot_address_entry *t = ggc_alloc<temp_slot_address_entry> ();
>> >    t->address = address;
>> >    t->temp_slot = temp_slot;
>> >    t->hash = temp_slot_address_compute_hash (t);
>> > @@ -801,7 +801,7 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
>> >
>> >           if (best_p->size - rounded_size >= alignment)
>> >             {
>> > -             p = ggc_alloc_temp_slot ();
>> > +             p = ggc_alloc<temp_slot> ();
>> >               p->in_use = 0;
>> >               p->size = best_p->size - rounded_size;
>> >               p->base_offset = best_p->base_offset + rounded_size;
>> > @@ -825,7 +825,7 @@ assign_stack_temp_for_type (enum machine_mode mode, HOST_WIDE_INT size,
>> >      {
>> >        HOST_WIDE_INT frame_offset_old = frame_offset;
>> >
>> > -      p = ggc_alloc_temp_slot ();
>> > +      p = ggc_alloc<temp_slot> ();
>> >
>> >        /* We are passing an explicit alignment request to assign_stack_local.
>> >          One side effect of that is assign_stack_local will not round SIZE
>> > @@ -1253,10 +1253,10 @@ get_hard_reg_initial_val (enum machine_mode mode, unsigned int regno)
>> >    ivs = crtl->hard_reg_initial_vals;
>> >    if (ivs == 0)
>> >      {
>> > -      ivs = ggc_alloc_initial_value_struct ();
>> > +      ivs = ggc_alloc<initial_value_struct> ();
>> >        ivs->num_entries = 0;
>> >        ivs->max_entries = 5;
>> > -      ivs->entries = ggc_alloc_vec_initial_value_pair (5);
>> > +      ivs->entries = ggc_vec_alloc<initial_value_pair> (5);
>> >        crtl->hard_reg_initial_vals = ivs;
>> >      }
>> >
>> > @@ -4498,7 +4498,7 @@ allocate_struct_function (tree fndecl, bool abstract_p)
>> >  {
>> >    tree fntype = fndecl ? TREE_TYPE (fndecl) : NULL_TREE;
>> >
>> > -  cfun = ggc_alloc_cleared_function ();
>> > +  cfun = ggc_cleared_alloc<function> ();
>> >
>> >    init_eh_for_function ();
>> >
>> > @@ -4572,7 +4572,7 @@ prepare_function_start (void)
>> >
>> >    if (flag_stack_usage_info)
>> >      {
>> > -      cfun->su = ggc_alloc_cleared_stack_usage ();
>> > +      cfun->su = ggc_cleared_alloc<stack_usage> ();
>> >        cfun->su->static_stack_size = -1;
>> >      }
>> >
>> > @@ -6936,7 +6936,7 @@ types_used_by_var_decl_insert (tree type, tree var_decl)
>> >        if (*slot == NULL)
>> >         {
>> >           struct types_used_by_vars_entry *entry;
>> > -         entry = ggc_alloc_types_used_by_vars_entry ();
>> > +         entry = ggc_alloc<types_used_by_vars_entry> ();
>> >           entry->type = type;
>> >           entry->var_decl = var_decl;
>> >           *slot = entry;
>> > diff --git a/gcc/gengtype.c b/gcc/gengtype.c
>> > index b3c966c..d85300b 100644
>> > --- a/gcc/gengtype.c
>> > +++ b/gcc/gengtype.c
>> > @@ -4938,133 +4938,6 @@ write_roots (pair_p variables, bool emit_pch)
>> >                      "gt_pch_scalar_rtab");
>> >  }
>> >
>> > -/* TRUE if type S has the GTY variable_size annotation.  */
>> > -
>> > -static bool
>> > -variable_size_p (const type_p s)
>> > -{
>> > -  options_p o;
>> > -  for (o = s->u.s.opt; o; o = o->next)
>> > -    if (strcmp (o->name, "variable_size") == 0)
>> > -      return true;
>> > -  return false;
>> > -}
>> > -
>> > -enum alloc_quantity
>> > -{ single, vector };
>> > -
>> > -/* Writes one typed allocator definition into output F for type
>> > -   identifier TYPE_NAME with optional type specifier TYPE_SPECIFIER.
>> > -   The allocator name will contain ALLOCATOR_TYPE.  If VARIABLE_SIZE
>> > -   is true, the allocator will have an extra parameter specifying
>> > -   number of bytes to allocate.  If QUANTITY is set to VECTOR, a
>> > -   vector allocator will be output.  */
>> > -
>> > -static void
>> > -write_typed_alloc_def (outf_p f,
>> > -                       bool variable_size, const char *type_specifier,
>> > -                       const char *type_name, const char *allocator_type,
>> > -                       enum alloc_quantity quantity)
>> > -{
>> > -  bool two_args = variable_size && (quantity == vector);
>> > -  if (variable_size)
>> > -    return;
>> > -
>> > -  gcc_assert (f != NULL);
>> > -  const char *type_name_as_id = filter_type_name (type_name);
>> > -  oprintf (f, "#define ggc_alloc_%s%s", allocator_type, type_name_as_id);
>> > -  oprintf (f, "(%s%s%s) ",
>> > -          (variable_size ? "SIZE" : ""),
>> > -          (two_args ? ", " : ""),
>> > -          (quantity == vector) ? "n" : "");
>> > -  oprintf (f, "((%s%s *)", type_specifier, type_name);
>> > -  oprintf (f, "(ggc_internal_%salloc (", allocator_type);
>> > -  if (variable_size)
>> > -    oprintf (f, "SIZE");
>> > -  else
>> > -    oprintf (f, "sizeof (%s%s)", type_specifier, type_name);
>> > -  if (quantity == vector)
>> > -    oprintf (f, ", n");
>> > -  oprintf (f, " MEM_STAT_INFO)))\n");
>> > -  if (type_name_as_id != type_name)
>> > -    free (CONST_CAST (char *, type_name_as_id));
>> > -}
>> > -
>> > -/* Writes a typed allocator definition into output F for a struct or
>> > -   union S, with a given ALLOCATOR_TYPE and QUANTITY for ZONE.  */
>> > -
>> > -static void
>> > -write_typed_struct_alloc_def (outf_p f,
>> > -                             const type_p s, const char *allocator_type,
>> > -                             enum alloc_quantity quantity)
>> > -{
>> > -  gcc_assert (union_or_struct_p (s));
>> > -  write_typed_alloc_def (f, variable_size_p (s), get_type_specifier (s),
>> > -                         s->u.s.tag, allocator_type, quantity);
>> > -}
>> > -
>> > -/* Writes a typed allocator definition into output F for a typedef P,
>> > -   with a given ALLOCATOR_TYPE and QUANTITY for ZONE.  */
>> > -
>> > -static void
>> > -write_typed_typedef_alloc_def (outf_p f,
>> > -                               const pair_p p, const char *allocator_type,
>> > -                               enum alloc_quantity quantity)
>> > -{
>> > -  write_typed_alloc_def (f, variable_size_p (p->type), "", p->name,
>> > -                         allocator_type, quantity);
>> > -}
>> > -
>> > -/* Writes typed allocator definitions into output F for the types in
>> > -   STRUCTURES and TYPEDEFS that are used by GC.  */
>> > -
>> > -static void
>> > -write_typed_alloc_defns (outf_p f,
>> > -                         const type_p structures, const pair_p typedefs)
>> > -{
>> > -  type_p s;
>> > -  pair_p p;
>> > -
>> > -  gcc_assert (f != NULL);
>> > -  oprintf (f,
>> > -          "\n/* Allocators for known structs and unions.  */\n\n");
>> > -  for (s = structures; s; s = s->next)
>> > -    {
>> > -      if (!USED_BY_TYPED_GC_P (s))
>> > -       continue;
>> > -      gcc_assert (union_or_struct_p (s));
>> > -      /* In plugin mode onput output ggc_alloc macro definitions
>> > -        relevant to plugin input files.  */
>> > -      if (nb_plugin_files > 0
>> > -         && ((s->u.s.line.file == NULL) || !s->u.s.line.file->inpisplugin))
>> > -       continue;
>> > -      write_typed_struct_alloc_def (f, s, "", single);
>> > -      write_typed_struct_alloc_def (f, s, "cleared_", single);
>> > -      write_typed_struct_alloc_def (f, s, "vec_", vector);
>> > -      write_typed_struct_alloc_def (f, s, "cleared_vec_", vector);
>> > -    }
>> > -
>> > -  oprintf (f, "\n/* Allocators for known typedefs.  */\n");
>> > -  for (p = typedefs; p; p = p->next)
>> > -    {
>> > -      s = p->type;
>> > -      if (!USED_BY_TYPED_GC_P (s) || (strcmp (p->name, s->u.s.tag) == 0))
>> > -       continue;
>> > -      /* In plugin mode onput output ggc_alloc macro definitions
>> > -        relevant to plugin input files.  */
>> > -      if (nb_plugin_files > 0)
>> > -       {
>> > -         struct fileloc* filoc = type_fileloc (s);
>> > -         if (!filoc || !filoc->file->inpisplugin)
>> > -           continue;
>> > -       };
>> > -      write_typed_typedef_alloc_def (f, p, "", single);
>> > -      write_typed_typedef_alloc_def (f, p, "cleared_", single);
>> > -      write_typed_typedef_alloc_def (f, p, "vec_", vector);
>> > -      write_typed_typedef_alloc_def (f, p, "cleared_vec_", vector);
>> > -    }
>> > -}
>> > -
>> >  /* Prints not-as-ugly version of a typename of T to OF.  Trades the uniquness
>> >     guaranteee for somewhat increased readability.  If name conflicts do happen,
>> >     this funcion will have to be adjusted to be more like
>> > @@ -5775,7 +5648,6 @@ main (int argc, char **argv)
>> >    open_base_files ();
>> >
>> >    output_header = plugin_output ? plugin_output : header_file;
>> > -  write_typed_alloc_defns (output_header, structures, typedefs);
>> >    DBGPRINT_COUNT_TYPE ("structures before write_types outputheader",
>> >                        structures);
>> >    DBGPRINT_COUNT_TYPE ("param_structs before write_types outputheader",
>> > diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
>> > index e1cc48e..e89cc64 100644
>> > --- a/gcc/ggc-common.c
>> > +++ b/gcc/ggc-common.c
>> > @@ -232,7 +232,7 @@ ggc_cleared_alloc_htab_ignore_args (size_t c ATTRIBUTE_UNUSED,
>> >                                     size_t n ATTRIBUTE_UNUSED)
>> >  {
>> >    gcc_assert (c * n == sizeof (struct htab));
>> > -  return ggc_alloc_cleared_htab ();
>> > +  return ggc_cleared_alloc<htab> ();
>> >  }
>> >
>> >  /* TODO: once we actually use type information in GGC, create a new tag
>> > @@ -241,7 +241,7 @@ void *
>> >  ggc_cleared_alloc_ptr_array_two_args (size_t c, size_t n)
>> >  {
>> >    gcc_assert (sizeof (PTR *) == n);
>> > -  return ggc_internal_cleared_vec_alloc (sizeof (PTR *), c);
>> > +  return ggc_cleared_vec_alloc<PTR *> (c);
>> >  }
>> >
>> >  /* These are for splay_tree_new_ggc.  */
>> > diff --git a/gcc/ggc.h b/gcc/ggc.h
>> > index 736305d..2c567de 100644
>> > --- a/gcc/ggc.h
>> > +++ b/gcc/ggc.h
>> > @@ -156,16 +156,35 @@ extern void dump_ggc_loc_statistics (bool);
>> >  #define GGC_RESIZEVEC(T, P, N) \
>> >      ((T *) ggc_realloc ((P), (N) * sizeof (T) MEM_STAT_INFO))
>> >
>> > -static inline void *
>> > -ggc_internal_vec_alloc (size_t s, size_t c MEM_STAT_DECL)
>> > +template<typename T>
>> > +static inline T *
>> > +ggc_alloc (ALONE_CXX_MEM_STAT_INFO)
>> >  {
>> > -    return ggc_internal_alloc (c * s PASS_MEM_STAT);
>> > +  return static_cast<T *> (ggc_internal_alloc (sizeof (T) PASS_MEM_STAT));
>> >  }
>> >
>> > -static inline void *
>> > -ggc_internal_cleared_vec_alloc (size_t s, size_t c CXX_MEM_STAT_INFO)
>> > +template<typename T>
>> > +static inline T *
>> > +ggc_cleared_alloc (ALONE_CXX_MEM_STAT_INFO)
>> > +{
>> > +  return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T)
>> > +                                                      PASS_MEM_STAT));
>> > +}
>> > +
>> > +template<typename T>
>> > +static inline T *
>> > +ggc_vec_alloc (size_t c CXX_MEM_STAT_INFO)
>> > +{
>> > +    return static_cast<T *> (ggc_internal_alloc (c * sizeof (T)
>> > +                                                PASS_MEM_STAT));
>> > +}
>> > +
>> > +template<typename T>
>> > +static inline T *
>> > +ggc_cleared_vec_alloc (size_t c CXX_MEM_STAT_INFO)
>> >  {
>> > -    return ggc_internal_cleared_alloc (c * s PASS_MEM_STAT);
>> > +    return static_cast<T *> (ggc_internal_cleared_alloc (c * sizeof (T)
>> > +                                                        PASS_MEM_STAT));
>> >  }
>> >
>> >  static inline void *
>> > diff --git a/gcc/gimple.c b/gcc/gimple.c
>> > index fc6ecb9..165a4bd 100644
>> > --- a/gcc/gimple.c
>> > +++ b/gcc/gimple.c
>> > @@ -835,8 +835,7 @@ gimple_build_omp_for (gimple_seq body, int kind, tree clauses, size_t collapse,
>> >    gimple_omp_for_set_clauses (p, clauses);
>> >    gimple_omp_for_set_kind (p, kind);
>> >    p->collapse = collapse;
>> > -  p->iter =  static_cast <struct gimple_omp_for_iter *> (
>> > -   ggc_internal_cleared_vec_alloc (sizeof (*p->iter), collapse));
>> > +  p->iter =  ggc_cleared_vec_alloc<gimple_omp_for_iter> (collapse);
>> >
>> >    if (pre_body)
>> >      gimple_omp_for_set_pre_body (p, pre_body);
>> > @@ -1664,10 +1663,8 @@ gimple_copy (gimple stmt)
>> >           {
>> >             gimple_statement_omp_for *omp_for_copy =
>> >               as_a <gimple_statement_omp_for *> (copy);
>> > -           omp_for_copy->iter =
>> > -             static_cast <struct gimple_omp_for_iter *> (
>> > -                 ggc_internal_vec_alloc (sizeof (struct gimple_omp_for_iter),
>> > -                                         gimple_omp_for_collapse (stmt)));
>> > +           omp_for_copy->iter = ggc_vec_alloc<gimple_omp_for_iter>
>> > +             ( gimple_omp_for_collapse (stmt));
>> >            }
>> >           for (i = 0; i < gimple_omp_for_collapse (stmt); i++)
>> >             {
>> > diff --git a/gcc/go/go-lang.c b/gcc/go/go-lang.c
>> > index c0f2f1f..7231b34 100644
>> > --- a/gcc/go/go-lang.c
>> > +++ b/gcc/go/go-lang.c
>> > @@ -51,7 +51,7 @@ struct GTY(()) lang_type
>> >
>> >  /* Language-dependent contents of a decl.  */
>> >
>> > -struct GTY((variable_size)) lang_decl
>> > +struct GTY(()) lang_decl
>> >  {
>> >    char dummy;
>> >  };
>> > diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
>> > index 479963c..d1f882a 100644
>> > --- a/gcc/ipa-cp.c
>> > +++ b/gcc/ipa-cp.c
>> > @@ -2599,7 +2599,7 @@ get_replacement_map (struct ipa_node_params *info, tree value, int parm_num)
>> >    struct ipa_replace_map *replace_map;
>> >
>> >
>> > -  replace_map = ggc_alloc_ipa_replace_map ();
>> > +  replace_map = ggc_alloc<ipa_replace_map> ();
>> >    if (dump_file)
>> >      {
>> >        fprintf (dump_file, "    replacing ");
>> > @@ -3182,7 +3182,7 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node,
>> >           if (!item->value)
>> >             continue;
>> >
>> > -         v = ggc_alloc_ipa_agg_replacement_value ();
>> > +         v = ggc_alloc<ipa_agg_replacement_value> ();
>> >           v->index = i;
>> >           v->offset = item->offset;
>> >           v->value = item->value;
>> > @@ -3212,7 +3212,7 @@ known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs)
>> >      FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item)
>> >        {
>> >         struct ipa_agg_replacement_value *v;
>> > -       v = ggc_alloc_ipa_agg_replacement_value ();
>> > +       v = ggc_alloc<ipa_agg_replacement_value> ();
>> >         v->index = i;
>> >         v->offset = item->offset;
>> >         v->value = item->value;
>> > diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
>> > index 4ff31fc..bacbeec 100644
>> > --- a/gcc/ipa-devirt.c
>> > +++ b/gcc/ipa-devirt.c
>> > @@ -491,7 +491,7 @@ get_odr_type (tree type, bool insert)
>> >        tree binfo = TYPE_BINFO (type);
>> >        unsigned int i;
>> >
>> > -      val = ggc_alloc_cleared_odr_type_d ();
>> > +      val = ggc_cleared_alloc<odr_type_d> ();
>> >        val->type = type;
>> >        val->bases = vNULL;
>> >        val->derived_types = vNULL;
>> > diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
>> > index 9f144fa..336dd97 100644
>> > --- a/gcc/ipa-prop.c
>> > +++ b/gcc/ipa-prop.c
>> > @@ -3311,7 +3311,7 @@ ipa_node_duplication_hook (struct cgraph_node *src, struct cgraph_node *dst,
>> >      {
>> >        struct ipa_agg_replacement_value *v;
>> >
>> > -      v = ggc_alloc_ipa_agg_replacement_value ();
>> > +      v = ggc_alloc<ipa_agg_replacement_value> ();
>> >        memcpy (v, old_av, sizeof (*v));
>> >        v->next = new_av;
>> >        new_av = v;
>> > @@ -4670,7 +4670,7 @@ read_agg_replacement_chain (struct lto_input_block *ib,
>> >        struct ipa_agg_replacement_value *av;
>> >        struct bitpack_d bp;
>> >
>> > -      av = ggc_alloc_ipa_agg_replacement_value ();
>> > +      av = ggc_alloc<ipa_agg_replacement_value> ();
>> >        av->offset = streamer_read_uhwi (ib);
>> >        av->index = streamer_read_uhwi (ib);
>> >        av->value = stream_read_tree (ib, data_in);
>> > diff --git a/gcc/java/class.c b/gcc/java/class.c
>> > index 94c2568..a1e4a86 100644
>> > --- a/gcc/java/class.c
>> > +++ b/gcc/java/class.c
>> > @@ -764,9 +764,7 @@ add_method_1 (tree this_class, int access_flags, tree name, tree function_type)
>> >    fndecl = build_decl (input_location, FUNCTION_DECL, name, method_type);
>> >    DECL_CONTEXT (fndecl) = this_class;
>> >
>> > -  DECL_LANG_SPECIFIC (fndecl)
>> > -    = (struct lang_decl *) ggc_internal_cleared_alloc
>> > -    (sizeof (struct lang_decl));
>> > +  DECL_LANG_SPECIFIC (fndecl) = ggc_cleared_alloc<struct lang_decl> ();
>> >    DECL_LANG_SPECIFIC (fndecl)->desc = LANG_DECL_FUNC;
>> >
>> >    /* Initialize the static initializer test table.  */
>> > @@ -3195,7 +3193,7 @@ java_treetreehash_new (htab_t ht, tree t)
>> >    e = htab_find_slot_with_hash (ht, t, hv, INSERT);
>> >    if (*e == NULL)
>> >      {
>> > -      tthe = ggc_alloc_cleared_treetreehash_entry ();
>> > +      tthe = ggc_cleared_alloc<treetreehash_entry> ();
>> >        tthe->key = t;
>> >        *e = tthe;
>> >      }
>> > diff --git a/gcc/java/constants.c b/gcc/java/constants.c
>> > index 51449ef..2e317c9 100644
>> > --- a/gcc/java/constants.c
>> > +++ b/gcc/java/constants.c
>> > @@ -46,11 +46,8 @@ set_constant_entry (CPool *cpool, int index, int tag, jword value)
>> >    if (cpool->data == NULL)
>> >      {
>> >        cpool->capacity = 100;
>> > -      cpool->tags = (uint8 *) ggc_internal_cleared_alloc (sizeof (uint8)
>> > -                                                         * cpool->capacity);
>> > -      cpool->data = (cpool_entry *) ggc_internal_cleared_alloc (sizeof
>> > -                                                      (union cpool_entry)
>> > -                                                      * cpool->capacity);
>> > +      cpool->tags = ggc_cleared_vec_alloc<uint8> (cpool->capacity);
>> > +      cpool->data = ggc_cleared_vec_alloc<cpool_entry> (cpool->capacity);
>> >        cpool->count = 1;
>> >      }
>> >    if (index >= cpool->capacity)
>> > @@ -338,7 +335,7 @@ cpool_for_class (tree klass)
>> >
>> >    if (cpool == NULL)
>> >      {
>> > -      cpool = ggc_alloc_cleared_CPool ();
>> > +      cpool = ggc_cleared_alloc<CPool> ();
>> >        TYPE_CPOOL (klass) = cpool;
>> >      }
>> >    return cpool;
>> > diff --git a/gcc/java/decl.c b/gcc/java/decl.c
>> > index 9f2f0ca..841fb4c 100644
>> > --- a/gcc/java/decl.c
>> > +++ b/gcc/java/decl.c
>> > @@ -1307,7 +1307,7 @@ static struct binding_level *
>> >  make_binding_level (void)
>> >  {
>> >    /* NOSTRICT */
>> > -  return ggc_alloc_cleared_binding_level ();
>> > +  return ggc_cleared_alloc<binding_level> ();
>> >  }
>> >
>> >  void
>> > @@ -1646,7 +1646,7 @@ java_dup_lang_specific_decl (tree node)
>> >      return;
>> >
>> >    lang_decl_size = sizeof (struct lang_decl);
>> > -  x = (struct lang_decl *) ggc_internal_alloc (lang_decl_size);
>> > +  x = ggc_alloc<struct lang_decl> ();
>> >    memcpy (x, DECL_LANG_SPECIFIC (node), lang_decl_size);
>> >    DECL_LANG_SPECIFIC (node) = x;
>> >  }
>> > diff --git a/gcc/java/expr.c b/gcc/java/expr.c
>> > index 69f6819..0fa5724 100644
>> > --- a/gcc/java/expr.c
>> > +++ b/gcc/java/expr.c
>> > @@ -470,7 +470,7 @@ add_type_assertion (tree klass, int assertion_code, tree op1, tree op2)
>> >    if (*as_pp)
>> >      return;
>> >
>> > -  *as_pp = ggc_alloc_type_assertion ();
>> > +  *as_pp = ggc_alloc<type_assertion> ();
>> >    **(type_assertion **)as_pp = as;
>> >  }
>> >
>> > diff --git a/gcc/java/java-tree.h b/gcc/java/java-tree.h
>> > index 43a8258..e832f44 100644
>> > --- a/gcc/java/java-tree.h
>> > +++ b/gcc/java/java-tree.h
>> > @@ -699,9 +699,7 @@ union GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
>> >  #define MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC(T)                       \
>> >    if (DECL_LANG_SPECIFIC (T) == NULL)                                \
>> >      {                                                                \
>> > -      DECL_LANG_SPECIFIC ((T))                                       \
>> > -        = (struct lang_decl *) ggc_internal_cleared_alloc            \
>> > -      (sizeof (struct lang_decl));                                   \
>> > +      DECL_LANG_SPECIFIC ((T)) = ggc_cleared_alloc<struct lang_decl> (); \
>> >        DECL_LANG_SPECIFIC (T)->desc = LANG_DECL_VAR;                  \
>> >      }
>> >
>> > @@ -809,7 +807,7 @@ struct GTY(()) lang_decl_var {
>> >
>> >  enum lang_decl_desc {LANG_DECL_FUNC, LANG_DECL_VAR};
>> >
>> > -struct GTY((variable_size)) lang_decl {
>> > +struct GTY(()) lang_decl {
>> >    enum lang_decl_desc desc;
>> >    union lang_decl_u
>> >      {
>> > @@ -826,9 +824,7 @@ struct GTY((variable_size)) lang_decl {
>> >  #define TYPE_CPOOL_DATA_REF(T) (TYPE_LANG_SPECIFIC (T)->cpool_data_ref)
>> >  #define MAYBE_CREATE_TYPE_TYPE_LANG_SPECIFIC(T) \
>> >    if (TYPE_LANG_SPECIFIC ((T)) == NULL)                \
>> > -     TYPE_LANG_SPECIFIC ((T))                  \
>> > -       = (struct lang_type *) ggc_internal_cleared_alloc \
>> > -(sizeof (struct lang_type));     \
>> > +     TYPE_LANG_SPECIFIC ((T)) = ggc_cleared_alloc<struct lang_type> ();
>> >
>> >  #define TYPE_DUMMY(T)          (TYPE_LANG_SPECIFIC(T)->dummy_class)
>> >
>> > @@ -871,10 +867,7 @@ typedef struct GTY(()) method_entry_d {
>> >  } method_entry;
>> >
>> >
>> > -/* FIXME: the variable_size annotation here is needed because these types are
>> > -   variable-sized in some other frontends.  Due to gengtype deficiency the GTY
>> > -   options of such types have to agree across all frontends. */
>> > -struct GTY((variable_size)) lang_type {
>> > +struct GTY(()) lang_type {
>> >    tree signature;
>> >    struct JCF *jcf;
>> >    struct CPool *cpool;
>> > diff --git a/gcc/java/jcf-parse.c b/gcc/java/jcf-parse.c
>> > index afe35f0..e57a044 100644
>> > --- a/gcc/java/jcf-parse.c
>> > +++ b/gcc/java/jcf-parse.c
>> > @@ -1905,7 +1905,7 @@ java_parse_file (void)
>> >        if (magic == 0xcafebabe)
>> >         {
>> >           CLASS_FILE_P (node) = 1;
>> > -         current_jcf = ggc_alloc_cleared_JCF ();
>> > +         current_jcf = ggc_cleared_alloc<JCF> ();
>> >           current_jcf->read_state = finput;
>> >           current_jcf->filbuf = jcf_filbuf_from_stdio;
>> >           jcf_parse (current_jcf);
>> > @@ -1922,7 +1922,7 @@ java_parse_file (void)
>> >         }
>> >        else if (magic == (JCF_u4)ZIPMAGIC)
>> >         {
>> > -         main_jcf = ggc_alloc_cleared_JCF ();
>> > +         main_jcf = ggc_cleared_alloc<JCF> ();
>> >           main_jcf->read_state = finput;
>> >           main_jcf->filbuf = jcf_filbuf_from_stdio;
>> >           linemap_add (line_table, LC_ENTER, false, filename, 0);
>> > @@ -2178,7 +2178,7 @@ process_zip_dir (FILE *finput)
>> >
>> >        class_name = compute_class_name (zdir);
>> >        file_name  = XNEWVEC (char, zdir->filename_length+1);
>> > -      jcf = ggc_alloc_cleared_JCF ();
>> > +      jcf = ggc_cleared_alloc<JCF> ();
>> >
>> >        strncpy (file_name, class_name_in_zip_dir, zdir->filename_length);
>> >        file_name [zdir->filename_length] = '\0';
>> > diff --git a/gcc/java/jcf.h b/gcc/java/jcf.h
>> > index 8aa077e..0988d65 100644
>> > --- a/gcc/java/jcf.h
>> > +++ b/gcc/java/jcf.h
>> > @@ -65,7 +65,7 @@ jcf_open_exact_case (const char* filename, int oflag);
>> >  struct JCF;
>> >  typedef int (*jcf_filbuf_t) (struct JCF*, int needed);
>> >
>> > -union GTY((variable_size)) cpool_entry {
>> > +union GTY(()) cpool_entry {
>> >    jword GTY ((tag ("0"))) w;
>> >    tree GTY ((tag ("1"))) t;
>> >  };
>> > diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c
>> > index 42bcb75..6acc4c9 100644
>> > --- a/gcc/loop-iv.c
>> > +++ b/gcc/loop-iv.c
>> > @@ -3036,7 +3036,7 @@ get_simple_loop_desc (struct loop *loop)
>> >
>> >    /* At least desc->infinite is not always initialized by
>> >       find_simple_loop_exit.  */
>> > -  desc = ggc_alloc_cleared_niter_desc ();
>> > +  desc = ggc_cleared_alloc<niter_desc> ();
>> >    iv_analysis_loop_init (loop);
>> >    find_simple_exit (loop, desc);
>> >    loop->simple_loop_desc = desc;
>> > diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
>> > index 58084cd..d4a6d38 100644
>> > --- a/gcc/lto-cgraph.c
>> > +++ b/gcc/lto-cgraph.c
>> > @@ -1755,7 +1755,7 @@ input_node_opt_summary (struct cgraph_node *node,
>> >    count = streamer_read_uhwi (ib_main);
>> >    for (i = 0; i < count; i++)
>> >      {
>> > -      struct ipa_replace_map *map = ggc_alloc_ipa_replace_map ();
>> > +      struct ipa_replace_map *map = ggc_alloc<ipa_replace_map> ();
>> >
>> >        vec_safe_push (node->clone.tree_map, map);
>> >        map->parm_num = streamer_read_uhwi (ib_main);
>> > diff --git a/gcc/lto-section-in.c b/gcc/lto-section-in.c
>> > index 9aa7639..d887763 100644
>> > --- a/gcc/lto-section-in.c
>> > +++ b/gcc/lto-section-in.c
>> > @@ -364,7 +364,7 @@ lto_get_decl_name_mapping (struct lto_file_decl_data *decl_data,
>> >  struct lto_in_decl_state *
>> >  lto_new_in_decl_state (void)
>> >  {
>> > -  return ggc_alloc_cleared_lto_in_decl_state ();
>> > +  return ggc_cleared_alloc<lto_in_decl_state> ();
>> >  }
>> >
>> >  /* Delete STATE and its components. */
>> > diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c
>> > index 20835f7..deb9b1c 100644
>> > --- a/gcc/lto-streamer-in.c
>> > +++ b/gcc/lto-streamer-in.c
>> > @@ -279,7 +279,7 @@ lto_input_eh_catch_list (struct lto_input_block *ib, struct data_in *data_in,
>> >        lto_tag_check_range (tag, LTO_eh_catch, LTO_eh_catch);
>> >
>> >        /* Read the catch node.  */
>> > -      n = ggc_alloc_cleared_eh_catch_d ();
>> > +      n = ggc_cleared_alloc<eh_catch_d> ();
>> >        n->type_list = stream_read_tree (ib, data_in);
>> >        n->filter_list = stream_read_tree (ib, data_in);
>> >        n->label = stream_read_tree (ib, data_in);
>> > @@ -319,7 +319,7 @@ input_eh_region (struct lto_input_block *ib, struct data_in *data_in, int ix)
>> >    if (tag == LTO_null)
>> >      return NULL;
>> >
>> > -  r = ggc_alloc_cleared_eh_region_d ();
>> > +  r = ggc_cleared_alloc<eh_region_d> ();
>> >    r->index = streamer_read_hwi (ib);
>> >
>> >    gcc_assert (r->index == ix);
>> > @@ -396,7 +396,7 @@ input_eh_lp (struct lto_input_block *ib, struct data_in *data_in, int ix)
>> >
>> >    lto_tag_check_range (tag, LTO_eh_landing_pad, LTO_eh_landing_pad);
>> >
>> > -  lp = ggc_alloc_cleared_eh_landing_pad_d ();
>> > +  lp = ggc_cleared_alloc<eh_landing_pad_d> ();
>> >    lp->index = streamer_read_hwi (ib);
>> >    gcc_assert (lp->index == ix);
>> >    lp->next_lp = (eh_landing_pad) (intptr_t) streamer_read_hwi (ib);
>> > @@ -682,7 +682,7 @@ input_cfg (struct lto_input_block *ib, struct data_in *data_in,
>> >    if (n_loops == 0)
>> >      return;
>> >
>> > -  struct loops *loops = ggc_alloc_cleared_loops ();
>> > +  struct loops *loops = ggc_cleared_alloc<struct loops> ();
>> >    init_loops_structure (fn, loops, n_loops);
>> >    set_loops_for_fn (fn, loops);
>> >
>> > diff --git a/gcc/lto/lto-tree.h b/gcc/lto/lto-tree.h
>> > index b1c3d2a..4e3f5d6 100644
>> > --- a/gcc/lto/lto-tree.h
>> > +++ b/gcc/lto/lto-tree.h
>> > @@ -28,12 +28,12 @@ struct GTY(()) lang_identifier
>> >    struct tree_identifier base;
>> >  };
>> >
>> > -struct GTY((variable_size)) lang_decl
>> > +struct GTY(()) lang_decl
>> >  {
>> >    int dummy;  /* Added because ggc does not like empty structs.  */
>> >  };
>> >
>> > -struct GTY((variable_size)) lang_type
>> > +struct GTY(()) lang_type
>> >  {
>> >    int dummy;  /* Added because ggc does not like empty structs.  */
>> >  };
>> > diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
>> > index 5f4478a..38e1149 100644
>> > --- a/gcc/lto/lto.c
>> > +++ b/gcc/lto/lto.c
>> > @@ -244,7 +244,7 @@ lto_read_in_decl_state (struct data_in *data_in, const uint32_t *data,
>> >    for (i = 0; i < LTO_N_DECL_STREAMS; i++)
>> >      {
>> >        uint32_t size = *data++;
>> > -      tree *decls = ggc_alloc_vec_tree (size);
>> > +      tree *decls = ggc_vec_alloc<tree> (size);
>> >
>> >        for (j = 0; j < size; j++)
>> >         decls[j] = streamer_tree_cache_get_tree (data_in->reader_cache, data[j]);
>> > @@ -2159,7 +2159,7 @@ create_subid_section_table (struct lto_section_slot *ls, splay_tree file_ids,
>> >      }
>> >    else
>> >      {
>> > -      file_data = ggc_alloc_lto_file_decl_data ();
>> > +      file_data = ggc_alloc<lto_file_decl_data> ();
>> >        memset(file_data, 0, sizeof (struct lto_file_decl_data));
>> >        file_data->id = id;
>> >        file_data->section_hash_table = lto_obj_create_section_hash_table ();;
>> > @@ -2860,7 +2860,7 @@ lto_flatten_files (struct lto_file_decl_data **orig, int count, int last_file_ix
>> >
>> >    lto_stats.num_input_files = count;
>> >    all_file_decl_data
>> > -    = ggc_alloc_cleared_vec_lto_file_decl_data_ptr (count + 1);
>> > +    = ggc_cleared_vec_alloc<lto_file_decl_data_ptr> (count + 1);
>> >    /* Set the hooks so that all of the ipa passes can read in their data.  */
>> >    lto_set_in_hooks (all_file_decl_data, get_section_data, free_section_data);
>> >    for (i = 0, k = 0; i < last_file_ix; i++)
>> > @@ -2903,7 +2903,7 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
>> >    timevar_push (TV_IPA_LTO_DECL_IN);
>> >
>> >    real_file_decl_data
>> > -    = decl_data = ggc_alloc_cleared_vec_lto_file_decl_data_ptr (nfiles + 1);
>> > +    = decl_data = ggc_cleared_vec_alloc<lto_file_decl_data_ptr> (nfiles + 1);
>> >    real_file_count = nfiles;
>> >
>> >    /* Read the resolution file.  */
>> > diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
>> > index cda345b..551325a 100644
>> > --- a/gcc/objc/objc-act.c
>> > +++ b/gcc/objc/objc-act.c
>> > @@ -3198,7 +3198,7 @@ objc_build_string_object (tree string)
>> >
>> >    if (!desc)
>> >      {
>> > -      *loc = desc = ggc_alloc_string_descriptor ();
>> > +      *loc = desc = ggc_alloc<string_descriptor> ();
>> >        desc->literal = string;
>> >        desc->constructor =
>> >         (*runtime.build_const_string_constructor) (input_location, string, length);
>> > @@ -7040,7 +7040,7 @@ continue_class (tree klass)
>> >         uprivate_record = CLASS_STATIC_TEMPLATE (implementation_template);
>> >         objc_instance_type = build_pointer_type (uprivate_record);
>> >
>> > -       imp_entry = ggc_alloc_imp_entry ();
>> > +       imp_entry = ggc_alloc<struct imp_entry> ();
>> >
>> >         imp_entry->next = imp_list;
>> >         imp_entry->imp_context = klass;
>> > diff --git a/gcc/objc/objc-act.h b/gcc/objc/objc-act.h
>> > index a050727..7e1e265 100644
>> > --- a/gcc/objc/objc-act.h
>> > +++ b/gcc/objc/objc-act.h
>> > @@ -192,9 +192,7 @@ typedef enum objc_property_assign_semantics {
>> >  #define SIZEOF_OBJC_TYPE_LANG_SPECIFIC sizeof (struct lang_type)
>> >  #define ALLOC_OBJC_TYPE_LANG_SPECIFIC(NODE)                            \
>> >    do {                                                                 \
>> > -    TYPE_LANG_SPECIFIC (NODE)                                          \
>> > -      = (struct lang_type *) ggc_internal_cleared_alloc     \
>> > -      (sizeof (struct lang_type));     \
>> > +      TYPE_LANG_SPECIFIC (NODE) = ggc_cleared_alloc<struct lang_type> (); \
>> >    } while (0)
>> >
>> >  #define TYPE_HAS_OBJC_INFO(TYPE)                               \
>> > diff --git a/gcc/objc/objc-map.c b/gcc/objc/objc-map.c
>> > index 386d2c5..aaee729 100644
>> > --- a/gcc/objc/objc-map.c
>> > +++ b/gcc/objc/objc-map.c
>> > @@ -56,7 +56,7 @@ next_power_of_two (size_t x)
>> >  objc_map_t
>> >  objc_map_alloc_ggc (size_t initial_capacity)
>> >  {
>> > -  objc_map_t map = (objc_map_t) ggc_internal_cleared_vec_alloc (1, sizeof (struct objc_map_private));
>> > +  objc_map_t map = ggc_cleared_alloc<objc_map_private> ();
>> >    if (map == NULL)
>> >      OUT_OF_MEMORY;
>> >
>> > @@ -67,8 +67,8 @@ objc_map_alloc_ggc (size_t initial_capacity)
>> >    map->maximum_load_factor = 70;
>> >    map->max_number_of_non_empty_slots = (initial_capacity * map->maximum_load_factor) / 100;
>> >
>> > -  map->slots = (tree *)ggc_internal_cleared_vec_alloc (initial_capacity, sizeof (tree));
>> > -  map->values = (tree *)ggc_internal_cleared_vec_alloc (initial_capacity, sizeof (tree));
>> > +  map->slots = ggc_cleared_vec_alloc<tree> (initial_capacity);
>> > +  map->values = ggc_cleared_vec_alloc<tree> (initial_capacity);
>> >
>> >    if (map->slots == NULL)
>> >      OUT_OF_MEMORY;
>> > @@ -112,8 +112,8 @@ objc_map_private_resize (objc_map_t map, size_t new_number_of_slots)
>> >    map->max_number_of_non_empty_slots = (map->number_of_slots * map->maximum_load_factor) / 100;
>> >
>> >
>> > -  map->slots = (tree *)ggc_internal_cleared_vec_alloc (map->number_of_slots, sizeof (tree));
>> > -  map->values = (tree *)ggc_internal_cleared_vec_alloc (map->number_of_slots, sizeof (tree));
>> > +  map->slots = ggc_cleared_vec_alloc<tree> (map->number_of_slots);
>> > +  map->values = ggc_cleared_vec_alloc<tree> (map->number_of_slots);
>> >
>> >    if (map->slots == NULL)
>> >      OUT_OF_MEMORY;
>> > diff --git a/gcc/objc/objc-next-runtime-abi-02.c b/gcc/objc/objc-next-runtime-abi-02.c
>> > index ee43d2d..85033a3 100644
>> > --- a/gcc/objc/objc-next-runtime-abi-02.c
>> > +++ b/gcc/objc/objc-next-runtime-abi-02.c
>> > @@ -238,7 +238,7 @@ static GTY ((length ("SIZEHASHTABLE"))) hash *extern_names;
>> >  bool
>> >  objc_next_runtime_abi_02_init (objc_runtime_hooks *rthooks)
>> >  {
>> > -  extern_names = ggc_alloc_cleared_vec_hash (SIZEHASHTABLE);
>> > +  extern_names = ggc_cleared_vec_alloc<hash> (SIZEHASHTABLE);
>> >
>> >    if (flag_objc_exceptions && flag_objc_sjlj_exceptions)
>> >      {
>> > @@ -857,7 +857,7 @@ hash_name_enter (hash *hashlist, tree id)
>> >    hash obj;
>> >    int slot = IDENTIFIER_HASH_VALUE (DECL_NAME (id)) % SIZEHASHTABLE;
>> >
>> > -  obj = ggc_alloc_hashed_entry ();
>> > +  obj = ggc_alloc<hashed_entry> ();
>> >    obj->list = 0;
>> >    obj->next = hashlist[slot];
>> >    obj->key = id;
>> > diff --git a/gcc/optabs.c b/gcc/optabs.c
>> > index 54f07ab..e465cbc 100644
>> > --- a/gcc/optabs.c
>> > +++ b/gcc/optabs.c
>> > @@ -6156,7 +6156,7 @@ set_optab_libfunc (optab op, enum machine_mode mode, const char *name)
>> >      val = 0;
>> >    slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
>> >    if (*slot == NULL)
>> > -    *slot = ggc_alloc_libfunc_entry ();
>> > +    *slot = ggc_alloc<libfunc_entry> ();
>> >    (*slot)->op = op;
>> >    (*slot)->mode1 = mode;
>> >    (*slot)->mode2 = VOIDmode;
>> > @@ -6184,7 +6184,7 @@ set_conv_libfunc (convert_optab optab, enum machine_mode tmode,
>> >      val = 0;
>> >    slot = (struct libfunc_entry **) htab_find_slot (libfunc_hash, &e, INSERT);
>> >    if (*slot == NULL)
>> > -    *slot = ggc_alloc_libfunc_entry ();
>> > +    *slot = ggc_alloc<libfunc_entry> ();
>> >    (*slot)->op = optab;
>> >    (*slot)->mode1 = tmode;
>> >    (*slot)->mode2 = fmode;
>> > diff --git a/gcc/passes.c b/gcc/passes.c
>> > index fb60fc8..78277a2 100644
>> > --- a/gcc/passes.c
>> > +++ b/gcc/passes.c
>> > @@ -1542,7 +1542,7 @@ do_per_function_toporder (void (*callback) (void *data), void *data)
>> >    else
>> >      {
>> >        gcc_assert (!order);
>> > -      order = ggc_alloc_vec_cgraph_node_ptr (cgraph_n_nodes);
>> > +      order = ggc_vec_alloc<cgraph_node_ptr> (cgraph_n_nodes);
>> >        nnodes = ipa_reverse_postorder (order);
>> >        for (i = nnodes - 1; i >= 0; i--)
>> >          order[i]->process = 1;
>> > diff --git a/gcc/rtl.h b/gcc/rtl.h
>> > index 595b699..d8dca30 100644
>> > --- a/gcc/rtl.h
>> > +++ b/gcc/rtl.h
>> > @@ -251,7 +251,7 @@ struct GTY(()) object_block {
>> >  /* RTL expression ("rtx").  */
>> >
>> >  struct GTY((chain_next ("RTX_NEXT (&%h)"),
>> > -           chain_prev ("RTX_PREV (&%h)"), variable_size)) rtx_def {
>> > +           chain_prev ("RTX_PREV (&%h)"))) rtx_def {
>> >    /* The kind of expression this is.  */
>> >    ENUM_BITFIELD(rtx_code) code: 16;
>> >
>> > @@ -382,7 +382,7 @@ struct GTY((chain_next ("RTX_NEXT (&%h)"),
>> >     for a variable number of things.  The principle use is inside
>> >     PARALLEL expressions.  */
>> >
>> > -struct GTY((variable_size)) rtvec_def {
>> > +struct GTY(()) rtvec_def {
>> >    int num_elem;                /* number of elements */
>> >    rtx GTY ((length ("%h.num_elem"))) elem[1];
>> >  };
>> > diff --git a/gcc/sese.c b/gcc/sese.c
>> > index 342c5e8..a0b0899 100644
>> > --- a/gcc/sese.c
>> > +++ b/gcc/sese.c
>> > @@ -698,7 +698,7 @@ if_region_set_false_region (ifsese if_region, sese region)
>> >
>> >    if (slot)
>> >      {
>> > -      struct loop_exit *loop_exit = ggc_alloc_cleared_loop_exit ();
>> > +      struct loop_exit *loop_exit = ggc_cleared_alloc<struct loop_exit> ();
>> >
>> >        memcpy (loop_exit, *((struct loop_exit **) slot), sizeof (struct loop_exit));
>> >        htab_clear_slot (current_loops->exits, slot);
>> > diff --git a/gcc/stringpool.c b/gcc/stringpool.c
>> > index e317525..c880cb1 100644
>> > --- a/gcc/stringpool.c
>> > +++ b/gcc/stringpool.c
>> > @@ -258,10 +258,10 @@ static GTY(()) struct string_pool_data * spd;
>> >  void
>> >  gt_pch_save_stringpool (void)
>> >  {
>> > -  spd = ggc_alloc_string_pool_data ();
>> > +  spd = ggc_alloc<string_pool_data> ();
>> >    spd->nslots = ident_hash->nslots;
>> >    spd->nelements = ident_hash->nelements;
>> > -  spd->entries = ggc_alloc_vec_ht_identifier_ptr (spd->nslots);
>> > +  spd->entries = ggc_vec_alloc<ht_identifier_ptr> (spd->nslots);
>> >    memcpy (spd->entries, ident_hash->entries,
>> >           spd->nslots * sizeof (spd->entries[0]));
>> >  }
>> > diff --git a/gcc/target-globals.c b/gcc/target-globals.c
>> > index 7cf95ae..5f1a208 100644
>> > --- a/gcc/target-globals.c
>> > +++ b/gcc/target-globals.c
>> > @@ -83,13 +83,13 @@ save_target_globals (void)
>> >    g = (struct target_globals *) p;
>> >    g->flag_state = &p->flag_state;
>> >    g->regs = ggc_internal_cleared_alloc (sizeof (struct target_regs));
>> > -  g->rtl = ggc_alloc_cleared_target_rtl ();
>> > +  g->rtl = ggc_cleared_alloc<target_rtl> ();
>> >    g->hard_regs
>> >      = ggc_internal_cleared_alloc (sizeof (struct target_hard_regs));
>> >    g->reload = ggc_internal_cleared_alloc (sizeof (struct target_reload));
>> >    g->expmed =  ggc_internal_cleared_alloc (sizeof (struct target_expmed));
>> >    g->optabs = &p->optabs;
>> > -  g->libfuncs = ggc_alloc_cleared_target_libfuncs ();
>> > +  g->libfuncs = ggc_cleared_alloc<target_libfuncs> ();
>> >    g->cfgloop = &p->cfgloop;
>> >    g->ira = ggc_internal_cleared_alloc (sizeof (struct target_ira));
>> >    g->ira_int = ggc_internal_cleared_alloc (sizeof (struct target_ira_int));
>> > diff --git a/gcc/toplev.c b/gcc/toplev.c
>> > index 9535bd0..2f9c9f5 100644
>> > --- a/gcc/toplev.c
>> > +++ b/gcc/toplev.c
>> > @@ -1156,7 +1156,7 @@ general_init (const char *argv0)
>> >       table.  */
>> >    init_ggc ();
>> >    init_stringpool ();
>> > -  line_table = ggc_alloc_line_maps ();
>> > +  line_table = ggc_alloc<line_maps> ();
>> >    linemap_init (line_table);
>> >    line_table->reallocator = realloc_for_line_map;
>> >    line_table->round_alloc_size = ggc_round_alloc_size;
>> > diff --git a/gcc/trans-mem.c b/gcc/trans-mem.c
>> > index 417ca8a..52777d5 100644
>> > --- a/gcc/trans-mem.c
>> > +++ b/gcc/trans-mem.c
>> > @@ -479,7 +479,7 @@ record_tm_replacement (tree from, tree to)
>> >    if (tm_wrap_map == NULL)
>> >      tm_wrap_map = htab_create_ggc (32, tree_map_hash, tree_map_eq, 0);
>> >
>> > -  h = ggc_alloc_tree_map ();
>> > +  h = ggc_alloc<tree_map> ();
>> >    h->hash = htab_hash_pointer (from);
>> >    h->base.from = from;
>> >    h->to = to;
>> > @@ -3070,7 +3070,7 @@ split_bb_make_tm_edge (gimple stmt, basic_block dest_bb,
>> >    struct tm_restart_node *n = (struct tm_restart_node *) *slot;
>> >    if (n == NULL)
>> >      {
>> > -      n = ggc_alloc_tm_restart_node ();
>> > +      n = ggc_alloc<tm_restart_node> ();
>> >        *n = dummy;
>> >      }
>> >    else
>> > diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
>> > index 0fb2681..446e0f2 100644
>> > --- a/gcc/tree-cfg.c
>> > +++ b/gcc/tree-cfg.c
>> > @@ -6893,7 +6893,7 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb,
>> >      }
>> >
>> >    /* Initialize an empty loop tree.  */
>> > -  struct loops *loops = ggc_alloc_cleared_loops ();
>> > +  struct loops *loops = ggc_cleared_alloc<struct loops> ();
>> >    init_loops_structure (dest_cfun, loops, 1);
>> >    loops->state = LOOPS_MAY_HAVE_MULTIPLE_LATCHES;
>> >    set_loops_for_fn (dest_cfun, loops);
>> > diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h
>> > index 8810a3e..f4075fc 100644
>> > --- a/gcc/tree-data-ref.h
>> > +++ b/gcc/tree-data-ref.h
>> > @@ -565,7 +565,7 @@ lambda_vector_gcd (lambda_vector vector, int size)
>> >  static inline lambda_vector
>> >  lambda_vector_new (int size)
>> >  {
>> > -  return (lambda_vector) ggc_internal_cleared_alloc (sizeof (int) * size);
>> > +  return ggc_cleared_vec_alloc<int> (size);
>> >  }
>> >
>> >  /* Clear out vector VEC1 of length SIZE.  */
>> > diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
>> > index 960c04a..914ef68 100644
>> > --- a/gcc/tree-eh.c
>> > +++ b/gcc/tree-eh.c
>> > @@ -82,7 +82,7 @@ add_stmt_to_eh_lp_fn (struct function *ifun, gimple t, int num)
>> >
>> >    gcc_assert (num != 0);
>> >
>> > -  n = ggc_alloc_throw_stmt_node ();
>> > +  n = ggc_alloc<throw_stmt_node> ();
>> >    n->stmt = t;
>> >    n->lp_nr = num;
>> >
>> > diff --git a/gcc/tree-iterator.c b/gcc/tree-iterator.c
>> > index 37ee752..c4412ba 100644
>> > --- a/gcc/tree-iterator.c
>> > +++ b/gcc/tree-iterator.c
>> > @@ -131,7 +131,7 @@ tsi_link_before (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
>> >      }
>> >    else
>> >      {
>> > -      head = ggc_alloc_tree_statement_list_node ();
>> > +      head = ggc_alloc<tree_statement_list_node> ();
>> >        head->prev = NULL;
>> >        head->next = NULL;
>> >        head->stmt = t;
>> > @@ -207,7 +207,7 @@ tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
>> >      }
>> >    else
>> >      {
>> > -      head = ggc_alloc_tree_statement_list_node ();
>> > +      head = ggc_alloc<tree_statement_list_node> ();
>> >        head->prev = NULL;
>> >        head->next = NULL;
>> >        head->stmt = t;
>> > diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
>> > index f1ddc24..fc0b0d1 100644
>> > --- a/gcc/tree-scalar-evolution.c
>> > +++ b/gcc/tree-scalar-evolution.c
>> > @@ -332,7 +332,7 @@ new_scev_info_str (basic_block instantiated_below, tree var)
>> >  {
>> >    struct scev_info_str *res;
>> >
>> > -  res = ggc_alloc_scev_info_str ();
>> > +  res = ggc_alloc<scev_info_str> ();
>> >    res->name_version = SSA_NAME_VERSION (var);
>> >    res->chrec = chrec_not_analyzed_yet;
>> >    res->instantiated_below = instantiated_below->index;
>> > diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
>> > index 7628363..04effab 100644
>> > --- a/gcc/tree-ssa-loop-niter.c
>> > +++ b/gcc/tree-ssa-loop-niter.c
>> > @@ -2678,7 +2678,7 @@ record_estimate (struct loop *loop, tree bound, double_int i_bound,
>> >           || loop->nb_iterations == NULL_TREE
>> >           || TREE_CODE (loop->nb_iterations) != INTEGER_CST))
>> >      {
>> > -      struct nb_iter_bound *elt = ggc_alloc_nb_iter_bound ();
>> > +      struct nb_iter_bound *elt = ggc_alloc<nb_iter_bound> ();
>> >
>> >        elt->bound = i_bound;
>> >        elt->stmt = at_stmt;
>> > diff --git a/gcc/tree-ssa-operands.h b/gcc/tree-ssa-operands.h
>> > index 5f9edd4..42fe5a7 100644
>> > --- a/gcc/tree-ssa-operands.h
>> > +++ b/gcc/tree-ssa-operands.h
>> > @@ -45,7 +45,7 @@ typedef struct use_optype_d *use_optype_p;
>> >     operand memory manager.  Operands are suballocated out of this block.  The
>> >     MEM array varies in size.  */
>> >
>> > -struct GTY((chain_next("%h.next"), variable_size)) ssa_operand_memory_d {
>> > +struct GTY((chain_next("%h.next"))) ssa_operand_memory_d {
>> >    struct ssa_operand_memory_d *next;
>> >    char mem[1];
>> >  };
>> > diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
>> > index 1ea639d..f6f9dc9 100644
>> > --- a/gcc/tree-ssa.c
>> > +++ b/gcc/tree-ssa.c
>> > @@ -1120,7 +1120,7 @@ uid_ssaname_map_hash (const void *item)
>> >  void
>> >  init_tree_ssa (struct function *fn)
>> >  {
>> > -  fn->gimple_df = ggc_alloc_cleared_gimple_df ();
>> > +  fn->gimple_df = ggc_cleared_alloc<gimple_df> ();
>> >    fn->gimple_df->default_defs = htab_create_ggc (20, uid_ssaname_map_hash,
>> >                                                  uid_ssaname_map_eq, NULL);
>> >    pt_solution_reset (&fn->gimple_df->escaped);
>> > diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
>> > index 02db6a5..b013149 100644
>> > --- a/gcc/tree-ssanames.c
>> > +++ b/gcc/tree-ssanames.c
>> > @@ -196,7 +196,7 @@ set_range_info (tree name, enum value_range_type range_type, double_int min,
>> >    /* Allocate if not available.  */
>> >    if (ri == NULL)
>> >      {
>> > -      ri = ggc_alloc_cleared_range_info_def ();
>> > +      ri = ggc_cleared_alloc<range_info_def> ();
>> >        SSA_NAME_RANGE_INFO (name) = ri;
>> >        ri->nonzero_bits = double_int::mask (TYPE_PRECISION (TREE_TYPE (name)));
>> >      }
>> > @@ -437,7 +437,7 @@ get_ptr_info (tree t)
>> >    pi = SSA_NAME_PTR_INFO (t);
>> >    if (pi == NULL)
>> >      {
>> > -      pi = ggc_alloc_cleared_ptr_info_def ();
>> > +      pi = ggc_cleared_alloc<ptr_info_def> ();
>> >        pt_solution_reset (&pi->pt);
>> >        mark_ptr_info_alignment_unknown (pi);
>> >        SSA_NAME_PTR_INFO (t) = pi;
>> > @@ -481,7 +481,7 @@ duplicate_ssa_name_ptr_info (tree name, struct ptr_info_def *ptr_info)
>> >    if (!ptr_info)
>> >      return;
>> >
>> > -  new_ptr_info = ggc_alloc_ptr_info_def ();
>> > +  new_ptr_info = ggc_alloc<ptr_info_def> ();
>> >    *new_ptr_info = *ptr_info;
>> >
>> >    SSA_NAME_PTR_INFO (name) = new_ptr_info;
>> > @@ -502,7 +502,7 @@ duplicate_ssa_name_range_info (tree name, enum value_range_type range_type,
>> >    if (!range_info)
>> >      return;
>> >
>> > -  new_range_info = ggc_alloc_range_info_def ();
>> > +  new_range_info = ggc_alloc<range_info_def> ();
>> >    *new_range_info = *range_info;
>> >
>> >    gcc_assert (range_type == VR_RANGE || range_type == VR_ANTI_RANGE);
>> > diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c
>> > index b02bb6b..aa61187 100644
>> > --- a/gcc/tree-streamer-in.c
>> > +++ b/gcc/tree-streamer-in.c
>> > @@ -176,7 +176,7 @@ unpack_ts_real_cst_value_fields (struct bitpack_d *bp, tree expr)
>> >    for (i = 0; i < SIGSZ; i++)
>> >      r.sig[i] = (unsigned long) bp_unpack_value (bp, HOST_BITS_PER_LONG);
>> >
>> > -  rp = ggc_alloc_real_value ();
>> > +  rp = ggc_alloc<real_value> ();
>> >    memcpy (rp, &r, sizeof (REAL_VALUE_TYPE));
>> >    TREE_REAL_CST_PTR (expr) = rp;
>> >  }
>> > @@ -188,7 +188,7 @@ unpack_ts_real_cst_value_fields (struct bitpack_d *bp, tree expr)
>> >  static void
>> >  unpack_ts_fixed_cst_value_fields (struct bitpack_d *bp, tree expr)
>> >  {
>> > -  FIXED_VALUE_TYPE *fp = ggc_alloc_fixed_value ();
>> > +  FIXED_VALUE_TYPE *fp = ggc_alloc<fixed_value> ();
>> >    fp->mode = bp_unpack_enum (bp, machine_mode, MAX_MACHINE_MODE);
>> >    fp->data.low = bp_unpack_var_len_int (bp);
>> >    fp->data.high = bp_unpack_var_len_int (bp);
>> > diff --git a/gcc/tree.c b/gcc/tree.c
>> > index 365faf2..9a3e7e9 100644
>> > --- a/gcc/tree.c
>> > +++ b/gcc/tree.c
>> > @@ -1577,7 +1577,7 @@ build_fixed (tree type, FIXED_VALUE_TYPE f)
>> >    FIXED_VALUE_TYPE *fp;
>> >
>> >    v = make_node (FIXED_CST);
>> > -  fp = ggc_alloc_fixed_value ();
>> > +  fp = ggc_alloc<fixed_value> ();
>> >    memcpy (fp, &f, sizeof (FIXED_VALUE_TYPE));
>> >
>> >    TREE_TYPE (v) = type;
>> > @@ -1598,7 +1598,7 @@ build_real (tree type, REAL_VALUE_TYPE d)
>> >       Consider doing it via real_convert now.  */
>> >
>> >    v = make_node (REAL_CST);
>> > -  dp = ggc_alloc_real_value ();
>> > +  dp = ggc_alloc<real_value> ();
>> >    memcpy (dp, &d, sizeof (REAL_VALUE_TYPE));
>> >
>> >    TREE_TYPE (v) = type;
>> > @@ -6390,7 +6390,7 @@ decl_priority_info (tree decl)
>> >    h = (struct tree_priority_map *) *loc;
>> >    if (!h)
>> >      {
>> > -      h = ggc_alloc_cleared_tree_priority_map ();
>> > +      h = ggc_cleared_alloc<tree_priority_map> ();
>> >        *loc = h;
>> >        h->base.from = decl;
>> >        h->init = DEFAULT_INIT_PRIORITY;
>> > @@ -6473,7 +6473,7 @@ decl_debug_expr_insert (tree from, tree to)
>> >    struct tree_decl_map *h;
>> >    void **loc;
>> >
>> > -  h = ggc_alloc_tree_decl_map ();
>> > +  h = ggc_alloc<tree_decl_map> ();
>> >    h->base.from = from;
>> >    h->to = to;
>> >    loc = htab_find_slot_with_hash (debug_expr_for_decl, h, DECL_UID (from),
>> > @@ -6504,7 +6504,7 @@ decl_value_expr_insert (tree from, tree to)
>> >    struct tree_decl_map *h;
>> >    void **loc;
>> >
>> > -  h = ggc_alloc_tree_decl_map ();
>> > +  h = ggc_alloc<tree_decl_map> ();
>> >    h->base.from = from;
>> >    h->to = to;
>> >    loc = htab_find_slot_with_hash (value_expr_for_decl, h, DECL_UID (from),
>> > @@ -6545,7 +6545,7 @@ decl_debug_args_insert (tree from)
>> >    if (debug_args_for_decl == NULL)
>> >      debug_args_for_decl = htab_create_ggc (64, tree_vec_map_hash,
>> >                                            tree_vec_map_eq, 0);
>> > -  h = ggc_alloc_tree_vec_map ();
>> > +  h = ggc_alloc<tree_vec_map> ();
>> >    h->base.from = from;
>> >    h->to = NULL;
>> >    loc = htab_find_slot_with_hash (debug_args_for_decl, h, DECL_UID (from),
>> > @@ -6728,7 +6728,7 @@ type_hash_add (hashval_t hashcode, tree type)
>> >    struct type_hash *h;
>> >    void **loc;
>> >
>> > -  h = ggc_alloc_type_hash ();
>> > +  h = ggc_alloc<type_hash> ();
>> >    h->hash = hashcode;
>> >    h->type = type;
>> >    loc = htab_find_slot_with_hash (type_hash_table, h, hashcode, INSERT);
>> > diff --git a/gcc/ubsan.c b/gcc/ubsan.c
>> > index d9d740c..11461d0 100644
>> > --- a/gcc/ubsan.c
>> > +++ b/gcc/ubsan.c
>> > @@ -99,7 +99,7 @@ decl_for_type_insert (tree type, tree decl)
>> >    struct tree_type_map *h;
>> >    void **slot;
>> >
>> > -  h = ggc_alloc_tree_type_map ();
>> > +  h = ggc_alloc<tree_type_map> ();
>> >    h->type.from = type;
>> >    h->decl = decl;
>> >    slot = htab_find_slot_with_hash (decl_tree_for_type, h, TYPE_UID (type),
>> > diff --git a/gcc/varasm.c b/gcc/varasm.c
>> > index 3b42faa..4c59d35 100644
>> > --- a/gcc/varasm.c
>> > +++ b/gcc/varasm.c
>> > @@ -242,7 +242,7 @@ get_unnamed_section (unsigned int flags, void (*callback) (const void *),
>> >  {
>> >    section *sect;
>> >
>> > -  sect = ggc_alloc_section ();
>> > +  sect = ggc_alloc<section> ();
>> >    sect->unnamed.common.flags = flags | SECTION_UNNAMED;
>> >    sect->unnamed.callback = callback;
>> >    sect->unnamed.data = data;
>> > @@ -259,7 +259,7 @@ get_noswitch_section (unsigned int flags, noswitch_section_callback callback)
>> >  {
>> >    section *sect;
>> >
>> > -  sect = ggc_alloc_section ();
>> > +  sect = ggc_alloc<section> ();
>> >    sect->noswitch.common.flags = flags | SECTION_NOSWITCH;
>> >    sect->noswitch.callback = callback;
>> >
>> > @@ -280,7 +280,7 @@ get_section (const char *name, unsigned int flags, tree decl)
>> >    flags |= SECTION_NAMED;
>> >    if (*slot == NULL)
>> >      {
>> > -      sect = ggc_alloc_section ();
>> > +      sect = ggc_alloc<section> ();
>> >        sect->named.common.flags = flags;
>> >        sect->named.name = ggc_strdup (name);
>> >        sect->named.decl = decl;
>> > @@ -361,7 +361,7 @@ get_block_for_section (section *sect)
>> >    block = (struct object_block *) *slot;
>> >    if (block == NULL)
>> >      {
>> > -      block = ggc_alloc_cleared_object_block ();
>> > +      block = ggc_cleared_alloc<object_block> ();
>> >        block->sect = sect;
>> >        *slot = block;
>> >      }
>> > @@ -3203,7 +3203,7 @@ build_constant_desc (tree exp)
>> >    int labelno;
>> >    tree decl;
>> >
>> > -  desc = ggc_alloc_constant_descriptor_tree ();
>> > +  desc = ggc_alloc<constant_descriptor_tree> ();
>> >    desc->value = copy_constant (exp);
>> >
>> >    /* Create a string containing the label name, in LABEL.  */
>> > @@ -3607,7 +3607,7 @@ create_constant_pool (void)
>> >  {
>> >    struct rtx_constant_pool *pool;
>> >
>> > -  pool = ggc_alloc_rtx_constant_pool ();
>> > +  pool = ggc_alloc<rtx_constant_pool> ();
>> >    pool->const_rtx_htab = htab_create_ggc (31, const_desc_rtx_hash,
>> >                                           const_desc_rtx_eq, NULL);
>> >    pool->first = NULL;
>> > @@ -3673,7 +3673,7 @@ force_const_mem (enum machine_mode mode, rtx x)
>> >      return copy_rtx (desc->mem);
>> >
>> >    /* Otherwise, create a new descriptor.  */
>> > -  desc = ggc_alloc_constant_descriptor_rtx ();
>> > +  desc = ggc_alloc<constant_descriptor_rtx> ();
>> >    *slot = desc;
>> >
>> >    /* Align the location counter as required by EXP's data type.  */
>> > @@ -5721,7 +5721,7 @@ record_tm_clone_pair (tree o, tree n)
>> >    if (tm_clone_hash == NULL)
>> >      tm_clone_hash = htab_create_ggc (32, tree_map_hash, tree_map_eq, 0);
>> >
>> > -  h = ggc_alloc_tree_map ();
>> > +  h = ggc_alloc<tree_map> ();
>> >    h->hash = htab_hash_pointer (o);
>> >    h->base.from = o;
>> >    h->to = n;
>> > diff --git a/gcc/varpool.c b/gcc/varpool.c
>> > index 69172c6..45ff88d 100644
>> > --- a/gcc/varpool.c
>> > +++ b/gcc/varpool.c
>> > @@ -135,7 +135,7 @@ varpool_call_variable_insertion_hooks (varpool_node *node)
>> >  varpool_node *
>> >  varpool_create_empty_node (void)
>> >  {
>> > -  varpool_node *node = ggc_alloc_cleared_varpool_node ();
>> > +  varpool_node *node = ggc_cleared_alloc<varpool_node> ();
>> >    node->type = SYMTAB_VARIABLE;
>> >    return node;
>> >  }
>> > --
>> > 2.0.0.rc0
>> >

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/6] add finalizers to ggc
  2014-04-29 13:00   ` Richard Biener
@ 2014-04-29 13:26     ` Trevor Saunders
  2014-04-29 14:37       ` Richard Biener
  0 siblings, 1 reply; 18+ messages in thread
From: Trevor Saunders @ 2014-04-29 13:26 UTC (permalink / raw)
  To: Richard Biener; +Cc: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 13360 bytes --]

On Tue, Apr 29, 2014 at 02:58:11PM +0200, Richard Biener wrote:
> On Tue, Apr 29, 2014 at 1:08 PM,  <tsaunders@mozilla.com> wrote:
> > From: Trevor Saunders <tsaunders@mozilla.com>
> >
> > Hi,
> >
> > This implements finalizers by keeping a list of registered finalizers
> > and after every mark but before sweeping check to see if any of them are
> > for unmarked blocks.
> >
> > bootstrapped + regtested on x86_64-unknown-linux-gnu, ok?
> >
> > Trev
> >
> > gcc/ChangeLog:
> >
> >         * ggc-common.c (ggc_internal_cleared_alloc): Adjust.
> >         * ggc-none.c (ggc_internal_alloc): Assert if a finalizer is passed.
> >         (ggc_internal_cleared_alloc): Likewise.
> >         * ggc-page.c (finalizer): New class.
> >         (globals::finalizer_lists): New member.
> >         (ggc_internal_alloc): Record the finalizer if any for the block being
> >         allocated.
> >         (ggc_handle_finalizers): New function.
> >         (ggc_collect): Call ggc_handle_finalizers.
> >         * ggc.h (ggc_internal_alloc):Add arguments to allow installing a
> >         finalizer.
> >         (ggc_internal_cleared_alloc): Likewise.
> >         (finalize): New function.
> >         (need_finalization_p): Likewise.
> >         (ggc_alloc): Install the type's destructor as the finalizer if it
> >         might do something.
> >         (ggc_cleared_alloc): Likewise.
> >         (ggc_vec_alloc): Likewise.
> >         (ggc_cleared_vec_alloc): Likewise.
> > ---
> >  gcc/ggc-common.c |  5 +++--
> >  gcc/ggc-none.c   |  8 ++++++--
> >  gcc/ggc-page.c   | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
> >  gcc/ggc.h        | 52 ++++++++++++++++++++++++++++++++++++++++++++++------
> >  4 files changed, 104 insertions(+), 11 deletions(-)
> >
> > diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
> > index e89cc64..b11a10c 100644
> > --- a/gcc/ggc-common.c
> > +++ b/gcc/ggc-common.c
> > @@ -174,9 +174,10 @@ ggc_mark_roots (void)
> >
> >  /* Allocate a block of memory, then clear it.  */
> >  void *
> > -ggc_internal_cleared_alloc (size_t size MEM_STAT_DECL)
> > +ggc_internal_cleared_alloc (size_t size, void (*f)(void *), size_t s, size_t n
> > +                           MEM_STAT_DECL)
> >  {
> > -  void *buf = ggc_internal_alloc (size PASS_MEM_STAT);
> > +  void *buf = ggc_internal_alloc (size, f, s, n PASS_MEM_STAT);
> >    memset (buf, 0, size);
> >    return buf;
> >  }
> > diff --git a/gcc/ggc-none.c b/gcc/ggc-none.c
> > index aad89bf..97d3566 100644
> > --- a/gcc/ggc-none.c
> > +++ b/gcc/ggc-none.c
> > @@ -41,14 +41,18 @@ ggc_round_alloc_size (size_t requested_size)
> >  }
> >
> >  void *
> > -ggc_internal_alloc (size_t size MEM_STAT_DECL)
> > +ggc_internal_alloc (size_t size, void (*f)(void *), size_t, size_t
> > +                   MEM_STAT_DECL)
> >  {
> > +  gcc_assert (!f); // ggc-none doesn't support finalizers
> >    return xmalloc (size);
> >  }
> >
> >  void *
> > -ggc_internal_cleared_alloc (size_t size MEM_STAT_DECL)
> > +ggc_internal_cleared_alloc (size_t size, void (*f)(void *), size_t, size_t
> > +                           MEM_STAT_DECL)
> >  {
> > +  gcc_assert (!f); // ggc-none doesn't support finalizers
> >    return xcalloc (size, 1);
> >  }
> >
> > diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
> > index ae5e88a..208b526 100644
> > --- a/gcc/ggc-page.c
> > +++ b/gcc/ggc-page.c
> > @@ -332,6 +332,27 @@ typedef struct page_table_chain
> >
> >  #endif
> >
> > +class finalizer
> > +{
> > +public:
> > +  finalizer (uintptr_t addr, void (*f)(void *), size_t s, size_t n) :
> > +    m_addr (addr), m_function (f), m_object_size (s), m_n_objects (n) {}
> > +
> > +  void call () const
> > +    {
> > +      for (size_t i = 0; i < m_n_objects; i++)
> > +       m_function (reinterpret_cast<void *> (m_addr + (i * m_object_size)));
> > +    }
> > +
> > +  uintptr_t addr () const { return m_addr; }
> > +
> > +private:
> > +  uintptr_t m_addr;
> > +  void (*m_function)(void *);
> > +  size_t m_object_size;
> > +  size_t m_n_objects;
> > +};
> > +
> >  #ifdef ENABLE_GC_ALWAYS_COLLECT
> >  /* List of free objects to be verified as actually free on the
> >     next collection.  */
> > @@ -425,6 +446,9 @@ static struct globals
> >       better runtime data access pattern.  */
> >    unsigned long **save_in_use;
> >
> > +  /* finalizer_lists[i] is the list of finalizers for blocks of order i.  */
> > +  vec<finalizer> finalizer_lists[NUM_ORDERS];
> > +
> >  #ifdef ENABLE_GC_ALWAYS_COLLECT
> >    /* List of free objects to be verified as actually free on the
> >       next collection.  */
> > @@ -1202,7 +1226,8 @@ ggc_round_alloc_size (size_t requested_size)
> >  /* Allocate a chunk of memory of SIZE bytes.  Its contents are undefined.  */
> >
> >  void *
> > -ggc_internal_alloc (size_t size MEM_STAT_DECL)
> > +ggc_internal_alloc (size_t size, void (*f)(void *), size_t s, size_t n
> > +                   MEM_STAT_DECL)
> >  {
> >    size_t order, word, bit, object_offset, object_size;
> >    struct page_entry *entry;
> > @@ -1345,6 +1370,10 @@ ggc_internal_alloc (size_t size MEM_STAT_DECL)
> >    /* For timevar statistics.  */
> >    timevar_ggc_mem_total += object_size;
> >
> > +  if (f)
> > +    G.finalizer_lists[order]
> > +      .safe_push (finalizer (reinterpret_cast<uintptr_t> (result), f, s, n));
> > +
> >    if (GATHER_STATISTICS)
> >      {
> >        size_t overhead = object_size - size;
> > @@ -1811,6 +1840,24 @@ clear_marks (void)
> >      }
> >  }
> >
> > +static void
> > +ggc_handle_finalizers ()
> > +{
> > +  for (unsigned int order = 2; order < NUM_ORDERS; order++)
> > +    {
> > +      unsigned int length = G.finalizer_lists[order].length ();
> > +      for (unsigned int i = length - 1; i < length; i--)
> 
> I suppose you are walking backwards here to handle dependences
> properly.

I only did it because it seemed epsilon easier than iterating forward
and dealing with removals from the list.

I suppose dependancies between objects could be a reason to do it
backwards, but I tend to think getting dependancies of that sort right
is impossible and you shouldn't rely on any given ordering.  So just
write itempotent dtors and all's good ;)

> But it doesn't address dependencies across different allocation
> orders (what's the reason to even have one vector per order?).

 I think I did it for locality, but otherwise I don't think there's a
 great reason other than copying what other stuff does with orders.

> > +       {
> > +         finalizer &f = G.finalizer_lists[order][i];
> > +         if (!ggc_marked_p (reinterpret_cast<void *> (f.addr ())))
> > +           {
> > +             f.call ();
> > +             G.finalizer_lists[order].ordered_remove (i);
> 
> But this clearly will be an efficiency issue.  Can you delay
> removing the element from the list and instead do it in
> a second forward run over all finalizers of that order (if there
> were any finalizers run in the first)?

 Or if we agree to not care about order we can just use the non ordered
 remove.

> I suppose that the overall complexity of walking the finalizers isn't
> that bad as we walked all reachable ggc memory anyway.

yeah, its bad but not as bad as gc itself is my thought.

> So the only issue would be memory inefficiencies for a lot
> of small individual objects that need finalization.  Thus,
> 
> > +private:
> > +  uintptr_t m_addr;
> > +  void (*m_function)(void *);
> > +  size_t m_object_size;
> > +  size_t m_n_objects;
> 
> could be improved by noting that m_function and m_object_size
> are somewhat redundant (and m_object_size and m_n_objects
> are unused for non-vectors).  So, instead of m_function and
> m_object_size you could store an index into a global vector
> of m_function/m_object_size pairs (eventually even statically
> compute it by gengtype.c to avoid some kind of lookup
> at allocation time).

deciding if a type needs finalization would mean teaching gengtype about
a lot of C++ :/  Well actually maybe not, if we don't maybe we could
just have gengtype emit a blob of C++ that does it if we're really
clever, but that would take some thought.

> As finalization order is currently broken (see above) you could
> also have two vectors of finalizers, one for the vector case
> and one for the non-vector case.

that certainly seems doable.

> An optimization would also be to look at the last added
> finalizer and see if the current object is adjacent to it
> and only adjust m_n_objects.   (not sure if that would trigger
> often)

What happens if they aren't freed at the same time though?

> I suppose given we don't have many uses of finalizers (yet)
> this all isn't much of an issue.  Still please eventually
> reduce to a single finalizer vector and avoid the ordered remove.

both of those certainly seem doable.

thanks!

Trev

> 
> Thanks,
> Richard.
> 
> > +           }
> > +       }
> > +    }
> > +}
> > +
> >  /* Free all empty pages.  Partially empty pages need no attention
> >     because the `mark' bit doubles as an `unused' bit.  */
> >
> > @@ -2075,6 +2122,7 @@ ggc_collect (void)
> >
> >    clear_marks ();
> >    ggc_mark_roots ();
> > +  ggc_handle_finalizers ();
> >
> >    if (GATHER_STATISTICS)
> >      ggc_prune_overhead_list ();
> > diff --git a/gcc/ggc.h b/gcc/ggc.h
> > index 50fb199..4c59597 100644
> > --- a/gcc/ggc.h
> > +++ b/gcc/ggc.h
> > @@ -136,13 +136,16 @@ extern void gt_pch_save (FILE *f);
> >  /* Allocation.  */
> >
> >  /* The internal primitive.  */
> > -extern void *ggc_internal_alloc (size_t CXX_MEM_STAT_INFO) ATTRIBUTE_MALLOC;
> > +extern void *ggc_internal_alloc (size_t, void (*)(void *) = NULL, size_t = 0,
> > +                                size_t = 1 CXX_MEM_STAT_INFO)
> > +     ATTRIBUTE_MALLOC;
> >
> >  extern size_t ggc_round_alloc_size (size_t requested_size);
> >
> >  /* Allocates cleared memory.  */
> > -extern void *ggc_internal_cleared_alloc (size_t CXX_MEM_STAT_INFO)
> > -  ATTRIBUTE_MALLOC;
> > +extern void *ggc_internal_cleared_alloc (size_t, void (*)(void *) = NULL,
> > +                                        size_t = 0, size_t = 1
> > +                                        CXX_MEM_STAT_INFO) ATTRIBUTE_MALLOC;
> >
> >  /* Resize a block.  */
> >  extern void *ggc_realloc (void *, size_t CXX_MEM_STAT_INFO);
> > @@ -157,24 +160,55 @@ extern void dump_ggc_loc_statistics (bool);
> >      ((T *) ggc_realloc ((P), (N) * sizeof (T) MEM_STAT_INFO))
> >
> >  template<typename T>
> > +void
> > +finalize (void *p)
> > +{
> > +  static_cast<T *> (p)->~T ();
> > +}
> > +
> > +template<typename T>
> > +static inline bool
> > +need_finalization_p ()
> > +{
> > +#if GCC_VERSION >= 4003
> > +  return !__has_trivial_destructor (T);
> > +#else
> > +  return true;
> > +#endif
> > +}
> > +
> > +template<typename T>
> >  static inline T *
> >  ggc_alloc (ALONE_CXX_MEM_STAT_INFO)
> >  {
> > -  return static_cast<T *> (ggc_internal_alloc (sizeof (T) PASS_MEM_STAT));
> > +  if (need_finalization_p<T> ())
> > +    return static_cast<T *> (ggc_internal_alloc (sizeof (T), finalize<T>
> > +                                                PASS_MEM_STAT));
> > +  else
> > +    return static_cast<T *> (ggc_internal_alloc (sizeof (T) PASS_MEM_STAT));
> >  }
> >
> >  template<typename T>
> >  static inline T *
> >  ggc_cleared_alloc (ALONE_CXX_MEM_STAT_INFO)
> >  {
> > -  return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T)
> > -                                                      PASS_MEM_STAT));
> > +  if (need_finalization_p<T> ())
> > +    return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T),
> > +                                                        finalize<T>
> > +                                                        PASS_MEM_STAT));
> > +  else
> > +    return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T)
> > +                                                        PASS_MEM_STAT));
> >  }
> >
> >  template<typename T>
> >  static inline T *
> >  ggc_vec_alloc (size_t c CXX_MEM_STAT_INFO)
> >  {
> > +  if (need_finalization_p<T> ())
> > +    return static_cast<T *> (ggc_internal_alloc (c * sizeof (T), finalize<T>,
> > +                                                sizeof (T), c PASS_MEM_STAT));
> > +  else
> >      return static_cast<T *> (ggc_internal_alloc (c * sizeof (T)
> >                                                  PASS_MEM_STAT));
> >  }
> > @@ -183,6 +217,12 @@ template<typename T>
> >  static inline T *
> >  ggc_cleared_vec_alloc (size_t c CXX_MEM_STAT_INFO)
> >  {
> > +  if (need_finalization_p<T> ())
> > +    return static_cast<T *> (ggc_internal_cleared_alloc (c * sizeof (T),
> > +                                                        finalize<T>,
> > +                                                        sizeof (T), c
> > +                                                        PASS_MEM_STAT));
> > +  else
> >      return static_cast<T *> (ggc_internal_cleared_alloc (c * sizeof (T)
> >                                                          PASS_MEM_STAT));
> >  }
> > --
> > 2.0.0.rc0
> >

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/6] add finalizers to ggc
  2014-04-29 13:26     ` Trevor Saunders
@ 2014-04-29 14:37       ` Richard Biener
  0 siblings, 0 replies; 18+ messages in thread
From: Richard Biener @ 2014-04-29 14:37 UTC (permalink / raw)
  To: Trevor Saunders; +Cc: GCC Patches

On Tue, Apr 29, 2014 at 3:21 PM, Trevor Saunders <tsaunders@mozilla.com> wrote:
> On Tue, Apr 29, 2014 at 02:58:11PM +0200, Richard Biener wrote:
>> On Tue, Apr 29, 2014 at 1:08 PM,  <tsaunders@mozilla.com> wrote:
>> > From: Trevor Saunders <tsaunders@mozilla.com>
>> >
>> > Hi,
>> >
>> > This implements finalizers by keeping a list of registered finalizers
>> > and after every mark but before sweeping check to see if any of them are
>> > for unmarked blocks.
>> >
>> > bootstrapped + regtested on x86_64-unknown-linux-gnu, ok?
>> >
>> > Trev
>> >
>> > gcc/ChangeLog:
>> >
>> >         * ggc-common.c (ggc_internal_cleared_alloc): Adjust.
>> >         * ggc-none.c (ggc_internal_alloc): Assert if a finalizer is passed.
>> >         (ggc_internal_cleared_alloc): Likewise.
>> >         * ggc-page.c (finalizer): New class.
>> >         (globals::finalizer_lists): New member.
>> >         (ggc_internal_alloc): Record the finalizer if any for the block being
>> >         allocated.
>> >         (ggc_handle_finalizers): New function.
>> >         (ggc_collect): Call ggc_handle_finalizers.
>> >         * ggc.h (ggc_internal_alloc):Add arguments to allow installing a
>> >         finalizer.
>> >         (ggc_internal_cleared_alloc): Likewise.
>> >         (finalize): New function.
>> >         (need_finalization_p): Likewise.
>> >         (ggc_alloc): Install the type's destructor as the finalizer if it
>> >         might do something.
>> >         (ggc_cleared_alloc): Likewise.
>> >         (ggc_vec_alloc): Likewise.
>> >         (ggc_cleared_vec_alloc): Likewise.
>> > ---
>> >  gcc/ggc-common.c |  5 +++--
>> >  gcc/ggc-none.c   |  8 ++++++--
>> >  gcc/ggc-page.c   | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
>> >  gcc/ggc.h        | 52 ++++++++++++++++++++++++++++++++++++++++++++++------
>> >  4 files changed, 104 insertions(+), 11 deletions(-)
>> >
>> > diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
>> > index e89cc64..b11a10c 100644
>> > --- a/gcc/ggc-common.c
>> > +++ b/gcc/ggc-common.c
>> > @@ -174,9 +174,10 @@ ggc_mark_roots (void)
>> >
>> >  /* Allocate a block of memory, then clear it.  */
>> >  void *
>> > -ggc_internal_cleared_alloc (size_t size MEM_STAT_DECL)
>> > +ggc_internal_cleared_alloc (size_t size, void (*f)(void *), size_t s, size_t n
>> > +                           MEM_STAT_DECL)
>> >  {
>> > -  void *buf = ggc_internal_alloc (size PASS_MEM_STAT);
>> > +  void *buf = ggc_internal_alloc (size, f, s, n PASS_MEM_STAT);
>> >    memset (buf, 0, size);
>> >    return buf;
>> >  }
>> > diff --git a/gcc/ggc-none.c b/gcc/ggc-none.c
>> > index aad89bf..97d3566 100644
>> > --- a/gcc/ggc-none.c
>> > +++ b/gcc/ggc-none.c
>> > @@ -41,14 +41,18 @@ ggc_round_alloc_size (size_t requested_size)
>> >  }
>> >
>> >  void *
>> > -ggc_internal_alloc (size_t size MEM_STAT_DECL)
>> > +ggc_internal_alloc (size_t size, void (*f)(void *), size_t, size_t
>> > +                   MEM_STAT_DECL)
>> >  {
>> > +  gcc_assert (!f); // ggc-none doesn't support finalizers
>> >    return xmalloc (size);
>> >  }
>> >
>> >  void *
>> > -ggc_internal_cleared_alloc (size_t size MEM_STAT_DECL)
>> > +ggc_internal_cleared_alloc (size_t size, void (*f)(void *), size_t, size_t
>> > +                           MEM_STAT_DECL)
>> >  {
>> > +  gcc_assert (!f); // ggc-none doesn't support finalizers
>> >    return xcalloc (size, 1);
>> >  }
>> >
>> > diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
>> > index ae5e88a..208b526 100644
>> > --- a/gcc/ggc-page.c
>> > +++ b/gcc/ggc-page.c
>> > @@ -332,6 +332,27 @@ typedef struct page_table_chain
>> >
>> >  #endif
>> >
>> > +class finalizer
>> > +{
>> > +public:
>> > +  finalizer (uintptr_t addr, void (*f)(void *), size_t s, size_t n) :
>> > +    m_addr (addr), m_function (f), m_object_size (s), m_n_objects (n) {}
>> > +
>> > +  void call () const
>> > +    {
>> > +      for (size_t i = 0; i < m_n_objects; i++)
>> > +       m_function (reinterpret_cast<void *> (m_addr + (i * m_object_size)));
>> > +    }
>> > +
>> > +  uintptr_t addr () const { return m_addr; }
>> > +
>> > +private:
>> > +  uintptr_t m_addr;
>> > +  void (*m_function)(void *);
>> > +  size_t m_object_size;
>> > +  size_t m_n_objects;
>> > +};
>> > +
>> >  #ifdef ENABLE_GC_ALWAYS_COLLECT
>> >  /* List of free objects to be verified as actually free on the
>> >     next collection.  */
>> > @@ -425,6 +446,9 @@ static struct globals
>> >       better runtime data access pattern.  */
>> >    unsigned long **save_in_use;
>> >
>> > +  /* finalizer_lists[i] is the list of finalizers for blocks of order i.  */
>> > +  vec<finalizer> finalizer_lists[NUM_ORDERS];
>> > +
>> >  #ifdef ENABLE_GC_ALWAYS_COLLECT
>> >    /* List of free objects to be verified as actually free on the
>> >       next collection.  */
>> > @@ -1202,7 +1226,8 @@ ggc_round_alloc_size (size_t requested_size)
>> >  /* Allocate a chunk of memory of SIZE bytes.  Its contents are undefined.  */
>> >
>> >  void *
>> > -ggc_internal_alloc (size_t size MEM_STAT_DECL)
>> > +ggc_internal_alloc (size_t size, void (*f)(void *), size_t s, size_t n
>> > +                   MEM_STAT_DECL)
>> >  {
>> >    size_t order, word, bit, object_offset, object_size;
>> >    struct page_entry *entry;
>> > @@ -1345,6 +1370,10 @@ ggc_internal_alloc (size_t size MEM_STAT_DECL)
>> >    /* For timevar statistics.  */
>> >    timevar_ggc_mem_total += object_size;
>> >
>> > +  if (f)
>> > +    G.finalizer_lists[order]
>> > +      .safe_push (finalizer (reinterpret_cast<uintptr_t> (result), f, s, n));
>> > +
>> >    if (GATHER_STATISTICS)
>> >      {
>> >        size_t overhead = object_size - size;
>> > @@ -1811,6 +1840,24 @@ clear_marks (void)
>> >      }
>> >  }
>> >
>> > +static void
>> > +ggc_handle_finalizers ()
>> > +{
>> > +  for (unsigned int order = 2; order < NUM_ORDERS; order++)
>> > +    {
>> > +      unsigned int length = G.finalizer_lists[order].length ();
>> > +      for (unsigned int i = length - 1; i < length; i--)
>>
>> I suppose you are walking backwards here to handle dependences
>> properly.
>
> I only did it because it seemed epsilon easier than iterating forward
> and dealing with removals from the list.

Heh, but iterating forward is as easy as

  unsigned keep = 0, pick = 0;
  for (; pick < length; ++pick)
    {
       if (!ggc_marked (...))
         {
...
         }
       else if (pick != keep)
         G.finalizer_list[order][keep++] = G.finalizer_list[order][pick];
    }
  G.finalizer_list[oder].truncate (keep);

either as 2nd loop doing the removal (with empty ggc_marked () case)
or by doing the walk forward in the first place.

With a single vector we can then impose a "reasonable"
order of destruction.

Or, as you say, we can also use unordered remove which should
be even more efficient as it avoids all copying.

> I suppose dependancies between objects could be a reason to do it
> backwards, but I tend to think getting dependancies of that sort right
> is impossible and you shouldn't rely on any given ordering.  So just
> write itempotent dtors and all's good ;)
>
>> But it doesn't address dependencies across different allocation
>> orders (what's the reason to even have one vector per order?).
>
>  I think I did it for locality, but otherwise I don't think there's a
>  great reason other than copying what other stuff does with orders.

Hmm, I'd reduce it to a single vector (otherwise you'd eventually
even want a vector per GC page).

>> > +       {
>> > +         finalizer &f = G.finalizer_lists[order][i];
>> > +         if (!ggc_marked_p (reinterpret_cast<void *> (f.addr ())))
>> > +           {
>> > +             f.call ();
>> > +             G.finalizer_lists[order].ordered_remove (i);
>>
>> But this clearly will be an efficiency issue.  Can you delay
>> removing the element from the list and instead do it in
>> a second forward run over all finalizers of that order (if there
>> were any finalizers run in the first)?
>
>  Or if we agree to not care about order we can just use the non ordered
>  remove.

Right.  With a single vector and backward walk I can't think of
a case that we could break though?  Of course better make
sure any dependence on order will break immediately
(and thus finalize in the "wrong" forward order).

>> I suppose that the overall complexity of walking the finalizers isn't
>> that bad as we walked all reachable ggc memory anyway.
>
> yeah, its bad but not as bad as gc itself is my thought.
>
>> So the only issue would be memory inefficiencies for a lot
>> of small individual objects that need finalization.  Thus,
>>
>> > +private:
>> > +  uintptr_t m_addr;
>> > +  void (*m_function)(void *);
>> > +  size_t m_object_size;
>> > +  size_t m_n_objects;
>>
>> could be improved by noting that m_function and m_object_size
>> are somewhat redundant (and m_object_size and m_n_objects
>> are unused for non-vectors).  So, instead of m_function and
>> m_object_size you could store an index into a global vector
>> of m_function/m_object_size pairs (eventually even statically
>> compute it by gengtype.c to avoid some kind of lookup
>> at allocation time).
>
> deciding if a type needs finalization would mean teaching gengtype about
> a lot of C++ :/  Well actually maybe not, if we don't maybe we could
> just have gengtype emit a blob of C++ that does it if we're really
> clever, but that would take some thought.

Yeah, I think we can improve on this with a followup if it turns out
necessary.

>> As finalization order is currently broken (see above) you could
>> also have two vectors of finalizers, one for the vector case
>> and one for the non-vector case.
>
> that certainly seems doable.

Or go with this in the mean time.  Actually that would be my
preference - iterate forward (and document dependences are
not handled) using unordered removes and have overall
two vectors.

>> An optimization would also be to look at the last added
>> finalizer and see if the current object is adjacent to it
>> and only adjust m_n_objects.   (not sure if that would trigger
>> often)
>
> What happens if they aren't freed at the same time though?

Good question.  Ok, so lets not do this.

>> I suppose given we don't have many uses of finalizers (yet)
>> this all isn't much of an issue.  Still please eventually
>> reduce to a single finalizer vector and avoid the ordered remove.
>
> both of those certainly seem doable.

Thanks,
Richard.

> thanks!
>
> Trev
>
>>
>> Thanks,
>> Richard.
>>
>> > +           }
>> > +       }
>> > +    }
>> > +}
>> > +
>> >  /* Free all empty pages.  Partially empty pages need no attention
>> >     because the `mark' bit doubles as an `unused' bit.  */
>> >
>> > @@ -2075,6 +2122,7 @@ ggc_collect (void)
>> >
>> >    clear_marks ();
>> >    ggc_mark_roots ();
>> > +  ggc_handle_finalizers ();
>> >
>> >    if (GATHER_STATISTICS)
>> >      ggc_prune_overhead_list ();
>> > diff --git a/gcc/ggc.h b/gcc/ggc.h
>> > index 50fb199..4c59597 100644
>> > --- a/gcc/ggc.h
>> > +++ b/gcc/ggc.h
>> > @@ -136,13 +136,16 @@ extern void gt_pch_save (FILE *f);
>> >  /* Allocation.  */
>> >
>> >  /* The internal primitive.  */
>> > -extern void *ggc_internal_alloc (size_t CXX_MEM_STAT_INFO) ATTRIBUTE_MALLOC;
>> > +extern void *ggc_internal_alloc (size_t, void (*)(void *) = NULL, size_t = 0,
>> > +                                size_t = 1 CXX_MEM_STAT_INFO)
>> > +     ATTRIBUTE_MALLOC;
>> >
>> >  extern size_t ggc_round_alloc_size (size_t requested_size);
>> >
>> >  /* Allocates cleared memory.  */
>> > -extern void *ggc_internal_cleared_alloc (size_t CXX_MEM_STAT_INFO)
>> > -  ATTRIBUTE_MALLOC;
>> > +extern void *ggc_internal_cleared_alloc (size_t, void (*)(void *) = NULL,
>> > +                                        size_t = 0, size_t = 1
>> > +                                        CXX_MEM_STAT_INFO) ATTRIBUTE_MALLOC;
>> >
>> >  /* Resize a block.  */
>> >  extern void *ggc_realloc (void *, size_t CXX_MEM_STAT_INFO);
>> > @@ -157,24 +160,55 @@ extern void dump_ggc_loc_statistics (bool);
>> >      ((T *) ggc_realloc ((P), (N) * sizeof (T) MEM_STAT_INFO))
>> >
>> >  template<typename T>
>> > +void
>> > +finalize (void *p)
>> > +{
>> > +  static_cast<T *> (p)->~T ();
>> > +}
>> > +
>> > +template<typename T>
>> > +static inline bool
>> > +need_finalization_p ()
>> > +{
>> > +#if GCC_VERSION >= 4003
>> > +  return !__has_trivial_destructor (T);
>> > +#else
>> > +  return true;
>> > +#endif
>> > +}
>> > +
>> > +template<typename T>
>> >  static inline T *
>> >  ggc_alloc (ALONE_CXX_MEM_STAT_INFO)
>> >  {
>> > -  return static_cast<T *> (ggc_internal_alloc (sizeof (T) PASS_MEM_STAT));
>> > +  if (need_finalization_p<T> ())
>> > +    return static_cast<T *> (ggc_internal_alloc (sizeof (T), finalize<T>
>> > +                                                PASS_MEM_STAT));
>> > +  else
>> > +    return static_cast<T *> (ggc_internal_alloc (sizeof (T) PASS_MEM_STAT));
>> >  }
>> >
>> >  template<typename T>
>> >  static inline T *
>> >  ggc_cleared_alloc (ALONE_CXX_MEM_STAT_INFO)
>> >  {
>> > -  return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T)
>> > -                                                      PASS_MEM_STAT));
>> > +  if (need_finalization_p<T> ())
>> > +    return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T),
>> > +                                                        finalize<T>
>> > +                                                        PASS_MEM_STAT));
>> > +  else
>> > +    return static_cast<T *> (ggc_internal_cleared_alloc (sizeof (T)
>> > +                                                        PASS_MEM_STAT));
>> >  }
>> >
>> >  template<typename T>
>> >  static inline T *
>> >  ggc_vec_alloc (size_t c CXX_MEM_STAT_INFO)
>> >  {
>> > +  if (need_finalization_p<T> ())
>> > +    return static_cast<T *> (ggc_internal_alloc (c * sizeof (T), finalize<T>,
>> > +                                                sizeof (T), c PASS_MEM_STAT));
>> > +  else
>> >      return static_cast<T *> (ggc_internal_alloc (c * sizeof (T)
>> >                                                  PASS_MEM_STAT));
>> >  }
>> > @@ -183,6 +217,12 @@ template<typename T>
>> >  static inline T *
>> >  ggc_cleared_vec_alloc (size_t c CXX_MEM_STAT_INFO)
>> >  {
>> > +  if (need_finalization_p<T> ())
>> > +    return static_cast<T *> (ggc_internal_cleared_alloc (c * sizeof (T),
>> > +                                                        finalize<T>,
>> > +                                                        sizeof (T), c
>> > +                                                        PASS_MEM_STAT));
>> > +  else
>> >      return static_cast<T *> (ggc_internal_cleared_alloc (c * sizeof (T)
>> >                                                          PASS_MEM_STAT));
>> >  }
>> > --
>> > 2.0.0.rc0
>> >

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/6] don't have gengtype autocreate allocation macros for variably sized types
  2014-04-29 12:32   ` Richard Biener
@ 2014-04-30  9:17     ` Laurynas Biveinis
  2014-04-30  9:19       ` Richard Biener
  0 siblings, 1 reply; 18+ messages in thread
From: Laurynas Biveinis @ 2014-04-30  9:17 UTC (permalink / raw)
  To: Richard Biener; +Cc: tsaunders, GCC Patches

> ISTR we went to typed allocs as part of a transition which not
> fully materialised?

Yes. I had plans to replace the call-based GC marker routines with a
generic routine that operates on a type marker stored next to the
object. That enables partial, generational, etc GC.

>  I actually dislike that we get back the
> ugly casts here - so, can we keep the allocators or use
> a macro similar to the XNEW family?

My 2c suggestion would be to keep the typed allocators at least until
a new plan for GC is developed.

-- 
Laurynas

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/6] don't have gengtype autocreate allocation macros for variably sized types
  2014-04-30  9:17     ` Laurynas Biveinis
@ 2014-04-30  9:19       ` Richard Biener
  0 siblings, 0 replies; 18+ messages in thread
From: Richard Biener @ 2014-04-30  9:19 UTC (permalink / raw)
  To: Laurynas Biveinis; +Cc: tsaunders, GCC Patches

On Wed, Apr 30, 2014 at 11:04 AM, Laurynas Biveinis
<laurynas.biveinis@gmail.com> wrote:
>> ISTR we went to typed allocs as part of a transition which not
>> fully materialised?
>
> Yes. I had plans to replace the call-based GC marker routines with a
> generic routine that operates on a type marker stored next to the
> object. That enables partial, generational, etc GC.

Ah, ok.  It would also naturally allow finalization.

>>  I actually dislike that we get back the
>> ugly casts here - so, can we keep the allocators or use
>> a macro similar to the XNEW family?
>
> My 2c suggestion would be to keep the typed allocators at least until
> a new plan for GC is developed.

The current patches keep them in some way.  But the use of
C++ (and its more complex types) made types more difficult
to access.  I suppose integrating gengtype with the C++ frontend
would be the only reasonable way out here (eh, and maybe that
then naturally develops to C++11 garbage collection support - who
knows).

Thanks,
Richard.

> --
> Laurynas

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2014-04-30  9:18 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-29 11:08 [PATH 0/6] ggc finalizers and TLC tsaunders
2014-04-29 11:09 ` [PATCH 2/6] don't have gengtype autocreate allocation macros for variably sized types tsaunders
2014-04-29 12:32   ` Richard Biener
2014-04-30  9:17     ` Laurynas Biveinis
2014-04-30  9:19       ` Richard Biener
2014-04-29 11:09 ` [PATCH 3/6] use templates instead of gengtype for typed allocation functions tsaunders
2014-04-29 12:41   ` Richard Biener
2014-04-29 13:08     ` Trevor Saunders
2014-04-29 13:15       ` Richard Biener
2014-04-29 11:09 ` [PATCH 4/6] remove unused function tsaunders
2014-04-29 12:25   ` Richard Biener
2014-04-29 11:09 ` [PATCH 6/6] move many members of target_globals out of gc memory tsaunders
2014-04-29 11:09 ` [PATCH 1/6] rm a bunch of _stat allocation functions tsaunders
2014-04-29 12:19   ` Richard Biener
2014-04-29 11:59 ` [PATCH 5/6] add finalizers to ggc tsaunders
2014-04-29 13:00   ` Richard Biener
2014-04-29 13:26     ` Trevor Saunders
2014-04-29 14:37       ` Richard Biener

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).