store-layout.c (finish_record_layout): Add free_p parameter.

* store-layout.c (finish_record_layout): Add free_p parameter.
	(layout_type): Pass it.
	* tree.h (finish_record_layout): Update prototype.

	* class.c (walk_subobject_offsets): Correct the calculation of
	offsets for virtual bases.  Correct the counting of array
	elements.
	(layout_nonempty_base_or_field): Simplify.  Correct the
	calculation of offsets to be propagated through the binfo
	hierarchy.
	(build_base_field): Avoid creating a FIELD_DECL for empty bases.
	Add the FIELD_DECL to TYPE_FIELDS.
	(build_base_fields): Adjust accordingly.
	(layout_virtual_bases): Use build_base_field.
	(end_of_class): Return a tree, not an integer.
	(warn_about_ambiguous_direct_bases): Rename to ...
	(warn_about_ambiguous_bases): ... this.
	(include_empty_classes): New function.
	(layout_class_type): Create an alternative version of the type to
	be used when as a base class type.  Do not call
	finish_record_layout until we are done laying out the class.
	* cp-tree.h (lang_type_class): Remove size, size_unit.  Add
	as_base.
	(CLASSTYPE_SIZE): Reimplement.
	(CLASSTYPE_SIZE_UNIT): Likewise.
	(CLASSTYPE_ALIGN): Likweise.
	(CLASSTYPE_USER_ALIGN): Likewise.
	(CLASSTYPE_AS_BASE): New macro.
	(DECL_INITIALIZED_P): Likewise.
	(extract_init): Remove prototype.
	(build_forced_zero_init): Rename to ...
	(build_zero_init): ... this.
	(force_store_init_value): Remove.
	* decl.c (obscure_complex_init): Remove.
	(duplicate_decls): Copy DECL_INITIALIZED_P.
	(check_initializer): Do not leave junk in DECL_INITIAL.
	(cp_finish_decl): Handle zero-initialization of entities with
	static storage duration.
	* expr.c (extract_init): Remove.
	* init.c (build_forced_zero_init): Remove.
	(build_zero_init): New function.
	(build_default_init): Use it.
	(build_field_list): Skip FIELD_DECLs for base subobjects.
	(push_base_cleanups): Likewise.
	* method.c (do_build_assign_ref): Likewise.
	(synthesize_exception_spec): Likewise.
	* pt.c (tsubst_decl): Clear DECL_INITIALIZED_P.
	(regenerate_decl_from_template): To not set DECL_INITIAL for a
	static data member whose initialization took place in its class.
	(instantiate_decl): Do not pass an initializer to cp_finish_decl
	in that situation.
	* search.c (dfs_push_decls): Skip FIELD_DECLs for base subobjects.
	(dfs_unuse_fields): Likewise.
	* tree.c (pod_type_p): Handle error_mark_node.
	(zero_init_p): Likewise.
	* typeck.c (lookup_anon_field): Skip FIELD_DECLs for base
	subobjects.
	* typeck2.c (store_init_value): Remove #if 0'd code.
	(force_store_init_value): Remove.
	(process_init_constructor): Use build_zero_init.

	* g++.dg/abi/empty7.C: New test.
	* g++.dg/init/pm2.C: Likewise.

From-SVN: r57654
This commit is contained in:
Mark Mitchell 2002-09-30 16:52:19 +00:00 committed by Mark Mitchell
parent acc59b855d
commit 17bbb839f1
18 changed files with 631 additions and 464 deletions

View file

@ -1,3 +1,9 @@
2002-09-30 Mark Mitchell <mark@codesourcery.com>
* store-layout.c (finish_record_layout): Add free_p parameter.
(layout_type): Pass it.
* tree.h (finish_record_layout): Update prototype.
Mon Sep 30 14:57:18 CEST 2002 Jan Hubicka <jh@suse.cz>
* i386.h (TARGET_CPP_CPU_BUILTINS): Define __SSE_MATH__.

View file

@ -1,3 +1,62 @@
2002-09-30 Mark Mitchell <mark@codesourcery.com>
* class.c (walk_subobject_offsets): Correct the calculation of
offsets for virtual bases. Correct the counting of array
elements.
(layout_nonempty_base_or_field): Simplify. Correct the
calculation of offsets to be propagated through the binfo
hierarchy.
(build_base_field): Avoid creating a FIELD_DECL for empty bases.
Add the FIELD_DECL to TYPE_FIELDS.
(build_base_fields): Adjust accordingly.
(layout_virtual_bases): Use build_base_field.
(end_of_class): Return a tree, not an integer.
(warn_about_ambiguous_direct_bases): Rename to ...
(warn_about_ambiguous_bases): ... this.
(include_empty_classes): New function.
(layout_class_type): Create an alternative version of the type to
be used when as a base class type. Do not call
finish_record_layout until we are done laying out the class.
* cp-tree.h (lang_type_class): Remove size, size_unit. Add
as_base.
(CLASSTYPE_SIZE): Reimplement.
(CLASSTYPE_SIZE_UNIT): Likewise.
(CLASSTYPE_ALIGN): Likweise.
(CLASSTYPE_USER_ALIGN): Likewise.
(CLASSTYPE_AS_BASE): New macro.
(DECL_INITIALIZED_P): Likewise.
(extract_init): Remove prototype.
(build_forced_zero_init): Rename to ...
(build_zero_init): ... this.
(force_store_init_value): Remove.
* decl.c (obscure_complex_init): Remove.
(duplicate_decls): Copy DECL_INITIALIZED_P.
(check_initializer): Do not leave junk in DECL_INITIAL.
(cp_finish_decl): Handle zero-initialization of entities with
static storage duration.
* expr.c (extract_init): Remove.
* init.c (build_forced_zero_init): Remove.
(build_zero_init): New function.
(build_default_init): Use it.
(build_field_list): Skip FIELD_DECLs for base subobjects.
(push_base_cleanups): Likewise.
* method.c (do_build_assign_ref): Likewise.
(synthesize_exception_spec): Likewise.
* pt.c (tsubst_decl): Clear DECL_INITIALIZED_P.
(regenerate_decl_from_template): To not set DECL_INITIAL for a
static data member whose initialization took place in its class.
(instantiate_decl): Do not pass an initializer to cp_finish_decl
in that situation.
* search.c (dfs_push_decls): Skip FIELD_DECLs for base subobjects.
(dfs_unuse_fields): Likewise.
* tree.c (pod_type_p): Handle error_mark_node.
(zero_init_p): Likewise.
* typeck.c (lookup_anon_field): Skip FIELD_DECLs for base
subobjects.
* typeck2.c (store_init_value): Remove #if 0'd code.
(force_store_init_value): Remove.
(process_init_constructor): Use build_zero_init.
2002-09-29 Nathan Sidwell <nathan@codesourcery.com>
PR c++/7788

View file

@ -137,21 +137,22 @@ static void check_bitfield_decl PARAMS ((tree));
static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *));
static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *,
int *));
static bool build_base_field PARAMS ((record_layout_info, tree, int *,
splay_tree, tree));
static bool build_base_fields PARAMS ((record_layout_info, int *,
splay_tree, tree));
static tree *build_base_field PARAMS ((record_layout_info, tree, int *,
splay_tree, tree *));
static void build_base_fields PARAMS ((record_layout_info, int *,
splay_tree, tree *));
static void check_methods PARAMS ((tree));
static void remove_zero_width_bit_fields PARAMS ((tree));
static void check_bases PARAMS ((tree, int *, int *, int *));
static void check_bases_and_members PARAMS ((tree, int *));
static tree create_vtable_ptr PARAMS ((tree, int *, tree *));
static void include_empty_classes (record_layout_info);
static void layout_class_type PARAMS ((tree, int *, int *, tree *));
static void fixup_pending_inline PARAMS ((tree));
static void fixup_inline_methods PARAMS ((tree));
static void set_primary_base PARAMS ((tree, tree, int *));
static void propagate_binfo_offsets PARAMS ((tree, tree, tree));
static void layout_virtual_bases PARAMS ((tree, splay_tree));
static void layout_virtual_bases (record_layout_info, splay_tree);
static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
static void add_vcall_offset_vtbl_entries_r PARAMS ((tree, vtbl_init_data *));
@ -171,9 +172,8 @@ static tree build_vtable PARAMS ((tree, tree, tree));
static void initialize_vtable PARAMS ((tree, tree));
static void initialize_array PARAMS ((tree, tree));
static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
tree, tree,
splay_tree, tree));
static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
tree, tree, splay_tree));
static tree end_of_class PARAMS ((tree, int));
static bool layout_empty_base PARAMS ((tree, tree, splay_tree, tree));
static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
@ -208,7 +208,7 @@ static void record_subobject_offsets PARAMS ((tree, tree, splay_tree, int));
static int layout_conflict_p PARAMS ((tree, tree, splay_tree, int));
static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1,
splay_tree_key k2));
static void warn_about_ambiguous_direct_bases PARAMS ((tree));
static void warn_about_ambiguous_bases PARAMS ((tree));
static bool type_requires_array_cookie PARAMS ((tree));
static bool contains_empty_class_p (tree);
@ -3512,6 +3512,7 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
if (CLASS_TYPE_P (type))
{
tree field;
tree binfo;
int i;
/* Record the location of TYPE. */
@ -3522,7 +3523,11 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
/* Iterate through the direct base classes of TYPE. */
for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
{
tree binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
if (abi_version_at_least (2)
&& TREE_VIA_VIRTUAL (binfo))
continue;
if (!vbases_p
&& TREE_VIA_VIRTUAL (binfo)
@ -3536,14 +3541,40 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
BINFO_OFFSET (binfo)),
offsets,
max_offset,
vbases_p);
(abi_version_at_least (2)
? /*vbases_p=*/0 : vbases_p));
if (r)
return r;
}
/* Iterate through the virtual base classes of TYPE. In G++
3.2, we included virtual bases in the direct base class loop
above, which results in incorrect results; the correct
offsets for virtual bases are only known when working with
the most derived type. */
if (abi_version_at_least (2) && vbases_p)
{
tree vbase;
for (vbase = CLASSTYPE_VBASECLASSES (type);
vbase;
vbase = TREE_CHAIN (vbase))
{
binfo = TREE_VALUE (vbase);
r = walk_subobject_offsets (BINFO_TYPE (binfo),
f,
size_binop (PLUS_EXPR,
offset,
BINFO_OFFSET (binfo)),
offsets,
max_offset,
/*vbases_p=*/0);
}
}
/* Iterate through the fields of TYPE. */
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
if (TREE_CODE (field) == FIELD_DECL && !DECL_ARTIFICIAL (field))
{
tree field_offset;
@ -3571,8 +3602,11 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
tree index;
/* Step through each of the elements in the array. */
for (index = size_zero_node;
INT_CST_LT (index, TYPE_MAX_VALUE (domain));
for (index = size_zero_node;
/* G++ 3.2 had an off-by-one error here. */
(abi_version_at_least (2)
? !INT_CST_LT (TYPE_MAX_VALUE (domain), index)
: INT_CST_LT (index, TYPE_MAX_VALUE (domain)));
index = size_binop (PLUS_EXPR, index, size_one_node))
{
r = walk_subobject_offsets (TREE_TYPE (type),
@ -3640,22 +3674,34 @@ layout_conflict_p (type, offset, offsets, vbases_p)
/* DECL is a FIELD_DECL corresponding either to a base subobject of a
non-static data member of the type indicated by RLI. BINFO is the
binfo corresponding to the base subobject, OFFSETS maps offsets to
types already located at those offsets. T is the most derived
type. This function determines the position of the DECL. */
types already located at those offsets. This function determines
the position of the DECL. */
static void
layout_nonempty_base_or_field (rli, decl, binfo, offsets, t)
record_layout_info rli;
tree decl;
tree binfo;
splay_tree offsets;
tree t;
layout_nonempty_base_or_field (record_layout_info rli,
tree decl,
tree binfo,
splay_tree offsets)
{
tree t = rli->t;
tree offset = NULL_TREE;
tree type = TREE_TYPE (decl);
/* If we are laying out a base class, rather than a field, then
DECL_ARTIFICIAL will be set on the FIELD_DECL. */
int field_p = !DECL_ARTIFICIAL (decl);
bool field_p;
tree type;
if (binfo)
{
/* For the purposes of determining layout conflicts, we want to
use the class type of BINFO; TREE_TYPE (DECL) will be the
CLASSTYPE_AS_BASE version, which does not contain entries for
zero-sized bases. */
type = TREE_TYPE (binfo);
field_p = false;
}
else
{
type = TREE_TYPE (decl);
field_p = true;
}
/* Try to place the field. It may take more than one try if we have
a hard time placing the field without putting two objects of the
@ -3683,10 +3729,7 @@ layout_nonempty_base_or_field (rli, decl, binfo, offsets, t)
empty class, have nonzero size, any overlap can happen only
with a direct or indirect base-class -- it can't happen with
a data member. */
if (layout_conflict_p (TREE_TYPE (decl),
offset,
offsets,
field_p))
if (layout_conflict_p (type, offset, offsets, field_p))
{
/* Strip off the size allocated to this field. That puts us
at the first place we could have put the field with
@ -3709,8 +3752,15 @@ layout_nonempty_base_or_field (rli, decl, binfo, offsets, t)
/* Now that we know where it will be placed, update its
BINFO_OFFSET. */
if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
/* Indirect virtual bases may have a non-zero BINFO_OFFSET at
this point because their BINFO_OFFSET is copied from another
hierarchy. Therefore, we may not need to add the entire
OFFSET. */
propagate_binfo_offsets (binfo,
convert (ssizetype, offset), t);
size_diffop (convert (ssizetype, offset),
convert (ssizetype,
BINFO_OFFSET (binfo))),
t);
}
/* Layout the empty base BINFO. EOC indicates the byte currently just
@ -3768,60 +3818,74 @@ layout_empty_base (binfo, eoc, offsets, t)
return atend;
}
/* Build a FIELD_DECL for the base given by BINFO in the class
indicated by RLI. If the new object is non-empty, clear *EMPTY_P.
*BASE_ALIGN is a running maximum of the alignments of any base
class. OFFSETS gives the location of empty base subobjects. T is
the most derived type. Return nonzero if the new object cannot be
nearly-empty. */
/* Layout the the base given by BINFO in the class indicated by RLI.
If the new object is non-empty, and EMPTY_P is non-NULL, clear
*EMPTY_P. *BASE_ALIGN is a running maximum of the alignments of
any base class. OFFSETS gives the location of empty base
subobjects. T is the most derived type. Return nonzero if the new
object cannot be nearly-empty. A new FIELD_DECL is inserted at
*NEXT_FIELD, unless BINFO is for an empty base class.
static bool
build_base_field (rli, binfo, empty_p, offsets, t)
record_layout_info rli;
tree binfo;
int *empty_p;
splay_tree offsets;
tree t;
Returns the location at which the next field should be inserted. */
static tree *
build_base_field (record_layout_info rli, tree binfo, int *empty_p,
splay_tree offsets, tree *next_field)
{
tree t = rli->t;
tree basetype = BINFO_TYPE (binfo);
tree decl;
bool atend = false;
if (!COMPLETE_TYPE_P (basetype))
/* This error is now reported in xref_tag, thus giving better
location information. */
return atend;
return next_field;
decl = build_decl (FIELD_DECL, NULL_TREE, basetype);
DECL_ARTIFICIAL (decl) = 1;
DECL_FIELD_CONTEXT (decl) = rli->t;
DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
/* Tell the backend not to round up to TYPE_ALIGN. */
DECL_PACKED (decl) = 1;
if (!integer_zerop (DECL_SIZE (decl)))
/* Place the base class. */
if (!is_empty_class (basetype))
{
tree decl;
/* The containing class is non-empty because it has a non-empty
base class. */
*empty_p = 0;
if (empty_p)
*empty_p = 0;
/* Create the FIELD_DECL. */
decl = build_decl (FIELD_DECL, NULL_TREE, CLASSTYPE_AS_BASE (basetype));
DECL_ARTIFICIAL (decl) = 1;
DECL_FIELD_CONTEXT (decl) = t;
DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
/* Tell the backend not to round up to TYPE_ALIGN. */
DECL_PACKED (decl) = 1;
/* Try to place the field. It may take more than one try if we
have a hard time placing the field without putting two
objects of the same type at the same address. */
layout_nonempty_base_or_field (rli, decl, binfo, offsets, t);
layout_nonempty_base_or_field (rli, decl, binfo, offsets);
/* Add the new FIELD_DECL to the list of fields for T. */
TREE_CHAIN (decl) = *next_field;
*next_field = decl;
next_field = &TREE_CHAIN (decl);
}
else
{
unsigned HOST_WIDE_INT eoc;
tree eoc;
/* On some platforms (ARM), even empty classes will not be
byte-aligned. */
eoc = tree_low_cst (rli_size_unit_so_far (rli), 0);
eoc = CEIL (eoc, DECL_ALIGN_UNIT (decl)) * DECL_ALIGN_UNIT (decl);
atend |= layout_empty_base (binfo, size_int (eoc), offsets, t);
eoc = round_up (rli_size_unit_so_far (rli),
CLASSTYPE_ALIGN_UNIT (basetype));
if (layout_empty_base (binfo, eoc, offsets, t))
CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
/* We do not create a FIELD_DECL for empty base classes because
it might overlap some other field. We want to be able to
create CONSTRUCTORs for the class by iterating over the
FIELD_DECLs, and the back end does not handle overlapping
FIELD_DECLs. */
}
/* Record the offsets of BINFO and its base subobjects. */
@ -3829,42 +3893,41 @@ build_base_field (rli, binfo, empty_p, offsets, t)
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0);
return atend;
return next_field;
}
/* Layout all of the non-virtual base classes. Record empty
subobjects in OFFSETS. T is the most derived type. Return
nonzero if the type cannot be nearly empty. */
subobjects in OFFSETS. T is the most derived type. Return nonzero
if the type cannot be nearly empty. The fields created
corresponding to the base classes will be inserted at
*NEXT_FIELD. */
static bool
build_base_fields (rli, empty_p, offsets, t)
record_layout_info rli;
int *empty_p;
splay_tree offsets;
tree t;
static void
build_base_fields (record_layout_info rli, int *empty_p,
splay_tree offsets, tree *next_field)
{
/* Chain to hold all the new FIELD_DECLs which stand in for base class
subobjects. */
tree rec = rli->t;
int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
tree t = rli->t;
int n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
int i;
bool atend = 0;
/* The primary base class is always allocated first. */
if (CLASSTYPE_HAS_PRIMARY_BASE_P (rec))
build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (rec),
empty_p, offsets, t);
if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
next_field = build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (t),
empty_p, offsets, next_field);
/* Now allocate the rest of the bases. */
for (i = 0; i < n_baseclasses; ++i)
{
tree base_binfo;
base_binfo = BINFO_BASETYPE (TYPE_BINFO (rec), i);
base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
/* The primary base was already allocated above, so we don't
need to allocate it again here. */
if (base_binfo == CLASSTYPE_PRIMARY_BINFO (rec))
if (base_binfo == CLASSTYPE_PRIMARY_BINFO (t))
continue;
/* A primary virtual base class is allocated just like any other
@ -3874,9 +3937,9 @@ build_base_fields (rli, empty_p, offsets, t)
&& !BINFO_PRIMARY_P (base_binfo))
continue;
atend |= build_base_field (rli, base_binfo, empty_p, offsets, t);
next_field = build_base_field (rli, base_binfo, empty_p,
offsets, next_field);
}
return atend;
}
/* Go through the TYPE_METHODS of T issuing any appropriate
@ -4567,36 +4630,41 @@ dfs_set_offset_for_unshared_vbases (binfo, data)
return NULL_TREE;
}
/* Set BINFO_OFFSET for all of the virtual bases for T. Update
/* Set BINFO_OFFSET for all of the virtual bases for RLI->T. Update
TYPE_ALIGN and TYPE_SIZE for T. OFFSETS gives the location of
empty subobjects of T. */
static void
layout_virtual_bases (t, offsets)
tree t;
splay_tree offsets;
layout_virtual_bases (record_layout_info rli, splay_tree offsets)
{
tree vbases, dsize;
unsigned HOST_WIDE_INT eoc;
tree vbases;
tree t = rli->t;
bool first_vbase = true;
tree *next_field;
if (CLASSTYPE_N_BASECLASSES (t) == 0)
return;
if (!abi_version_at_least(2))
{
/* In G++ 3.2, we incorrectly rounded the size before laying out
the virtual bases. */
finish_record_layout (rli, /*free_p=*/false);
#ifdef STRUCTURE_SIZE_BOUNDARY
/* Packed structures don't need to have minimum size. */
if (! TYPE_PACKED (t))
TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), STRUCTURE_SIZE_BOUNDARY);
/* Packed structures don't need to have minimum size. */
if (! TYPE_PACKED (t))
TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), STRUCTURE_SIZE_BOUNDARY);
#endif
rli->offset = TYPE_SIZE_UNIT (t);
rli->bitpos = bitsize_zero_node;
rli->record_align = TYPE_ALIGN (t);
}
/* DSIZE is the size of the class without the virtual bases. */
if (abi_version_at_least(2))
dsize = CLASSTYPE_SIZE (t);
else
dsize = TYPE_SIZE (t);
/* Make every class have alignment of at least one. */
TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), BITS_PER_UNIT);
/* Find the last field. The artificial fields created for virtual
bases will go after the last extant field to date. */
next_field = &TYPE_FIELDS (t);
while (*next_field)
next_field = &TREE_CHAIN (*next_field);
/* Go through the virtual bases, allocating space for each virtual
base that is not already a primary base class. These are
@ -4614,45 +4682,12 @@ layout_virtual_bases (t, offsets)
if (!BINFO_PRIMARY_P (vbase))
{
tree basetype = TREE_TYPE (vbase);
/* This virtual base is not a primary base of any class in the
hierarchy, so we have to add space for it. */
tree basetype, usize;
unsigned int desired_align;
basetype = BINFO_TYPE (vbase);
desired_align = CLASSTYPE_ALIGN (basetype);
TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align);
/* Add padding so that we can put the virtual base class at an
appropriately aligned offset. */
dsize = round_up (dsize, desired_align);
usize = size_binop (CEIL_DIV_EXPR, dsize, bitsize_unit_node);
/* We try to squish empty virtual bases in just like
ordinary empty bases. */
if (is_empty_class (basetype))
layout_empty_base (vbase,
convert (sizetype, usize),
offsets, t);
else
{
tree offset;
offset = convert (ssizetype, usize);
offset = size_diffop (offset,
convert (ssizetype,
BINFO_OFFSET (vbase)));
/* And compute the offset of the virtual base. */
propagate_binfo_offsets (vbase, offset, t);
/* Every virtual baseclass takes a least a UNIT, so that
we can take it's address and get something different
for each base. */
dsize = size_binop (PLUS_EXPR, dsize,
size_binop (MAX_EXPR, bitsize_unit_node,
CLASSTYPE_SIZE (basetype)));
}
next_field = build_base_field (rli, vbase, /*empty_p=*/NULL,
offsets, next_field);
/* If the first virtual base might have been placed at a
lower address, had we started from CLASSTYPE_SIZE, rather
@ -4663,20 +4698,15 @@ layout_virtual_bases (t, offsets)
the results which is not particularly tractable. */
if (warn_abi
&& first_vbase
&& tree_int_cst_lt (size_binop (CEIL_DIV_EXPR,
round_up (CLASSTYPE_SIZE (t),
desired_align),
bitsize_unit_node),
BINFO_OFFSET (vbase)))
&& (tree_int_cst_lt
(size_binop (CEIL_DIV_EXPR,
round_up (CLASSTYPE_SIZE (t),
CLASSTYPE_ALIGN (basetype)),
bitsize_unit_node),
BINFO_OFFSET (vbase))))
warning ("offset of virtual base `%T' is not ABI-compliant and may change in a future version of GCC",
basetype);
/* Keep track of the offsets assigned to this virtual base. */
record_subobject_offsets (BINFO_TYPE (vbase),
BINFO_OFFSET (vbase),
offsets,
/*vbases_p=*/0);
first_vbase = false;
}
}
@ -4687,45 +4717,18 @@ layout_virtual_bases (t, offsets)
in lookup_base depend on the BINFO_OFFSETs being set
correctly. */
dfs_walk (TYPE_BINFO (t), dfs_set_offset_for_unshared_vbases, NULL, t);
/* If we had empty base classes that protruded beyond the end of the
class, we didn't update DSIZE above; we were hoping to overlay
multiple such bases at the same location. */
eoc = end_of_class (t, /*include_virtuals_p=*/1);
dsize = size_binop (MAX_EXPR, dsize, bitsize_int (eoc * BITS_PER_UNIT));
/* Now, make sure that the total size of the type is a multiple of
its alignment. */
dsize = round_up (dsize, TYPE_ALIGN (t));
TYPE_SIZE (t) = dsize;
TYPE_SIZE_UNIT (t) = convert (sizetype,
size_binop (CEIL_DIV_EXPR, TYPE_SIZE (t),
bitsize_unit_node));
/* Check for ambiguous virtual bases. */
if (extra_warnings)
for (vbases = CLASSTYPE_VBASECLASSES (t);
vbases;
vbases = TREE_CHAIN (vbases))
{
tree basetype = BINFO_TYPE (TREE_VALUE (vbases));
if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
basetype, t);
}
}
/* Returns the offset of the byte just past the end of the base class
with the highest offset in T. If INCLUDE_VIRTUALS_P is zero, then
only non-virtual bases are included. */
static unsigned HOST_WIDE_INT
static tree
end_of_class (t, include_virtuals_p)
tree t;
int include_virtuals_p;
{
unsigned HOST_WIDE_INT result = 0;
tree result = size_zero_node;
int i;
for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
@ -4733,7 +4736,6 @@ end_of_class (t, include_virtuals_p)
tree base_binfo;
tree offset;
tree size;
unsigned HOST_WIDE_INT end_of_base;
base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
@ -4752,15 +4754,14 @@ end_of_class (t, include_virtuals_p)
offset = size_binop (PLUS_EXPR,
BINFO_OFFSET (base_binfo),
size);
end_of_base = tree_low_cst (offset, /*pos=*/1);
if (end_of_base > result)
result = end_of_base;
if (INT_CST_LT_UNSIGNED (result, offset))
result = offset;
}
return result;
}
/* Warn about direct bases of T that are inaccessible because they are
/* Warn about bases of T that are inaccessible because they are
ambiguous. For example:
struct S {};
@ -4771,19 +4772,35 @@ end_of_class (t, include_virtuals_p)
subobjects of U. */
static void
warn_about_ambiguous_direct_bases (t)
warn_about_ambiguous_bases (t)
tree t;
{
int i;
tree vbases;
tree basetype;
/* Check direct bases. */
for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
{
tree basetype = TYPE_BINFO_BASETYPE (t, i);
basetype = TYPE_BINFO_BASETYPE (t, i);
if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
basetype, t);
basetype, t);
}
/* Check for ambiguous virtual bases. */
if (extra_warnings)
for (vbases = CLASSTYPE_VBASECLASSES (t);
vbases;
vbases = TREE_CHAIN (vbases))
{
basetype = BINFO_TYPE (TREE_VALUE (vbases));
if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
basetype, t);
}
}
/* Compare two INTEGER_CSTs K1 and K2. */
@ -4796,6 +4813,29 @@ splay_tree_compare_integer_csts (k1, k2)
return tree_int_cst_compare ((tree) k1, (tree) k2);
}
/* Increase the size indicated in RLI to account for empty classes
that are "off the end" of the class. */
static void
include_empty_classes (record_layout_info rli)
{
tree eoc;
/* It might be the case that we grew the class to allocate a
zero-sized base class. That won't be reflected in RLI, yet,
because we are willing to overlay multiple bases at the same
offset. However, now we need to make sure that RLI is big enough
to reflect the entire class. */
eoc = end_of_class (rli->t,
CLASSTYPE_AS_BASE (rli->t) != NULL_TREE);
if (TREE_CODE (rli_size_unit_so_far (rli)) == INTEGER_CST
&& INT_CST_LT_UNSIGNED (rli_size_unit_so_far (rli), eoc))
{
rli->offset = size_binop (MAX_EXPR, rli->offset, eoc);
rli->bitpos = bitsize_zero_node;
}
}
/* Calculate the TYPE_SIZE, TYPE_ALIGN, etc for T. Calculate
BINFO_OFFSETs for all of the base-classes. Position the vtable
pointer. Accumulate declared virtual functions on VIRTUALS_P. */
@ -4811,12 +4851,15 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
tree field;
tree vptr;
record_layout_info rli;
unsigned HOST_WIDE_INT eoc;
/* Maps offsets (represented as INTEGER_CSTs) to a TREE_LIST of
types that appear at that offset. */
splay_tree empty_base_offsets;
/* True if the last field layed out was a bit-field. */
bool last_field_was_bitfield = false;
/* The location at which the next field should be inserted. */
tree *next_field;
/* T, as a base class. */
tree base_t;
/* Keep track of the first non-static data member. */
non_static_data_members = TYPE_FIELDS (t);
@ -4834,15 +4877,18 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
/* The vptr is always the first thing in the class. */
if (vptr)
{
TYPE_FIELDS (t) = chainon (vptr, TYPE_FIELDS (t));
TREE_CHAIN (vptr) = TYPE_FIELDS (t);
TYPE_FIELDS (t) = vptr;
next_field = &TREE_CHAIN (vptr);
place_field (rli, vptr);
}
else
next_field = &TYPE_FIELDS (t);
/* Build FIELD_DECLs for all of the non-virtual base-types. */
empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts,
NULL, NULL);
if (build_base_fields (rli, empty_p, empty_base_offsets, t))
CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
build_base_fields (rli, empty_p, empty_base_offsets, next_field);
/* Layout the non-static data members. */
for (field = non_static_data_members; field; field = TREE_CHAIN (field))
@ -4917,7 +4963,7 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
padding = NULL_TREE;
layout_nonempty_base_or_field (rli, field, NULL_TREE,
empty_base_offsets, t);
empty_base_offsets);
/* If a bit-field does not immediately follow another bit-field,
and yet it starts in the middle of a byte, we have failed to
@ -4957,76 +5003,59 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
DECL_USER_ALIGN (padding_field) = 0;
layout_nonempty_base_or_field (rli, padding_field,
NULL_TREE,
empty_base_offsets, t);
empty_base_offsets);
}
last_field_was_bitfield = DECL_C_BIT_FIELD (field);
}
/* It might be the case that we grew the class to allocate a
zero-sized base class. That won't be reflected in RLI, yet,
because we are willing to overlay multiple bases at the same
offset. However, now we need to make sure that RLI is big enough
to reflect the entire class. */
eoc = end_of_class (t, /*include_virtuals_p=*/0);
if (TREE_CODE (rli_size_unit_so_far (rli)) == INTEGER_CST
&& compare_tree_int (rli_size_unit_so_far (rli), eoc) < 0)
{
rli->offset = size_binop (MAX_EXPR, rli->offset, size_int (eoc));
rli->bitpos = bitsize_zero_node;
}
/* We make all structures have at least one element, so that they
have nonzero size. The class may be empty even if it has
basetypes. Therefore, we add the fake field after all the other
fields; if there are already FIELD_DECLs on the list, their
offsets will not be disturbed. */
if (!eoc && *empty_p)
{
tree padding;
padding = build_decl (FIELD_DECL, NULL_TREE, char_type_node);
place_field (rli, padding);
}
else if (abi_version_at_least (2)
&& !integer_zerop (rli->bitpos))
if (abi_version_at_least (2) && !integer_zerop (rli->bitpos))
/* Make sure that we are on a byte boundary so that the size of
the class without virtual bases will always be a round number
of bytes. */
rli->bitpos = round_up (rli->bitpos, BITS_PER_UNIT);
/* Let the back-end lay out the type. Note that at this point we
have only included non-virtual base-classes; we will lay out the
virtual base classes later. So, the TYPE_SIZE/TYPE_ALIGN after
this call are not necessarily correct; they are just the size and
alignment when no virtual base clases are used. */
finish_record_layout (rli);
/* Make sure that empty classes are reflected in RLI at this
point. */
include_empty_classes(rli);
/* Delete all zero-width bit-fields from the list of fields. Now
that the type is laid out they are no longer important. */
remove_zero_width_bit_fields (t);
/* Remember the size and alignment of the class before adding
the virtual bases. */
if (*empty_p)
/* Create the version of T used for virtual bases. We do not use
make_aggr_type for this version; this is an artificial type. For
a POD type, we just reuse T. */
if (CLASSTYPE_NON_POD_P (t) || *empty_p)
{
CLASSTYPE_SIZE (t) = bitsize_zero_node;
CLASSTYPE_SIZE_UNIT (t) = size_zero_node;
}
/* If this is a POD, we can't reuse its tail padding. */
else if (!CLASSTYPE_NON_POD_P (t))
{
CLASSTYPE_SIZE (t) = TYPE_SIZE (t);
CLASSTYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (t);
base_t = make_node (TREE_CODE (t));
/* Set the size and alignment for the new type. */
TYPE_SIZE (base_t) = rli_size_so_far (rli);
TYPE_SIZE_UNIT (base_t) = rli_size_unit_so_far (rli);
TYPE_ALIGN (base_t) = rli->record_align;
TYPE_USER_ALIGN (base_t) = TYPE_USER_ALIGN (t);
/* Copy the fields from T. */
next_field = &TYPE_FIELDS (base_t);
for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
{
*next_field = build_decl (FIELD_DECL,
DECL_NAME (field),
TREE_TYPE (field));
DECL_CONTEXT (*next_field) = base_t;
DECL_FIELD_OFFSET (*next_field) = DECL_FIELD_OFFSET (field);
DECL_FIELD_BIT_OFFSET (*next_field)
= DECL_FIELD_BIT_OFFSET (field);
next_field = &TREE_CHAIN (*next_field);
}
/* Record the base version of the type. */
CLASSTYPE_AS_BASE (t) = base_t;
}
else
{
CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t);
CLASSTYPE_SIZE_UNIT (t) = TYPE_BINFO_SIZE_UNIT (t);
}
CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t);
CLASSTYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (t);
CLASSTYPE_AS_BASE (t) = t;
/* Set the TYPE_DECL for this type to contain the right
value for DECL_OFFSET, so that we can use it as part
@ -5037,11 +5066,22 @@ layout_class_type (t, empty_p, vfuns_p, virtuals_p)
around. We must get these done before we try to lay out the
virtual function table. As a side-effect, this will remove the
base subobject fields. */
layout_virtual_bases (t, empty_base_offsets);
layout_virtual_bases (rli, empty_base_offsets);
/* Warn about direct bases that can't be talked about due to
ambiguity. */
warn_about_ambiguous_direct_bases (t);
/* Make sure that empty classes are reflected in RLI at this
point. */
include_empty_classes(rli);
/* Make sure not to create any structures with zero size. */
if (integer_zerop (rli_size_unit_so_far (rli)) && *empty_p)
place_field (rli,
build_decl (FIELD_DECL, NULL_TREE, char_type_node));
/* Let the back-end lay out the type. */
finish_record_layout (rli, /*free_p=*/true);
/* Warn about bases that can't be talked about due to ambiguity. */
warn_about_ambiguous_bases (t);
/* Clean up. */
splay_tree_delete (empty_base_offsets);
@ -6414,7 +6454,9 @@ contains_empty_class_p (tree type)
if (contains_empty_class_p (TYPE_BINFO_BASETYPE (type, i)))
return true;
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (contains_empty_class_p (TREE_TYPE (field)))
if (TREE_CODE (field) == FIELD_DECL
&& !DECL_ARTIFICIAL (field)
&& is_empty_class (TREE_TYPE (field)))
return true;
}
else if (TREE_CODE (type) == ARRAY_TYPE)

View file

@ -59,6 +59,7 @@ struct diagnostic_context;
INHERITED_VALUE_BINDING_P (in CPLUS_BINDING)
ICS_ELLIPSIS_FLAG (in _CONV)
BINFO_ACCESS (in BINFO)
DECL_INITIALIZED_P (in VAR_DECL)
2: IDENTIFIER_OPNAME_P.
TYPE_POLYMORPHIC_P (in _TYPE)
ICS_THIS_FLAG (in _CONV)
@ -96,11 +97,10 @@ struct diagnostic_context;
DECL_MUTABLE_P (in FIELD_DECL)
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
DECL_C_BITFIELD (in FIELD_DECL)
2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL)
3: DECL_IN_AGGR_P.
4: DECL_C_BIT_FIELD
4: DECL_C_BIT_FIELD (in a FIELD_DECL)
5: DECL_INTERFACE_KNOWN.
6: DECL_THIS_STATIC (in VAR_DECL or FUNCTION_DECL).
7: DECL_DEAD_FOR_LOCAL (in VAR_DECL).
@ -1150,8 +1150,7 @@ struct lang_type_class GTY(())
tree vfields;
tree vbases;
tree tags;
tree size;
tree size_unit;
tree as_base;
tree pure_virtuals;
tree friend_classes;
tree rtti;
@ -1396,12 +1395,17 @@ struct lang_type GTY(())
#define CLASSTYPE_N_BASECLASSES(NODE) \
(BINFO_N_BASETYPES (TYPE_BINFO (NODE)))
/* The type corresponding to NODE when NODE is used as a base class,
i.e., NODE without virtual base classes. */
#define CLASSTYPE_AS_BASE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->as_base)
/* These are the size and alignment of the type without its virtual
base classes, for when we use this type as a base itself. */
#define CLASSTYPE_SIZE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->size)
#define CLASSTYPE_SIZE_UNIT(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->size_unit)
#define CLASSTYPE_ALIGN(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->align)
#define CLASSTYPE_USER_ALIGN(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->user_align)
#define CLASSTYPE_SIZE(NODE) TYPE_SIZE (CLASSTYPE_AS_BASE (NODE))
#define CLASSTYPE_SIZE_UNIT(NODE) TYPE_SIZE_UNIT (CLASSTYPE_AS_BASE (NODE))
#define CLASSTYPE_ALIGN(NODE) TYPE_ALIGN (CLASSTYPE_AS_BASE (NODE))
#define CLASSTYPE_USER_ALIGN(NODE) TYPE_USER_ALIGN (CLASSTYPE_AS_BASE (NODE))
/* The alignment of NODE, without its virtual bases, in bytes. */
#define CLASSTYPE_ALIGN_UNIT(NODE) \
@ -1954,6 +1958,11 @@ struct lang_decl GTY(())
should be allocated. */
#define DECL_IN_AGGR_P(NODE) (DECL_LANG_FLAG_3 (NODE))
/* Nonzero for a VAR_DECL means that the variable's initialization has
been processed. */
#define DECL_INITIALIZED_P(NODE) \
(TREE_LANG_FLAG_1 (VAR_DECL_CHECK (NODE)))
/* Nonzero if the DECL was initialized in the class definition itself,
rather than outside the class. */
#define DECL_INITIALIZED_IN_CLASS_P(DECL) \
@ -3850,7 +3859,6 @@ extern void check_handlers PARAMS ((tree));
extern void choose_personality_routine PARAMS ((enum languages));
/* in expr.c */
extern int extract_init PARAMS ((tree, tree));
extern rtx cxx_expand_expr PARAMS ((tree, rtx,
enum machine_mode,
int));
@ -3870,7 +3878,7 @@ extern tree build_init PARAMS ((tree, tree, int));
extern int is_aggr_type PARAMS ((tree, int));
extern tree get_aggr_from_typedef PARAMS ((tree, int));
extern tree get_type_value PARAMS ((tree));
extern tree build_forced_zero_init PARAMS ((tree));
extern tree build_zero_init (tree, bool);
extern tree build_member_call PARAMS ((tree, tree, tree));
extern tree build_offset_ref PARAMS ((tree, tree));
extern tree resolve_offset_ref PARAMS ((tree));
@ -4344,7 +4352,6 @@ extern tree binfo_or_else PARAMS ((tree, tree));
extern void readonly_error PARAMS ((tree, const char *, int));
extern int abstract_virtuals_error PARAMS ((tree, tree));
extern tree force_store_init_value PARAMS ((tree, tree));
extern tree store_init_value PARAMS ((tree, tree));
extern tree digest_init PARAMS ((tree, tree, tree *));
extern tree build_scoped_ref PARAMS ((tree, tree, tree *));

View file

@ -67,7 +67,6 @@ static int ambi_op_p PARAMS ((enum tree_code));
static int unary_op_p PARAMS ((enum tree_code));
static tree store_bindings PARAMS ((tree, tree));
static tree lookup_tag_reverse PARAMS ((tree, tree));
static tree obscure_complex_init PARAMS ((tree, tree));
static tree lookup_name_real PARAMS ((tree, int, int, int));
static void push_local_name PARAMS ((tree));
static void warn_extern_redeclared_static PARAMS ((tree, tree));
@ -3460,7 +3459,11 @@ duplicate_decls (newdecl, olddecl)
newtype = oldtype;
if (TREE_CODE (newdecl) == VAR_DECL)
DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
{
DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
}
/* Do this after calling `merge_types' so that default
parameters don't confuse us. */
else if (TREE_CODE (newdecl) == FUNCTION_DECL
@ -7548,45 +7551,6 @@ grok_reference_init (decl, type, init)
return NULL_TREE;
}
/* Fill in DECL_INITIAL with some magical value to prevent expand_decl from
mucking with forces it does not comprehend (i.e. initialization with a
constructor). If we are at global scope and won't go into COMMON, fill
it in with a dummy CONSTRUCTOR to force the variable into .data;
otherwise we can use error_mark_node. */
static tree
obscure_complex_init (decl, init)
tree decl, init;
{
if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
{
error ("run-time initialization of thread-local storage");
return NULL_TREE;
}
if (! flag_no_inline && TREE_STATIC (decl))
{
if (extract_init (decl, init))
return NULL_TREE;
}
#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
if (toplevel_bindings_p () && ! DECL_COMMON (decl))
DECL_INITIAL (decl) = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE,
NULL_TREE);
else
#endif
{
if (zero_init_p (TREE_TYPE (decl)))
DECL_INITIAL (decl) = error_mark_node;
/* Otherwise, force_store_init_value will have already stored a
zero-init initializer in DECL_INITIAL, that should be
retained. */
}
return init;
}
/* When parsing `int a[] = {1, 2};' we don't know the size of the
array until we finish parsing the initializer. If that's the
situation we're in, update DECL accordingly. */
@ -7773,17 +7737,18 @@ check_initializer (decl, init)
tree decl;
tree init;
{
tree type;
if (TREE_CODE (decl) == FIELD_DECL)
return init;
type = TREE_TYPE (decl);
tree type = TREE_TYPE (decl);
/* If `start_decl' didn't like having an initialization, ignore it now. */
if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
init = NULL_TREE;
/* If an initializer is present, DECL_INITIAL has been
error_mark_node, to indicate that an as-of-yet unevaluated
initialization will occur. From now on, DECL_INITIAL reflects
the static initialization -- if any -- of DECL. */
DECL_INITIAL (decl) = NULL_TREE;
/* Check the initializer. */
if (init)
{
@ -7823,21 +7788,9 @@ check_initializer (decl, init)
init = NULL_TREE;
}
else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
{
init = grok_reference_init (decl, type, init);
if (init)
init = obscure_complex_init (decl, init);
}
else if (!DECL_EXTERNAL (decl) && !zero_init_p (type))
{
force_store_init_value (decl, build_forced_zero_init (type));
if (init)
goto process_init;
}
init = grok_reference_init (decl, type, init);
else if (init)
{
process_init:
if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
{
if (TREE_CODE (type) == ARRAY_TYPE)
@ -7861,11 +7814,6 @@ check_initializer (decl, init)
if (TREE_CODE (init) != TREE_VEC)
init = store_init_value (decl, init);
}
if (init)
/* We must hide the initializer so that expand_decl
won't try to do something it does not understand. */
init = obscure_complex_init (decl, init);
}
else if (DECL_EXTERNAL (decl))
;
@ -7884,10 +7832,6 @@ check_initializer (decl, init)
}
check_for_uninitialized_const_var (decl);
if (COMPLETE_TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
init = obscure_complex_init (decl, NULL_TREE);
}
else
check_for_uninitialized_const_var (decl);
@ -8255,10 +8199,54 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
make_decl_rtl (decl, asmspec);
}
/* Deduce size of array from initialization, if not already known. */
init = check_initializer (decl, init);
maybe_deduce_size_from_array_init (decl, init);
else if (TREE_CODE (decl) == RESULT_DECL)
init = check_initializer (decl, init);
else if (TREE_CODE (decl) == VAR_DECL)
{
/* Only PODs can have thread-local storage. Other types may require
various kinds of non-trivial initialization. */
if (DECL_THREAD_LOCAL (decl) && !pod_type_p (TREE_TYPE (decl)))
error ("`%D' cannot be thread-local because it has non-POD type `%T'",
decl, TREE_TYPE (decl));
/* Convert the initializer to the type of DECL, if we have not
already initialized DECL. */
if (!DECL_INITIALIZED_P (decl)
/* If !DECL_EXTERNAL then DECL is being defined. In the
case of a static data memberm initialized inside the
class-specifier, there can be an initializer even if DECL
is *not* defined. */
&& (!DECL_EXTERNAL (decl) || init))
{
init = check_initializer (decl, init);
/* If DECL has an array type without a specific bound, deduce the
array size from the initializer. Note that this must be done
after check_initializer is called because of cases like this:
struct S { int a; int b; };
struct S a[] = { 1, 2 };
which creates a one-element array, not a two-element array. */
maybe_deduce_size_from_array_init (decl, init);
/* Handle:
[dcl.init]
The memory occupied by any object of static storage
duration is zero-initialized at program startup before
any other initialization takes place.
We cannot create an appropriate initializer until after
the type of DECL is finalized. If DECL_INITIAL is set,
then the DECL is statically initialized, and any
necessary zero-initialization has already been performed. */
if (TREE_STATIC (decl) && !DECL_INITIAL (decl))
DECL_INITIAL (decl) = build_zero_init (TREE_TYPE (decl),
/*static_storage_p=*/true);
/* Remember that the initialization for this variable has
taken place. */
DECL_INITIALIZED_P (decl) = 1;
}
}
/* Add this declaration to the statement-tree. This needs to happen
after the call to check_initializer so that the DECL_STMT for a

View file

@ -127,11 +127,3 @@ cxx_expand_expr (exp, target, tmode, modifier)
/* NOTREACHED */
return NULL;
}
int
extract_init (decl, init)
tree decl ATTRIBUTE_UNUSED, init ATTRIBUTE_UNUSED;
{
return 0;
}

View file

@ -156,70 +156,151 @@ initialize_vtbl_ptrs (addr)
dfs_marked_real_bases_queue_p, type);
}
/* Types containing pointers to data members cannot be
zero-initialized with zeros, because the NULL value for such
pointers is -1.
TYPE is a type that requires such zero initialization. The
returned value is the initializer. */
/* Return an expression for the zero-initialization of an object with
type T. This expression will either be a constant (in the case
that T is a scalar), or a CONSTRUCTOR (in the case that T is an
aggregate). In either case, the value can be used as DECL_INITIAL
for a decl of the indicated TYPE; it is a valid static initializer.
If STATIC_STORAGE_P is TRUE, initializers are only generated for
entities for which zero-initialization does not simply mean filling
the storage with zero bytes. */
tree
build_forced_zero_init (type)
tree type;
build_zero_init (tree type, bool static_storage_p)
{
tree init = NULL;
tree init = NULL_TREE;
if (AGGREGATE_TYPE_P (type) && !TYPE_PTRMEMFUNC_P (type))
/* [dcl.init]
To zero-initialization storage for an object of type T means:
-- if T is a scalar type, the storage is set to the value of zero
converted to T.
-- if T is a non-union class type, the storage for each nonstatic
data member and each base-class subobject is zero-initialized.
-- if T is a union type, the storage for its first data member is
zero-initialized.
-- if T is an array type, the storage for each element is
zero-initialized.
-- if T is a reference type, no initialization is performed. */
if (type == error_mark_node)
;
else if (static_storage_p && zero_init_p (type))
/* In order to save space, we do not explicitly build initializers
for items that do not need them. GCC's semantics are that
items with static storage duration that are not otherwise
initialized are initialized to zero. */
;
else if (SCALAR_TYPE_P (type))
init = convert (type, integer_zero_node);
else if (CLASS_TYPE_P (type))
{
/* This is a default initialization of an aggregate, but not one of
non-POD class type. We cleverly notice that the initialization
rules in such a case are the same as for initialization with an
empty brace-initialization list. */
init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE);
tree field;
tree inits;
/* Build a constructor to contain the initializations. */
init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
/* Iterate over the fields, building initializations. */
inits = NULL_TREE;
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
if (TREE_CODE (field) != FIELD_DECL)
continue;
/* Note that for class types there will be FIELD_DECLs
corresponding to base classes as well. Thus, iterating
over TYPE_FIELDs will result in correct initialization of
all of the subobjects. */
if (static_storage_p && !zero_init_p (TREE_TYPE (field)))
inits = tree_cons (field,
build_zero_init (TREE_TYPE (field),
static_storage_p),
inits);
/* For unions, only the first field is initialized. */
if (TREE_CODE (type) == UNION_TYPE)
break;
}
CONSTRUCTOR_ELTS (init) = nreverse (inits);
}
else if (TREE_CODE (type) == ARRAY_TYPE)
{
tree index;
tree max_index;
tree inits;
/* Build a constructor to contain the initializations. */
init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
/* Iterate over the array elements, building initializations. */
inits = NULL_TREE;
for (index = size_zero_node, max_index = array_type_nelts (type);
!tree_int_cst_lt (max_index, index);
index = size_binop (PLUS_EXPR, index, size_one_node))
inits = tree_cons (index,
build_zero_init (TREE_TYPE (type),
static_storage_p),
inits);
CONSTRUCTOR_ELTS (init) = nreverse (inits);
}
else if (TREE_CODE (type) == REFERENCE_TYPE)
/* --if T is a reference type, no initialization is performed. */
return NULL_TREE;
;
else
{
init = integer_zero_node;
if (TREE_CODE (type) == ENUMERAL_TYPE)
/* We must make enumeral types the right type. */
init = fold (build1 (NOP_EXPR, type, init));
}
abort ();
init = digest_init (type, init, 0);
/* In all cases, the initializer is a constant. */
if (init)
TREE_CONSTANT (init) = 1;
return init;
}
/* [dcl.init]:
To default-initialize an object of type T means:
--if T is a non-POD class type (clause _class_), the default construc-
tor for T is called (and the initialization is ill-formed if T has
no accessible default constructor);
--if T is an array type, each element is default-initialized;
--otherwise, the storage for the object is zero-initialized.
A program that calls for default-initialization of an entity of refer-
ence type is ill-formed. */
/* Build an expression for the default-initialization of an object
with type T. If initialization T requires calling constructors,
this function returns NULL_TREE; the caller is responsible for
arranging for the constructors to be called. */
static tree
build_default_init (type)
tree type;
{
if (TYPE_NEEDS_CONSTRUCTING (type))
/* Other code will handle running the default constructor. We can't do
anything with a CONSTRUCTOR for arrays here, as that would imply
copy-initialization. */
return NULL_TREE;
/* [dcl.init]:
return build_forced_zero_init (type);
To default-initialize an object of type T means:
--if T is a non-POD class type (clause _class_), the default construc-
tor for T is called (and the initialization is ill-formed if T has
no accessible default constructor);
--if T is an array type, each element is default-initialized;
--otherwise, the storage for the object is zero-initialized.
A program that calls for default-initialization of an entity of refer-
ence type is ill-formed. */
/* If TYPE_NEEDS_CONSTRUCTING is true, the caller is responsible for
performing the initialization. This is confusing in that some
non-PODs do not have TYPE_NEEDS_CONSTRUCTING set. (For example,
a class with a pointer-to-data member as a non-static data member
does not have TYPE_NEEDS_CONSTRUCTING set.) Therefore, we end up
passing non-PODs to build_zero_init below, which is contrary to
the semantics quoted above from [dcl.init].
It happens, however, that the behavior of the constructor the
standard says we should have generated would be precisely the
same as that obtained by calling build_zero_init below, so things
work out OK. */
if (TYPE_NEEDS_CONSTRUCTING (type))
return NULL_TREE;
/* At this point, TYPE is either a POD class type, an array of POD
classes, or something even more inoccuous. */
return build_zero_init (type, /*static_storage_p=*/false);
}
/* Subroutine of emit_base_init. */
@ -335,7 +416,7 @@ build_field_list (t, list, uses_unions_p)
for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields))
{
/* Skip CONST_DECLs for enumeration constants and so forth. */
if (TREE_CODE (fields) != FIELD_DECL)
if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
continue;
/* Keep track of whether or not any fields are unions. */
@ -3337,7 +3418,7 @@ push_base_cleanups ()
for (member = TYPE_FIELDS (current_class_type); member;
member = TREE_CHAIN (member))
{
if (TREE_CODE (member) != FIELD_DECL)
if (TREE_CODE (member) != FIELD_DECL || DECL_ARTIFICIAL (member))
continue;
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
{

View file

@ -668,7 +668,7 @@ do_build_assign_ref (fndecl)
tree comp, init, t;
tree field = fields;
if (TREE_CODE (field) != FIELD_DECL)
if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
if (CP_TYPE_CONST_P (TREE_TYPE (field)))
@ -824,7 +824,7 @@ synthesize_exception_spec (type, extractor, client)
tree type = TREE_TYPE (fields);
tree fn;
if (TREE_CODE (fields) != FIELD_DECL)
if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
continue;
while (TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type);

View file

@ -6141,7 +6141,10 @@ tsubst_decl (t, args, type, complain)
/* Even if the original location is out of scope, the newly
substituted one is not. */
if (TREE_CODE (r) == VAR_DECL)
DECL_DEAD_FOR_LOCAL (r) = 0;
{
DECL_DEAD_FOR_LOCAL (r) = 0;
DECL_INITIALIZED_P (r) = 0;
}
if (!local_p)
{
@ -9860,9 +9863,10 @@ regenerate_decl_from_template (decl, tmpl)
if (TREE_CODE (decl) == VAR_DECL)
{
/* Set up DECL_INITIAL, since tsubst doesn't. */
DECL_INITIAL (new_decl) =
tsubst_expr (DECL_INITIAL (code_pattern), args,
tf_error, DECL_TI_TEMPLATE (decl));
if (!DECL_INITIALIZED_IN_CLASS_P (decl))
DECL_INITIAL (new_decl) =
tsubst_expr (DECL_INITIAL (code_pattern), args,
tf_error, DECL_TI_TEMPLATE (decl));
}
else if (TREE_CODE (decl) == FUNCTION_DECL)
{
@ -10142,7 +10146,10 @@ instantiate_decl (d, defer_ok)
DECL_EXTERNAL (d) = 1;
DECL_NOT_REALLY_EXTERN (d) = 1;
}
cp_finish_decl (d, DECL_INITIAL (d), NULL_TREE, 0);
cp_finish_decl (d,
(!DECL_INITIALIZED_IN_CLASS_P (d)
? DECL_INITIAL (d) : NULL_TREE),
NULL_TREE, 0);
}
else if (TREE_CODE (d) == FUNCTION_DECL)
{

View file

@ -2536,7 +2536,8 @@ dfs_push_decls (binfo, data)
for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
if (DECL_NAME (fields)
&& TREE_CODE (fields) != TYPE_DECL
&& TREE_CODE (fields) != USING_DECL)
&& TREE_CODE (fields) != USING_DECL
&& !DECL_ARTIFICIAL (fields))
setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/0);
else if (TREE_CODE (fields) == FIELD_DECL
&& ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
@ -2597,7 +2598,7 @@ dfs_unuse_fields (binfo, data)
for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
{
if (TREE_CODE (fields) != FIELD_DECL)
if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
continue;
TREE_USED (fields) = 0;

View file

@ -1937,6 +1937,8 @@ pod_type_p (t)
{
t = strip_array_types (t);
if (t == error_mark_node)
return 1;
if (INTEGRAL_TYPE_P (t))
return 1; /* integral, character or enumeral type */
if (FLOAT_TYPE_P (t))
@ -1964,6 +1966,9 @@ zero_init_p (t)
{
t = strip_array_types (t);
if (t == error_mark_node)
return 1;
/* NULL pointers to data members are initialized with -1. */
if (TYPE_PTRMEM_P (t))
return 0;

View file

@ -1811,7 +1811,7 @@ lookup_anon_field (t, type)
{
if (TREE_STATIC (field))
continue;
if (TREE_CODE (field) != FIELD_DECL)
if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
/* If we find it directly, return the field. */

View file

@ -320,12 +320,6 @@ store_init_value (decl, init)
if (TREE_CODE (type) == ERROR_MARK)
return NULL_TREE;
#if 0
/* This breaks arrays, and should not have any effect for other decls. */
/* Take care of C++ business up here. */
type = TYPE_MAIN_VARIANT (type);
#endif
if (IS_AGGR_TYPE (type))
{
if (! TYPE_HAS_TRIVIAL_INIT_REF (type)
@ -337,35 +331,6 @@ store_init_value (decl, init)
error ("constructor syntax used, but no constructor declared for type `%T'", type);
init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (init));
}
#if 0
if (TREE_CODE (init) == CONSTRUCTOR)
{
tree field;
/* Check that we're really an aggregate as ARM 8.4.1 defines it. */
if (CLASSTYPE_N_BASECLASSES (type))
cp_error_at ("initializer list construction invalid for derived class object `%D'", decl);
if (CLASSTYPE_VTBL_PTR (type))
cp_error_at ("initializer list construction invalid for polymorphic class object `%D'", decl);
if (TYPE_NEEDS_CONSTRUCTING (type))
{
cp_error_at ("initializer list construction invalid for `%D'", decl);
error ("due to the presence of a constructor");
}
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
if (TREE_PRIVATE (field) || TREE_PROTECTED (field))
{
cp_error_at ("initializer list construction invalid for `%D'", decl);
cp_error_at ("due to non-public access of member `%D'", field);
}
for (field = TYPE_METHODS (type); field; field = TREE_CHAIN (field))
if (TREE_PRIVATE (field) || TREE_PROTECTED (field))
{
cp_error_at ("initializer list construction invalid for `%D'", decl);
cp_error_at ("due to non-public access of member `%D'", field);
}
}
#endif
}
else if (TREE_CODE (init) == TREE_LIST
&& TREE_TYPE (init) != unknown_type_node)
@ -457,27 +422,6 @@ store_init_value (decl, init)
return NULL_TREE;
}
/* Same as store_init_value, but used for known-to-be-valid static
initializers. Used to introduce a static initializer even in data
structures that may require dynamic initialization. */
tree
force_store_init_value (decl, init)
tree decl, init;
{
tree type = TREE_TYPE (decl);
int needs_constructing = TYPE_NEEDS_CONSTRUCTING (type);
TYPE_NEEDS_CONSTRUCTING (type) = 0;
init = store_init_value (decl, init);
if (init)
abort ();
TYPE_NEEDS_CONSTRUCTING (type) = needs_constructing;
return init;
}
/* Digest the parser output INIT as an initializer for type TYPE.
Return a C expression of type TYPE to represent the initial value.
@ -791,7 +735,8 @@ process_init_constructor (type, init, elts)
next1 = digest_init (TREE_TYPE (type), next1, 0);
}
else if (! zero_init_p (TREE_TYPE (type)))
next1 = build_forced_zero_init (TREE_TYPE (type));
next1 = build_zero_init (TREE_TYPE (type),
/*static_storage_p=*/false);
else
/* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */
@ -840,7 +785,7 @@ process_init_constructor (type, init, elts)
continue;
}
if (TREE_CODE (field) != FIELD_DECL)
if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
if (tail)
@ -909,7 +854,8 @@ process_init_constructor (type, init, elts)
warning ("missing initializer for member `%D'", field);
if (! zero_init_p (TREE_TYPE (field)))
next1 = build_forced_zero_init (TREE_TYPE (field));
next1 = build_zero_init (TREE_TYPE (field),
/*static_storage_p=*/false);
else
/* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */
@ -933,8 +879,7 @@ process_init_constructor (type, init, elts)
/* Find the first named field. ANSI decided in September 1990
that only named fields count here. */
while (field && (DECL_NAME (field) == 0
|| TREE_CODE (field) != FIELD_DECL))
while (field && (!DECL_NAME (field) || TREE_CODE (field) != FIELD_DECL))
field = TREE_CHAIN (field);
/* If this element specifies a field, initialize via that field. */

View file

@ -1484,11 +1484,14 @@ finalize_type_size (type)
/* Do all of the work required to layout the type indicated by RLI,
once the fields have been laid out. This function will call `free'
for RLI. */
for RLI, unless FREE_P is false. Passing a value other than false
for FREE_P is bad practice; this option only exists to support the
G++ 3.2 ABI. */
void
finish_record_layout (rli)
finish_record_layout (rli, free_p)
record_layout_info rli;
int free_p;
{
/* Compute the final size. */
finalize_record_size (rli);
@ -1508,7 +1511,8 @@ finish_record_layout (rli)
}
/* Clean up. */
free (rli);
if (free_p)
free (rli);
}
/* Calculate the mode, size, and alignment for TYPE.
@ -1763,7 +1767,7 @@ layout_type (type)
(*lang_adjust_rli) (rli);
/* Finish laying out the record. */
finish_record_layout (rli);
finish_record_layout (rli, /*free_p=*/true);
}
break;

View file

@ -1,3 +1,8 @@
2002-09-30 Mark Mitchell <mark@codesourcery.com>
* g++.dg/abi/empty7.C: New test.
* g++.dg/init/pm2.C: Likewise.
2002-09-29 Nathan Sidwell <nathan@codesourcery.com>
* g++.dg/rtti/crash1.C: New test.

View file

@ -0,0 +1,18 @@
// { dg-do run { target i?86-*-* } }
// { dg-options "-fabi-version=0" }
struct S1 {};
struct S2 { virtual void f () {} S1 s1[4]; };
struct S3 : virtual public S2 {};
struct S4 : virtual public S2 { int i; };
struct S5 : public S3, virtual public S4 {};
struct S6 { S5 s5; };
struct S7 { S1 s1[5]; };
struct S8 : public S1, public S6, virtual public S7 { };
S8 s8;
int main () {
if ((char *)(S7 *)&s8 - (char *)&s8 != 24)
return 1;
}

View file

@ -0,0 +1,7 @@
struct S {
S ();
int S::* sp;
int i;
};
S s[2] = {};

View file

@ -2434,7 +2434,7 @@ extern tree rli_size_so_far PARAMS ((record_layout_info));
extern void normalize_rli PARAMS ((record_layout_info));
extern void place_field PARAMS ((record_layout_info, tree));
extern void compute_record_mode PARAMS ((tree));
extern void finish_record_layout PARAMS ((record_layout_info));
extern void finish_record_layout PARAMS ((record_layout_info, int));
/* Given a hashcode and a ..._TYPE node (for which the hashcode was made),
return a canonicalized ..._TYPE node, so that duplicates are not made.