Commit 607cf131 by Mark Mitchell Committed by Mark Mitchell

class.c (check_field_decls): Don't return a value.

1999-12-16  Mark Mitchell  <mark@codesourcery.com>

	* class.c (check_field_decls): Don't return a value.
	(avoid_overlap): Moved here from tree.c.
	(build_base_fields): Likewise.
	(check_bases): New function, split out from finish_base_struct.
	(check_bases_and_members): New function, split out from finish_struct_1.
	(struct base_info): Remove cant_have_default_ctor,
	cant_have_const_ctor, cant_have_asn_ref.
	(finish_base_struct): Split semantic analysis into check_bases.
	(finish_struct_methods): Fix bogus assertion.
	(check_field_decls): Call finish_struct_anon here.
	(build_vbase_pointer_fields): Use CLASSTYPE_N_BASECLASSES.
	(finish_struct_1): Use check_bases_and_members.  Reorganize.
	* cp-tree.h (CLASSTYPE_VBASECLASSES): Improve documentation.
	(build_base_fields): Don't declare.
	* tree.c (avoid_overlap): Remove.
	(build_base_fields): Likewise.

From-SVN: r30983
parent a97901e6
1999-12-16 Mark Mitchell <mark@codesourcery.com> 1999-12-16 Mark Mitchell <mark@codesourcery.com>
* class.c (check_field_decls): Don't return a value.
(avoid_overlap): Moved here from tree.c.
(build_base_fields): Likewise.
(check_bases): New function, split out from finish_base_struct.
(check_bases_and_members): New function, split out from finish_struct_1.
(struct base_info): Remove cant_have_default_ctor,
cant_have_const_ctor, cant_have_asn_ref.
(finish_base_struct): Split semantic analysis into check_bases.
(finish_struct_methods): Fix bogus assertion.
(check_field_decls): Call finish_struct_anon here.
(build_vbase_pointer_fields): Use CLASSTYPE_N_BASECLASSES.
(finish_struct_1): Use check_bases_and_members. Reorganize.
* cp-tree.h (CLASSTYPE_VBASECLASSES): Improve documentation.
(build_base_fields): Don't declare.
* tree.c (avoid_overlap): Remove.
(build_base_fields): Likewise.
* optimize.c (struct inline_data): Remove scope_stmt. * optimize.c (struct inline_data): Remove scope_stmt.
(remap_block): Don't use insert_block_after_note. Don't update (remap_block): Don't use insert_block_after_note. Don't update
scope_stmt. scope_stmt.
......
...@@ -123,12 +123,16 @@ static int count_fields PROTO((tree)); ...@@ -123,12 +123,16 @@ static int count_fields PROTO((tree));
static int add_fields_to_vec PROTO((tree, tree, int)); static int add_fields_to_vec PROTO((tree, tree, int));
static void check_bitfield_decl PROTO((tree)); static void check_bitfield_decl PROTO((tree));
static void check_field_decl PROTO((tree, tree, int *, int *, int *, int *)); static void check_field_decl PROTO((tree, tree, int *, int *, int *, int *));
static tree* check_field_decls PROTO((tree, tree *, int *, int *, int *, static void check_field_decls PROTO((tree, tree *, int *, int *, int *,
int *)); int *));
static int avoid_overlap PROTO((tree, tree, int *));
static tree build_base_fields PROTO((tree, int *));
static tree build_vbase_pointer_fields PROTO((tree, int *)); static tree build_vbase_pointer_fields PROTO((tree, int *));
static tree build_vtbl_or_vbase_field PROTO((tree, tree, tree, tree, int *)); static tree build_vtbl_or_vbase_field PROTO((tree, tree, tree, tree, int *));
static void check_methods PROTO((tree)); static void check_methods PROTO((tree));
static void remove_zero_width_bit_fields PROTO((tree)); static void remove_zero_width_bit_fields PROTO((tree));
static void check_bases PROTO((tree, int *, int *, int *));
static void check_bases_and_members PROTO((tree, int *));
/* Variables shared between class.c and call.c. */ /* Variables shared between class.c and call.c. */
...@@ -1486,52 +1490,43 @@ struct base_info ...@@ -1486,52 +1490,43 @@ struct base_info
tree vfield; tree vfield;
tree vfields; tree vfields;
tree rtti; tree rtti;
char cant_have_default_ctor;
char cant_have_const_ctor;
char no_const_asn_ref;
}; };
/* Record information about type T derived from its base classes. /* Run through the base clases of T, updating
Store most of that information in T itself, and place the CANT_HAVE_DEFAULT_CTOR_P, CANT_HAVE_CONST_CTOR_P, and
remaining information in the struct BASE_INFO. NO_CONST_ASN_REF_P. Also set flag bits in T based on properties of
the bases. */
Propagate basetype offsets throughout the lattice. Note that the
lattice topped by T is really a pair: it's a DAG that gives the
structure of the derivation hierarchy, and it's a list of the
virtual baseclasses that appear anywhere in the DAG. When a vbase
type appears in the DAG, it's offset is 0, and it's children start
their offsets from that point. When a vbase type appears in the list,
its offset is the offset it has in the hierarchy, and its children's
offsets include that offset in theirs.
Returns the index of the first base class to have virtual functions, static void
or -1 if no such base class. */ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
no_const_asn_ref_p)
static int
finish_base_struct (t, b)
tree t; tree t;
struct base_info *b; int *cant_have_default_ctor_p;
int *cant_have_const_ctor_p;
int *no_const_asn_ref_p;
{ {
tree binfos = TYPE_BINFO_BASETYPES (t); int n_baseclasses;
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; int i;
int first_vfn_base_index = -1; tree binfos;
bzero ((char *) b, sizeof (struct base_info));
for (i = 0; i < n_baseclasses; i++) binfos = TYPE_BINFO_BASETYPES (t);
n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
/* An aggregate cannot have baseclasses. */
CLASSTYPE_NON_AGGREGATE (t) |= (n_baseclasses != 0);
for (i = 0; i < n_baseclasses; ++i)
{ {
tree base_binfo = TREE_VEC_ELT (binfos, i); tree base_binfo;
tree basetype = BINFO_TYPE (base_binfo); tree basetype;
/* Effective C++ rule 14. We only need to check TYPE_VIRTUAL_P /* Figure out what base we're looking at. */
here because the case of virtual functions but non-virtual base_binfo = TREE_VEC_ELT (binfos, i);
dtor is handled in finish_struct_1. */ basetype = TREE_TYPE (base_binfo);
if (warn_ecpp && ! TYPE_VIRTUAL_P (basetype)
&& TYPE_HAS_DESTRUCTOR (basetype))
cp_warning ("base class `%#T' has a non-virtual destructor", basetype);
/* If the type of basetype is incomplete, then /* If the type of basetype is incomplete, then we already
we already complained about that fact complained about that fact (and we should have fixed it up as
(and we should have fixed it up as well). */ well). */
if (TYPE_SIZE (basetype) == 0) if (TYPE_SIZE (basetype) == 0)
{ {
int j; int j;
...@@ -1544,15 +1539,33 @@ finish_base_struct (t, b) ...@@ -1544,15 +1539,33 @@ finish_base_struct (t, b)
n_baseclasses -= 1; n_baseclasses -= 1;
for (j = i; j+1 < n_baseclasses; j++) for (j = i; j+1 < n_baseclasses; j++)
TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1); TREE_VEC_ELT (binfos, j) = TREE_VEC_ELT (binfos, j+1);
continue;
} }
if (! TYPE_HAS_CONST_INIT_REF (basetype)) /* Effective C++ rule 14. We only need to check TYPE_VIRTUAL_P
b->cant_have_const_ctor = 1; here because the case of virtual functions but non-virtual
dtor is handled in finish_struct_1. */
if (warn_ecpp && ! TYPE_VIRTUAL_P (basetype)
&& TYPE_HAS_DESTRUCTOR (basetype))
cp_warning ("base class `%#T' has a non-virtual destructor",
basetype);
/* If the base class doesn't have copy constructors or
assignment operators that take const references, then the
derived class cannot have such a member automatically
generated. */
if (! TYPE_HAS_CONST_INIT_REF (basetype))
*cant_have_const_ctor_p = 1;
if (TYPE_HAS_ASSIGN_REF (basetype)
&& !TYPE_HAS_CONST_ASSIGN_REF (basetype))
*no_const_asn_ref_p = 1;
/* Similarly, if the base class doesn't have a default
constructor, then the derived class won't have an
automatically generated default constructor. */
if (TYPE_HAS_CONSTRUCTOR (basetype) if (TYPE_HAS_CONSTRUCTOR (basetype)
&& ! TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)) && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype))
{ {
b->cant_have_default_ctor = 1; *cant_have_default_ctor_p = 1;
if (! TYPE_HAS_CONSTRUCTOR (t)) if (! TYPE_HAS_CONSTRUCTOR (t))
{ {
cp_pedwarn ("base `%T' with only non-default constructor", cp_pedwarn ("base `%T' with only non-default constructor",
...@@ -1561,30 +1574,61 @@ finish_base_struct (t, b) ...@@ -1561,30 +1574,61 @@ finish_base_struct (t, b)
} }
} }
if (TYPE_HAS_ASSIGN_REF (basetype) /* A lot of properties from the bases also apply to the derived
&& !TYPE_HAS_CONST_ASSIGN_REF (basetype)) class. */
b->no_const_asn_ref = 1;
TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype); TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (basetype);
TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype); TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_NEEDS_DESTRUCTOR (basetype);
TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype); TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|= TYPE_HAS_COMPLEX_ASSIGN_REF (basetype);
TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (basetype); TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_HAS_COMPLEX_INIT_REF (basetype);
TYPE_OVERLOADS_CALL_EXPR (t) |= TYPE_OVERLOADS_CALL_EXPR (basetype); TYPE_OVERLOADS_CALL_EXPR (t) |= TYPE_OVERLOADS_CALL_EXPR (basetype);
TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype); TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype);
TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype); TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype);
/* Derived classes can implicitly become COMified if their bases
are COM. */
if (CLASSTYPE_COM_INTERFACE (basetype)) if (CLASSTYPE_COM_INTERFACE (basetype))
{ CLASSTYPE_COM_INTERFACE (t) = 1;
CLASSTYPE_COM_INTERFACE (t) = 1; else if (i == 0 && CLASSTYPE_COM_INTERFACE (t))
}
else if (CLASSTYPE_COM_INTERFACE (t) && i == 0)
{ {
cp_error cp_error
("COM interface type `%T' with non-COM leftmost base class `%T'", ("COM interface type `%T' with non-COM leftmost base class `%T'",
t, basetype); t, basetype);
CLASSTYPE_COM_INTERFACE (t) = 0; CLASSTYPE_COM_INTERFACE (t) = 0;
} }
}
}
/* Record information about type T derived from its base classes.
Store most of that information in T itself, and place the
remaining information in the struct BASE_INFO.
Propagate basetype offsets throughout the lattice. Note that the
lattice topped by T is really a pair: it's a DAG that gives the
structure of the derivation hierarchy, and it's a list of the
virtual baseclasses that appear anywhere in the DAG. When a vbase
type appears in the DAG, it's offset is 0, and it's children start
their offsets from that point. When a vbase type appears in the list,
its offset is the offset it has in the hierarchy, and its children's
offsets include that offset in theirs.
Returns the index of the first base class to have virtual functions,
or -1 if no such base class. */
static int
finish_base_struct (t, b)
tree t;
struct base_info *b;
{
tree binfos = TYPE_BINFO_BASETYPES (t);
int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
int first_vfn_base_index = -1;
bzero ((char *) b, sizeof (struct base_info));
for (i = 0; i < n_baseclasses; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
tree basetype = BINFO_TYPE (base_binfo);
if (TYPE_VIRTUAL_P (basetype)) if (TYPE_VIRTUAL_P (basetype))
{ {
...@@ -2009,8 +2053,8 @@ finish_struct_methods (t) ...@@ -2009,8 +2053,8 @@ finish_struct_methods (t)
return; return;
} }
my_friendly_assert (method_vec != NULL_TREE, 19991215);
method_vec = CLASSTYPE_METHOD_VEC (t); method_vec = CLASSTYPE_METHOD_VEC (t);
my_friendly_assert (method_vec != NULL_TREE, 19991215);
len = TREE_VEC_LENGTH (method_vec); len = TREE_VEC_LENGTH (method_vec);
/* First fill in entry 0 with the constructors, entry 1 with destructors, /* First fill in entry 0 with the constructors, entry 1 with destructors,
...@@ -3387,7 +3431,7 @@ check_field_decl (field, t, cant_have_const_ctor, ...@@ -3387,7 +3431,7 @@ check_field_decl (field, t, cant_have_const_ctor,
Returns a pointer to the end of the TYPE_FIELDs chain; additional Returns a pointer to the end of the TYPE_FIELDs chain; additional
fields can be added by adding to this chain. */ fields can be added by adding to this chain. */
static tree* static void
check_field_decls (t, access_decls, empty_p, check_field_decls (t, access_decls, empty_p,
cant_have_default_ctor_p, cant_have_const_ctor_p, cant_have_default_ctor_p, cant_have_const_ctor_p,
no_const_asn_ref_p) no_const_asn_ref_p)
...@@ -3606,12 +3650,13 @@ check_field_decls (t, access_decls, empty_p, ...@@ -3606,12 +3650,13 @@ check_field_decls (t, access_decls, empty_p,
cp_warning (" but does not override `operator=(const %T&)'", t); cp_warning (" but does not override `operator=(const %T&)'", t);
} }
/* Check anonymous struct/anonymous union fields. */
finish_struct_anon (t);
/* We've built up the list of access declarations in reverse order. /* We've built up the list of access declarations in reverse order.
Fix that now. */ Fix that now. */
*access_decls = nreverse (*access_decls); *access_decls = nreverse (*access_decls);
/* Return the last field. */
return field;
} }
/* Return a FIELD_DECL for a pointer-to-virtual-table or /* Return a FIELD_DECL for a pointer-to-virtual-table or
...@@ -3662,7 +3707,7 @@ build_vbase_pointer_fields (rec, empty_p) ...@@ -3662,7 +3707,7 @@ build_vbase_pointer_fields (rec, empty_p)
base classes. */ base classes. */
tree vbase_decls = NULL_TREE; tree vbase_decls = NULL_TREE;
tree binfos = TYPE_BINFO_BASETYPES (rec); tree binfos = TYPE_BINFO_BASETYPES (rec);
int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
tree decl; tree decl;
int i; int i;
...@@ -3725,6 +3770,129 @@ build_vbase_pointer_fields (rec, empty_p) ...@@ -3725,6 +3770,129 @@ build_vbase_pointer_fields (rec, empty_p)
return vbase_decls; return vbase_decls;
} }
/* If the empty base field in DECL overlaps with a base of the same type in
NEWDECL, which is either another base field or the first data field of
the class, pad the base just before NEWDECL and return 1. Otherwise,
return 0. */
static int
avoid_overlap (decl, newdecl, empty_p)
tree decl, newdecl;
int *empty_p;
{
tree field;
if (newdecl == NULL_TREE
|| ! types_overlap_p (TREE_TYPE (decl), TREE_TYPE (newdecl)))
return 0;
for (field = decl; TREE_CHAIN (field) && TREE_CHAIN (field) != newdecl;
field = TREE_CHAIN (field))
;
DECL_SIZE (field) = integer_one_node;
/* The containing class cannot be empty; this field takes up space. */
*empty_p = 0;
return 1;
}
/* Returns a list of fields to stand in for the base class subobjects
of REC. These fields are later removed by layout_basetypes. */
static tree
build_base_fields (rec, empty_p)
tree rec;
int *empty_p;
{
/* Chain to hold all the new FIELD_DECLs which stand in for base class
subobjects. */
tree base_decls = NULL_TREE;
tree binfos = TYPE_BINFO_BASETYPES (rec);
int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
tree decl, nextdecl;
int i, saw_empty = 0;
unsigned int base_align = 0;
for (i = 0; i < n_baseclasses; ++i)
{
register tree base_binfo = TREE_VEC_ELT (binfos, i);
register tree basetype = BINFO_TYPE (base_binfo);
if (TYPE_SIZE (basetype) == 0)
/* This error is now reported in xref_tag, thus giving better
location information. */
continue;
if (TREE_VIA_VIRTUAL (base_binfo))
continue;
decl = build_lang_decl (FIELD_DECL, NULL_TREE, basetype);
DECL_ARTIFICIAL (decl) = 1;
DECL_FIELD_CONTEXT (decl) = DECL_CLASS_CONTEXT (decl) = rec;
DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
TREE_CHAIN (decl) = base_decls;
base_decls = decl;
if (flag_new_abi && DECL_SIZE (decl) == integer_zero_node)
saw_empty = 1;
else
{
/* The containing class is non-empty because it has a
non-empty base class. */
*empty_p = 0;
if (! flag_new_abi)
{
/* Brain damage for backwards compatibility. For no
good reason, the old layout_basetypes made every base
at least as large as the alignment for the bases up
to that point, gratuitously wasting space. So we do
the same thing here. */
base_align = MAX (base_align, DECL_ALIGN (decl));
DECL_SIZE (decl)
= size_int (MAX (TREE_INT_CST_LOW (DECL_SIZE (decl)),
(int) base_align));
}
}
}
/* Reverse the list of fields so we allocate the bases in the proper
order. */
base_decls = nreverse (base_decls);
/* In the presence of empty base classes, we run the risk of allocating
two objects of the same class on top of one another. Avoid that. */
if (flag_new_abi && saw_empty)
for (decl = base_decls; decl; decl = TREE_CHAIN (decl))
{
if (DECL_SIZE (decl) == integer_zero_node)
{
/* First step through the following bases until we find
an overlap or a non-empty base. */
for (nextdecl = TREE_CHAIN (decl); nextdecl;
nextdecl = TREE_CHAIN (nextdecl))
{
if (avoid_overlap (decl, nextdecl, empty_p)
|| DECL_SIZE (nextdecl) != integer_zero_node)
goto nextbase;
}
/* If we're still looking, also check against the first
field. */
for (nextdecl = TYPE_FIELDS (rec);
nextdecl && TREE_CODE (nextdecl) != FIELD_DECL;
nextdecl = TREE_CHAIN (nextdecl))
/* keep looking */;
avoid_overlap (decl, nextdecl, empty_p);
}
nextbase:;
}
return base_decls;
}
/* Go through the TYPE_METHODS of T issuing any appropriate /* Go through the TYPE_METHODS of T issuing any appropriate
diagnostics, figuring out which methods override which other diagnostics, figuring out which methods override which other
methods, and so forth. Returns non-zero if this class has any methods, and so forth. Returns non-zero if this class has any
...@@ -3800,6 +3968,80 @@ remove_zero_width_bit_fields (t) ...@@ -3800,6 +3968,80 @@ remove_zero_width_bit_fields (t)
} }
} }
/* Check the validity of the bases and members declared in T. Add any
implicitly-generated functions (like copy-constructors and
assignment operators). Compute various flag bits (like
CLASSTYPE_NON_POD_T) for T. This routine works purely at the C++
level: i.e., independently of the ABI in use. */
static void
check_bases_and_members (t, empty_p)
tree t;
int *empty_p;
{
/* Nonzero if we are not allowed to generate a default constructor
for this case. */
int cant_have_default_ctor;
/* Nonzero if the implicitly generated copy constructor should take
a non-const reference argument. */
int cant_have_const_ctor;
/* Nonzero if the the implicitly generated assignment operator
should take a non-const reference argument. */
int no_const_asn_ref;
tree access_decls;
/* By default, we use const reference arguments and generate default
constructors. */
cant_have_default_ctor = 0;
cant_have_const_ctor = 0;
no_const_asn_ref = 0;
/* Check all the base-classes. */
check_bases (t, &cant_have_default_ctor, &cant_have_const_ctor,
&no_const_asn_ref);
/* Check all the data member declarations. */
check_field_decls (t, &access_decls, empty_p,
&cant_have_default_ctor,
&cant_have_const_ctor,
&no_const_asn_ref);
/* Check all the method declarations. */
check_methods (t);
/* Do some bookkeeping that will guide the generation of implicitly
declared member functions. */
TYPE_HAS_COMPLEX_INIT_REF (t)
|= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t));
TYPE_NEEDS_CONSTRUCTING (t)
|= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t));
CLASSTYPE_NON_AGGREGATE (t) |= TYPE_HAS_CONSTRUCTOR (t);
CLASSTYPE_NON_POD_P (t)
|= (CLASSTYPE_NON_AGGREGATE (t) || TYPE_HAS_DESTRUCTOR (t)
|| TYPE_HAS_ASSIGN_REF (t));
TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t);
TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t);
/* Synthesize any needed methods. Note that methods will be synthesized
for anonymous unions; grok_x_components undoes that. */
add_implicitly_declared_members (t, cant_have_default_ctor,
cant_have_const_ctor,
no_const_asn_ref);
/* Build and sort the CLASSTYPE_METHOD_VEC. */
finish_struct_methods (t);
/* Process the access-declarations. We wait until now to do this
because handle_using_decls requires that the CLASSTYPE_METHOD_VEC
be set up correctly. */
while (access_decls)
{
handle_using_decl (TREE_VALUE (access_decls), t);
access_decls = TREE_CHAIN (access_decls);
}
}
/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration /* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
(or C++ class declaration). (or C++ class declaration).
...@@ -3831,19 +4073,13 @@ void ...@@ -3831,19 +4073,13 @@ void
finish_struct_1 (t) finish_struct_1 (t)
tree t; tree t;
{ {
tree fields;
tree x; tree x;
tree *next_field;
int has_virtual; int has_virtual;
int max_has_virtual; int max_has_virtual;
tree pending_virtuals = NULL_TREE; tree pending_virtuals = NULL_TREE;
tree pending_hard_virtuals = NULL_TREE; tree pending_hard_virtuals = NULL_TREE;
tree vfield; tree vfield;
tree vfields; tree vfields;
tree virtual_dtor;
int cant_have_default_ctor;
int cant_have_const_ctor;
int no_const_asn_ref;
int n_fields = 0; int n_fields = 0;
/* The index of the first base class which has virtual /* The index of the first base class which has virtual
...@@ -3851,8 +4087,6 @@ finish_struct_1 (t) ...@@ -3851,8 +4087,6 @@ finish_struct_1 (t)
int first_vfn_base_index; int first_vfn_base_index;
int n_baseclasses; int n_baseclasses;
tree access_decls;
int aggregate = 1;
int empty = 1; int empty = 1;
tree inline_friends; tree inline_friends;
...@@ -3874,8 +4108,25 @@ finish_struct_1 (t) ...@@ -3874,8 +4108,25 @@ finish_struct_1 (t)
TYPE_SIZE (t) = NULL_TREE; TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0; CLASSTYPE_GOT_SEMICOLON (t) = 0;
first_vfn_base_index = -1;
has_virtual = 0;
max_has_virtual = 0;
vfield = NULL_TREE;
vfields = NULL_TREE;
CLASSTYPE_RTTI (t) = NULL_TREE;
n_baseclasses = CLASSTYPE_N_BASECLASSES (t); n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
/* Do end-of-class semantic processing: checking the validity of the
bases and members and adding implicitly generated methods. */
check_bases_and_members (t, &empty);
/* Add pointers to all of our virtual base-classes. */
TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (t, &empty),
TYPE_FIELDS (t));
/* Build FIELD_DECLs for all of the non-virtual base-types. */
TYPE_FIELDS (t) = chainon (build_base_fields (t, &empty),
TYPE_FIELDS (t));
if (n_baseclasses > 0) if (n_baseclasses > 0)
{ {
struct base_info base_info; struct base_info base_info;
...@@ -3890,74 +4141,8 @@ finish_struct_1 (t) ...@@ -3890,74 +4141,8 @@ finish_struct_1 (t)
vfields = base_info.vfields; vfields = base_info.vfields;
CLASSTYPE_VFIELDS (t) = vfields; CLASSTYPE_VFIELDS (t) = vfields;
CLASSTYPE_RTTI (t) = base_info.rtti; CLASSTYPE_RTTI (t) = base_info.rtti;
cant_have_default_ctor = base_info.cant_have_default_ctor;
cant_have_const_ctor = base_info.cant_have_const_ctor;
no_const_asn_ref = base_info.no_const_asn_ref;
aggregate = 0;
}
else
{
first_vfn_base_index = -1;
has_virtual = 0;
max_has_virtual = 0;
vfield = NULL_TREE;
vfields = NULL_TREE;
CLASSTYPE_RTTI (t) = NULL_TREE;
cant_have_default_ctor = 0;
cant_have_const_ctor = 0;
no_const_asn_ref = 0;
}
/* Check all the data member declarations. */
next_field = check_field_decls (t, &access_decls, &empty,
&cant_have_default_ctor,
&cant_have_const_ctor,
&no_const_asn_ref);
/* Add pointers to all of our virtual base-classes. */
if (n_baseclasses)
TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (t, &empty),
TYPE_FIELDS (t));
/* Build FIELD_DECLs for all of the non-virtual base-types. */
fields = TYPE_FIELDS (t);
if (n_baseclasses)
{
TYPE_FIELDS (t) = chainon (build_base_fields (t), TYPE_FIELDS (t));
/* If any base is non-empty, then we are non-empty. */
for (x = TYPE_FIELDS (t); empty && x != fields; x = TREE_CHAIN (x))
if (DECL_SIZE (x) != integer_zero_node)
empty = 0;
fields = TYPE_FIELDS (t);
} }
/* Check all the method declarations. */
check_methods (t);
/* Do some bookkeeping that will guide the generation of implicitly
declared member functions. */
TYPE_HAS_COMPLEX_INIT_REF (t)
|= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t));
TYPE_NEEDS_CONSTRUCTING (t)
|= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t));
CLASSTYPE_NON_AGGREGATE (t)
= ! aggregate || TYPE_HAS_CONSTRUCTOR (t);
CLASSTYPE_NON_POD_P (t)
|= (CLASSTYPE_NON_AGGREGATE (t) || TYPE_HAS_DESTRUCTOR (t)
|| TYPE_HAS_ASSIGN_REF (t));
TYPE_HAS_REAL_ASSIGN_REF (t) |= TYPE_HAS_ASSIGN_REF (t);
TYPE_HAS_COMPLEX_ASSIGN_REF (t)
|= TYPE_HAS_ASSIGN_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t);
/* Synthesize any needed methods. Note that methods will be synthesized
for anonymous unions; grok_x_components undoes that. */
virtual_dtor
= add_implicitly_declared_members (t, cant_have_default_ctor,
cant_have_const_ctor,
no_const_asn_ref);
/* Loop over the virtual functions, adding them to our various /* Loop over the virtual functions, adding them to our various
vtables. */ vtables. */
for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x)) for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
...@@ -3965,16 +4150,6 @@ finish_struct_1 (t) ...@@ -3965,16 +4150,6 @@ finish_struct_1 (t)
add_virtual_function (&pending_virtuals, &pending_hard_virtuals, add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
&has_virtual, x, t); &has_virtual, x, t);
/* Build and sort the CLASSTYPE_METHOD_VEC. */
finish_struct_methods (t);
/* Process the access-declarations. */
while (access_decls)
{
handle_using_decl (TREE_VALUE (access_decls), t);
access_decls = TREE_CHAIN (access_decls);
}
if (vfield == NULL_TREE && has_virtual) if (vfield == NULL_TREE && has_virtual)
{ {
/* We build this decl with vtbl_ptr_type_node, which is a /* We build this decl with vtbl_ptr_type_node, which is a
...@@ -4002,7 +4177,7 @@ finish_struct_1 (t) ...@@ -4002,7 +4177,7 @@ finish_struct_1 (t)
t, t,
&empty); &empty);
TYPE_VFIELD (t) = vfield; TYPE_VFIELD (t) = vfield;
*next_field = vfield; TYPE_FIELDS (t) = chainon (TYPE_FIELDS (t), vfield);
vfields = chainon (vfields, build_tree_list (NULL_TREE, t)); vfields = chainon (vfields, build_tree_list (NULL_TREE, t));
} }
...@@ -4046,8 +4221,6 @@ finish_struct_1 (t) ...@@ -4046,8 +4221,6 @@ finish_struct_1 (t)
CLASSTYPE_SIZE (t) = TYPE_SIZE (t); CLASSTYPE_SIZE (t) = TYPE_SIZE (t);
CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t); CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t);
finish_struct_anon (t);
/* Set the TYPE_DECL for this type to contain the right /* Set the TYPE_DECL for this type to contain the right
value for DECL_OFFSET, so that we can use it as part value for DECL_OFFSET, so that we can use it as part
of a COMPONENT_REF for multiple inheritance. */ of a COMPONENT_REF for multiple inheritance. */
......
...@@ -1388,7 +1388,8 @@ struct lang_type ...@@ -1388,7 +1388,8 @@ struct lang_type
/* The number of virtual functions defined for this /* The number of virtual functions defined for this
_CLASSTYPE node. */ _CLASSTYPE node. */
#define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize) #define CLASSTYPE_VSIZE(NODE) (TYPE_LANG_SPECIFIC(NODE)->vsize)
/* The virtual base classes that this type uses. */ /* The direct and indirect virtual base classes that this type uses in
depth-first left-to-right order. */
#define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbases) #define CLASSTYPE_VBASECLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->vbases)
/* The virtual function pointer fields that this type contains. */ /* The virtual function pointer fields that this type contains. */
#define CLASSTYPE_VFIELDS(NODE) (TYPE_LANG_SPECIFIC(NODE)->vfields) #define CLASSTYPE_VFIELDS(NODE) (TYPE_LANG_SPECIFIC(NODE)->vfields)
...@@ -4012,7 +4013,6 @@ extern tree build_cplus_method_type PROTO((tree, tree, tree)); ...@@ -4012,7 +4013,6 @@ extern tree build_cplus_method_type PROTO((tree, tree, tree));
extern tree build_cplus_staticfn_type PROTO((tree, tree, tree)); extern tree build_cplus_staticfn_type PROTO((tree, tree, tree));
extern tree build_cplus_array_type PROTO((tree, tree)); extern tree build_cplus_array_type PROTO((tree, tree));
extern int layout_basetypes PROTO((tree, int)); extern int layout_basetypes PROTO((tree, int));
extern tree build_base_fields PROTO((tree));
extern tree hash_tree_cons PROTO((tree, tree, tree)); extern tree hash_tree_cons PROTO((tree, tree, tree));
extern tree hash_tree_chain PROTO((tree, tree)); extern tree hash_tree_chain PROTO((tree, tree));
extern tree hash_chainon PROTO((tree, tree)); extern tree hash_chainon PROTO((tree, tree));
......
...@@ -98,6 +98,7 @@ static int is_back_referenceable_type PROTO((tree)); ...@@ -98,6 +98,7 @@ static int is_back_referenceable_type PROTO((tree));
static int check_btype PROTO((tree)); static int check_btype PROTO((tree));
static void build_mangled_name_for_type PROTO((tree)); static void build_mangled_name_for_type PROTO((tree));
static void build_mangled_name_for_type_with_Gcode PROTO((tree, int)); static void build_mangled_name_for_type_with_Gcode PROTO((tree, int));
static void fixup_pending_inline PROTO((struct pending_inline *));
# define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0) # define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0)
# define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C))) # define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C)))
...@@ -142,6 +143,27 @@ init_method () ...@@ -142,6 +143,27 @@ init_method ()
value. */ value. */
static char digit_buffer[128]; static char digit_buffer[128];
/* Fixup the inline function given by INFO now that the class is
complete. */
static void
fixup_pending_inline (info)
struct pending_inline *info;
{
if (info)
{
tree args;
tree fn = info->fndecl;
args = DECL_ARGUMENTS (fn);
while (args)
{
DECL_CONTEXT (args) = fn;
args = TREE_CHAIN (args);
}
}
}
/* Move inline function definitions out of structure so that they /* Move inline function definitions out of structure so that they
can be processed normally. CNAME is the name of the class can be processed normally. CNAME is the name of the class
we are working from, METHOD_LIST is the list of method lists we are working from, METHOD_LIST is the list of method lists
...@@ -164,43 +186,13 @@ do_inline_function_hair (type, friend_list) ...@@ -164,43 +186,13 @@ do_inline_function_hair (type, friend_list)
method = TREE_VEC_ELT (method, 2); method = TREE_VEC_ELT (method, 2);
} }
while (method) /* Do inline member functions. */
{ for (; method; method = TREE_CHAIN (method))
/* Do inline member functions. */ fixup_pending_inline (DECL_PENDING_INLINE_INFO (method));
struct pending_inline *info = DECL_PENDING_INLINE_INFO (method);
if (info)
{
tree args;
my_friendly_assert (info->fndecl == method, 238);
args = DECL_ARGUMENTS (method);
while (args)
{
DECL_CONTEXT (args) = method;
args = TREE_CHAIN (args);
}
}
method = TREE_CHAIN (method);
}
while (friend_list)
{
tree fndecl = TREE_VALUE (friend_list);
struct pending_inline *info = DECL_PENDING_INLINE_INFO (fndecl);
if (info)
{
tree args;
my_friendly_assert (info->fndecl == fndecl, 239);
args = DECL_ARGUMENTS (fndecl);
while (args)
{
DECL_CONTEXT (args) = fndecl;
args = TREE_CHAIN (args);
}
}
friend_list = TREE_CHAIN (friend_list); /* Do friends. */
} for (; friend_list; friend_list = TREE_CHAIN (friend_list))
fixup_pending_inline (DECL_PENDING_INLINE_INFO (TREE_VALUE (friend_list)));
} }
/* Here is where overload code starts. */ /* Here is where overload code starts. */
......
...@@ -38,7 +38,6 @@ static void list_hash_add PROTO((int, tree)); ...@@ -38,7 +38,6 @@ static void list_hash_add PROTO((int, tree));
static int list_hash PROTO((tree, tree, tree)); static int list_hash PROTO((tree, tree, tree));
static tree list_hash_lookup PROTO((int, tree, tree, tree)); static tree list_hash_lookup PROTO((int, tree, tree, tree));
static void propagate_binfo_offsets PROTO((tree, tree)); static void propagate_binfo_offsets PROTO((tree, tree));
static int avoid_overlap PROTO((tree, tree));
static cp_lvalue_kind lvalue_p_1 PROTO((tree, int)); static cp_lvalue_kind lvalue_p_1 PROTO((tree, int));
static tree no_linkage_helper PROTO((tree *, int *, void *)); static tree no_linkage_helper PROTO((tree *, int *, void *));
static tree build_srcloc PROTO((char *, int)); static tree build_srcloc PROTO((char *, int));
...@@ -878,117 +877,6 @@ layout_basetypes (rec, max) ...@@ -878,117 +877,6 @@ layout_basetypes (rec, max)
return max; return max;
} }
/* If the empty base field in DECL overlaps with a base of the same type in
NEWDECL, which is either another base field or the first data field of
the class, pad the base just before NEWDECL and return 1. Otherwise,
return 0. */
static int
avoid_overlap (decl, newdecl)
tree decl, newdecl;
{
tree field;
if (newdecl == NULL_TREE
|| ! types_overlap_p (TREE_TYPE (decl), TREE_TYPE (newdecl)))
return 0;
for (field = decl; TREE_CHAIN (field) && TREE_CHAIN (field) != newdecl;
field = TREE_CHAIN (field))
;
DECL_SIZE (field) = integer_one_node;
return 1;
}
/* Returns a list of fields to stand in for the base class subobjects
of REC. These fields are later removed by layout_basetypes. */
tree
build_base_fields (rec)
tree rec;
{
/* Chain to hold all the new FIELD_DECLs which stand in for base class
subobjects. */
tree base_decls = NULL_TREE;
tree binfos = TYPE_BINFO_BASETYPES (rec);
int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
tree decl, nextdecl;
int i, saw_empty = 0;
unsigned int base_align = 0;
for (i = 0; i < n_baseclasses; ++i)
{
register tree base_binfo = TREE_VEC_ELT (binfos, i);
register tree basetype = BINFO_TYPE (base_binfo);
if (TYPE_SIZE (basetype) == 0)
/* This error is now reported in xref_tag, thus giving better
location information. */
continue;
if (TREE_VIA_VIRTUAL (base_binfo))
continue;
decl = build_lang_decl (FIELD_DECL, NULL_TREE, basetype);
DECL_ARTIFICIAL (decl) = 1;
DECL_FIELD_CONTEXT (decl) = DECL_CLASS_CONTEXT (decl) = rec;
DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
TREE_CHAIN (decl) = base_decls;
base_decls = decl;
if (! flag_new_abi)
{
/* Brain damage for backwards compatibility. For no good reason,
the old layout_basetypes made every base at least as large as
the alignment for the bases up to that point, gratuitously
wasting space. So we do the same thing here. */
base_align = MAX (base_align, DECL_ALIGN (decl));
DECL_SIZE (decl)
= size_int (MAX (TREE_INT_CST_LOW (DECL_SIZE (decl)),
(int) base_align));
}
else if (DECL_SIZE (decl) == integer_zero_node)
saw_empty = 1;
}
/* Reverse the list of fields so we allocate the bases in the proper
order. */
base_decls = nreverse (base_decls);
/* In the presence of empty base classes, we run the risk of allocating
two objects of the same class on top of one another. Avoid that. */
if (flag_new_abi && saw_empty)
for (decl = base_decls; decl; decl = TREE_CHAIN (decl))
{
if (DECL_SIZE (decl) == integer_zero_node)
{
/* First step through the following bases until we find
an overlap or a non-empty base. */
for (nextdecl = TREE_CHAIN (decl); nextdecl;
nextdecl = TREE_CHAIN (nextdecl))
{
if (avoid_overlap (decl, nextdecl)
|| DECL_SIZE (nextdecl) != integer_zero_node)
goto nextbase;
}
/* If we're still looking, also check against the first
field. */
for (nextdecl = TYPE_FIELDS (rec);
nextdecl && TREE_CODE (nextdecl) != FIELD_DECL;
nextdecl = TREE_CHAIN (nextdecl))
/* keep looking */;
avoid_overlap (decl, nextdecl);
}
nextbase:;
}
return base_decls;
}
/* Hashing of lists so that we don't make duplicates. /* Hashing of lists so that we don't make duplicates.
The entry point is `list_hash_canon'. */ The entry point is `list_hash_canon'. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment