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:
parent
acc59b855d
commit
17bbb839f1
18 changed files with 631 additions and 464 deletions
|
@ -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__.
|
||||
|
|
|
@ -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
|
||||
|
|
540
gcc/cp/class.c
540
gcc/cp/class.c
|
@ -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)
|
||||
|
|
|
@ -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 *));
|
||||
|
|
134
gcc/cp/decl.c
134
gcc/cp/decl.c
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
175
gcc/cp/init.c
175
gcc/cp/init.c
|
@ -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)))
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
17
gcc/cp/pt.c
17
gcc/cp/pt.c
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
18
gcc/testsuite/g++.dg/abi/empty7.C
Normal file
18
gcc/testsuite/g++.dg/abi/empty7.C
Normal 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;
|
||||
}
|
7
gcc/testsuite/g++.dg/init/pm2.C
Normal file
7
gcc/testsuite/g++.dg/init/pm2.C
Normal file
|
@ -0,0 +1,7 @@
|
|||
struct S {
|
||||
S ();
|
||||
int S::* sp;
|
||||
int i;
|
||||
};
|
||||
|
||||
S s[2] = {};
|
|
@ -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.
|
||||
|
|
Loading…
Add table
Reference in a new issue