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