Commit 08b962b0 by Mark Mitchell Committed by Mark Mitchell

class.c (check_field_decls): Split out from ...

	* class.c (check_field_decls): Split out from ...
	(finish_struct_1): ... here.  Use it.  Tidy.

From-SVN: r30934
parent f4f1acad
1999-12-14 Mark Mitchell <mark@codesourcery.com>
* class.c (check_field_decls): Split out from ...
(finish_struct_1): ... here. Use it. Tidy.
* cp-tree.h (remap_save_expr): Add walk_subtrees parameter.
* optimize.c (copy_body_r): Pass it.
* tree.c (remap_save_expr): Clear walk_subtrees for an
......
......@@ -123,6 +123,8 @@ static int count_fields PROTO((tree));
static int add_fields_to_vec PROTO((tree, tree, int));
static void check_bitfield_decl PROTO((tree));
static void check_field_decl PROTO((tree, tree, int *, int *, int *, int *));
static tree* check_field_decls PROTO((tree, tree *, int *, int *, int *,
int *));
/* Variables shared between class.c and call.c. */
......@@ -3339,202 +3341,94 @@ check_field_decl (field, t, cant_have_const_ctor,
: TYPE_ALIGN (TREE_TYPE (field))));
};
/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
(or C++ class declaration).
For C++, we must handle the building of derived classes.
Also, C++ allows static class members. The way that this is
handled is to keep the field name where it is (as the DECL_NAME
of the field), and place the overloaded decl in the DECL_FIELD_BITPOS
of the field. layout_record and layout_union will know about this.
More C++ hair: inline functions have text in their
DECL_PENDING_INLINE_INFO nodes which must somehow be parsed into
meaningful tree structure. After the struct has been laid out, set
things up so that this can happen.
And still more: virtual functions. In the case of single inheritance,
when a new virtual function is seen which redefines a virtual function
from the base class, the new virtual function is placed into
the virtual function table at exactly the same address that
it had in the base class. When this is extended to multiple
inheritance, the same thing happens, except that multiple virtual
function tables must be maintained. The first virtual function
table is treated in exactly the same way as in the case of single
inheritance. Additional virtual function tables have different
DELTAs, which tell how to adjust `this' to point to the right thing.
ATTRIBUTES is the set of decl attributes to be applied, if any. */
void
finish_struct_1 (t)
tree t;
{
tree fields = TYPE_FIELDS (t);
tree x, last_x, method_vec;
int has_virtual;
int max_has_virtual;
tree pending_virtuals = NULL_TREE;
tree pending_hard_virtuals = NULL_TREE;
tree abstract_virtuals = NULL_TREE;
tree vfield;
tree vfields;
tree virtual_dtor;
int cant_have_default_ctor;
int cant_have_const_ctor;
int no_const_asn_ref;
int has_mutable = 0;
int n_fields = 0;
int non_pod_class = 0;
/* The index of the first base class which has virtual
functions. Only applied to non-virtual baseclasses. */
int first_vfn_base_index;
/* Check the data members (both static and non-static), class-scoped
typedefs, etc., appearing in the declaration of T. Issue
appropriate diagnostics. Sets ACCESS_DECLS to a list (in
declaration order) of access declarations; each TREE_VALUE in this
list is a USING_DECL.
int n_baseclasses;
int any_default_members = 0;
int const_sans_init = 0;
int ref_sans_init = 0;
tree access_decls = NULL_TREE;
int aggregate = 1;
int empty = 1;
int has_pointers = 0;
tree inline_friends;
if (TYPE_SIZE (t))
{
if (IS_AGGR_TYPE (t))
cp_error ("redefinition of `%#T'", t);
else
my_friendly_abort (172);
popclass ();
return;
}
In addition, set the following flags:
GNU_xref_decl (current_function_decl, t);
EMPTY_P
The class is empty, i.e., contains no non-static data members.
/* If this type was previously laid out as a forward reference,
make sure we lay it out again. */
CANT_HAVE_DEFAULT_CTOR_P
This class cannot have an implicitly generated default
constructor.
TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0;
CANT_HAVE_CONST_CTOR_P
This class cannot have an implicitly generated copy constructor
taking a const reference.
/* Install struct as DECL_FIELD_CONTEXT of each field decl.
Also process specified field sizes.
Set DECL_FIELD_SIZE to the specified size, or 0 if none specified.
The specified size is found in the DECL_INITIAL.
Store 0 there, except for ": 0" fields (so we can find them
and delete them, below). */
CANT_HAVE_CONST_ASN_REF
This class cannot have an implicitly generated assignment
operator taking a const reference.
if (TYPE_BINFO_BASETYPES (t))
n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (t));
else
n_baseclasses = 0;
All of these flags should be initialized before calling this
function.
if (n_baseclasses > 0)
{
struct base_info base_info;
Returns a pointer to the end of the TYPE_FIELDs chain; additional
fields can be added by adding to this chain. */
first_vfn_base_index = finish_base_struct (t, &base_info);
/* Remember where we got our vfield from. */
CLASSTYPE_VFIELD_PARENT (t) = first_vfn_base_index;
has_virtual = base_info.has_virtual;
max_has_virtual = base_info.max_has_virtual;
vfield = base_info.vfield;
vfields = base_info.vfields;
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 = has_virtual;
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;
}
/* The three of these are approximations which may later be
modified. Needed at this point to make add_virtual_function
and modify_vtable_entries work. */
CLASSTYPE_VFIELDS (t) = vfields;
TYPE_VFIELD (t) = vfield;
static tree*
check_field_decls (t, access_decls, empty_p,
cant_have_default_ctor_p, cant_have_const_ctor_p,
no_const_asn_ref_p)
tree t;
tree *access_decls;
int *empty_p;
int *cant_have_default_ctor_p;
int *cant_have_const_ctor_p;
int *no_const_asn_ref_p;
{
tree *field;
tree *next;
int has_pointers;
int any_default_members;
/* Assume there are no access declarations. */
*access_decls = NULL_TREE;
/* Assume this class has no pointer members. */
has_pointers = 0;
/* Assume none of the members of this class have default
initializations. */
any_default_members = 0;
for (field = &TYPE_FIELDS (t); *field; field = next)
{
tree x = *field;
tree type = TREE_TYPE (x);
for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
{
GNU_xref_member (current_class_name, x);
/* If this was an evil function, don't keep it in class. */
if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
continue;
/* Do both of these, even though they're in the same union;
if the insn `r' member and the size `i' member are
different sizes, as on the alpha, the larger of the two
will end up with garbage in it. */
DECL_SAVED_INSNS (x) = 0;
DECL_FIELD_SIZE (x) = 0;
check_for_override (x, t);
if (DECL_ABSTRACT_VIRTUAL_P (x) && ! DECL_VINDEX (x))
cp_error_at ("initializer specified for non-virtual method `%D'", x);
/* The name of the field is the original field name
Save this in auxiliary field for later overloading. */
if (DECL_VINDEX (x))
{
add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
&has_virtual, x, t);
if (DECL_ABSTRACT_VIRTUAL_P (x))
abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals);
#if 0
/* XXX Why did I comment this out? (jason) */
else
TREE_USED (x) = 1;
#endif
}
}
if (n_baseclasses)
fields = chainon (build_vbase_pointer_fields (t), fields);
last_x = NULL_TREE;
for (x = fields; x; x = TREE_CHAIN (x))
{
tree type = TREE_TYPE (x);
GNU_xref_member (current_class_name, x);
next = &TREE_CHAIN (x);
if (TREE_CODE (x) == FIELD_DECL)
{
DECL_PACKED (x) |= TYPE_PACKED (t);
if (DECL_C_BIT_FIELD (x) && integer_zerop (DECL_INITIAL (x)))
/* A zero-width bitfield doesn't do the trick. */;
/* We don't treat zero-width bitfields as making a class
non-empty. */
;
else
empty = 0;
*empty_p = 0;
}
if (TREE_CODE (x) == USING_DECL)
{
/* Save access declarations for later. */
if (last_x)
TREE_CHAIN (last_x) = TREE_CHAIN (x);
else
fields = TREE_CHAIN (x);
access_decls = tree_cons (NULL_TREE, x, access_decls);
/* Prune the access declaration from the list of fields. */
*field = TREE_CHAIN (x);
/* Save the access declarations for our caller. */
*access_decls = tree_cons (NULL_TREE, x, *access_decls);
/* Since we've reset *FIELD there's no reason to skip to the
next field. */
next = field;
continue;
}
last_x = x;
if (TREE_CODE (x) == TYPE_DECL
|| TREE_CODE (x) == TEMPLATE_DECL)
continue;
......@@ -3570,11 +3464,6 @@ finish_struct_1 (t)
TREE_TYPE (x) = type;
}
#if 0
if (DECL_NAME (x) == constructor_name (t))
cant_have_default_ctor = 1;
#endif
if (type == error_mark_node)
continue;
......@@ -3599,22 +3488,21 @@ finish_struct_1 (t)
/* Now it can only be a FIELD_DECL. */
if (TREE_PRIVATE (x) || TREE_PROTECTED (x))
aggregate = 0;
CLASSTYPE_NON_AGGREGATE (t) = 1;
/* If this is of reference type, check if it needs an init.
Also do a little ANSI jig if necessary. */
if (TREE_CODE (type) == REFERENCE_TYPE)
{
non_pod_class = 1;
CLASSTYPE_NON_POD_P (t) = 1;
if (DECL_INITIAL (x) == NULL_TREE)
ref_sans_init = 1;
CLASSTYPE_REF_FIELDS_NEED_INIT (t) = 1;
/* ARM $12.6.2: [A member initializer list] (or, for an
aggregate, initialization by a brace-enclosed list) is the
only way to initialize nonstatic const and reference
members. */
cant_have_default_ctor = 1;
*cant_have_default_ctor_p = 1;
TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
......@@ -3632,26 +3520,26 @@ finish_struct_1 (t)
has_pointers = 1;
if (DECL_MUTABLE_P (x) || TYPE_HAS_MUTABLE_P (type))
has_mutable = 1;
CLASSTYPE_HAS_MUTABLE (t) = 1;
if (! pod_type_p (type)
/* For some reason, pointers to members are POD types themselves,
but are not allowed in POD structs. Silly. */
|| TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type))
non_pod_class = 1;
CLASSTYPE_NON_POD_P (t) = 1;
/* If any field is const, the structure type is pseudo-const. */
if (CP_TYPE_CONST_P (type))
{
C_TYPE_FIELDS_READONLY (t) = 1;
if (DECL_INITIAL (x) == NULL_TREE)
const_sans_init = 1;
CLASSTYPE_READONLY_FIELDS_NEED_INIT (t) = 1;
/* ARM $12.6.2: [A member initializer list] (or, for an
aggregate, initialization by a brace-enclosed list) is the
only way to initialize nonstatic const and reference
members. */
cant_have_default_ctor = 1;
*cant_have_default_ctor_p = 1;
TYPE_HAS_COMPLEX_ASSIGN_REF (t) = 1;
if (! TYPE_HAS_CONSTRUCTOR (t) && extra_warnings)
......@@ -3662,17 +3550,12 @@ finish_struct_1 (t)
cp_warning_at ("non-static const member in class without a constructor", x);
}
}
else
/* A field that is pseudo-const makes the structure likewise. */
else if (IS_AGGR_TYPE (type))
{
/* A field that is pseudo-const makes the structure
likewise. */
if (IS_AGGR_TYPE (type))
{
if (C_TYPE_FIELDS_READONLY (type))
C_TYPE_FIELDS_READONLY (t) = 1;
if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (type))
const_sans_init = 1;
}
C_TYPE_FIELDS_READONLY (t) |= C_TYPE_FIELDS_READONLY (type);
CLASSTYPE_READONLY_FIELDS_NEED_INIT (t)
|= CLASSTYPE_READONLY_FIELDS_NEED_INIT (type);
}
/* We set DECL_C_BIT_FIELD in grokbitfield.
......@@ -3681,21 +3564,12 @@ finish_struct_1 (t)
check_bitfield_decl (x);
else
check_field_decl (x, t,
&cant_have_const_ctor,
&cant_have_default_ctor,
&no_const_asn_ref,
cant_have_const_ctor_p,
cant_have_default_ctor_p,
no_const_asn_ref_p,
&any_default_members);
}
/* If this type has any constant members which did not come
with their own initialization, mark that fact here. It is
not an error here, since such types can be saved either by their
constructors, or by fortuitous initialization. */
CLASSTYPE_READONLY_FIELDS_NEED_INIT (t) = const_sans_init;
CLASSTYPE_REF_FIELDS_NEED_INIT (t) = ref_sans_init;
CLASSTYPE_ABSTRACT_VIRTUALS (t) = abstract_virtuals;
CLASSTYPE_HAS_MUTABLE (t) = has_mutable;
/* Effective C++ rule 11. */
if (has_pointers && warn_ecpp && TYPE_HAS_CONSTRUCTOR (t)
&& ! (TYPE_HAS_INIT_REF (t) && TYPE_HAS_ASSIGN_REF (t)))
......@@ -3711,20 +3585,205 @@ finish_struct_1 (t)
else if (! TYPE_HAS_ASSIGN_REF (t))
cp_warning (" but does not override `operator=(const %T&)'", t);
}
/* We've built up the list of access declarations in reverse order.
Fix that now. */
*access_decls = nreverse (*access_decls);
/* Return the last field. */
return field;
}
/* Create a RECORD_TYPE or UNION_TYPE node for a C struct or union declaration
(or C++ class declaration).
For C++, we must handle the building of derived classes.
Also, C++ allows static class members. The way that this is
handled is to keep the field name where it is (as the DECL_NAME
of the field), and place the overloaded decl in the DECL_FIELD_BITPOS
of the field. layout_record and layout_union will know about this.
More C++ hair: inline functions have text in their
DECL_PENDING_INLINE_INFO nodes which must somehow be parsed into
meaningful tree structure. After the struct has been laid out, set
things up so that this can happen.
And still more: virtual functions. In the case of single inheritance,
when a new virtual function is seen which redefines a virtual function
from the base class, the new virtual function is placed into
the virtual function table at exactly the same address that
it had in the base class. When this is extended to multiple
inheritance, the same thing happens, except that multiple virtual
function tables must be maintained. The first virtual function
table is treated in exactly the same way as in the case of single
inheritance. Additional virtual function tables have different
DELTAs, which tell how to adjust `this' to point to the right thing.
ATTRIBUTES is the set of decl attributes to be applied, if any. */
void
finish_struct_1 (t)
tree t;
{
tree fields;
tree x, method_vec;
tree *next_field;
int has_virtual;
int max_has_virtual;
tree pending_virtuals = NULL_TREE;
tree pending_hard_virtuals = NULL_TREE;
tree abstract_virtuals = NULL_TREE;
tree vfield;
tree vfields;
tree virtual_dtor;
int cant_have_default_ctor;
int cant_have_const_ctor;
int no_const_asn_ref;
int n_fields = 0;
/* The index of the first base class which has virtual
functions. Only applied to non-virtual baseclasses. */
int first_vfn_base_index;
int n_baseclasses;
int const_sans_init = 0;
tree access_decls;
int aggregate = 1;
int empty = 1;
tree inline_friends;
if (TYPE_SIZE (t))
{
if (IS_AGGR_TYPE (t))
cp_error ("redefinition of `%#T'", t);
else
my_friendly_abort (172);
popclass ();
return;
}
GNU_xref_decl (current_function_decl, t);
/* If this type was previously laid out as a forward reference,
make sure we lay it out again. */
TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0;
/* Install struct as DECL_FIELD_CONTEXT of each field decl.
Also process specified field sizes.
Set DECL_FIELD_SIZE to the specified size, or 0 if none specified.
The specified size is found in the DECL_INITIAL.
Store 0 there, except for ": 0" fields (so we can find them
and delete them, below). */
if (TYPE_BINFO_BASETYPES (t))
n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (t));
else
n_baseclasses = 0;
if (n_baseclasses > 0)
{
struct base_info base_info;
first_vfn_base_index = finish_base_struct (t, &base_info);
/* Remember where we got our vfield from. */
CLASSTYPE_VFIELD_PARENT (t) = first_vfn_base_index;
has_virtual = base_info.has_virtual;
max_has_virtual = base_info.max_has_virtual;
vfield = base_info.vfield;
vfields = base_info.vfields;
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 = has_virtual;
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;
}
/* The three of these are approximations which may later be
modified. Needed at this point to make add_virtual_function
and modify_vtable_entries work. */
CLASSTYPE_VFIELDS (t) = vfields;
TYPE_VFIELD (t) = vfield;
for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
{
GNU_xref_member (current_class_name, x);
/* If this was an evil function, don't keep it in class. */
if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x)))
continue;
/* Do both of these, even though they're in the same union;
if the insn `r' member and the size `i' member are
different sizes, as on the alpha, the larger of the two
will end up with garbage in it. */
DECL_SAVED_INSNS (x) = 0;
DECL_FIELD_SIZE (x) = 0;
check_for_override (x, t);
if (DECL_ABSTRACT_VIRTUAL_P (x) && ! DECL_VINDEX (x))
cp_error_at ("initializer specified for non-virtual method `%D'", x);
/* The name of the field is the original field name
Save this in auxiliary field for later overloading. */
if (DECL_VINDEX (x))
{
add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
&has_virtual, x, t);
if (DECL_ABSTRACT_VIRTUAL_P (x))
abstract_virtuals = tree_cons (NULL_TREE, x, abstract_virtuals);
#if 0
/* XXX Why did I comment this out? (jason) */
else
TREE_USED (x) = 1;
#endif
}
}
if (n_baseclasses)
TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (t),
TYPE_FIELDS (t));
/* Check all the data member declarations for legality. */
next_field = check_field_decls (t, &access_decls, &empty,
&cant_have_default_ctor,
&cant_have_const_ctor,
&no_const_asn_ref);
fields = TYPE_FIELDS (t);
/* If this type has any constant members which did not come
with their own initialization, mark that fact here. It is
not an error here, since such types can be saved either by their
constructors, or by fortuitous initialization. */
CLASSTYPE_READONLY_FIELDS_NEED_INIT (t) = const_sans_init;
CLASSTYPE_ABSTRACT_VIRTUALS (t) = abstract_virtuals;
/* 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)
|| has_virtual || any_default_members);
|| has_virtual);
TYPE_NEEDS_CONSTRUCTING (t)
|= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t)
|| has_virtual || any_default_members);
|| has_virtual);
CLASSTYPE_NON_AGGREGATE (t)
= ! aggregate || has_virtual || TYPE_HAS_CONSTRUCTOR (t);
CLASSTYPE_NON_POD_P (t)
= non_pod_class || CLASSTYPE_NON_AGGREGATE (t)
|| TYPE_HAS_DESTRUCTOR (t) || TYPE_HAS_ASSIGN_REF (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);
......@@ -3754,9 +3813,12 @@ finish_struct_1 (t)
TYPE_HAS_DESTRUCTOR (t) = 0;
}
for (access_decls = nreverse (access_decls); access_decls;
access_decls = TREE_CHAIN (access_decls))
handle_using_decl (TREE_VALUE (access_decls), t, method_vec, fields);
/* Process the access-declarations. */
while (access_decls)
{
handle_using_decl (TREE_VALUE (access_decls), t, method_vec, fields);
access_decls = TREE_CHAIN (access_decls);
}
if (vfield == NULL_TREE && has_virtual)
{
......@@ -3794,23 +3856,7 @@ finish_struct_1 (t)
DECL_SAVED_INSNS (vfield) = 0;
DECL_FIELD_SIZE (vfield) = 0;
DECL_ALIGN (vfield) = TYPE_ALIGN (ptr_type_node);
#if 0
/* This is more efficient, but breaks binary compatibility, turn
it on sometime when we don't care. If we turn it on, we also
have to enable the code in dfs_init_vbase_pointers. */
/* vfield is always first entry in structure. */
TREE_CHAIN (vfield) = fields;
fields = vfield;
#else
if (last_x)
{
my_friendly_assert (TREE_CHAIN (last_x) == NULL_TREE, 175);
TREE_CHAIN (last_x) = vfield;
last_x = vfield;
}
else
fields = vfield;
#endif
*next_field = vfield;
empty = 0;
vfields = chainon (vfields, build_tree_list (NULL_TREE, t));
}
......@@ -3829,10 +3875,10 @@ finish_struct_1 (t)
if (n_baseclasses)
{
last_x = build_base_fields (t);
TYPE_FIELDS (t) = chainon (build_base_fields (t), TYPE_FIELDS (t));
/* If all our bases are empty, we can be empty too. */
for (x = last_x; empty && x; x = TREE_CHAIN (x))
for (x = TYPE_FIELDS (t); empty && x != fields; x = TREE_CHAIN (x))
if (DECL_SIZE (x) != integer_zero_node)
empty = 0;
}
......@@ -3855,9 +3901,6 @@ finish_struct_1 (t)
TREE_STATIC (TYPE_NONCOPIED_PARTS (t)) = 1;
}
if (n_baseclasses)
TYPE_FIELDS (t) = chainon (last_x, TYPE_FIELDS (t));
layout_type (t);
/* Remember the size and alignment of the class before adding
......@@ -4180,8 +4223,6 @@ finish_struct_1 (t)
/* Finish debugging output for this type. */
rest_of_type_compilation (t, toplevel_bindings_p ());
return;
}
/* When T was built up, the member declarations were added in reverse
......
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