Commit 58010b57 by Mark Mitchell Committed by Mark Mitchell

class.c (handle_using_decl): Get TYPE_FIELDS and TYPE_METHODS out of the class...

	* class.c (handle_using_decl): Get TYPE_FIELDS and TYPE_METHODS
	out of the class, rather than taking them as parameters.
	(build_vbase_pointer_fields): Move here from tree.c.
	(build_vtbl_or_vbase_field): New function.
	(check_methods): Likewise.
	(remove_zero_width_bitfields): Likewise.
	(add_virtual_function): Use tree_cons instead of temp_tree_cons.
	(delete_duplicate_fields_1): Tidy.  Don't delete duplicate
	USING_DECLs here.
	(finish_struct_methods): Handle the case where there are no
	methods here.
	(get_basefndecls): Use tree_cons instead of temp_tree_cons.
	(check_field_decls): Call delete_duplicate_fields here.
	(finish_struct_1): Tidy.  Use check_methods and
	remove_zero_width_bitfields.
	* cp-tree.h (build_vbase_pointer_fields): Remove.
	* decl.c (grokdeclarator): Use tree_cons instead of
	temp_tree_cons.
	* decl2.c (qualified_lookup_using_namespace): Use tree_cons
	instead of temp_tree_cons.
	* lex.c (cons_up_default_function): Remove dead code.
	* method.c (fixup_pending_inline): New function, split out from	...
	(do_inline_function_hair): ... here.
	* tree.c (build_vbase_pointer_fields): Remove.

From-SVN: r30966
parent 5afb79e7
1999-12-15 Mark Mitchell <mark@codesourcery.com>
* class.c (handle_using_decl): Get TYPE_FIELDS and TYPE_METHODS
out of the class, rather than taking them as parameters.
(build_vbase_pointer_fields): Move here from tree.c.
(build_vtbl_or_vbase_field): New function.
(check_methods): Likewise.
(remove_zero_width_bitfields): Likewise.
(add_virtual_function): Use tree_cons instead of temp_tree_cons.
(delete_duplicate_fields_1): Tidy. Don't delete duplicate
USING_DECLs here.
(finish_struct_methods): Handle the case where there are no
methods here.
(get_basefndecls): Use tree_cons instead of temp_tree_cons.
(check_field_decls): Call delete_duplicate_fields here.
(finish_struct_1): Tidy. Use check_methods and
remove_zero_width_bitfields.
* cp-tree.h (build_vbase_pointer_fields): Remove.
* decl.c (grokdeclarator): Use tree_cons instead of
temp_tree_cons.
* decl2.c (qualified_lookup_using_namespace): Use tree_cons
instead of temp_tree_cons.
* lex.c (cons_up_default_function): Remove dead code.
* method.c (fixup_pending_inline): New function, split out from ...
(do_inline_function_hair): ... here.
* tree.c (build_vbase_pointer_fields): Remove.
1999-12-15 Jason Merrill <jason@casey.cygnus.com> 1999-12-15 Jason Merrill <jason@casey.cygnus.com>
* tree.c (walk_tree): Walk operand subtrees in forward order. * tree.c (walk_tree): Walk operand subtrees in forward order.
......
...@@ -94,7 +94,7 @@ static tree delete_duplicate_fields_1 PROTO((tree, tree)); ...@@ -94,7 +94,7 @@ static tree delete_duplicate_fields_1 PROTO((tree, tree));
static void delete_duplicate_fields PROTO((tree)); static void delete_duplicate_fields PROTO((tree));
static void finish_struct_bits PROTO((tree, int)); static void finish_struct_bits PROTO((tree, int));
static int alter_access PROTO((tree, tree, tree, tree)); static int alter_access PROTO((tree, tree, tree, tree));
static void handle_using_decl PROTO((tree, tree, tree, tree)); static void handle_using_decl PROTO((tree, tree));
static int overrides PROTO((tree, tree)); static int overrides PROTO((tree, tree));
static int strictly_overrides PROTO((tree, tree)); static int strictly_overrides PROTO((tree, tree));
static void merge_overrides PROTO((tree, tree, int, tree)); static void merge_overrides PROTO((tree, tree, int, tree));
...@@ -125,6 +125,10 @@ static void check_bitfield_decl PROTO((tree)); ...@@ -125,6 +125,10 @@ 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 tree* check_field_decls PROTO((tree, tree *, int *, int *, int *,
int *)); int *));
static tree build_vbase_pointer_fields PROTO((tree, int *));
static tree build_vtbl_or_vbase_field PROTO((tree, tree, tree, tree, int *));
static void check_methods PROTO((tree));
static void remove_zero_width_bit_fields PROTO((tree));
/* Variables shared between class.c and call.c. */ /* Variables shared between class.c and call.c. */
...@@ -1049,9 +1053,9 @@ add_virtual_function (pv, phv, has_virtual, fndecl, t) ...@@ -1049,9 +1053,9 @@ add_virtual_function (pv, phv, has_virtual, fndecl, t)
{ {
/* Need an entry in some other virtual function table. /* Need an entry in some other virtual function table.
Deal with this after we have laid out our virtual base classes. */ Deal with this after we have laid out our virtual base classes. */
pending_hard_virtuals = temp_tree_cons (NULL_TREE, pending_hard_virtuals = tree_cons (NULL_TREE,
fndecl, fndecl,
pending_hard_virtuals); pending_hard_virtuals);
} }
*pv = pending_virtuals; *pv = pending_virtuals;
*phv = pending_hard_virtuals; *phv = pending_hard_virtuals;
...@@ -1289,43 +1293,46 @@ delete_duplicate_fields_1 (field, fields) ...@@ -1289,43 +1293,46 @@ delete_duplicate_fields_1 (field, fields)
TREE_CHAIN (prev) = TREE_CHAIN (x); TREE_CHAIN (prev) = TREE_CHAIN (x);
} }
} }
else else if (TREE_CODE (field) == USING_DECL)
/* A using declaration may is allowed to appear more than
once. We'll prune these from the field list later, and
handle_using_decl will complain about invalid multiple
uses. */
;
else if (DECL_NAME (field) == DECL_NAME (x))
{ {
if (DECL_NAME (field) == DECL_NAME (x)) if (TREE_CODE (field) == CONST_DECL
&& TREE_CODE (x) == CONST_DECL)
cp_error_at ("duplicate enum value `%D'", x);
else if (TREE_CODE (field) == CONST_DECL
|| TREE_CODE (x) == CONST_DECL)
cp_error_at ("duplicate field `%D' (as enum and non-enum)",
x);
else if (DECL_DECLARES_TYPE_P (field)
&& DECL_DECLARES_TYPE_P (x))
{ {
if (TREE_CODE (field) == CONST_DECL if (same_type_p (TREE_TYPE (field), TREE_TYPE (x)))
&& TREE_CODE (x) == CONST_DECL) continue;
cp_error_at ("duplicate enum value `%D'", x); cp_error_at ("duplicate nested type `%D'", x);
else if (TREE_CODE (field) == CONST_DECL
|| TREE_CODE (x) == CONST_DECL)
cp_error_at ("duplicate field `%D' (as enum and non-enum)",
x);
else if (DECL_DECLARES_TYPE_P (field)
&& DECL_DECLARES_TYPE_P (x))
{
if (same_type_p (TREE_TYPE (field), TREE_TYPE (x)))
continue;
cp_error_at ("duplicate nested type `%D'", x);
}
else if (DECL_DECLARES_TYPE_P (field)
|| DECL_DECLARES_TYPE_P (x))
{
/* Hide tag decls. */
if ((TREE_CODE (field) == TYPE_DECL
&& DECL_ARTIFICIAL (field))
|| (TREE_CODE (x) == TYPE_DECL
&& DECL_ARTIFICIAL (x)))
continue;
cp_error_at ("duplicate field `%D' (as type and non-type)",
x);
}
else
cp_error_at ("duplicate member `%D'", x);
if (prev == 0)
fields = TREE_CHAIN (fields);
else
TREE_CHAIN (prev) = TREE_CHAIN (x);
} }
else if (DECL_DECLARES_TYPE_P (field)
|| DECL_DECLARES_TYPE_P (x))
{
/* Hide tag decls. */
if ((TREE_CODE (field) == TYPE_DECL
&& DECL_ARTIFICIAL (field))
|| (TREE_CODE (x) == TYPE_DECL
&& DECL_ARTIFICIAL (x)))
continue;
cp_error_at ("duplicate field `%D' (as type and non-type)",
x);
}
else
cp_error_at ("duplicate member `%D'", x);
if (prev == 0)
fields = TREE_CHAIN (fields);
else
TREE_CHAIN (prev) = TREE_CHAIN (x);
} }
} }
} }
...@@ -1379,15 +1386,12 @@ alter_access (t, binfo, fdecl, access) ...@@ -1379,15 +1386,12 @@ alter_access (t, binfo, fdecl, access)
return 0; return 0;
} }
/* Process the USING_DECL, which is a member of T. The METHOD_VEC, if /* Process the USING_DECL, which is a member of T. */
non-NULL, is the methods of T. The FIELDS are the fields of T. */
static void static void
handle_using_decl (using_decl, t, method_vec, fields) handle_using_decl (using_decl, t)
tree using_decl; tree using_decl;
tree t; tree t;
tree method_vec;
tree fields;
{ {
tree ctype = DECL_INITIAL (using_decl); tree ctype = DECL_INITIAL (using_decl);
tree name = DECL_NAME (using_decl); tree name = DECL_NAME (using_decl);
...@@ -1397,6 +1401,8 @@ handle_using_decl (using_decl, t, method_vec, fields) ...@@ -1397,6 +1401,8 @@ handle_using_decl (using_decl, t, method_vec, fields)
: access_public_node; : access_public_node;
tree fdecl, binfo; tree fdecl, binfo;
tree flist = NULL_TREE; tree flist = NULL_TREE;
tree fields = TYPE_FIELDS (t);
tree method_vec = CLASSTYPE_METHOD_VEC (t);
tree tmp; tree tmp;
int i; int i;
int n_methods; int n_methods;
...@@ -1989,9 +1995,23 @@ finish_struct_methods (t) ...@@ -1989,9 +1995,23 @@ finish_struct_methods (t)
tree t; tree t;
{ {
tree fn_fields; tree fn_fields;
tree method_vec = CLASSTYPE_METHOD_VEC (t); tree method_vec;
tree ctor_name = constructor_name (t); tree ctor_name = constructor_name (t);
int slot, len = method_vec ? TREE_VEC_LENGTH (method_vec) : 0; int slot, len;
if (!TYPE_METHODS (t))
{
/* Clear these for safety; perhaps some parsing error could set
these incorrectly. */
TYPE_HAS_CONSTRUCTOR (t) = 0;
TYPE_HAS_DESTRUCTOR (t) = 0;
CLASSTYPE_METHOD_VEC (t) = NULL_TREE;
return;
}
my_friendly_assert (method_vec != NULL_TREE, 19991215);
method_vec = CLASSTYPE_METHOD_VEC (t);
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,
and the next few with type conversion operators (if any). */ and the next few with type conversion operators (if any). */
...@@ -2051,9 +2071,6 @@ finish_struct_methods (t) ...@@ -2051,9 +2071,6 @@ finish_struct_methods (t)
no methods, then some public defaults are generated. */ no methods, then some public defaults are generated. */
maybe_warn_about_overly_private_class (t); maybe_warn_about_overly_private_class (t);
if (method_vec == NULL_TREE)
return;
/* Now sort the methods. */ /* Now sort the methods. */
while (len > 2 && TREE_VEC_ELT (method_vec, len-1) == NULL_TREE) while (len > 2 && TREE_VEC_ELT (method_vec, len-1) == NULL_TREE)
len--; len--;
...@@ -2812,7 +2829,7 @@ get_basefndecls (fndecl, t) ...@@ -2812,7 +2829,7 @@ get_basefndecls (fndecl, t)
if (TREE_CODE (methods) == FUNCTION_DECL if (TREE_CODE (methods) == FUNCTION_DECL
&& DECL_VINDEX (methods) != NULL_TREE && DECL_VINDEX (methods) != NULL_TREE
&& DECL_NAME (fndecl) == DECL_NAME (methods)) && DECL_NAME (fndecl) == DECL_NAME (methods))
base_fndecls = temp_tree_cons (fndecl, methods, base_fndecls); base_fndecls = tree_cons (fndecl, methods, base_fndecls);
methods = TREE_CHAIN (methods); methods = TREE_CHAIN (methods);
} }
...@@ -3386,6 +3403,9 @@ check_field_decls (t, access_decls, empty_p, ...@@ -3386,6 +3403,9 @@ check_field_decls (t, access_decls, empty_p,
int has_pointers; int has_pointers;
int any_default_members; int any_default_members;
/* First, delete any duplicate fields. */
delete_duplicate_fields (TYPE_FIELDS (t));
/* Assume there are no access declarations. */ /* Assume there are no access declarations. */
*access_decls = NULL_TREE; *access_decls = NULL_TREE;
/* Assume this class has no pointer members. */ /* Assume this class has no pointer members. */
...@@ -3594,6 +3614,192 @@ check_field_decls (t, access_decls, empty_p, ...@@ -3594,6 +3614,192 @@ check_field_decls (t, access_decls, empty_p,
return field; return field;
} }
/* Return a FIELD_DECL for a pointer-to-virtual-table or
pointer-to-virtual-base. The NAME, ASSEMBLER_NAME, and TYPE of the
field are as indicated. The CLASS_TYPE in which this field occurs
is also indicated. *EMPTY_P is set to a non-zero value by this
function to indicate that a class containing this field is
non-empty. */
static tree
build_vtbl_or_vbase_field (name, assembler_name, type, class_type,
empty_p)
tree name;
tree assembler_name;
tree type;
tree class_type;
int *empty_p;
{
tree field;
/* This class is non-empty. */
*empty_p = 0;
/* Build the FIELD_DECL. */
field = build_lang_decl (FIELD_DECL, name, type);
DECL_ASSEMBLER_NAME (field) = assembler_name;
DECL_VIRTUAL_P (field) = 1;
DECL_ARTIFICIAL (field) = 1;
DECL_FIELD_CONTEXT (field) = class_type;
DECL_CLASS_CONTEXT (field) = class_type;
DECL_FCONTEXT (field) = class_type;
DECL_SAVED_INSNS (field) = 0;
DECL_FIELD_SIZE (field) = 0;
DECL_ALIGN (field) = TYPE_ALIGN (type);
/* Return it. */
return field;
}
/* Returns list of virtual base class pointers in a FIELD_DECL chain. */
static tree
build_vbase_pointer_fields (rec, empty_p)
tree rec;
int *empty_p;
{
/* Chain to hold all the new FIELD_DECLs which point at virtual
base classes. */
tree vbase_decls = NULL_TREE;
tree binfos = TYPE_BINFO_BASETYPES (rec);
int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
tree decl;
int i;
/* Handle basetypes almost like fields, but record their
offsets differently. */
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;
/* All basetypes are recorded in the association list of the
derived type. */
if (TREE_VIA_VIRTUAL (base_binfo))
{
int j;
const char *name;
/* The offset for a virtual base class is only used in computing
virtual function tables and for initializing virtual base
pointers. It is built once `get_vbase_types' is called. */
/* If this basetype can come from another vbase pointer
without an additional indirection, we will share
that pointer. If an indirection is involved, we
make our own pointer. */
for (j = 0; j < n_baseclasses; j++)
{
tree other_base_binfo = TREE_VEC_ELT (binfos, j);
if (! TREE_VIA_VIRTUAL (other_base_binfo)
&& binfo_member (basetype,
CLASSTYPE_VBASECLASSES (BINFO_TYPE
(other_base_binfo))
))
goto got_it;
}
FORMAT_VBASE_NAME (name, basetype);
decl = build_vtbl_or_vbase_field (get_identifier (name),
get_identifier (VTABLE_BASE),
build_pointer_type (basetype),
rec,
empty_p);
BINFO_VPTR_FIELD (base_binfo) = decl;
TREE_CHAIN (decl) = vbase_decls;
vbase_decls = decl;
*empty_p = 0;
got_it:
/* The space this decl occupies has already been accounted for. */
;
}
}
return vbase_decls;
}
/* Go through the TYPE_METHODS of T issuing any appropriate
diagnostics, figuring out which methods override which other
methods, and so forth. Returns non-zero if this class has any
virtual methods. */
static void
check_methods (t)
tree t;
{
tree x;
int has_virtual;
/* Assume there are no virtual methods. */
has_virtual = 0;
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))
{
has_virtual = 1;
if (DECL_ABSTRACT_VIRTUAL_P (x))
CLASSTYPE_ABSTRACT_VIRTUALS (t)
= tree_cons (NULL_TREE, x, CLASSTYPE_ABSTRACT_VIRTUALS (t));
}
}
/* A class with virtual functions needs constructing because, if
nothing else, the vtable pointer must be initialized. */
TYPE_HAS_COMPLEX_INIT_REF (t) |= has_virtual;
TYPE_NEEDS_CONSTRUCTING (t) |= has_virtual;
/* [dcl.init.aggr]
An aggregate is a ... class ... with ... no virtual functions. */
CLASSTYPE_NON_AGGREGATE (t) |= has_virtual;
}
/* Remove all zero-width bit-fields from T. */
static void
remove_zero_width_bit_fields (t)
tree t;
{
tree *fieldsp;
fieldsp = &TYPE_FIELDS (t);
while (*fieldsp)
{
if (TREE_CODE (*fieldsp) == FIELD_DECL
&& DECL_C_BIT_FIELD (*fieldsp)
&& DECL_INITIAL (*fieldsp))
*fieldsp = TREE_CHAIN (*fieldsp);
else
fieldsp = &TREE_CHAIN (*fieldsp);
}
}
/* 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).
...@@ -3626,13 +3832,12 @@ finish_struct_1 (t) ...@@ -3626,13 +3832,12 @@ finish_struct_1 (t)
tree t; tree t;
{ {
tree fields; tree fields;
tree x, method_vec; tree x;
tree *next_field; 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 abstract_virtuals = NULL_TREE;
tree vfield; tree vfield;
tree vfields; tree vfields;
tree virtual_dtor; tree virtual_dtor;
...@@ -3646,7 +3851,6 @@ finish_struct_1 (t) ...@@ -3646,7 +3851,6 @@ finish_struct_1 (t)
int first_vfn_base_index; int first_vfn_base_index;
int n_baseclasses; int n_baseclasses;
int const_sans_init = 0;
tree access_decls; tree access_decls;
int aggregate = 1; int aggregate = 1;
int empty = 1; int empty = 1;
...@@ -3670,17 +3874,7 @@ finish_struct_1 (t) ...@@ -3670,17 +3874,7 @@ finish_struct_1 (t)
TYPE_SIZE (t) = NULL_TREE; TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0; CLASSTYPE_GOT_SEMICOLON (t) = 0;
/* Install struct as DECL_FIELD_CONTEXT of each field decl. n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
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) if (n_baseclasses > 0)
{ {
...@@ -3692,7 +3886,9 @@ finish_struct_1 (t) ...@@ -3692,7 +3886,9 @@ finish_struct_1 (t)
has_virtual = base_info.has_virtual; has_virtual = base_info.has_virtual;
max_has_virtual = base_info.max_has_virtual; max_has_virtual = base_info.max_has_virtual;
vfield = base_info.vfield; vfield = base_info.vfield;
TYPE_VFIELD (t) = vfield;
vfields = base_info.vfields; vfields = base_info.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_default_ctor = base_info.cant_have_default_ctor;
cant_have_const_ctor = base_info.cant_have_const_ctor; cant_have_const_ctor = base_info.cant_have_const_ctor;
...@@ -3703,7 +3899,7 @@ finish_struct_1 (t) ...@@ -3703,7 +3899,7 @@ finish_struct_1 (t)
{ {
first_vfn_base_index = -1; first_vfn_base_index = -1;
has_virtual = 0; has_virtual = 0;
max_has_virtual = has_virtual; max_has_virtual = 0;
vfield = NULL_TREE; vfield = NULL_TREE;
vfields = NULL_TREE; vfields = NULL_TREE;
CLASSTYPE_RTTI (t) = NULL_TREE; CLASSTYPE_RTTI (t) = NULL_TREE;
...@@ -3712,75 +3908,42 @@ finish_struct_1 (t) ...@@ -3712,75 +3908,42 @@ finish_struct_1 (t)
no_const_asn_ref = 0; no_const_asn_ref = 0;
} }
/* The three of these are approximations which may later be /* Check all the data member declarations. */
modified. Needed at this point to make add_virtual_function next_field = check_field_decls (t, &access_decls, &empty,
and modify_vtable_entries work. */ &cant_have_default_ctor,
CLASSTYPE_VFIELDS (t) = vfields; &cant_have_const_ctor,
TYPE_VFIELD (t) = vfield; &no_const_asn_ref);
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. */ /* Add pointers to all of our virtual base-classes. */
if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (x))) if (n_baseclasses)
continue; TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (t, &empty),
TYPE_FIELDS (t));
/* Do both of these, even though they're in the same union; /* Build FIELD_DECLs for all of the non-virtual base-types. */
if the insn `r' member and the size `i' member are fields = TYPE_FIELDS (t);
different sizes, as on the alpha, the larger of the two if (n_baseclasses)
will end up with garbage in it. */ {
DECL_SAVED_INSNS (x) = 0; TYPE_FIELDS (t) = chainon (build_base_fields (t), TYPE_FIELDS (t));
DECL_FIELD_SIZE (x) = 0;
check_for_override (x, t); /* If any base is non-empty, then we are non-empty. */
if (DECL_ABSTRACT_VIRTUAL_P (x) && ! DECL_VINDEX (x)) for (x = TYPE_FIELDS (t); empty && x != fields; x = TREE_CHAIN (x))
cp_error_at ("initializer specified for non-virtual method `%D'", x); if (DECL_SIZE (x) != integer_zero_node)
empty = 0;
/* The name of the field is the original field name fields = TYPE_FIELDS (t);
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) /* Check all the method declarations. */
TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (t), check_methods (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 /* Do some bookkeeping that will guide the generation of implicitly
declared member functions. */ declared member functions. */
TYPE_HAS_COMPLEX_INIT_REF (t) TYPE_HAS_COMPLEX_INIT_REF (t)
|= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t) |= (TYPE_HAS_INIT_REF (t) || TYPE_USES_VIRTUAL_BASECLASSES (t));
|| has_virtual);
TYPE_NEEDS_CONSTRUCTING (t) TYPE_NEEDS_CONSTRUCTING (t)
|= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t) |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t));
|| has_virtual);
CLASSTYPE_NON_AGGREGATE (t) CLASSTYPE_NON_AGGREGATE (t)
= ! aggregate || has_virtual || TYPE_HAS_CONSTRUCTOR (t); = ! aggregate || TYPE_HAS_CONSTRUCTOR (t);
CLASSTYPE_NON_POD_P (t) CLASSTYPE_NON_POD_P (t)
|= (CLASSTYPE_NON_AGGREGATE (t) || TYPE_HAS_DESTRUCTOR (t) |= (CLASSTYPE_NON_AGGREGATE (t) || TYPE_HAS_DESTRUCTOR (t)
|| TYPE_HAS_ASSIGN_REF (t)); || TYPE_HAS_ASSIGN_REF (t));
...@@ -3794,29 +3957,21 @@ finish_struct_1 (t) ...@@ -3794,29 +3957,21 @@ finish_struct_1 (t)
= add_implicitly_declared_members (t, cant_have_default_ctor, = add_implicitly_declared_members (t, cant_have_default_ctor,
cant_have_const_ctor, cant_have_const_ctor,
no_const_asn_ref); no_const_asn_ref);
if (virtual_dtor)
add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
&has_virtual, virtual_dtor, t);
if (TYPE_METHODS (t)) /* Loop over the virtual functions, adding them to our various
{ vtables. */
finish_struct_methods (t); for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
method_vec = CLASSTYPE_METHOD_VEC (t); if (DECL_VINDEX (x))
} add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
else &has_virtual, x, t);
{
method_vec = 0;
/* Just in case these got accidentally /* Build and sort the CLASSTYPE_METHOD_VEC. */
filled in by syntax errors. */ finish_struct_methods (t);
TYPE_HAS_CONSTRUCTOR (t) = 0;
TYPE_HAS_DESTRUCTOR (t) = 0;
}
/* Process the access-declarations. */ /* Process the access-declarations. */
while (access_decls) while (access_decls)
{ {
handle_using_decl (TREE_VALUE (access_decls), t, method_vec, fields); handle_using_decl (TREE_VALUE (access_decls), t);
access_decls = TREE_CHAIN (access_decls); access_decls = TREE_CHAIN (access_decls);
} }
...@@ -3841,60 +3996,32 @@ finish_struct_1 (t) ...@@ -3841,60 +3996,32 @@ finish_struct_1 (t)
bounds. That's better than using `void*' or some such; it's bounds. That's better than using `void*' or some such; it's
cleaner, and it let's the alias analysis code know that these cleaner, and it let's the alias analysis code know that these
stores cannot alias stores to void*! */ stores cannot alias stores to void*! */
vfield = build_lang_decl (FIELD_DECL, get_vfield_name (t), vfield = build_vtbl_or_vbase_field (get_vfield_name (t),
vtbl_ptr_type_node); get_identifier (VFIELD_BASE),
/* If you change any of the below, take a look at all the vtbl_ptr_type_node,
other VFIELD_BASEs and VTABLE_BASEs in the code, and change t,
them too. */ &empty);
DECL_ASSEMBLER_NAME (vfield) = get_identifier (VFIELD_BASE);
TYPE_VFIELD (t) = vfield; TYPE_VFIELD (t) = vfield;
DECL_VIRTUAL_P (vfield) = 1;
DECL_ARTIFICIAL (vfield) = 1;
DECL_FIELD_CONTEXT (vfield) = t;
DECL_CLASS_CONTEXT (vfield) = t;
DECL_FCONTEXT (vfield) = t;
DECL_SAVED_INSNS (vfield) = 0;
DECL_FIELD_SIZE (vfield) = 0;
DECL_ALIGN (vfield) = TYPE_ALIGN (ptr_type_node);
*next_field = vfield; *next_field = vfield;
empty = 0;
vfields = chainon (vfields, build_tree_list (NULL_TREE, t)); vfields = chainon (vfields, build_tree_list (NULL_TREE, t));
} }
/* Now DECL_INITIAL is null on all members except for zero-width bit-fields.
C++: maybe we will support default field initialization some day... */
/* Delete all duplicate fields from the fields */
delete_duplicate_fields (fields);
/* Now we have the nearly final fieldlist for the data fields. Record it,
then lay out the structure or union (including the fields). */
TYPE_FIELDS (t) = fields;
if (n_baseclasses)
{
TYPE_FIELDS (t) = chainon (build_base_fields (t), TYPE_FIELDS (t));
/* If all our bases are empty, we can be empty too. */
for (x = TYPE_FIELDS (t); empty && x != fields; x = TREE_CHAIN (x))
if (DECL_SIZE (x) != integer_zero_node)
empty = 0;
}
/* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS. Thus, /* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS. Thus,
we have to save this before we start modifying we have to save this before we start modifying
TYPE_NONCOPIED_PARTS. */ TYPE_NONCOPIED_PARTS. */
inline_friends = CLASSTYPE_INLINE_FRIENDS (t); inline_friends = CLASSTYPE_INLINE_FRIENDS (t);
CLASSTYPE_INLINE_FRIENDS (t) = NULL_TREE; CLASSTYPE_INLINE_FRIENDS (t) = NULL_TREE;
/* We make all structures have at least one element, so that they
have non-zero size. The field that we add here is fake, in the
sense that, for example, we don't want people to be able to
initialize it later. So, we add it just long enough to let the
back-end lay out the type, and then remove it. */
if (empty) if (empty)
{ {
/* C++: do not let empty structures exist. */
tree decl = build_lang_decl tree decl = build_lang_decl
(FIELD_DECL, NULL_TREE, char_type_node); (FIELD_DECL, NULL_TREE, char_type_node);
TREE_CHAIN (decl) = fields; TREE_CHAIN (decl) = TYPE_FIELDS (t);
TYPE_FIELDS (t) = decl; TYPE_FIELDS (t) = decl;
TYPE_NONCOPIED_PARTS (t) TYPE_NONCOPIED_PARTS (t)
= tree_cons (NULL_TREE, decl, TYPE_NONCOPIED_PARTS (t)); = tree_cons (NULL_TREE, decl, TYPE_NONCOPIED_PARTS (t));
...@@ -3903,6 +4030,11 @@ finish_struct_1 (t) ...@@ -3903,6 +4030,11 @@ finish_struct_1 (t)
layout_type (t); layout_type (t);
/* If we added an extra field to make this class non-empty, remove
it now. */
if (empty)
TYPE_FIELDS (t) = TREE_CHAIN (TYPE_FIELDS (t));
/* Remember the size and alignment of the class before adding /* Remember the size and alignment of the class before adding
the virtual bases. */ the virtual bases. */
if (empty && flag_new_abi) if (empty && flag_new_abi)
...@@ -3930,22 +4062,10 @@ finish_struct_1 (t) ...@@ -3930,22 +4062,10 @@ finish_struct_1 (t)
if (n_baseclasses) if (n_baseclasses)
/* layout_basetypes will remove the base subobject fields. */ /* layout_basetypes will remove the base subobject fields. */
max_has_virtual = layout_basetypes (t, max_has_virtual); max_has_virtual = layout_basetypes (t, max_has_virtual);
if (empty)
TYPE_FIELDS (t) = fields;
my_friendly_assert (TYPE_FIELDS (t) == fields, 981117);
/* Delete all zero-width bit-fields from the fieldlist */ /* Delete all zero-width bit-fields from the list of fields. Now
{ that we have layed out the type they are no longer important. */
tree *fieldsp = &fields; remove_zero_width_bit_fields (t);
while (*fieldsp)
if (TREE_CODE (*fieldsp) == FIELD_DECL
&& DECL_C_BIT_FIELD (*fieldsp) && DECL_INITIAL (*fieldsp))
*fieldsp = TREE_CHAIN (*fieldsp);
else
fieldsp = &TREE_CHAIN (*fieldsp);
}
TYPE_FIELDS (t) = fields;
if (TYPE_USES_VIRTUAL_BASECLASSES (t)) if (TYPE_USES_VIRTUAL_BASECLASSES (t))
{ {
...@@ -3998,10 +4118,6 @@ finish_struct_1 (t) ...@@ -3998,10 +4118,6 @@ finish_struct_1 (t)
TYPE_VFIELD (t) = vfield; TYPE_VFIELD (t) = vfield;
} }
#ifdef NOTQUITE
cp_warning ("Doing hard virtuals for %T...", t);
#endif
if (has_virtual > max_has_virtual) if (has_virtual > max_has_virtual)
max_has_virtual = has_virtual; max_has_virtual = has_virtual;
if (max_has_virtual > 0) if (max_has_virtual > 0)
...@@ -4141,7 +4257,7 @@ finish_struct_1 (t) ...@@ -4141,7 +4257,7 @@ finish_struct_1 (t)
/* Complete the rtl for any static member objects of the type we're /* Complete the rtl for any static member objects of the type we're
working on. */ working on. */
for (x = fields; x; x = TREE_CHAIN (x)) for (x = TYPE_FIELDS (t); x; x = TREE_CHAIN (x))
{ {
if (TREE_CODE (x) == VAR_DECL && TREE_STATIC (x) if (TREE_CODE (x) == VAR_DECL && TREE_STATIC (x)
&& TREE_TYPE (x) == t) && TREE_TYPE (x) == t)
...@@ -4152,20 +4268,18 @@ finish_struct_1 (t) ...@@ -4152,20 +4268,18 @@ finish_struct_1 (t)
} }
/* Done with FIELDS...now decide whether to sort these for /* Done with FIELDS...now decide whether to sort these for
faster lookups later. Don't worry about optimizing faster lookups later.
for structs only declared in inline functions...they're
not going to be referenced anywhere else.
The C front-end only does this when n_fields > 15. We use The C front-end only does this when n_fields > 15. We use
a smaller number because most searches fail (succeeding a smaller number because most searches fail (succeeding
ultimately as the search bores through the inheritance ultimately as the search bores through the inheritance
hierarchy), and we want this failure to occur quickly. */ hierarchy), and we want this failure to occur quickly. */
n_fields = count_fields (fields); n_fields = count_fields (TYPE_FIELDS (t));
if (n_fields > 7 && !allocation_temporary_p ()) if (n_fields > 7)
{ {
tree field_vec = make_tree_vec (n_fields); tree field_vec = make_tree_vec (n_fields);
add_fields_to_vec (fields, field_vec, 0); add_fields_to_vec (TYPE_FIELDS (t), field_vec, 0);
qsort (&TREE_VEC_ELT (field_vec, 0), n_fields, sizeof (tree), qsort (&TREE_VEC_ELT (field_vec, 0), n_fields, sizeof (tree),
(int (*)(const void *, const void *))field_decl_cmp); (int (*)(const void *, const void *))field_decl_cmp);
if (! DECL_LANG_SPECIFIC (TYPE_MAIN_DECL (t))) if (! DECL_LANG_SPECIFIC (TYPE_MAIN_DECL (t)))
...@@ -4201,7 +4315,7 @@ finish_struct_1 (t) ...@@ -4201,7 +4315,7 @@ finish_struct_1 (t)
vfield, TYPE_NONCOPIED_PARTS (t)); vfield, TYPE_NONCOPIED_PARTS (t));
if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t) if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t)
&& DECL_VINDEX (TREE_VEC_ELT (method_vec, 1)) == NULL_TREE) && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1)) == NULL_TREE)
cp_warning ("`%#T' has virtual functions but non-virtual destructor", cp_warning ("`%#T' has virtual functions but non-virtual destructor",
t); t);
} }
...@@ -4211,11 +4325,6 @@ finish_struct_1 (t) ...@@ -4211,11 +4325,6 @@ finish_struct_1 (t)
finish_vtbls (TYPE_BINFO (t), 1, t); finish_vtbls (TYPE_BINFO (t), 1, t);
hack_incomplete_structures (t); hack_incomplete_structures (t);
#if 0
if (TYPE_NAME (t) && TYPE_IDENTIFIER (t))
undo_template_name_overload (TYPE_IDENTIFIER (t), 1);
#endif
if (warn_overloaded_virtual) if (warn_overloaded_virtual)
warn_hidden (t); warn_hidden (t);
......
...@@ -4012,7 +4012,6 @@ extern tree build_cplus_method_type PROTO((tree, tree, tree)); ...@@ -4012,7 +4012,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_vbase_pointer_fields PROTO((tree));
extern tree build_base_fields PROTO((tree)); 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));
......
...@@ -9293,8 +9293,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -9293,8 +9293,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
/* Avoid giving two errors for this. */ /* Avoid giving two errors for this. */
IDENTIFIER_CLASS_VALUE (dname) = NULL_TREE; IDENTIFIER_CLASS_VALUE (dname) = NULL_TREE;
declspecs = temp_tree_cons (NULL_TREE, integer_type_node, declspecs = tree_cons (NULL_TREE, integer_type_node, declspecs);
declspecs);
*next = dname; *next = dname;
next = 0; next = 0;
break; break;
......
...@@ -4335,7 +4335,7 @@ qualified_lookup_using_namespace (name, scope, result, flags) ...@@ -4335,7 +4335,7 @@ qualified_lookup_using_namespace (name, scope, result, flags)
tree usings; tree usings;
while (scope && (result != error_mark_node)) while (scope && (result != error_mark_node))
{ {
seen = temp_tree_cons (scope, NULL_TREE, seen); seen = tree_cons (scope, NULL_TREE, seen);
result = ambiguous_decl (name, result, result = ambiguous_decl (name, result,
binding_for_name (name, scope), flags); binding_for_name (name, scope), flags);
if (!BINDING_VALUE (result) && !BINDING_TYPE (result)) if (!BINDING_VALUE (result) && !BINDING_TYPE (result))
...@@ -4345,7 +4345,7 @@ qualified_lookup_using_namespace (name, scope, result, flags) ...@@ -4345,7 +4345,7 @@ qualified_lookup_using_namespace (name, scope, result, flags)
/* If this was a real directive, and we have not seen it. */ /* If this was a real directive, and we have not seen it. */
if (!TREE_INDIRECT_USING (usings) if (!TREE_INDIRECT_USING (usings)
&& !purpose_member (TREE_PURPOSE (usings), seen)) && !purpose_member (TREE_PURPOSE (usings), seen))
todo = temp_tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo); todo = tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
if (todo) if (todo)
{ {
scope = TREE_PURPOSE (todo); scope = TREE_PURPOSE (todo);
......
...@@ -2000,9 +2000,6 @@ cons_up_default_function (type, full_name, kind) ...@@ -2000,9 +2000,6 @@ cons_up_default_function (type, full_name, kind)
switch (kind) switch (kind)
{ {
/* Destructors. */ /* Destructors. */
case 1:
declspecs = build_decl_list (NULL_TREE, ridpointers [(int) RID_VIRTUAL]);
/* Fall through... */
case 0: case 0:
name = build_parse_node (BIT_NOT_EXPR, name); name = build_parse_node (BIT_NOT_EXPR, name);
args = void_list_node; args = void_list_node;
......
...@@ -989,86 +989,6 @@ build_base_fields (rec) ...@@ -989,86 +989,6 @@ build_base_fields (rec)
return base_decls; return base_decls;
} }
/* Returns list of virtual base class pointers in a FIELD_DECL chain. */
tree
build_vbase_pointer_fields (rec)
tree rec;
{
/* Chain to hold all the new FIELD_DECLs which point at virtual
base classes. */
tree vbase_decls = NULL_TREE;
tree binfos = TYPE_BINFO_BASETYPES (rec);
int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
tree decl;
int i;
/* Handle basetypes almost like fields, but record their
offsets differently. */
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;
/* All basetypes are recorded in the association list of the
derived type. */
if (TREE_VIA_VIRTUAL (base_binfo))
{
int j;
const char *name;
/* The offset for a virtual base class is only used in computing
virtual function tables and for initializing virtual base
pointers. It is built once `get_vbase_types' is called. */
/* If this basetype can come from another vbase pointer
without an additional indirection, we will share
that pointer. If an indirection is involved, we
make our own pointer. */
for (j = 0; j < n_baseclasses; j++)
{
tree other_base_binfo = TREE_VEC_ELT (binfos, j);
if (! TREE_VIA_VIRTUAL (other_base_binfo)
&& binfo_member (basetype,
CLASSTYPE_VBASECLASSES (BINFO_TYPE
(other_base_binfo))
))
goto got_it;
}
FORMAT_VBASE_NAME (name, basetype);
decl = build_lang_decl (FIELD_DECL, get_identifier (name),
build_pointer_type (basetype));
/* If you change any of the below, take a look at all the
other VFIELD_BASEs and VTABLE_BASEs in the code, and change
them too. */
DECL_ASSEMBLER_NAME (decl) = get_identifier (VTABLE_BASE);
DECL_VIRTUAL_P (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
DECL_FIELD_CONTEXT (decl) = rec;
DECL_CLASS_CONTEXT (decl) = rec;
DECL_FCONTEXT (decl) = basetype;
DECL_SAVED_INSNS (decl) = 0;
DECL_FIELD_SIZE (decl) = 0;
DECL_ALIGN (decl) = TYPE_ALIGN (ptr_type_node);
TREE_CHAIN (decl) = vbase_decls;
BINFO_VPTR_FIELD (base_binfo) = decl;
vbase_decls = decl;
got_it:
/* The space this decl occupies has already been accounted for. */
;
}
}
return vbase_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