Add class record_builder to ease construction of records and unions.  Use it
in some appropriate places.

Nathan please review the vxworks changes.

tree.h
        New class record_builder.

tree.c
        Implement record_builder member functions.

asan.c
        Change asan_global_struct to use record_builder.

coverage.c
        Change build_info_type() to use record_builder.  It now takes a
        record_builder as a parameter and returns the tree representing
        the type.

        Change build_fn_info_type() to use record_builder.  It now returns
        the tree representing the type.

        Modify coverage_obj_init() to call them appropriately.

tree-mudflap.c
        Change mf_make_mf_cache_struct_type() to use record_builder.

target.def
        Replace the emutls var_fields hook with object_type hook.  The
        essential difference is that the hook is now responsible for full
        construction of the type, not just adding fields.

targhooks.h
        Replace default_emutls_var_fields() with default_emutls_object_type().

tree-emutls.c
        Replace default_emutls_var_fields() with default_emutls_object_type().
        Use record_builder within default_emutls_object_type().

        Change get_emutls_object_type to use the new target hook.

doc/tm.texi.in
        Replace TARGET_EMUTLS_VAR_FIELDS with TARGET_EMUTLS_OBJECT_TYPE.

doc/tm.texi
        Replace TARGET_EMUTLS_VAR_FIELDS with TARGET_EMUTLS_OBJECT_TYPE.

config/vxworks.c
        Replace vxworks_emutls_var_fields() with vxworks_emutls_object_type().
        Use record_builder within vxworks_emutls_object_type().

Tested on x86_64.  Tested with config-list.mk on vxworks targets.


Index: gcc/tree-emutls.c
===================================================================
--- gcc/tree-emutls.c   (revision 195904)
+++ gcc/tree-emutls.c   (working copy)
@@ -103,41 +103,22 @@ get_emutls_object_name (tree name)
   return prefix_name (prefix, name);
 }

-/* Create the fields of the type for the control variables.  Ordinarily
+/* Create the type for the control variables.  Ordinarily
    this must match struct __emutls_object defined in emutls.c.  However
    this is a target hook so that VxWorks can define its own layout.  */

 tree
-default_emutls_var_fields (tree type, tree *name ATTRIBUTE_UNUSED)
+default_emutls_object_type (void)
 {
-  tree word_type_node, field, next_field;
-
-  field = build_decl (UNKNOWN_LOCATION,
-                     FIELD_DECL, get_identifier ("__templ"), ptr_type_node);
-  DECL_CONTEXT (field) = type;
-  next_field = field;
-
-  field = build_decl (UNKNOWN_LOCATION,
-                     FIELD_DECL, get_identifier ("__offset"),
-                     ptr_type_node);
-  DECL_CONTEXT (field) = type;
-  DECL_CHAIN (field) = next_field;
-  next_field = field;
-
-  word_type_node = lang_hooks.types.type_for_mode (word_mode, 1);
-  field = build_decl (UNKNOWN_LOCATION,
-                     FIELD_DECL, get_identifier ("__align"),
-                     word_type_node);
-  DECL_CONTEXT (field) = type;
-  DECL_CHAIN (field) = next_field;
-  next_field = field;
-
-  field = build_decl (UNKNOWN_LOCATION,
-                     FIELD_DECL, get_identifier ("__size"), word_type_node);
-  DECL_CONTEXT (field) = type;
-  DECL_CHAIN (field) = next_field;
-
-  return field;
+  tree word_type_node = lang_hooks.types.type_for_mode (word_mode, 1);
+  record_builder rec;
+  rec.add_field ("__size", word_type_node);
+  rec.add_field ("__align", word_type_node);
+  rec.add_field ("__offset", ptr_type_node);
+  rec.add_field ("__templ", ptr_type_node);
+  rec.layout ();
+  rec.decl_name ("__emutls_object");
+  return rec.as_tree ();
 }

 /* Initialize emulated tls object TO, which refers to TLS variable DECL and
@@ -182,24 +163,9 @@ default_emutls_var_init (tree to, tree d
 static tree
 get_emutls_object_type (void)
 {
-  tree type, type_name, field;
-
-  type = emutls_object_type;
-  if (type)
-    return type;
-
-  emutls_object_type = type = lang_hooks.types.make_type (RECORD_TYPE);
-  type_name = NULL;
-  field = targetm.emutls.var_fields (type, &type_name);
-  if (!type_name)
-    type_name = get_identifier ("__emutls_object");
-  type_name = build_decl (UNKNOWN_LOCATION,
-                         TYPE_DECL, type_name, type);
-  TYPE_NAME (type) = type_name;
-  TYPE_FIELDS (type) = field;
-  layout_type (type);
-
-  return type;
+  if (!emutls_object_type)
+    emutls_object_type = targetm.emutls.object_type ();
+  return emutls_object_type;
 }

 /* Create a read-only variable like DECL, with the same DECL_INITIAL.
Index: gcc/asan.c
===================================================================
--- gcc/asan.c  (revision 195904)
+++ gcc/asan.c  (working copy)
@@ -1496,28 +1496,16 @@ transform_statements (void)
 static tree
 asan_global_struct (void)
 {
-  static const char *field_names[5]
-    = { "__beg", "__size", "__size_with_redzone",
-       "__name", "__has_dynamic_init" };
-  tree fields[5], ret;
-  int i;
-
-  ret = make_node (RECORD_TYPE);
-  for (i = 0; i < 5; i++)
-    {
-      fields[i]
-       = build_decl (UNKNOWN_LOCATION, FIELD_DECL,
-                     get_identifier (field_names[i]),
-                     (i == 0 || i == 3) ? const_ptr_type_node
-                     : build_nonstandard_integer_type (POINTER_SIZE, 1));
-      DECL_CONTEXT (fields[i]) = ret;
-      if (i)
-       DECL_CHAIN (fields[i - 1]) = fields[i];
-    }
-  TYPE_FIELDS (ret) = fields[0];
-  TYPE_NAME (ret) = get_identifier ("__asan_global");
-  layout_type (ret);
-  return ret;
+  tree ptrint_type = build_nonstandard_integer_type (POINTER_SIZE, 1);
+  record_builder rec;
+  rec.add_field ("__beg", const_ptr_type_node);
+  rec.add_field ("__size", ptrint_type);
+  rec.add_field ("__size_with_redzone", ptrint_type);
+  rec.add_field ("__name", const_ptr_type_node);
+  rec.add_field ("__has_dynamic_init", ptrint_type);
+  rec.layout ();
+  rec.tag_name ("__asan_global");
+  return rec.as_tree ();
 }

 /* Append description of a single global DECL into vector V.
Index: gcc/coverage.c
===================================================================
--- gcc/coverage.c      (revision 195904)
+++ gcc/coverage.c      (working copy)
@@ -121,8 +121,8 @@ static const char *const ctr_names[GCOV_
 /* Forward declarations.  */
 static void read_counts_file (void);
 static tree build_var (tree, tree, int);
-static void build_fn_info_type (tree, unsigned, tree);
-static void build_info_type (tree, tree);
+static tree build_fn_info_type (unsigned, tree);
+static tree build_info_type (record_builder &, tree);
 static tree build_fn_info (const struct coverage_data *, tree, tree);
 static tree build_info (tree, tree);
 static bool coverage_obj_init (void);
@@ -693,63 +693,47 @@ build_var (tree fn_decl, tree type, int
   return var;
 }

-/* Creates the gcov_fn_info RECORD_TYPE.  */
+/* Creates the gcov_fn_info RECORD_TYPE, given the number of COUNTERS and
+   using the GCOV_INFO_TYPE.  */

-static void
-build_fn_info_type (tree type, unsigned counters, tree gcov_info_type)
+static tree
+build_fn_info_type (unsigned counters, tree gcov_info_type)
 {
-  tree ctr_info = lang_hooks.types.make_type (RECORD_TYPE);
-  tree field, fields;
-  tree array_type;
-
   gcc_assert (counters);
-
-  /* ctr_info::num */
-  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
-                     get_gcov_unsigned_t ());
-  fields = field;
-
-  /* ctr_info::values */
-  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
-                     build_pointer_type (get_gcov_type ()));
-  DECL_CHAIN (field) = fields;
-  fields = field;
-
-  finish_builtin_struct (ctr_info, "__gcov_ctr_info", fields, NULL_TREE);

+  record_builder bld_ctr_info;
+  tree gcov_type = get_gcov_type ();
+  tree gcov_ptr_type = build_pointer_type (gcov_type);
+  bld_ctr_info.add_field (NULL_TREE, gcov_type, BUILTINS_LOCATION);
+  bld_ctr_info.add_field (NULL_TREE, gcov_ptr_type, BUILTINS_LOCATION);
+  bld_ctr_info.layout ();
+  bld_ctr_info.decl_name ("__gcov_ctr_info", BUILTINS_LOCATION);
+  tree ctr_info = bld_ctr_info.as_tree ();
+
+  record_builder bld_fn_info;
   /* key */
-  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
-                     build_pointer_type (build_qualified_type
-                                         (gcov_info_type, TYPE_QUAL_CONST)));
-  fields = field;
-
+  tree pc_gcov_info
+       = build_pointer_type (build_qualified_type (gcov_info_type,
+                                                   TYPE_QUAL_CONST));
+  bld_fn_info.add_field (NULL_TREE, pc_gcov_info, BUILTINS_LOCATION);
+
   /* ident */
-  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
-                     get_gcov_unsigned_t ());
-  DECL_CHAIN (field) = fields;
-  fields = field;
-
+  bld_fn_info.add_field (NULL_TREE, get_gcov_unsigned_t ());
+
   /* lineno_checksum */
-  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
-                     get_gcov_unsigned_t ());
-  DECL_CHAIN (field) = fields;
-  fields = field;
+  bld_fn_info.add_field (NULL_TREE, get_gcov_unsigned_t ());

   /* cfg checksum */
-  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
-                     get_gcov_unsigned_t ());
-  DECL_CHAIN (field) = fields;
-  fields = field;
-
-  array_type = build_index_type (size_int (counters - 1));
-  array_type = build_array_type (ctr_info, array_type);
+  bld_fn_info.add_field (NULL_TREE, get_gcov_unsigned_t ());

   /* counters */
-  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, array_type);
-  DECL_CHAIN (field) = fields;
-  fields = field;
+  tree index_type = build_index_type (size_int (counters - 1));
+  tree array_type = build_array_type (ctr_info, index_type);

-  finish_builtin_struct (type, "__gcov_fn_info", fields, NULL_TREE);
+  bld_fn_info.add_field (NULL_TREE, array_type, BUILTINS_LOCATION);
+  bld_fn_info.layout ();
+  bld_fn_info.decl_name ("__gcov_fn_info", BUILTINS_LOCATION);
+  return bld_fn_info.as_tree ();
 }

 /* Returns a CONSTRUCTOR for a gcov_fn_info.  DATA is
@@ -819,69 +803,52 @@ build_fn_info (const struct coverage_dat
   return build_constructor (type, v1);
 }

-/* Create gcov_info struct.  TYPE is the incomplete RECORD_TYPE to be
+/* Return gcov_info struct.  BLD_INFO_TYPE is the record_builder to be
    completed, and FN_INFO_PTR_TYPE is a pointer to the function info type.  */

-static void
-build_info_type (tree type, tree fn_info_ptr_type)
+static tree
+build_info_type (record_builder &bld_info_type, tree fn_info_ptr_type)
 {
-  tree field, fields = NULL_TREE;
-  tree merge_fn_type;
+  tree uns_type = get_gcov_unsigned_t ();

   /* Version ident */
-  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
-                     get_gcov_unsigned_t ());
-  DECL_CHAIN (field) = fields;
-  fields = field;
+  bld_info_type.add_field (NULL_TREE, uns_type, BUILTINS_LOCATION);

   /* next pointer */
-  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
-                     build_pointer_type (build_qualified_type
-                                         (type, TYPE_QUAL_CONST)));
-  DECL_CHAIN (field) = fields;
-  fields = field;
+  tree self_type = bld_info_type.as_tree ();
+  tree qual_info = build_qualified_type (self_type, TYPE_QUAL_CONST);
+  tree ptr_info = build_pointer_type (qual_info);
+  bld_info_type.add_field (NULL_TREE, ptr_info, BUILTINS_LOCATION);

   /* stamp */
-  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
-                     get_gcov_unsigned_t ());
-  DECL_CHAIN (field) = fields;
-  fields = field;
+  bld_info_type.add_field (NULL_TREE, uns_type, BUILTINS_LOCATION);

   /* Filename */
-  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
-                     build_pointer_type (build_qualified_type
-                                         (char_type_node, TYPE_QUAL_CONST)));
-  DECL_CHAIN (field) = fields;
-  fields = field;
+  tree qual_char = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
+  tree ptr_char = build_pointer_type (qual_char);
+  bld_info_type.add_field (NULL_TREE, ptr_char, BUILTINS_LOCATION);

   /* merge fn array */
-  merge_fn_type
+  tree merge_fn_type
     = build_function_type_list (void_type_node,
                                build_pointer_type (get_gcov_type ()),
-                               get_gcov_unsigned_t (), NULL_TREE);
-  merge_fn_type
+                               uns_type, NULL_TREE);
+  tree array_fn_type
     = build_array_type (build_pointer_type (merge_fn_type),
                        build_index_type (size_int (GCOV_COUNTERS - 1)));
-  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
-                     merge_fn_type);
-  DECL_CHAIN (field) = fields;
-  fields = field;
-
+  bld_info_type.add_field (NULL_TREE, array_fn_type, BUILTINS_LOCATION);
+
   /* n_functions */
-  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
-                     get_gcov_unsigned_t ());
-  DECL_CHAIN (field) = fields;
-  fields = field;
-
+  bld_info_type.add_field (NULL_TREE, uns_type, BUILTINS_LOCATION);
+
   /* function_info pointer pointer */
-  fn_info_ptr_type = build_pointer_type
+  tree fn_info_ptr_ptr_type = build_pointer_type
     (build_qualified_type (fn_info_ptr_type, TYPE_QUAL_CONST));
-  field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE,
-                     fn_info_ptr_type);
-  DECL_CHAIN (field) = fields;
-  fields = field;
+  bld_info_type.add_field (NULL_TREE, fn_info_ptr_ptr_type, BUILTINS_LOCATION);

-  finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE);
+  bld_info_type.layout ();
+  bld_info_type.decl_name ("__gcov_info");
+  return bld_info_type.as_tree ();
 }

 /* Returns a CONSTRUCTOR for the gcov_info object.  INFO_TYPE is the
@@ -974,7 +941,7 @@ build_info (tree info_type, tree fn_ary)
 static bool
 coverage_obj_init (void)
 {
-  tree gcov_info_type, ctor, stmt, init_fn;
+  tree ctor, stmt, init_fn;
   unsigned n_counters = 0;
   unsigned ix;
   struct coverage_data *fn;
@@ -1005,12 +972,11 @@ coverage_obj_init (void)
       n_counters++;

   /* Build the info and fn_info types.  These are mutually recursive.  */
-  gcov_info_type = lang_hooks.types.make_type (RECORD_TYPE);
-  gcov_fn_info_type = lang_hooks.types.make_type (RECORD_TYPE);
+  record_builder bld_info_type;
+  gcov_fn_info_type = build_fn_info_type (n_counters,
bld_info_type.as_tree ());
   gcov_fn_info_ptr_type = build_pointer_type
     (build_qualified_type (gcov_fn_info_type, TYPE_QUAL_CONST));
-  build_fn_info_type (gcov_fn_info_type, n_counters, gcov_info_type);
-  build_info_type (gcov_info_type, gcov_fn_info_ptr_type);
+  tree gcov_info_type = build_info_type (bld_info_type, gcov_fn_info_ptr_type);

   /* Build the gcov info var, this is referred to in its own
      initializer.  */
Index: gcc/tree-mudflap.c
===================================================================
--- gcc/tree-mudflap.c  (revision 195904)
+++ gcc/tree-mudflap.c  (working copy)
@@ -317,23 +317,12 @@ mf_make_builtin (enum tree_code category
 static inline tree
 mf_make_mf_cache_struct_type (tree field_type)
 {
-  /* There is, abominably, no language-independent way to construct a
-     RECORD_TYPE.  So we have to call the basic type construction
-     primitives by hand.  */
-  tree fieldlo = build_decl (UNKNOWN_LOCATION,
-                            FIELD_DECL, get_identifier ("low"), field_type);
-  tree fieldhi = build_decl (UNKNOWN_LOCATION,
-                            FIELD_DECL, get_identifier ("high"), field_type);
-
-  tree struct_type = make_node (RECORD_TYPE);
-  DECL_CONTEXT (fieldlo) = struct_type;
-  DECL_CONTEXT (fieldhi) = struct_type;
-  DECL_CHAIN (fieldlo) = fieldhi;
-  TYPE_FIELDS (struct_type) = fieldlo;
-  TYPE_NAME (struct_type) = get_identifier ("__mf_cache");
-  layout_type (struct_type);
-
-  return struct_type;
+  record_builder rec;
+  rec.add_field ("low", field_type);
+  rec.add_field ("high", field_type);
+  rec.layout ();
+  rec.tag_name ("__mf_cache");
+  return rec.as_tree ();
 }

 /* Initialize the global tree nodes that correspond to mf-runtime.h
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi     (revision 195904)
+++ gcc/doc/tm.texi     (working copy)
@@ -9966,12 +9966,10 @@ Contains the prefix to be prepended to T
 default of @code{NULL} uses a target-specific prefix.
 @end deftypevr

-@deftypefn {Target Hook} tree TARGET_EMUTLS_VAR_FIELDS (tree
@var{type}, tree *@var{name})
-Specifies a function that generates the FIELD_DECLs for a TLS control
-object type.  @var{type} is the RECORD_TYPE the fields are for and
-@var{name} should be filled with the structure tag, if the default of
-@code{__emutls_object} is unsuitable.  The default creates a type suitable
-for libgcc's emulated TLS function.
+@deftypefn {Target Hook} tree TARGET_EMUTLS_OBJECT_TYPE ()
+Specifies a function that generates the RECORD_TYPE for a TLS control
+object type.  The default creates a type, with structure tag
+@code{__emutls_object}, suitable for libgcc's emulated TLS function.
 @end deftypefn

 @deftypefn {Target Hook} tree TARGET_EMUTLS_VAR_INIT (tree @var{var},
tree @var{decl}, tree @var{tmpl_addr})
Index: gcc/doc/tm.texi.in
===================================================================
--- gcc/doc/tm.texi.in  (revision 195904)
+++ gcc/doc/tm.texi.in  (working copy)
@@ -9827,12 +9827,10 @@ Contains the prefix to be prepended to T
 default of @code{NULL} uses a target-specific prefix.
 @end deftypevr

-@hook TARGET_EMUTLS_VAR_FIELDS
-Specifies a function that generates the FIELD_DECLs for a TLS control
-object type.  @var{type} is the RECORD_TYPE the fields are for and
-@var{name} should be filled with the structure tag, if the default of
-@code{__emutls_object} is unsuitable.  The default creates a type suitable
-for libgcc's emulated TLS function.
+@hook TARGET_EMUTLS_OBJECT_TYPE
+Specifies a function that generates the RECORD_TYPE for a TLS control
+object type.  The default creates a type, with structure tag
+@code{__emutls_object}, suitable for libgcc's emulated TLS function.
 @end deftypefn

 @hook TARGET_EMUTLS_VAR_INIT
Index: gcc/targhooks.h
===================================================================
--- gcc/targhooks.h     (revision 195904)
+++ gcc/targhooks.h     (working copy)
@@ -141,7 +141,7 @@ extern void default_target_option_overri
 extern void hook_void_bitmap (bitmap);
 extern int default_reloc_rw_mask (void);
 extern tree default_mangle_decl_assembler_name (tree, tree);
-extern tree default_emutls_var_fields (tree, tree *);
+extern tree default_emutls_object_type ();
 extern tree default_emutls_var_init (tree, tree, tree);
 extern bool default_hard_regno_scratch_ok (unsigned int);
 extern bool default_mode_dependent_address_p (const_rtx, addr_space_t);
Index: gcc/config/vxworks.c
===================================================================
--- gcc/config/vxworks.c        (revision 195904)
+++ gcc/config/vxworks.c        (working copy)
@@ -56,35 +56,18 @@ vxworks_asm_out_destructor (rtx symbol,
   assemble_addr_to_section (symbol, sec);
 }

-/* Return the list of FIELD_DECLs that make up an emulated TLS
-   variable's control object.  TYPE is the structure these are fields
-   of and *NAME will be filled in with the structure tag that should
-   be used.  */
+/* Return the type of an emulated TLS variable's control object.  */

 static tree
-vxworks_emutls_var_fields (tree type, tree *name)
+vxworks_emutls_object_type ()
 {
-  tree field, next_field;
-
-  *name = get_identifier ("__tls_var");
-
-  field = build_decl (BUILTINS_LOCATION, FIELD_DECL,
-                     get_identifier ("size"), unsigned_type_node);
-  DECL_CONTEXT (field) = type;
-  next_field = field;
-
-  field = build_decl (BUILTINS_LOCATION, FIELD_DECL,
-                     get_identifier ("module_id"), unsigned_type_node);
-  DECL_CONTEXT (field) = type;
-  DECL_CHAIN (field) = next_field;
-  next_field = field;
-
-  field = build_decl (BUILTINS_LOCATION, FIELD_DECL,
-                     get_identifier ("offset"), unsigned_type_node);
-  DECL_CONTEXT (field) = type;
-  DECL_CHAIN (field) = next_field;
-
-  return field;
+  record_builder rec;
+  rec.add_field ("offset", unsigned_type_node);
+  rec.add_field ("module_id", unsigned_type_node);
+  rec.add_field ("size", unsigned_type_node);
+  rec.layout ();
+  rec.decl_name ("__tls_var");
+  return rec.as_tree ();
 }

 /* Return the CONSTRUCTOR to initialize an emulated TLS control
@@ -131,7 +114,7 @@ vxworks_override_options (void)
   targetm.emutls.tmpl_section = ".tls_data";
   targetm.emutls.var_prefix = "__tls__";
   targetm.emutls.tmpl_prefix = "";
-  targetm.emutls.var_fields = vxworks_emutls_var_fields;
+  targetm.emutls.object_type = vxworks_emutls_object_type;
   targetm.emutls.var_init = vxworks_emutls_var_init;
   targetm.emutls.var_align_fixed = true;
   targetm.emutls.debug_form_tls_address = true;
Index: gcc/target.def
===================================================================
--- gcc/target.def      (revision 195904)
+++ gcc/target.def      (working copy)
@@ -2741,12 +2741,12 @@ DEFHOOKPOD
  "",
  const char *, NULL)

-/* Function to generate field definitions of the proxy variable.  */
+/* Function to generate type of the proxy variable.  */
 DEFHOOK
-(var_fields,
+(object_type,
  "",
- tree, (tree type, tree *name),
- default_emutls_var_fields)
+ tree, (),
+ default_emutls_object_type)

 /* Function to initialize a proxy variable.  */
 DEFHOOK
Index: gcc/tree.c
===================================================================
--- gcc/tree.c  (revision 195904)
+++ gcc/tree.c  (working copy)
@@ -11624,4 +11624,95 @@ warn_deprecated_use (tree node, tree att
     }
 }

+
+/* Construct a record builder with the identifier IDENT.
+   It is a union if IS_UNION is true, otherwise it is a RECORD_TYPE.
+   QUAL_RECORD_TYPE is not supported.  */
+
+record_builder::record_builder (bool is_union)
+: building_ (lang_hooks.types.make_type (is_union ? UNION_TYPE : RECORD_TYPE)),
+  last_field_ (NULL)
+{
+}
+
+
+/* Add a field with an identifier IDENT and type TYPE to the record.  */
+
+void
+record_builder::add_field (tree ident, tree type, source_location loc)
+{
+  tree this_field = build_decl (loc, FIELD_DECL, ident, type);
+  DECL_CONTEXT (this_field) = building_;
+  if (last_field_)
+    DECL_CHAIN (last_field_) = this_field;
+  else
+    TYPE_FIELDS (building_) = this_field;
+  last_field_ = this_field;
+}
+
+void
+record_builder::add_field (const char *ident, tree type, source_location loc)
+{
+  add_field (get_identifier (ident), type, loc);
+}
+
+
+/* Add a TYPE_NAME to the record.  This can be a tag name directly from IDENT,
+   or a TYPE_DECL created with the IDENT.  */
+
+void
+record_builder::tag_name (tree ident)
+{
+  gcc_assert (TREE_CODE (ident) == IDENTIFIER_NODE);
+  TYPE_NAME (building_) = ident;
+}
+
+void
+record_builder::tag_name (const char *ident)
+{
+  tag_name (get_identifier (ident));
+}
+
+void
+record_builder::decl_name (tree ident, source_location loc)
+{
+  tree type_decl = build_decl (loc, TYPE_DECL, ident, building_);
+  TYPE_NAME (building_) = type_decl;
+}
+
+void
+record_builder::decl_name (const char *ident, source_location loc)
+{
+  decl_name (get_identifier (ident), loc);
+}
+
+
+/* Layout the fields of the record, aligning with ALIGN_TYPE if given.
+   Ensure that you call one of these functions after adding all fields.  */
+
+void
+record_builder::layout ()
+{
+  layout_type (building_);
+}
+
+void
+record_builder::layout (tree align_type)
+{
+  TYPE_ALIGN (building_) = TYPE_ALIGN (align_type);
+  TYPE_USER_ALIGN (building_) = TYPE_USER_ALIGN (align_type);
+  layout ();
+}
+
+
+/* Return the record as a tree.  You may call this function any time after
+   construction of the builder.  */
+
+tree
+record_builder::as_tree ()
+{
+  return building_;
+}
+
+
 #include "gt-tree.h"
Index: gcc/tree.h
===================================================================
--- gcc/tree.h  (revision 195904)
+++ gcc/tree.h  (working copy)
@@ -6529,4 +6529,28 @@ builtin_decl_implicit_p (enum built_in_f
          && builtin_info.implicit_p[uns_fncode]);
 }

+
+/* A class for simplifying the construction of RECORD_TYPE and UNION_TYPE.  */
+
+class record_builder
+{
+public:
+  record_builder (bool is_union = false);
+  void add_field (tree ident, tree type,
+                 source_location loc = UNKNOWN_LOCATION);
+  void add_field (const char *ident, tree type,
+                 source_location loc = UNKNOWN_LOCATION);
+  void layout ();
+  void layout (tree align_type);
+  void tag_name (tree ident);
+  void tag_name (const char *ident);
+  void decl_name (tree ident, source_location loc = UNKNOWN_LOCATION);
+  void decl_name (const char *ident, source_location loc = UNKNOWN_LOCATION);
+  tree as_tree ();
+private:
+  tree building_;
+  tree last_field_;
+}; // class record_builder
+
+
 #endif  /* GCC_TREE_H  */

-- 
Lawrence Crowl

Reply via email to