This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Oops: patch resend
- To: gcc-patches at gcc dot gnu dot org
- Subject: Oops: patch resend
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Thu, 16 Dec 1999 09:15:35 -0800
- Organization: CodeSourcery, LLC
Jason pointed out that I sent a message about more class.c cleanups,
but forgot to attach the patch. Here it is.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
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.
Index: class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.205
diff -c -p -r1.205 class.c
*** class.c 1999/12/15 00:36:57 1.205
--- class.c 1999/12/16 02:46:38
*************** static tree delete_duplicate_fields_1 PR
*** 94,100 ****
static void delete_duplicate_fields PROTO((tree));
static void finish_struct_bits PROTO((tree, int));
static int alter_access PROTO((tree, tree, tree, tree));
! static void handle_using_decl PROTO((tree, tree, tree, tree));
static int overrides PROTO((tree, tree));
static int strictly_overrides PROTO((tree, tree));
static void merge_overrides PROTO((tree, tree, int, tree));
--- 94,100 ----
static void delete_duplicate_fields PROTO((tree));
static void finish_struct_bits PROTO((tree, int));
static int alter_access PROTO((tree, tree, tree, tree));
! static void handle_using_decl PROTO((tree, tree));
static int overrides PROTO((tree, tree));
static int strictly_overrides PROTO((tree, tree));
static void merge_overrides PROTO((tree, tree, int, tree));
*************** static void check_bitfield_decl PROTO((t
*** 125,130 ****
--- 125,133 ----
static void check_field_decl PROTO((tree, tree, int *, int *, int *, int *));
static tree* check_field_decls PROTO((tree, tree *, 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 remove_zero_width_bit_fields PROTO((tree));
/* Variables shared between class.c and call.c. */
*************** add_virtual_function (pv, phv, has_virtu
*** 1049,1057 ****
{
/* Need an entry in some other virtual function table.
Deal with this after we have laid out our virtual base classes. */
! pending_hard_virtuals = temp_tree_cons (NULL_TREE,
! fndecl,
! pending_hard_virtuals);
}
*pv = pending_virtuals;
*phv = pending_hard_virtuals;
--- 1052,1060 ----
{
/* Need an entry in some other virtual function table.
Deal with this after we have laid out our virtual base classes. */
! pending_hard_virtuals = tree_cons (NULL_TREE,
! fndecl,
! pending_hard_virtuals);
}
*pv = pending_virtuals;
*phv = pending_hard_virtuals;
*************** delete_duplicate_fields_1 (field, fields
*** 1289,1331 ****
TREE_CHAIN (prev) = TREE_CHAIN (x);
}
}
! else
{
! 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 (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);
}
}
}
}
--- 1292,1337 ----
TREE_CHAIN (prev) = TREE_CHAIN (x);
}
}
! 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 (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 (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);
}
}
}
*************** alter_access (t, binfo, fdecl, access)
*** 1379,1393 ****
return 0;
}
! /* Process the USING_DECL, which is a member of T. The METHOD_VEC, if
! non-NULL, is the methods of T. The FIELDS are the fields of T. */
static void
! handle_using_decl (using_decl, t, method_vec, fields)
tree using_decl;
tree t;
- tree method_vec;
- tree fields;
{
tree ctype = DECL_INITIAL (using_decl);
tree name = DECL_NAME (using_decl);
--- 1385,1396 ----
return 0;
}
! /* Process the USING_DECL, which is a member of T. */
static void
! handle_using_decl (using_decl, t)
tree using_decl;
tree t;
{
tree ctype = DECL_INITIAL (using_decl);
tree name = DECL_NAME (using_decl);
*************** handle_using_decl (using_decl, t, method
*** 1397,1402 ****
--- 1400,1407 ----
: access_public_node;
tree fdecl, binfo;
tree flist = NULL_TREE;
+ tree fields = TYPE_FIELDS (t);
+ tree method_vec = CLASSTYPE_METHOD_VEC (t);
tree tmp;
int i;
int n_methods;
*************** finish_struct_methods (t)
*** 1989,1997 ****
tree t;
{
tree fn_fields;
! tree method_vec = CLASSTYPE_METHOD_VEC (t);
tree ctor_name = constructor_name (t);
! int slot, len = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
/* First fill in entry 0 with the constructors, entry 1 with destructors,
and the next few with type conversion operators (if any). */
--- 1994,2016 ----
tree t;
{
tree fn_fields;
! tree method_vec;
tree ctor_name = constructor_name (t);
! 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,
and the next few with type conversion operators (if any). */
*************** finish_struct_methods (t)
*** 2051,2059 ****
no methods, then some public defaults are generated. */
maybe_warn_about_overly_private_class (t);
- if (method_vec == NULL_TREE)
- return;
-
/* Now sort the methods. */
while (len > 2 && TREE_VEC_ELT (method_vec, len-1) == NULL_TREE)
len--;
--- 2070,2075 ----
*************** get_basefndecls (fndecl, t)
*** 2812,2818 ****
if (TREE_CODE (methods) == FUNCTION_DECL
&& DECL_VINDEX (methods) != NULL_TREE
&& DECL_NAME (fndecl) == DECL_NAME (methods))
! base_fndecls = temp_tree_cons (fndecl, methods, base_fndecls);
methods = TREE_CHAIN (methods);
}
--- 2828,2834 ----
if (TREE_CODE (methods) == FUNCTION_DECL
&& DECL_VINDEX (methods) != NULL_TREE
&& DECL_NAME (fndecl) == DECL_NAME (methods))
! base_fndecls = tree_cons (fndecl, methods, base_fndecls);
methods = TREE_CHAIN (methods);
}
*************** check_field_decls (t, access_decls, empt
*** 3386,3391 ****
--- 3402,3410 ----
int has_pointers;
int any_default_members;
+ /* First, delete any duplicate fields. */
+ delete_duplicate_fields (TYPE_FIELDS (t));
+
/* Assume there are no access declarations. */
*access_decls = NULL_TREE;
/* Assume this class has no pointer members. */
*************** check_field_decls (t, access_decls, empt
*** 3594,3599 ****
--- 3613,3804 ----
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
(or C++ class declaration).
*************** finish_struct_1 (t)
*** 3626,3638 ****
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;
--- 3831,3842 ----
tree t;
{
tree fields;
! tree x;
tree *next_field;
int has_virtual;
int max_has_virtual;
tree pending_virtuals = NULL_TREE;
tree pending_hard_virtuals = NULL_TREE;
tree vfield;
tree vfields;
tree virtual_dtor;
*************** finish_struct_1 (t)
*** 3646,3652 ****
int first_vfn_base_index;
int n_baseclasses;
- int const_sans_init = 0;
tree access_decls;
int aggregate = 1;
int empty = 1;
--- 3850,3855 ----
*************** finish_struct_1 (t)
*** 3670,3687 ****
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;
--- 3873,3880 ----
TYPE_SIZE (t) = NULL_TREE;
CLASSTYPE_GOT_SEMICOLON (t) = 0;
! n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
if (n_baseclasses > 0)
{
struct base_info base_info;
*************** finish_struct_1 (t)
*** 3692,3698 ****
--- 3885,3893 ----
has_virtual = base_info.has_virtual;
max_has_virtual = base_info.max_has_virtual;
vfield = base_info.vfield;
+ TYPE_VFIELD (t) = vfield;
vfields = base_info.vfields;
+ CLASSTYPE_VFIELDS (t) = 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;
*************** finish_struct_1 (t)
*** 3703,3709 ****
{
first_vfn_base_index = -1;
has_virtual = 0;
! max_has_virtual = has_virtual;
vfield = NULL_TREE;
vfields = NULL_TREE;
CLASSTYPE_RTTI (t) = NULL_TREE;
--- 3898,3904 ----
{
first_vfn_base_index = -1;
has_virtual = 0;
! max_has_virtual = 0;
vfield = NULL_TREE;
vfields = NULL_TREE;
CLASSTYPE_RTTI (t) = NULL_TREE;
*************** finish_struct_1 (t)
*** 3712,3786 ****
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);
TYPE_NEEDS_CONSTRUCTING (t)
! |= (TYPE_HAS_CONSTRUCTOR (t) || TYPE_USES_VIRTUAL_BASECLASSES (t)
! || has_virtual);
CLASSTYPE_NON_AGGREGATE (t)
! = ! aggregate || has_virtual || TYPE_HAS_CONSTRUCTOR (t);
CLASSTYPE_NON_POD_P (t)
|= (CLASSTYPE_NON_AGGREGATE (t) || TYPE_HAS_DESTRUCTOR (t)
|| TYPE_HAS_ASSIGN_REF (t));
--- 3907,3948 ----
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));
*************** finish_struct_1 (t)
*** 3794,3822 ****
= add_implicitly_declared_members (t, cant_have_default_ctor,
cant_have_const_ctor,
no_const_asn_ref);
- if (virtual_dtor)
- add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
- &has_virtual, virtual_dtor, t);
! if (TYPE_METHODS (t))
! {
! finish_struct_methods (t);
! method_vec = CLASSTYPE_METHOD_VEC (t);
! }
! else
! {
! method_vec = 0;
! /* Just in case these got accidentally
! filled in by syntax errors. */
! TYPE_HAS_CONSTRUCTOR (t) = 0;
! TYPE_HAS_DESTRUCTOR (t) = 0;
! }
/* Process the access-declarations. */
while (access_decls)
{
! handle_using_decl (TREE_VALUE (access_decls), t, method_vec, fields);
access_decls = TREE_CHAIN (access_decls);
}
--- 3956,3976 ----
= 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
! vtables. */
! for (x = TYPE_METHODS (t); x; x = TREE_CHAIN (x))
! if (DECL_VINDEX (x))
! add_virtual_function (&pending_virtuals, &pending_hard_virtuals,
! &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);
}
*************** finish_struct_1 (t)
*** 3841,3900 ****
bounds. That's better than using `void*' or some such; it's
cleaner, and it let's the alias analysis code know that these
stores cannot alias stores to void*! */
! vfield = build_lang_decl (FIELD_DECL, get_vfield_name (t),
! vtbl_ptr_type_node);
! /* 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 (vfield) = get_identifier (VFIELD_BASE);
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;
- empty = 0;
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,
we have to save this before we start modifying
TYPE_NONCOPIED_PARTS. */
inline_friends = CLASSTYPE_INLINE_FRIENDS (t);
CLASSTYPE_INLINE_FRIENDS (t) = NULL_TREE;
if (empty)
{
- /* C++: do not let empty structures exist. */
tree decl = build_lang_decl
(FIELD_DECL, NULL_TREE, char_type_node);
! TREE_CHAIN (decl) = fields;
TYPE_FIELDS (t) = decl;
TYPE_NONCOPIED_PARTS (t)
= tree_cons (NULL_TREE, decl, TYPE_NONCOPIED_PARTS (t));
--- 3995,4026 ----
bounds. That's better than using `void*' or some such; it's
cleaner, and it let's the alias analysis code know that these
stores cannot alias stores to void*! */
! vfield = build_vtbl_or_vbase_field (get_vfield_name (t),
! get_identifier (VFIELD_BASE),
! vtbl_ptr_type_node,
! t,
! &empty);
TYPE_VFIELD (t) = vfield;
*next_field = vfield;
vfields = chainon (vfields, build_tree_list (NULL_TREE, t));
}
/* CLASSTYPE_INLINE_FRIENDS is really TYPE_NONCOPIED_PARTS. Thus,
we have to save this before we start modifying
TYPE_NONCOPIED_PARTS. */
inline_friends = CLASSTYPE_INLINE_FRIENDS (t);
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)
{
tree decl = build_lang_decl
(FIELD_DECL, NULL_TREE, char_type_node);
! TREE_CHAIN (decl) = TYPE_FIELDS (t);
TYPE_FIELDS (t) = decl;
TYPE_NONCOPIED_PARTS (t)
= tree_cons (NULL_TREE, decl, TYPE_NONCOPIED_PARTS (t));
*************** finish_struct_1 (t)
*** 3903,3908 ****
--- 4029,4039 ----
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
the virtual bases. */
if (empty && flag_new_abi)
*************** finish_struct_1 (t)
*** 3930,3951 ****
if (n_baseclasses)
/* layout_basetypes will remove the base subobject fields. */
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 */
! {
! tree *fieldsp = &fields;
! 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))
{
--- 4061,4070 ----
if (n_baseclasses)
/* layout_basetypes will remove the base subobject fields. */
max_has_virtual = layout_basetypes (t, max_has_virtual);
! /* Delete all zero-width bit-fields from the list of fields. Now
! that we have layed out the type they are no longer important. */
! remove_zero_width_bit_fields (t);
if (TYPE_USES_VIRTUAL_BASECLASSES (t))
{
*************** finish_struct_1 (t)
*** 3998,4007 ****
TYPE_VFIELD (t) = vfield;
}
- #ifdef NOTQUITE
- cp_warning ("Doing hard virtuals for %T...", t);
- #endif
-
if (has_virtual > max_has_virtual)
max_has_virtual = has_virtual;
if (max_has_virtual > 0)
--- 4117,4122 ----
*************** finish_struct_1 (t)
*** 4141,4147 ****
/* Complete the rtl for any static member objects of the type we're
working on. */
! for (x = fields; x; x = TREE_CHAIN (x))
{
if (TREE_CODE (x) == VAR_DECL && TREE_STATIC (x)
&& TREE_TYPE (x) == t)
--- 4256,4262 ----
/* Complete the rtl for any static member objects of the type we're
working on. */
! for (x = TYPE_FIELDS (t); x; x = TREE_CHAIN (x))
{
if (TREE_CODE (x) == VAR_DECL && TREE_STATIC (x)
&& TREE_TYPE (x) == t)
*************** finish_struct_1 (t)
*** 4152,4171 ****
}
/* Done with FIELDS...now decide whether to sort these for
! faster lookups later. Don't worry about optimizing
! 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
a smaller number because most searches fail (succeeding
ultimately as the search bores through the inheritance
hierarchy), and we want this failure to occur quickly. */
! n_fields = count_fields (fields);
! if (n_fields > 7 && !allocation_temporary_p ())
{
tree field_vec = make_tree_vec (n_fields);
! add_fields_to_vec (fields, field_vec, 0);
qsort (&TREE_VEC_ELT (field_vec, 0), n_fields, sizeof (tree),
(int (*)(const void *, const void *))field_decl_cmp);
if (! DECL_LANG_SPECIFIC (TYPE_MAIN_DECL (t)))
--- 4267,4284 ----
}
/* Done with FIELDS...now decide whether to sort these for
! faster lookups later.
The C front-end only does this when n_fields > 15. We use
a smaller number because most searches fail (succeeding
ultimately as the search bores through the inheritance
hierarchy), and we want this failure to occur quickly. */
! n_fields = count_fields (TYPE_FIELDS (t));
! if (n_fields > 7)
{
tree field_vec = make_tree_vec (n_fields);
! add_fields_to_vec (TYPE_FIELDS (t), field_vec, 0);
qsort (&TREE_VEC_ELT (field_vec, 0), n_fields, sizeof (tree),
(int (*)(const void *, const void *))field_decl_cmp);
if (! DECL_LANG_SPECIFIC (TYPE_MAIN_DECL (t)))
*************** finish_struct_1 (t)
*** 4201,4207 ****
vfield, TYPE_NONCOPIED_PARTS (t));
if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t)
! && DECL_VINDEX (TREE_VEC_ELT (method_vec, 1)) == NULL_TREE)
cp_warning ("`%#T' has virtual functions but non-virtual destructor",
t);
}
--- 4314,4320 ----
vfield, TYPE_NONCOPIED_PARTS (t));
if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (t)
! && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (t), 1)) == NULL_TREE)
cp_warning ("`%#T' has virtual functions but non-virtual destructor",
t);
}
*************** finish_struct_1 (t)
*** 4210,4220 ****
the base types we marked. */
finish_vtbls (TYPE_BINFO (t), 1, 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)
warn_hidden (t);
--- 4323,4328 ----
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.360
diff -c -p -r1.360 cp-tree.h
*** cp-tree.h 1999/12/14 18:52:40 1.360
--- cp-tree.h 1999/12/16 02:46:41
*************** extern tree build_cplus_method_type PRO
*** 4011,4017 ****
extern tree build_cplus_staticfn_type PROTO((tree, tree, tree));
extern tree build_cplus_array_type PROTO((tree, tree));
extern int layout_basetypes PROTO((tree, int));
- extern tree build_vbase_pointer_fields PROTO((tree));
extern tree build_base_fields PROTO((tree));
extern tree hash_tree_cons PROTO((tree, tree, tree));
extern tree hash_tree_chain PROTO((tree, tree));
--- 4011,4016 ----
Index: decl.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl.c,v
retrieving revision 1.518
diff -c -p -r1.518 decl.c
*** decl.c 1999/12/11 19:02:10 1.518
--- decl.c 1999/12/16 02:46:49
*************** grokdeclarator (declarator, declspecs, d
*** 9282,9289 ****
/* Avoid giving two errors for this. */
IDENTIFIER_CLASS_VALUE (dname) = NULL_TREE;
! declspecs = temp_tree_cons (NULL_TREE, integer_type_node,
! declspecs);
*next = dname;
next = 0;
break;
--- 9282,9288 ----
/* Avoid giving two errors for this. */
IDENTIFIER_CLASS_VALUE (dname) = NULL_TREE;
! declspecs = tree_cons (NULL_TREE, integer_type_node, declspecs);
*next = dname;
next = 0;
break;
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/decl2.c,v
retrieving revision 1.287
diff -c -p -r1.287 decl2.c
*** decl2.c 1999/12/05 00:37:56 1.287
--- decl2.c 1999/12/16 02:46:53
*************** qualified_lookup_using_namespace (name,
*** 4334,4340 ****
tree usings;
while (scope && (result != error_mark_node))
{
! seen = temp_tree_cons (scope, NULL_TREE, seen);
result = ambiguous_decl (name, result,
binding_for_name (name, scope), flags);
if (!BINDING_VALUE (result) && !BINDING_TYPE (result))
--- 4334,4340 ----
tree usings;
while (scope && (result != error_mark_node))
{
! seen = tree_cons (scope, NULL_TREE, seen);
result = ambiguous_decl (name, result,
binding_for_name (name, scope), flags);
if (!BINDING_VALUE (result) && !BINDING_TYPE (result))
*************** qualified_lookup_using_namespace (name,
*** 4344,4350 ****
/* If this was a real directive, and we have not seen it. */
if (!TREE_INDIRECT_USING (usings)
&& !purpose_member (TREE_PURPOSE (usings), seen))
! todo = temp_tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
if (todo)
{
scope = TREE_PURPOSE (todo);
--- 4344,4350 ----
/* If this was a real directive, and we have not seen it. */
if (!TREE_INDIRECT_USING (usings)
&& !purpose_member (TREE_PURPOSE (usings), seen))
! todo = tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
if (todo)
{
scope = TREE_PURPOSE (todo);
Index: lex.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/lex.c,v
retrieving revision 1.168
diff -c -p -r1.168 lex.c
*** lex.c 1999/12/14 05:33:22 1.168
--- lex.c 1999/12/16 02:46:55
*************** cons_up_default_function (type, full_nam
*** 2000,2008 ****
switch (kind)
{
/* Destructors. */
- case 1:
- declspecs = build_decl_list (NULL_TREE, ridpointers [(int) RID_VIRTUAL]);
- /* Fall through... */
case 0:
name = build_parse_node (BIT_NOT_EXPR, name);
args = void_list_node;
--- 2000,2005 ----
Index: method.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/method.c,v
retrieving revision 1.127
diff -c -p -r1.127 method.c
*** method.c 1999/11/14 20:29:03 1.127
--- method.c 1999/12/16 02:46:56
*************** static int is_back_referenceable_type PR
*** 98,103 ****
--- 98,104 ----
static int check_btype 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 fixup_pending_inline PROTO((struct pending_inline *));
# define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0)
# define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C)))
*************** init_method ()
*** 142,147 ****
--- 143,169 ----
value. */
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
can be processed normally. CNAME is the name of the class
we are working from, METHOD_LIST is the list of method lists
*************** do_inline_function_hair (type, friend_li
*** 163,206 ****
else
method = TREE_VEC_ELT (method, 2);
}
-
- while (method)
- {
- /* Do inline member functions. */
- 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);
! }
}
/* Here is where overload code starts. */
--- 185,198 ----
else
method = TREE_VEC_ELT (method, 2);
}
! /* Do inline member functions. */
! for (; method; method = TREE_CHAIN (method))
! fixup_pending_inline (DECL_PENDING_INLINE_INFO (method));
!
! /* 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. */
Index: tree.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/tree.c,v
retrieving revision 1.167
diff -c -p -r1.167 tree.c
*** tree.c 1999/12/14 18:52:40 1.167
--- tree.c 1999/12/16 02:46:58
*************** build_base_fields (rec)
*** 989,1074 ****
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.
The entry point is `list_hash_canon'. */
--- 989,994 ----