This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: Fix ABI bug and crash
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 30 Sep 2002 09:59:39 -0700
- Subject: C++ PATCH: Fix ABI bug and crash
- Reply-to: mark at codesourcery dot com
This patch:
2002-05-14 Alexandre Oliva <aoliva@redhat.com>
* cp-tree.h (struct lang_type): Added non_zero_init.
contained this red-flag comment:
! /* This is a default initialization of an aggregate, but not one of
! non-POD class type. We cleverly notice that the initialization
! rules in such a case are the same as for initialization with an
! empty brace-initialization list. */
Note the user of clever. :-)
The approach used in this patch doesn't work; this, for example, is a
failing test case, distilled from our ABI testsuite:
struct S {
S ();
int S::* sp;
int i;
};
S s[2] = {};
(The root problem that Alexandre was trying to fix is that the new C++
ABI "cleverly" uses -1 to represent a NULL pointer-to-data-member;
that decision means that "zero-initialization" in the sense of the
language standard no longer means "fill with zeros".)
I fixed this by doing what I've talked about doing for ages; creating
separate variants of each type for the base class case vs. the
complete object case. That allows us to tell the middle end the truth
about the layout of a C++ class type, and that, in turn, makes it easy
to generate the correct zero-initializations.
This is not very clever, but I hope it will be right.
Our ABI testsuite also found a related problem again involving empty
base classes; I fixed that as well with -fabi-version=0. Here's a
test case:
struct S1 {};
struct S2 { virtual void f () {} S1 s1[4]; };
struct S3 : virtual public S2 {};
struct S4 : virtual public S2 { int i; };
struct S5 : public S3, virtual public S4 {};
struct S6 { S5 s5; };
struct S7 { S1 s1[5]; };
struct S8 : public S1, public S6, virtual public S7 { };
S8 s8;
int main () {
if ((char *)(S7 *)&s8 - (char *)&s8 != 24)
return 1;
}
Brownie points if you can figure out why we got that wrong. :-) [Hint;
I think you really do need all those classes to manfiest the bug. Or
at least almost all of them.]
Bootstrapped and tested on i686-pc-linux-gnu, applied on the mainline.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
2002-09-30 Mark Mitchell <mark@codesourcery.com>
* store-layout.c (finish_record_layout): Add free_p parameter.
(layout_type): Pass it.
* tree.h (finish_record_layout): Update prototype.
2002-09-30 Mark Mitchell <mark@codesourcery.com>
* class.c (walk_subobject_offsets): Correct the calculation of
offsets for virtual bases. Correct the counting of array
elements.
(layout_nonempty_base_or_field): Simplify. Correct the
calculation of offsets to be propagated through the binfo
hierarchy.
(build_base_field): Avoid creating a FIELD_DECL for empty bases.
Add the FIELD_DECL to TYPE_FIELDS.
(build_base_fields): Adjust accordingly.
(layout_virtual_bases): Use build_base_field.
(end_of_class): Return a tree, not an integer.
(warn_about_ambiguous_direct_bases): Rename to ...
(warn_about_ambiguous_bases): ... this.
(include_empty_classes): New function.
(layout_class_type): Create an alternative version of the type to
be used when as a base class type. Do not call
finish_record_layout until we are done laying out the class.
* cp-tree.h (lang_type_class): Remove size, size_unit. Add
as_base.
(CLASSTYPE_SIZE): Reimplement.
(CLASSTYPE_SIZE_UNIT): Likewise.
(CLASSTYPE_ALIGN): Likweise.
(CLASSTYPE_USER_ALIGN): Likewise.
(CLASSTYPE_AS_BASE): New macro.
(DECL_INITIALIZED_P): Likewise.
(extract_init): Remove prototype.
(build_forced_zero_init): Rename to ...
(build_zero_init): ... this.
(force_store_init_value): Remove.
* decl.c (obscure_complex_init): Remove.
(duplicate_decls): Copy DECL_INITIALIZED_P.
(check_initializer): Do not leave junk in DECL_INITIAL.
(cp_finish_decl): Handle zero-initialization of entities with
static storage duration.
* expr.c (extract_init): Remove.
* init.c (build_forced_zero_init): Remove.
(build_zero_init): New function.
(build_default_init): Use it.
(build_field_list): Skip FIELD_DECLs for base subobjects.
(push_base_cleanups): Likewise.
* method.c (do_build_assign_ref): Likewise.
(synthesize_exception_spec): Likewise.
* pt.c (tsubst_decl): Clear DECL_INITIALIZED_P.
(regenerate_decl_from_template): To not set DECL_INITIAL for a
static data member whose initialization took place in its class.
(instantiate_decl): Do not pass an initializer to cp_finish_decl
in that situation.
* search.c (dfs_push_decls): Skip FIELD_DECLs for base subobjects.
(dfs_unuse_fields): Likewise.
* tree.c (pod_type_p): Handle error_mark_node.
(zero_init_p): Likewise.
* typeck.c (lookup_anon_field): Skip FIELD_DECLs for base
subobjects.
* typeck2.c (store_init_value): Remove #if 0'd code.
(force_store_init_value): Remove.
(process_init_constructor): Use build_zero_init.
2002-09-30 Mark Mitchell <mark@codesourcery.com>
* g++.dg/abi/empty7.C: New test.
* g++.dg/init/pm2.C: Likewise.
Index: stor-layout.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/stor-layout.c,v
retrieving revision 1.129
diff -c -5 -p -r1.129 stor-layout.c
*** stor-layout.c 18 Sep 2002 18:51:13 -0000 1.129
--- stor-layout.c 30 Sep 2002 16:04:42 -0000
*************** finalize_type_size (type)
*** 1482,1496 ****
}
}
/* Do all of the work required to layout the type indicated by RLI,
once the fields have been laid out. This function will call `free'
! for RLI. */
void
! finish_record_layout (rli)
record_layout_info rli;
{
/* Compute the final size. */
finalize_record_size (rli);
/* Compute the TYPE_MODE for the record. */
--- 1482,1499 ----
}
}
/* Do all of the work required to layout the type indicated by RLI,
once the fields have been laid out. This function will call `free'
! for RLI, unless FREE_P is false. Passing a value other than false
! for FREE_P is bad practice; this option only exists to support the
! G++ 3.2 ABI. */
void
! finish_record_layout (rli, free_p)
record_layout_info rli;
+ int free_p;
{
/* Compute the final size. */
finalize_record_size (rli);
/* Compute the TYPE_MODE for the record. */
*************** finish_record_layout (rli)
*** 1506,1516 ****
layout_decl (TREE_VALUE (rli->pending_statics), 0);
rli->pending_statics = TREE_CHAIN (rli->pending_statics);
}
/* Clean up. */
! free (rli);
}
/* Calculate the mode, size, and alignment for TYPE.
For an array type, calculate the element separation as well.
Record TYPE on the chain of permanent or temporary types
--- 1509,1520 ----
layout_decl (TREE_VALUE (rli->pending_statics), 0);
rli->pending_statics = TREE_CHAIN (rli->pending_statics);
}
/* Clean up. */
! if (free_p)
! free (rli);
}
/* Calculate the mode, size, and alignment for TYPE.
For an array type, calculate the element separation as well.
Record TYPE on the chain of permanent or temporary types
*************** layout_type (type)
*** 1761,1771 ****
if (lang_adjust_rli)
(*lang_adjust_rli) (rli);
/* Finish laying out the record. */
! finish_record_layout (rli);
}
break;
case SET_TYPE: /* Used by Chill and Pascal. */
if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST
--- 1765,1775 ----
if (lang_adjust_rli)
(*lang_adjust_rli) (rli);
/* Finish laying out the record. */
! finish_record_layout (rli, /*free_p=*/true);
}
break;
case SET_TYPE: /* Used by Chill and Pascal. */
if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) != INTEGER_CST
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.353
diff -c -5 -p -r1.353 tree.h
*** tree.h 20 Sep 2002 07:33:25 -0000 1.353
--- tree.h 30 Sep 2002 16:04:43 -0000
*************** extern void normalize_offset PARAMS ((t
*** 2422,2432 ****
extern tree rli_size_unit_so_far PARAMS ((record_layout_info));
extern tree rli_size_so_far PARAMS ((record_layout_info));
extern void normalize_rli PARAMS ((record_layout_info));
extern void place_field PARAMS ((record_layout_info, tree));
extern void compute_record_mode PARAMS ((tree));
! extern void finish_record_layout PARAMS ((record_layout_info));
/* Given a hashcode and a ..._TYPE node (for which the hashcode was made),
return a canonicalized ..._TYPE node, so that duplicates are not made.
How the hash code is computed is up to the caller, as long as any two
callers that could hash identical-looking type nodes agree. */
--- 2422,2432 ----
extern tree rli_size_unit_so_far PARAMS ((record_layout_info));
extern tree rli_size_so_far PARAMS ((record_layout_info));
extern void normalize_rli PARAMS ((record_layout_info));
extern void place_field PARAMS ((record_layout_info, tree));
extern void compute_record_mode PARAMS ((tree));
! extern void finish_record_layout PARAMS ((record_layout_info, int));
/* Given a hashcode and a ..._TYPE node (for which the hashcode was made),
return a canonicalized ..._TYPE node, so that duplicates are not made.
How the hash code is computed is up to the caller, as long as any two
callers that could hash identical-looking type nodes agree. */
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.469
diff -c -5 -p -r1.469 class.c
*** cp/class.c 25 Sep 2002 19:07:32 -0000 1.469
--- cp/class.c 30 Sep 2002 16:04:45 -0000
*************** static int count_fields PARAMS ((tree));
*** 135,159 ****
static int add_fields_to_vec PARAMS ((tree, tree, int));
static void check_bitfield_decl PARAMS ((tree));
static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *));
static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *,
int *));
! static bool build_base_field PARAMS ((record_layout_info, tree, int *,
! splay_tree, tree));
! static bool build_base_fields PARAMS ((record_layout_info, int *,
! splay_tree, tree));
static void check_methods PARAMS ((tree));
static void remove_zero_width_bit_fields PARAMS ((tree));
static void check_bases PARAMS ((tree, int *, int *, int *));
static void check_bases_and_members PARAMS ((tree, int *));
static tree create_vtable_ptr PARAMS ((tree, int *, tree *));
static void layout_class_type PARAMS ((tree, int *, int *, tree *));
static void fixup_pending_inline PARAMS ((tree));
static void fixup_inline_methods PARAMS ((tree));
static void set_primary_base PARAMS ((tree, tree, int *));
static void propagate_binfo_offsets PARAMS ((tree, tree, tree));
! static void layout_virtual_bases PARAMS ((tree, splay_tree));
static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
static void add_vcall_offset_vtbl_entries_r PARAMS ((tree, vtbl_init_data *));
static void add_vcall_offset_vtbl_entries_1 PARAMS ((tree, vtbl_init_data *));
static void build_vcall_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
--- 135,160 ----
static int add_fields_to_vec PARAMS ((tree, tree, int));
static void check_bitfield_decl PARAMS ((tree));
static void check_field_decl PARAMS ((tree, tree, int *, int *, int *, int *));
static void check_field_decls PARAMS ((tree, tree *, int *, int *, int *,
int *));
! static tree *build_base_field PARAMS ((record_layout_info, tree, int *,
! splay_tree, tree *));
! static void build_base_fields PARAMS ((record_layout_info, int *,
! splay_tree, tree *));
static void check_methods PARAMS ((tree));
static void remove_zero_width_bit_fields PARAMS ((tree));
static void check_bases PARAMS ((tree, int *, int *, int *));
static void check_bases_and_members PARAMS ((tree, int *));
static tree create_vtable_ptr PARAMS ((tree, int *, tree *));
+ static void include_empty_classes (record_layout_info);
static void layout_class_type PARAMS ((tree, int *, int *, tree *));
static void fixup_pending_inline PARAMS ((tree));
static void fixup_inline_methods PARAMS ((tree));
static void set_primary_base PARAMS ((tree, tree, int *));
static void propagate_binfo_offsets PARAMS ((tree, tree, tree));
! static void layout_virtual_bases (record_layout_info, splay_tree);
static tree dfs_set_offset_for_unshared_vbases PARAMS ((tree, void *));
static void build_vbase_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
static void add_vcall_offset_vtbl_entries_r PARAMS ((tree, vtbl_init_data *));
static void add_vcall_offset_vtbl_entries_1 PARAMS ((tree, vtbl_init_data *));
static void build_vcall_offset_vtbl_entries PARAMS ((tree, vtbl_init_data *));
*************** static void dump_vtable PARAMS ((tree, t
*** 169,181 ****
static void dump_vtt PARAMS ((tree, tree));
static tree build_vtable PARAMS ((tree, tree, tree));
static void initialize_vtable PARAMS ((tree, tree));
static void initialize_array PARAMS ((tree, tree));
static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
! tree, tree,
! splay_tree, tree));
! static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
static bool layout_empty_base PARAMS ((tree, tree, splay_tree, tree));
static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
tree));
static void set_vindex PARAMS ((tree, int *));
--- 170,181 ----
static void dump_vtt PARAMS ((tree, tree));
static tree build_vtable PARAMS ((tree, tree, tree));
static void initialize_vtable PARAMS ((tree, tree));
static void initialize_array PARAMS ((tree, tree));
static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
! tree, tree, splay_tree));
! static tree end_of_class PARAMS ((tree, int));
static bool layout_empty_base PARAMS ((tree, tree, splay_tree, tree));
static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
tree));
static void set_vindex PARAMS ((tree, int *));
*************** static int walk_subobject_offsets PARAMS
*** 206,216 ****
tree, splay_tree, tree, int));
static void record_subobject_offsets PARAMS ((tree, tree, splay_tree, int));
static int layout_conflict_p PARAMS ((tree, tree, splay_tree, int));
static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1,
splay_tree_key k2));
! static void warn_about_ambiguous_direct_bases PARAMS ((tree));
static bool type_requires_array_cookie PARAMS ((tree));
static bool contains_empty_class_p (tree);
/* Macros for dfs walking during vtt construction. See
dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits
--- 206,216 ----
tree, splay_tree, tree, int));
static void record_subobject_offsets PARAMS ((tree, tree, splay_tree, int));
static int layout_conflict_p PARAMS ((tree, tree, splay_tree, int));
static int splay_tree_compare_integer_csts PARAMS ((splay_tree_key k1,
splay_tree_key k2));
! static void warn_about_ambiguous_bases PARAMS ((tree));
static bool type_requires_array_cookie PARAMS ((tree));
static bool contains_empty_class_p (tree);
/* Macros for dfs walking during vtt construction. See
dfs_ctor_vtable_bases_queue_p, dfs_build_secondary_vptr_vtt_inits
*************** walk_subobject_offsets (type, f, offset,
*** 3510,3530 ****
return 0;
if (CLASS_TYPE_P (type))
{
tree field;
int i;
/* Record the location of TYPE. */
r = (*f) (type, offset, offsets);
if (r)
return r;
/* Iterate through the direct base classes of TYPE. */
for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
{
! tree binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
if (!vbases_p
&& TREE_VIA_VIRTUAL (binfo)
&& !BINFO_PRIMARY_P (binfo))
continue;
--- 3510,3535 ----
return 0;
if (CLASS_TYPE_P (type))
{
tree field;
+ tree binfo;
int i;
/* Record the location of TYPE. */
r = (*f) (type, offset, offsets);
if (r)
return r;
/* Iterate through the direct base classes of TYPE. */
for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
{
! binfo = BINFO_BASETYPE (TYPE_BINFO (type), i);
!
! if (abi_version_at_least (2)
! && TREE_VIA_VIRTUAL (binfo))
! continue;
if (!vbases_p
&& TREE_VIA_VIRTUAL (binfo)
&& !BINFO_PRIMARY_P (binfo))
continue;
*************** walk_subobject_offsets (type, f, offset,
*** 3534,3551 ****
size_binop (PLUS_EXPR,
offset,
BINFO_OFFSET (binfo)),
offsets,
max_offset,
! vbases_p);
if (r)
return r;
}
/* Iterate through the fields of TYPE. */
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
! if (TREE_CODE (field) == FIELD_DECL)
{
tree field_offset;
if (abi_version_at_least (2))
field_offset = byte_position (field);
--- 3539,3582 ----
size_binop (PLUS_EXPR,
offset,
BINFO_OFFSET (binfo)),
offsets,
max_offset,
! (abi_version_at_least (2)
! ? /*vbases_p=*/0 : vbases_p));
if (r)
return r;
}
+ /* Iterate through the virtual base classes of TYPE. In G++
+ 3.2, we included virtual bases in the direct base class loop
+ above, which results in incorrect results; the correct
+ offsets for virtual bases are only known when working with
+ the most derived type. */
+ if (abi_version_at_least (2) && vbases_p)
+ {
+ tree vbase;
+
+ for (vbase = CLASSTYPE_VBASECLASSES (type);
+ vbase;
+ vbase = TREE_CHAIN (vbase))
+ {
+ binfo = TREE_VALUE (vbase);
+ r = walk_subobject_offsets (BINFO_TYPE (binfo),
+ f,
+ size_binop (PLUS_EXPR,
+ offset,
+ BINFO_OFFSET (binfo)),
+ offsets,
+ max_offset,
+ /*vbases_p=*/0);
+ }
+ }
+
/* Iterate through the fields of TYPE. */
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
! if (TREE_CODE (field) == FIELD_DECL && !DECL_ARTIFICIAL (field))
{
tree field_offset;
if (abi_version_at_least (2))
field_offset = byte_position (field);
*************** walk_subobject_offsets (type, f, offset,
*** 3569,3580 ****
{
tree domain = TYPE_DOMAIN (type);
tree index;
/* Step through each of the elements in the array. */
! for (index = size_zero_node;
! INT_CST_LT (index, TYPE_MAX_VALUE (domain));
index = size_binop (PLUS_EXPR, index, size_one_node))
{
r = walk_subobject_offsets (TREE_TYPE (type),
f,
offset,
--- 3600,3614 ----
{
tree domain = TYPE_DOMAIN (type);
tree index;
/* Step through each of the elements in the array. */
! for (index = size_zero_node;
! /* G++ 3.2 had an off-by-one error here. */
! (abi_version_at_least (2)
! ? !INT_CST_LT (TYPE_MAX_VALUE (domain), index)
! : INT_CST_LT (index, TYPE_MAX_VALUE (domain)));
index = size_binop (PLUS_EXPR, index, size_one_node))
{
r = walk_subobject_offsets (TREE_TYPE (type),
f,
offset,
*************** layout_conflict_p (type, offset, offsets
*** 3638,3663 ****
}
/* DECL is a FIELD_DECL corresponding either to a base subobject of a
non-static data member of the type indicated by RLI. BINFO is the
binfo corresponding to the base subobject, OFFSETS maps offsets to
! types already located at those offsets. T is the most derived
! type. This function determines the position of the DECL. */
static void
! layout_nonempty_base_or_field (rli, decl, binfo, offsets, t)
! record_layout_info rli;
! tree decl;
! tree binfo;
! splay_tree offsets;
! tree t;
{
tree offset = NULL_TREE;
! tree type = TREE_TYPE (decl);
! /* If we are laying out a base class, rather than a field, then
! DECL_ARTIFICIAL will be set on the FIELD_DECL. */
! int field_p = !DECL_ARTIFICIAL (decl);
/* Try to place the field. It may take more than one try if we have
a hard time placing the field without putting two objects of the
same type at the same address. */
while (1)
--- 3672,3709 ----
}
/* DECL is a FIELD_DECL corresponding either to a base subobject of a
non-static data member of the type indicated by RLI. BINFO is the
binfo corresponding to the base subobject, OFFSETS maps offsets to
! types already located at those offsets. This function determines
! the position of the DECL. */
static void
! layout_nonempty_base_or_field (record_layout_info rli,
! tree decl,
! tree binfo,
! splay_tree offsets)
{
+ tree t = rli->t;
tree offset = NULL_TREE;
! bool field_p;
! tree type;
!
! if (binfo)
! {
! /* For the purposes of determining layout conflicts, we want to
! use the class type of BINFO; TREE_TYPE (DECL) will be the
! CLASSTYPE_AS_BASE version, which does not contain entries for
! zero-sized bases. */
! type = TREE_TYPE (binfo);
! field_p = false;
! }
! else
! {
! type = TREE_TYPE (decl);
! field_p = true;
! }
/* Try to place the field. It may take more than one try if we have
a hard time placing the field without putting two objects of the
same type at the same address. */
while (1)
*************** layout_nonempty_base_or_field (rli, decl
*** 3681,3694 ****
as the S we already allocated. So, we have to skip ahead.
Since all data members, including those whose type is an
empty class, have nonzero size, any overlap can happen only
with a direct or indirect base-class -- it can't happen with
a data member. */
! if (layout_conflict_p (TREE_TYPE (decl),
! offset,
! offsets,
! field_p))
{
/* Strip off the size allocated to this field. That puts us
at the first place we could have put the field with
proper alignment. */
*rli = old_rli;
--- 3727,3737 ----
as the S we already allocated. So, we have to skip ahead.
Since all data members, including those whose type is an
empty class, have nonzero size, any overlap can happen only
with a direct or indirect base-class -- it can't happen with
a data member. */
! if (layout_conflict_p (type, offset, offsets, field_p))
{
/* Strip off the size allocated to this field. That puts us
at the first place we could have put the field with
proper alignment. */
*rli = old_rli;
*************** layout_nonempty_base_or_field (rli, decl
*** 3707,3718 ****
}
/* Now that we know where it will be placed, update its
BINFO_OFFSET. */
if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
propagate_binfo_offsets (binfo,
! convert (ssizetype, offset), t);
}
/* Layout the empty base BINFO. EOC indicates the byte currently just
past the end of the class, and should be correctly aligned for a
class of the type indicated by BINFO; OFFSETS gives the offsets of
--- 3750,3768 ----
}
/* Now that we know where it will be placed, update its
BINFO_OFFSET. */
if (binfo && CLASS_TYPE_P (BINFO_TYPE (binfo)))
+ /* Indirect virtual bases may have a non-zero BINFO_OFFSET at
+ this point because their BINFO_OFFSET is copied from another
+ hierarchy. Therefore, we may not need to add the entire
+ OFFSET. */
propagate_binfo_offsets (binfo,
! size_diffop (convert (ssizetype, offset),
! convert (ssizetype,
! BINFO_OFFSET (binfo))),
! t);
}
/* Layout the empty base BINFO. EOC indicates the byte currently just
past the end of the class, and should be correctly aligned for a
class of the type indicated by BINFO; OFFSETS gives the offsets of
*************** layout_empty_base (binfo, eoc, offsets,
*** 3766,3884 ****
}
}
return atend;
}
! /* Build a FIELD_DECL for the base given by BINFO in the class
! indicated by RLI. If the new object is non-empty, clear *EMPTY_P.
! *BASE_ALIGN is a running maximum of the alignments of any base
! class. OFFSETS gives the location of empty base subobjects. T is
! the most derived type. Return nonzero if the new object cannot be
! nearly-empty. */
!
! static bool
! build_base_field (rli, binfo, empty_p, offsets, t)
! record_layout_info rli;
! tree binfo;
! int *empty_p;
! splay_tree offsets;
! tree t;
{
tree basetype = BINFO_TYPE (binfo);
- tree decl;
- bool atend = false;
if (!COMPLETE_TYPE_P (basetype))
/* This error is now reported in xref_tag, thus giving better
location information. */
! return atend;
! decl = build_decl (FIELD_DECL, NULL_TREE, basetype);
! DECL_ARTIFICIAL (decl) = 1;
! DECL_FIELD_CONTEXT (decl) = rli->t;
! DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
! DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
! DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
! DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
! /* Tell the backend not to round up to TYPE_ALIGN. */
! DECL_PACKED (decl) = 1;
!
! if (!integer_zerop (DECL_SIZE (decl)))
{
/* The containing class is non-empty because it has a non-empty
base class. */
! *empty_p = 0;
!
/* Try to place the field. It may take more than one try if we
have a hard time placing the field without putting two
objects of the same type at the same address. */
! layout_nonempty_base_or_field (rli, decl, binfo, offsets, t);
}
else
{
! unsigned HOST_WIDE_INT eoc;
/* On some platforms (ARM), even empty classes will not be
byte-aligned. */
! eoc = tree_low_cst (rli_size_unit_so_far (rli), 0);
! eoc = CEIL (eoc, DECL_ALIGN_UNIT (decl)) * DECL_ALIGN_UNIT (decl);
! atend |= layout_empty_base (binfo, size_int (eoc), offsets, t);
}
/* Record the offsets of BINFO and its base subobjects. */
record_subobject_offsets (BINFO_TYPE (binfo),
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0);
! return atend;
}
/* Layout all of the non-virtual base classes. Record empty
! subobjects in OFFSETS. T is the most derived type. Return
! nonzero if the type cannot be nearly empty. */
! static bool
! build_base_fields (rli, empty_p, offsets, t)
! record_layout_info rli;
! int *empty_p;
! splay_tree offsets;
! tree t;
{
/* Chain to hold all the new FIELD_DECLs which stand in for base class
subobjects. */
! tree rec = rli->t;
! int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
int i;
- bool atend = 0;
/* The primary base class is always allocated first. */
! if (CLASSTYPE_HAS_PRIMARY_BASE_P (rec))
! build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (rec),
! empty_p, offsets, t);
/* Now allocate the rest of the bases. */
for (i = 0; i < n_baseclasses; ++i)
{
tree base_binfo;
! base_binfo = BINFO_BASETYPE (TYPE_BINFO (rec), i);
/* The primary base was already allocated above, so we don't
need to allocate it again here. */
! if (base_binfo == CLASSTYPE_PRIMARY_BINFO (rec))
continue;
/* A primary virtual base class is allocated just like any other
base class, but a non-primary virtual base is allocated
later, in layout_virtual_bases. */
if (TREE_VIA_VIRTUAL (base_binfo)
&& !BINFO_PRIMARY_P (base_binfo))
continue;
! atend |= build_base_field (rli, base_binfo, empty_p, offsets, t);
}
- return atend;
}
/* Go through the TYPE_METHODS of T issuing any appropriate
diagnostics, figuring out which methods override which other
methods, and so forth. */
--- 3816,3947 ----
}
}
return atend;
}
! /* Layout the the base given by BINFO in the class indicated by RLI.
! If the new object is non-empty, and EMPTY_P is non-NULL, clear
! *EMPTY_P. *BASE_ALIGN is a running maximum of the alignments of
! any base class. OFFSETS gives the location of empty base
! subobjects. T is the most derived type. Return nonzero if the new
! object cannot be nearly-empty. A new FIELD_DECL is inserted at
! *NEXT_FIELD, unless BINFO is for an empty base class.
!
! Returns the location at which the next field should be inserted. */
!
! static tree *
! build_base_field (record_layout_info rli, tree binfo, int *empty_p,
! splay_tree offsets, tree *next_field)
{
+ tree t = rli->t;
tree basetype = BINFO_TYPE (binfo);
if (!COMPLETE_TYPE_P (basetype))
/* This error is now reported in xref_tag, thus giving better
location information. */
! return next_field;
! /* Place the base class. */
! if (!is_empty_class (basetype))
{
+ tree decl;
+
/* The containing class is non-empty because it has a non-empty
base class. */
! if (empty_p)
! *empty_p = 0;
!
! /* Create the FIELD_DECL. */
! decl = build_decl (FIELD_DECL, NULL_TREE, CLASSTYPE_AS_BASE (basetype));
! DECL_ARTIFICIAL (decl) = 1;
! DECL_FIELD_CONTEXT (decl) = t;
! DECL_SIZE (decl) = CLASSTYPE_SIZE (basetype);
! DECL_SIZE_UNIT (decl) = CLASSTYPE_SIZE_UNIT (basetype);
! DECL_ALIGN (decl) = CLASSTYPE_ALIGN (basetype);
! DECL_USER_ALIGN (decl) = CLASSTYPE_USER_ALIGN (basetype);
! /* Tell the backend not to round up to TYPE_ALIGN. */
! DECL_PACKED (decl) = 1;
!
/* Try to place the field. It may take more than one try if we
have a hard time placing the field without putting two
objects of the same type at the same address. */
! layout_nonempty_base_or_field (rli, decl, binfo, offsets);
! /* Add the new FIELD_DECL to the list of fields for T. */
! TREE_CHAIN (decl) = *next_field;
! *next_field = decl;
! next_field = &TREE_CHAIN (decl);
}
else
{
! tree eoc;
/* On some platforms (ARM), even empty classes will not be
byte-aligned. */
! eoc = round_up (rli_size_unit_so_far (rli),
! CLASSTYPE_ALIGN_UNIT (basetype));
! if (layout_empty_base (binfo, eoc, offsets, t))
! CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
!
! /* We do not create a FIELD_DECL for empty base classes because
! it might overlap some other field. We want to be able to
! create CONSTRUCTORs for the class by iterating over the
! FIELD_DECLs, and the back end does not handle overlapping
! FIELD_DECLs. */
}
/* Record the offsets of BINFO and its base subobjects. */
record_subobject_offsets (BINFO_TYPE (binfo),
BINFO_OFFSET (binfo),
offsets,
/*vbases_p=*/0);
!
! return next_field;
}
/* Layout all of the non-virtual base classes. Record empty
! subobjects in OFFSETS. T is the most derived type. Return nonzero
! if the type cannot be nearly empty. The fields created
! corresponding to the base classes will be inserted at
! *NEXT_FIELD. */
! static void
! build_base_fields (record_layout_info rli, int *empty_p,
! splay_tree offsets, tree *next_field)
{
/* Chain to hold all the new FIELD_DECLs which stand in for base class
subobjects. */
! tree t = rli->t;
! int n_baseclasses = CLASSTYPE_N_BASECLASSES (t);
int i;
/* The primary base class is always allocated first. */
! if (CLASSTYPE_HAS_PRIMARY_BASE_P (t))
! next_field = build_base_field (rli, CLASSTYPE_PRIMARY_BINFO (t),
! empty_p, offsets, next_field);
/* Now allocate the rest of the bases. */
for (i = 0; i < n_baseclasses; ++i)
{
tree base_binfo;
! base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
/* The primary base was already allocated above, so we don't
need to allocate it again here. */
! if (base_binfo == CLASSTYPE_PRIMARY_BINFO (t))
continue;
/* A primary virtual base class is allocated just like any other
base class, but a non-primary virtual base is allocated
later, in layout_virtual_bases. */
if (TREE_VIA_VIRTUAL (base_binfo)
&& !BINFO_PRIMARY_P (base_binfo))
continue;
! next_field = build_base_field (rli, base_binfo, empty_p,
! offsets, next_field);
}
}
/* Go through the TYPE_METHODS of T issuing any appropriate
diagnostics, figuring out which methods override which other
methods, and so forth. */
*************** dfs_set_offset_for_unshared_vbases (binf
*** 4565,4604 ****
}
return NULL_TREE;
}
! /* Set BINFO_OFFSET for all of the virtual bases for T. Update
TYPE_ALIGN and TYPE_SIZE for T. OFFSETS gives the location of
empty subobjects of T. */
static void
! layout_virtual_bases (t, offsets)
! tree t;
! splay_tree offsets;
{
! tree vbases, dsize;
! unsigned HOST_WIDE_INT eoc;
bool first_vbase = true;
if (CLASSTYPE_N_BASECLASSES (t) == 0)
return;
#ifdef STRUCTURE_SIZE_BOUNDARY
! /* Packed structures don't need to have minimum size. */
! if (! TYPE_PACKED (t))
! TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), STRUCTURE_SIZE_BOUNDARY);
#endif
! /* DSIZE is the size of the class without the virtual bases. */
! if (abi_version_at_least(2))
! dsize = CLASSTYPE_SIZE (t);
! else
! dsize = TYPE_SIZE (t);
!
! /* Make every class have alignment of at least one. */
! TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), BITS_PER_UNIT);
/* Go through the virtual bases, allocating space for each virtual
base that is not already a primary base class. These are
allocated in inheritance graph order. */
for (vbases = TYPE_BINFO (t);
--- 4628,4672 ----
}
return NULL_TREE;
}
! /* Set BINFO_OFFSET for all of the virtual bases for RLI->T. Update
TYPE_ALIGN and TYPE_SIZE for T. OFFSETS gives the location of
empty subobjects of T. */
static void
! layout_virtual_bases (record_layout_info rli, splay_tree offsets)
{
! tree vbases;
! tree t = rli->t;
bool first_vbase = true;
+ tree *next_field;
if (CLASSTYPE_N_BASECLASSES (t) == 0)
return;
+ if (!abi_version_at_least(2))
+ {
+ /* In G++ 3.2, we incorrectly rounded the size before laying out
+ the virtual bases. */
+ finish_record_layout (rli, /*free_p=*/false);
#ifdef STRUCTURE_SIZE_BOUNDARY
! /* Packed structures don't need to have minimum size. */
! if (! TYPE_PACKED (t))
! TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), STRUCTURE_SIZE_BOUNDARY);
#endif
+ rli->offset = TYPE_SIZE_UNIT (t);
+ rli->bitpos = bitsize_zero_node;
+ rli->record_align = TYPE_ALIGN (t);
+ }
! /* Find the last field. The artificial fields created for virtual
! bases will go after the last extant field to date. */
! next_field = &TYPE_FIELDS (t);
! while (*next_field)
! next_field = &TREE_CHAIN (*next_field);
/* Go through the virtual bases, allocating space for each virtual
base that is not already a primary base class. These are
allocated in inheritance graph order. */
for (vbases = TYPE_BINFO (t);
*************** layout_virtual_bases (t, offsets)
*** 4612,4741 ****
vbase = binfo_for_vbase (BINFO_TYPE (vbases), t);
if (!BINFO_PRIMARY_P (vbase))
{
/* This virtual base is not a primary base of any class in the
hierarchy, so we have to add space for it. */
! tree basetype, usize;
! unsigned int desired_align;
!
! basetype = BINFO_TYPE (vbase);
!
! desired_align = CLASSTYPE_ALIGN (basetype);
! TYPE_ALIGN (t) = MAX (TYPE_ALIGN (t), desired_align);
!
! /* Add padding so that we can put the virtual base class at an
! appropriately aligned offset. */
! dsize = round_up (dsize, desired_align);
! usize = size_binop (CEIL_DIV_EXPR, dsize, bitsize_unit_node);
!
! /* We try to squish empty virtual bases in just like
! ordinary empty bases. */
! if (is_empty_class (basetype))
! layout_empty_base (vbase,
! convert (sizetype, usize),
! offsets, t);
! else
! {
! tree offset;
!
! offset = convert (ssizetype, usize);
! offset = size_diffop (offset,
! convert (ssizetype,
! BINFO_OFFSET (vbase)));
!
! /* And compute the offset of the virtual base. */
! propagate_binfo_offsets (vbase, offset, t);
! /* Every virtual baseclass takes a least a UNIT, so that
! we can take it's address and get something different
! for each base. */
! dsize = size_binop (PLUS_EXPR, dsize,
! size_binop (MAX_EXPR, bitsize_unit_node,
! CLASSTYPE_SIZE (basetype)));
! }
/* If the first virtual base might have been placed at a
lower address, had we started from CLASSTYPE_SIZE, rather
than TYPE_SIZE, issue a warning. There can be both false
positives and false negatives from this warning in rare
cases; to deal with all the possibilities would probably
require performing both layout algorithms and comparing
the results which is not particularly tractable. */
if (warn_abi
&& first_vbase
! && tree_int_cst_lt (size_binop (CEIL_DIV_EXPR,
! round_up (CLASSTYPE_SIZE (t),
! desired_align),
! bitsize_unit_node),
! BINFO_OFFSET (vbase)))
warning ("offset of virtual base `%T' is not ABI-compliant and may change in a future version of GCC",
basetype);
- /* Keep track of the offsets assigned to this virtual base. */
- record_subobject_offsets (BINFO_TYPE (vbase),
- BINFO_OFFSET (vbase),
- offsets,
- /*vbases_p=*/0);
-
first_vbase = false;
}
}
/* Now, go through the TYPE_BINFO hierarchy, setting the
BINFO_OFFSETs correctly for all non-primary copies of the virtual
bases and their direct and indirect bases. The ambiguity checks
in lookup_base depend on the BINFO_OFFSETs being set
correctly. */
dfs_walk (TYPE_BINFO (t), dfs_set_offset_for_unshared_vbases, NULL, t);
-
- /* If we had empty base classes that protruded beyond the end of the
- class, we didn't update DSIZE above; we were hoping to overlay
- multiple such bases at the same location. */
- eoc = end_of_class (t, /*include_virtuals_p=*/1);
- dsize = size_binop (MAX_EXPR, dsize, bitsize_int (eoc * BITS_PER_UNIT));
-
- /* Now, make sure that the total size of the type is a multiple of
- its alignment. */
- dsize = round_up (dsize, TYPE_ALIGN (t));
- TYPE_SIZE (t) = dsize;
- TYPE_SIZE_UNIT (t) = convert (sizetype,
- size_binop (CEIL_DIV_EXPR, TYPE_SIZE (t),
- bitsize_unit_node));
-
- /* Check for ambiguous virtual bases. */
- if (extra_warnings)
- for (vbases = CLASSTYPE_VBASECLASSES (t);
- vbases;
- vbases = TREE_CHAIN (vbases))
- {
- tree basetype = BINFO_TYPE (TREE_VALUE (vbases));
-
- if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
- warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
- basetype, t);
- }
}
/* Returns the offset of the byte just past the end of the base class
with the highest offset in T. If INCLUDE_VIRTUALS_P is zero, then
only non-virtual bases are included. */
! static unsigned HOST_WIDE_INT
end_of_class (t, include_virtuals_p)
tree t;
int include_virtuals_p;
{
! unsigned HOST_WIDE_INT result = 0;
int i;
for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
{
tree base_binfo;
tree offset;
tree size;
- unsigned HOST_WIDE_INT end_of_base;
base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
if (!include_virtuals_p
&& TREE_VIA_VIRTUAL (base_binfo)
--- 4680,4743 ----
vbase = binfo_for_vbase (BINFO_TYPE (vbases), t);
if (!BINFO_PRIMARY_P (vbase))
{
+ tree basetype = TREE_TYPE (vbase);
+
/* This virtual base is not a primary base of any class in the
hierarchy, so we have to add space for it. */
! next_field = build_base_field (rli, vbase, /*empty_p=*/NULL,
! offsets, next_field);
/* If the first virtual base might have been placed at a
lower address, had we started from CLASSTYPE_SIZE, rather
than TYPE_SIZE, issue a warning. There can be both false
positives and false negatives from this warning in rare
cases; to deal with all the possibilities would probably
require performing both layout algorithms and comparing
the results which is not particularly tractable. */
if (warn_abi
&& first_vbase
! && (tree_int_cst_lt
! (size_binop (CEIL_DIV_EXPR,
! round_up (CLASSTYPE_SIZE (t),
! CLASSTYPE_ALIGN (basetype)),
! bitsize_unit_node),
! BINFO_OFFSET (vbase))))
warning ("offset of virtual base `%T' is not ABI-compliant and may change in a future version of GCC",
basetype);
first_vbase = false;
}
}
/* Now, go through the TYPE_BINFO hierarchy, setting the
BINFO_OFFSETs correctly for all non-primary copies of the virtual
bases and their direct and indirect bases. The ambiguity checks
in lookup_base depend on the BINFO_OFFSETs being set
correctly. */
dfs_walk (TYPE_BINFO (t), dfs_set_offset_for_unshared_vbases, NULL, t);
}
/* Returns the offset of the byte just past the end of the base class
with the highest offset in T. If INCLUDE_VIRTUALS_P is zero, then
only non-virtual bases are included. */
! static tree
end_of_class (t, include_virtuals_p)
tree t;
int include_virtuals_p;
{
! tree result = size_zero_node;
int i;
for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
{
tree base_binfo;
tree offset;
tree size;
base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
if (!include_virtuals_p
&& TREE_VIA_VIRTUAL (base_binfo)
*************** end_of_class (t, include_virtuals_p)
*** 4750,4791 ****
else
size = CLASSTYPE_SIZE_UNIT (BINFO_TYPE (base_binfo));
offset = size_binop (PLUS_EXPR,
BINFO_OFFSET (base_binfo),
size);
! end_of_base = tree_low_cst (offset, /*pos=*/1);
! if (end_of_base > result)
! result = end_of_base;
}
return result;
}
! /* Warn about direct bases of T that are inaccessible because they are
ambiguous. For example:
struct S {};
struct T : public S {};
struct U : public S, public T {};
Here, `(S*) new U' is not allowed because there are two `S'
subobjects of U. */
static void
! warn_about_ambiguous_direct_bases (t)
tree t;
{
int i;
for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
{
! tree basetype = TYPE_BINFO_BASETYPE (t, i);
if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
! basetype, t);
}
}
/* Compare two INTEGER_CSTs K1 and K2. */
static int
--- 4752,4808 ----
else
size = CLASSTYPE_SIZE_UNIT (BINFO_TYPE (base_binfo));
offset = size_binop (PLUS_EXPR,
BINFO_OFFSET (base_binfo),
size);
! if (INT_CST_LT_UNSIGNED (result, offset))
! result = offset;
}
return result;
}
! /* Warn about bases of T that are inaccessible because they are
ambiguous. For example:
struct S {};
struct T : public S {};
struct U : public S, public T {};
Here, `(S*) new U' is not allowed because there are two `S'
subobjects of U. */
static void
! warn_about_ambiguous_bases (t)
tree t;
{
int i;
+ tree vbases;
+ tree basetype;
+ /* Check direct bases. */
for (i = 0; i < CLASSTYPE_N_BASECLASSES (t); ++i)
{
! basetype = TYPE_BINFO_BASETYPE (t, i);
if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
! basetype, t);
}
+
+ /* Check for ambiguous virtual bases. */
+ if (extra_warnings)
+ for (vbases = CLASSTYPE_VBASECLASSES (t);
+ vbases;
+ vbases = TREE_CHAIN (vbases))
+ {
+ basetype = BINFO_TYPE (TREE_VALUE (vbases));
+
+ if (!lookup_base (t, basetype, ba_ignore | ba_quiet, NULL))
+ warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
+ basetype, t);
+ }
}
/* Compare two INTEGER_CSTs K1 and K2. */
static int
*************** splay_tree_compare_integer_csts (k1, k2)
*** 4794,4803 ****
--- 4811,4843 ----
splay_tree_key k2;
{
return tree_int_cst_compare ((tree) k1, (tree) k2);
}
+ /* Increase the size indicated in RLI to account for empty classes
+ that are "off the end" of the class. */
+
+ static void
+ include_empty_classes (record_layout_info rli)
+ {
+ tree eoc;
+
+ /* It might be the case that we grew the class to allocate a
+ zero-sized base class. That won't be reflected in RLI, yet,
+ because we are willing to overlay multiple bases at the same
+ offset. However, now we need to make sure that RLI is big enough
+ to reflect the entire class. */
+ eoc = end_of_class (rli->t,
+ CLASSTYPE_AS_BASE (rli->t) != NULL_TREE);
+ if (TREE_CODE (rli_size_unit_so_far (rli)) == INTEGER_CST
+ && INT_CST_LT_UNSIGNED (rli_size_unit_so_far (rli), eoc))
+ {
+ rli->offset = size_binop (MAX_EXPR, rli->offset, eoc);
+ rli->bitpos = bitsize_zero_node;
+ }
+ }
+
/* Calculate the TYPE_SIZE, TYPE_ALIGN, etc for T. Calculate
BINFO_OFFSETs for all of the base-classes. Position the vtable
pointer. Accumulate declared virtual functions on VIRTUALS_P. */
static void
*************** layout_class_type (t, empty_p, vfuns_p,
*** 4809,4824 ****
{
tree non_static_data_members;
tree field;
tree vptr;
record_layout_info rli;
- unsigned HOST_WIDE_INT eoc;
/* Maps offsets (represented as INTEGER_CSTs) to a TREE_LIST of
types that appear at that offset. */
splay_tree empty_base_offsets;
/* True if the last field layed out was a bit-field. */
bool last_field_was_bitfield = false;
/* Keep track of the first non-static data member. */
non_static_data_members = TYPE_FIELDS (t);
/* Start laying out the record. */
--- 4849,4867 ----
{
tree non_static_data_members;
tree field;
tree vptr;
record_layout_info rli;
/* Maps offsets (represented as INTEGER_CSTs) to a TREE_LIST of
types that appear at that offset. */
splay_tree empty_base_offsets;
/* True if the last field layed out was a bit-field. */
bool last_field_was_bitfield = false;
+ /* The location at which the next field should be inserted. */
+ tree *next_field;
+ /* T, as a base class. */
+ tree base_t;
/* Keep track of the first non-static data member. */
non_static_data_members = TYPE_FIELDS (t);
/* Start laying out the record. */
*************** layout_class_type (t, empty_p, vfuns_p,
*** 4832,4850 ****
vptr = create_vtable_ptr (t, empty_p, virtuals_p);
/* The vptr is always the first thing in the class. */
if (vptr)
{
! TYPE_FIELDS (t) = chainon (vptr, TYPE_FIELDS (t));
place_field (rli, vptr);
}
/* Build FIELD_DECLs for all of the non-virtual base-types. */
empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts,
NULL, NULL);
! if (build_base_fields (rli, empty_p, empty_base_offsets, t))
! CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
/* Layout the non-static data members. */
for (field = non_static_data_members; field; field = TREE_CHAIN (field))
{
tree type;
--- 4875,4896 ----
vptr = create_vtable_ptr (t, empty_p, virtuals_p);
/* The vptr is always the first thing in the class. */
if (vptr)
{
! TREE_CHAIN (vptr) = TYPE_FIELDS (t);
! TYPE_FIELDS (t) = vptr;
! next_field = &TREE_CHAIN (vptr);
place_field (rli, vptr);
}
+ else
+ next_field = &TYPE_FIELDS (t);
/* Build FIELD_DECLs for all of the non-virtual base-types. */
empty_base_offsets = splay_tree_new (splay_tree_compare_integer_csts,
NULL, NULL);
! build_base_fields (rli, empty_p, empty_base_offsets, next_field);
/* Layout the non-static data members. */
for (field = non_static_data_members; field; field = TREE_CHAIN (field))
{
tree type;
*************** layout_class_type (t, empty_p, vfuns_p,
*** 4915,4925 ****
}
else
padding = NULL_TREE;
layout_nonempty_base_or_field (rli, field, NULL_TREE,
! empty_base_offsets, t);
/* If a bit-field does not immediately follow another bit-field,
and yet it starts in the middle of a byte, we have failed to
comply with the ABI. */
if (warn_abi
--- 4961,4971 ----
}
else
padding = NULL_TREE;
layout_nonempty_base_or_field (rli, field, NULL_TREE,
! empty_base_offsets);
/* If a bit-field does not immediately follow another bit-field,
and yet it starts in the middle of a byte, we have failed to
comply with the ABI. */
if (warn_abi
*************** layout_class_type (t, empty_p, vfuns_p,
*** 4955,5049 ****
DECL_SIZE (padding_field) = padding;
DECL_ALIGN (padding_field) = 1;
DECL_USER_ALIGN (padding_field) = 0;
layout_nonempty_base_or_field (rli, padding_field,
NULL_TREE,
! empty_base_offsets, t);
}
last_field_was_bitfield = DECL_C_BIT_FIELD (field);
}
! /* It might be the case that we grew the class to allocate a
! zero-sized base class. That won't be reflected in RLI, yet,
! because we are willing to overlay multiple bases at the same
! offset. However, now we need to make sure that RLI is big enough
! to reflect the entire class. */
! eoc = end_of_class (t, /*include_virtuals_p=*/0);
! if (TREE_CODE (rli_size_unit_so_far (rli)) == INTEGER_CST
! && compare_tree_int (rli_size_unit_so_far (rli), eoc) < 0)
! {
! rli->offset = size_binop (MAX_EXPR, rli->offset, size_int (eoc));
! rli->bitpos = bitsize_zero_node;
! }
!
! /* We make all structures have at least one element, so that they
! have nonzero size. The class may be empty even if it has
! basetypes. Therefore, we add the fake field after all the other
! fields; if there are already FIELD_DECLs on the list, their
! offsets will not be disturbed. */
! if (!eoc && *empty_p)
! {
! tree padding;
!
! padding = build_decl (FIELD_DECL, NULL_TREE, char_type_node);
! place_field (rli, padding);
! }
! else if (abi_version_at_least (2)
! && !integer_zerop (rli->bitpos))
/* Make sure that we are on a byte boundary so that the size of
the class without virtual bases will always be a round number
of bytes. */
rli->bitpos = round_up (rli->bitpos, BITS_PER_UNIT);
!
! /* Let the back-end lay out the type. Note that at this point we
! have only included non-virtual base-classes; we will lay out the
! virtual base classes later. So, the TYPE_SIZE/TYPE_ALIGN after
! this call are not necessarily correct; they are just the size and
! alignment when no virtual base clases are used. */
! finish_record_layout (rli);
/* Delete all zero-width bit-fields from the list of fields. Now
that the type is laid out they are no longer important. */
remove_zero_width_bit_fields (t);
! /* Remember the size and alignment of the class before adding
! the virtual bases. */
! if (*empty_p)
{
! CLASSTYPE_SIZE (t) = bitsize_zero_node;
! CLASSTYPE_SIZE_UNIT (t) = size_zero_node;
! }
! /* If this is a POD, we can't reuse its tail padding. */
! else if (!CLASSTYPE_NON_POD_P (t))
! {
! CLASSTYPE_SIZE (t) = TYPE_SIZE (t);
! CLASSTYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (t);
}
else
! {
! CLASSTYPE_SIZE (t) = TYPE_BINFO_SIZE (t);
! CLASSTYPE_SIZE_UNIT (t) = TYPE_BINFO_SIZE_UNIT (t);
! }
!
! CLASSTYPE_ALIGN (t) = TYPE_ALIGN (t);
! CLASSTYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (t);
/* Set the TYPE_DECL for this type to contain the right
value for DECL_OFFSET, so that we can use it as part
of a COMPONENT_REF for multiple inheritance. */
layout_decl (TYPE_MAIN_DECL (t), 0);
/* Now fix up any virtual base class types that we left lying
around. We must get these done before we try to lay out the
virtual function table. As a side-effect, this will remove the
base subobject fields. */
! layout_virtual_bases (t, empty_base_offsets);
! /* Warn about direct bases that can't be talked about due to
! ambiguity. */
! warn_about_ambiguous_direct_bases (t);
/* Clean up. */
splay_tree_delete (empty_base_offsets);
}
--- 5001,5089 ----
DECL_SIZE (padding_field) = padding;
DECL_ALIGN (padding_field) = 1;
DECL_USER_ALIGN (padding_field) = 0;
layout_nonempty_base_or_field (rli, padding_field,
NULL_TREE,
! empty_base_offsets);
}
last_field_was_bitfield = DECL_C_BIT_FIELD (field);
}
! if (abi_version_at_least (2) && !integer_zerop (rli->bitpos))
/* Make sure that we are on a byte boundary so that the size of
the class without virtual bases will always be a round number
of bytes. */
rli->bitpos = round_up (rli->bitpos, BITS_PER_UNIT);
!
! /* Make sure that empty classes are reflected in RLI at this
! point. */
! include_empty_classes(rli);
/* Delete all zero-width bit-fields from the list of fields. Now
that the type is laid out they are no longer important. */
remove_zero_width_bit_fields (t);
! /* Create the version of T used for virtual bases. We do not use
! make_aggr_type for this version; this is an artificial type. For
! a POD type, we just reuse T. */
! if (CLASSTYPE_NON_POD_P (t) || *empty_p)
{
! base_t = make_node (TREE_CODE (t));
!
! /* Set the size and alignment for the new type. */
! TYPE_SIZE (base_t) = rli_size_so_far (rli);
! TYPE_SIZE_UNIT (base_t) = rli_size_unit_so_far (rli);
! TYPE_ALIGN (base_t) = rli->record_align;
! TYPE_USER_ALIGN (base_t) = TYPE_USER_ALIGN (t);
!
! /* Copy the fields from T. */
! next_field = &TYPE_FIELDS (base_t);
! for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
! if (TREE_CODE (field) == FIELD_DECL)
! {
! *next_field = build_decl (FIELD_DECL,
! DECL_NAME (field),
! TREE_TYPE (field));
! DECL_CONTEXT (*next_field) = base_t;
! DECL_FIELD_OFFSET (*next_field) = DECL_FIELD_OFFSET (field);
! DECL_FIELD_BIT_OFFSET (*next_field)
! = DECL_FIELD_BIT_OFFSET (field);
! next_field = &TREE_CHAIN (*next_field);
! }
!
! /* Record the base version of the type. */
! CLASSTYPE_AS_BASE (t) = base_t;
}
else
! CLASSTYPE_AS_BASE (t) = t;
/* Set the TYPE_DECL for this type to contain the right
value for DECL_OFFSET, so that we can use it as part
of a COMPONENT_REF for multiple inheritance. */
layout_decl (TYPE_MAIN_DECL (t), 0);
/* Now fix up any virtual base class types that we left lying
around. We must get these done before we try to lay out the
virtual function table. As a side-effect, this will remove the
base subobject fields. */
! layout_virtual_bases (rli, empty_base_offsets);
!
! /* Make sure that empty classes are reflected in RLI at this
! point. */
! include_empty_classes(rli);
!
! /* Make sure not to create any structures with zero size. */
! if (integer_zerop (rli_size_unit_so_far (rli)) && *empty_p)
! place_field (rli,
! build_decl (FIELD_DECL, NULL_TREE, char_type_node));
!
! /* Let the back-end lay out the type. */
! finish_record_layout (rli, /*free_p=*/true);
! /* Warn about bases that can't be talked about due to ambiguity. */
! warn_about_ambiguous_bases (t);
/* Clean up. */
splay_tree_delete (empty_base_offsets);
}
*************** contains_empty_class_p (tree type)
*** 6412,6422 ****
for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
if (contains_empty_class_p (TYPE_BINFO_BASETYPE (type, i)))
return true;
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
! if (contains_empty_class_p (TREE_TYPE (field)))
return true;
}
else if (TREE_CODE (type) == ARRAY_TYPE)
return contains_empty_class_p (TREE_TYPE (type));
return false;
--- 6452,6464 ----
for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); ++i)
if (contains_empty_class_p (TYPE_BINFO_BASETYPE (type, i)))
return true;
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
! if (TREE_CODE (field) == FIELD_DECL
! && !DECL_ARTIFICIAL (field)
! && is_empty_class (TREE_TYPE (field)))
return true;
}
else if (TREE_CODE (type) == ARRAY_TYPE)
return contains_empty_class_p (TREE_TYPE (type));
return false;
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.752
diff -c -5 -p -r1.752 cp-tree.h
*** cp/cp-tree.h 23 Sep 2002 09:22:14 -0000 1.752
--- cp/cp-tree.h 30 Sep 2002 16:04:46 -0000
*************** struct diagnostic_context;
*** 57,66 ****
--- 57,67 ----
(TREE_CALLS_NEW) (in _EXPR or _REF) (commented-out).
TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (in _TYPE).
INHERITED_VALUE_BINDING_P (in CPLUS_BINDING)
ICS_ELLIPSIS_FLAG (in _CONV)
BINFO_ACCESS (in BINFO)
+ DECL_INITIALIZED_P (in VAR_DECL)
2: IDENTIFIER_OPNAME_P.
TYPE_POLYMORPHIC_P (in _TYPE)
ICS_THIS_FLAG (in _CONV)
BINDING_HAS_LEVEL_P (in CPLUS_BINDING)
BINFO_LOST_PRIMARY_P (in BINFO)
*************** struct diagnostic_context;
*** 94,108 ****
DECL_TEMPLATE_PARM_P (in PARM_DECL, CONST_DECL, TYPE_DECL, or TEMPLATE_DECL)
DECL_LOCAL_FUNCTION_P (in FUNCTION_DECL)
DECL_MUTABLE_P (in FIELD_DECL)
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
- DECL_C_BITFIELD (in FIELD_DECL)
2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL)
3: DECL_IN_AGGR_P.
! 4: DECL_C_BIT_FIELD
5: DECL_INTERFACE_KNOWN.
6: DECL_THIS_STATIC (in VAR_DECL or FUNCTION_DECL).
7: DECL_DEAD_FOR_LOCAL (in VAR_DECL).
DECL_THUNK_P (in a member FUNCTION_DECL)
--- 95,108 ----
DECL_TEMPLATE_PARM_P (in PARM_DECL, CONST_DECL, TYPE_DECL, or TEMPLATE_DECL)
DECL_LOCAL_FUNCTION_P (in FUNCTION_DECL)
DECL_MUTABLE_P (in FIELD_DECL)
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
DECL_IMPLICIT_TYPEDEF_P (in a TYPE_DECL)
3: DECL_IN_AGGR_P.
! 4: DECL_C_BIT_FIELD (in a FIELD_DECL)
5: DECL_INTERFACE_KNOWN.
6: DECL_THIS_STATIC (in VAR_DECL or FUNCTION_DECL).
7: DECL_DEAD_FOR_LOCAL (in VAR_DECL).
DECL_THUNK_P (in a member FUNCTION_DECL)
*************** struct lang_type_class GTY(())
*** 1148,1159 ****
tree primary_base;
tree vfields;
tree vbases;
tree tags;
! tree size;
! tree size_unit;
tree pure_virtuals;
tree friend_classes;
tree rtti;
tree methods;
tree template_info;
--- 1148,1158 ----
tree primary_base;
tree vfields;
tree vbases;
tree tags;
! tree as_base;
tree pure_virtuals;
tree friend_classes;
tree rtti;
tree methods;
tree template_info;
*************** struct lang_type GTY(())
*** 1394,1409 ****
/* Number of direct baseclasses of NODE. */
#define CLASSTYPE_N_BASECLASSES(NODE) \
(BINFO_N_BASETYPES (TYPE_BINFO (NODE)))
/* These are the size and alignment of the type without its virtual
base classes, for when we use this type as a base itself. */
! #define CLASSTYPE_SIZE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->size)
! #define CLASSTYPE_SIZE_UNIT(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->size_unit)
! #define CLASSTYPE_ALIGN(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->align)
! #define CLASSTYPE_USER_ALIGN(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->user_align)
/* The alignment of NODE, without its virtual bases, in bytes. */
#define CLASSTYPE_ALIGN_UNIT(NODE) \
(CLASSTYPE_ALIGN (NODE) / BITS_PER_UNIT)
--- 1393,1413 ----
/* Number of direct baseclasses of NODE. */
#define CLASSTYPE_N_BASECLASSES(NODE) \
(BINFO_N_BASETYPES (TYPE_BINFO (NODE)))
+ /* The type corresponding to NODE when NODE is used as a base class,
+ i.e., NODE without virtual base classes. */
+
+ #define CLASSTYPE_AS_BASE(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->as_base)
+
/* These are the size and alignment of the type without its virtual
base classes, for when we use this type as a base itself. */
! #define CLASSTYPE_SIZE(NODE) TYPE_SIZE (CLASSTYPE_AS_BASE (NODE))
! #define CLASSTYPE_SIZE_UNIT(NODE) TYPE_SIZE_UNIT (CLASSTYPE_AS_BASE (NODE))
! #define CLASSTYPE_ALIGN(NODE) TYPE_ALIGN (CLASSTYPE_AS_BASE (NODE))
! #define CLASSTYPE_USER_ALIGN(NODE) TYPE_USER_ALIGN (CLASSTYPE_AS_BASE (NODE))
/* The alignment of NODE, without its virtual bases, in bytes. */
#define CLASSTYPE_ALIGN_UNIT(NODE) \
(CLASSTYPE_ALIGN (NODE) / BITS_PER_UNIT)
*************** struct lang_decl GTY(())
*** 1952,1961 ****
--- 1956,1970 ----
detecting circularity in case members are multiply defined. In the
case of a VAR_DECL, it is also used to determine how program storage
should be allocated. */
#define DECL_IN_AGGR_P(NODE) (DECL_LANG_FLAG_3 (NODE))
+ /* Nonzero for a VAR_DECL means that the variable's initialization has
+ been processed. */
+ #define DECL_INITIALIZED_P(NODE) \
+ (TREE_LANG_FLAG_1 (VAR_DECL_CHECK (NODE)))
+
/* Nonzero if the DECL was initialized in the class definition itself,
rather than outside the class. */
#define DECL_INITIALIZED_IN_CLASS_P(DECL) \
(DECL_LANG_SPECIFIC (DECL)->decl_flags.initialized_in_class)
*************** extern void mark_all_runtime_matches
*** 3848,3858 ****
extern int nothrow_libfn_p PARAMS ((tree));
extern void check_handlers PARAMS ((tree));
extern void choose_personality_routine PARAMS ((enum languages));
/* in expr.c */
- extern int extract_init PARAMS ((tree, tree));
extern rtx cxx_expand_expr PARAMS ((tree, rtx,
enum machine_mode,
int));
extern tree cplus_expand_constant PARAMS ((tree));
--- 3857,3866 ----
*************** extern tree expand_member_init PARAMS
*** 3868,3878 ****
extern tree build_aggr_init PARAMS ((tree, tree, int));
extern tree build_init PARAMS ((tree, tree, int));
extern int is_aggr_type PARAMS ((tree, int));
extern tree get_aggr_from_typedef PARAMS ((tree, int));
extern tree get_type_value PARAMS ((tree));
! extern tree build_forced_zero_init PARAMS ((tree));
extern tree build_member_call PARAMS ((tree, tree, tree));
extern tree build_offset_ref PARAMS ((tree, tree));
extern tree resolve_offset_ref PARAMS ((tree));
extern tree build_new PARAMS ((tree, tree, tree, int));
extern tree build_vec_init PARAMS ((tree, tree, int));
--- 3876,3886 ----
extern tree build_aggr_init PARAMS ((tree, tree, int));
extern tree build_init PARAMS ((tree, tree, int));
extern int is_aggr_type PARAMS ((tree, int));
extern tree get_aggr_from_typedef PARAMS ((tree, int));
extern tree get_type_value PARAMS ((tree));
! extern tree build_zero_init (tree, bool);
extern tree build_member_call PARAMS ((tree, tree, tree));
extern tree build_offset_ref PARAMS ((tree, tree));
extern tree resolve_offset_ref PARAMS ((tree));
extern tree build_new PARAMS ((tree, tree, tree, int));
extern tree build_vec_init PARAMS ((tree, tree, int));
*************** extern void cxx_incomplete_type_error P
*** 4342,4352 ****
extern tree error_not_base_type PARAMS ((tree, tree));
extern tree binfo_or_else PARAMS ((tree, tree));
extern void readonly_error PARAMS ((tree, const char *, int));
extern int abstract_virtuals_error PARAMS ((tree, tree));
- extern tree force_store_init_value PARAMS ((tree, tree));
extern tree store_init_value PARAMS ((tree, tree));
extern tree digest_init PARAMS ((tree, tree, tree *));
extern tree build_scoped_ref PARAMS ((tree, tree, tree *));
extern tree build_x_arrow PARAMS ((tree));
extern tree build_m_component_ref PARAMS ((tree, tree));
--- 4350,4359 ----
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.936
diff -c -5 -p -r1.936 decl.c
*** cp/decl.c 21 Sep 2002 12:51:53 -0000 1.936
--- cp/decl.c 30 Sep 2002 16:04:49 -0000
*************** static void storedecls PARAMS ((tree));
*** 65,75 ****
static void require_complete_types_for_parms PARAMS ((tree));
static int ambi_op_p PARAMS ((enum tree_code));
static int unary_op_p PARAMS ((enum tree_code));
static tree store_bindings PARAMS ((tree, tree));
static tree lookup_tag_reverse PARAMS ((tree, tree));
- static tree obscure_complex_init PARAMS ((tree, tree));
static tree lookup_name_real PARAMS ((tree, int, int, int));
static void push_local_name PARAMS ((tree));
static void warn_extern_redeclared_static PARAMS ((tree, tree));
static tree grok_reference_init PARAMS ((tree, tree, tree));
static tree grokfndecl PARAMS ((tree, tree, tree, tree, int,
--- 65,74 ----
*************** duplicate_decls (newdecl, olddecl)
*** 3458,3468 ****
if (TREE_CODE (newdecl) == TYPE_DECL
&& newtype == DECL_ORIGINAL_TYPE (newdecl))
newtype = oldtype;
if (TREE_CODE (newdecl) == VAR_DECL)
! DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
/* Do this after calling `merge_types' so that default
parameters don't confuse us. */
else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
!= TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl))))
--- 3457,3471 ----
if (TREE_CODE (newdecl) == TYPE_DECL
&& newtype == DECL_ORIGINAL_TYPE (newdecl))
newtype = oldtype;
if (TREE_CODE (newdecl) == VAR_DECL)
! {
! DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
! DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
! }
!
/* Do this after calling `merge_types' so that default
parameters don't confuse us. */
else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
!= TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl))))
*************** grok_reference_init (decl, type, init)
*** 7546,7594 ****
DECL_INITIAL (decl) = tmp;
return NULL_TREE;
}
- /* Fill in DECL_INITIAL with some magical value to prevent expand_decl from
- mucking with forces it does not comprehend (i.e. initialization with a
- constructor). If we are at global scope and won't go into COMMON, fill
- it in with a dummy CONSTRUCTOR to force the variable into .data;
- otherwise we can use error_mark_node. */
-
- static tree
- obscure_complex_init (decl, init)
- tree decl, init;
- {
- if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
- {
- error ("run-time initialization of thread-local storage");
- return NULL_TREE;
- }
-
- if (! flag_no_inline && TREE_STATIC (decl))
- {
- if (extract_init (decl, init))
- return NULL_TREE;
- }
-
- #if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
- if (toplevel_bindings_p () && ! DECL_COMMON (decl))
- DECL_INITIAL (decl) = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE,
- NULL_TREE);
- else
- #endif
- {
- if (zero_init_p (TREE_TYPE (decl)))
- DECL_INITIAL (decl) = error_mark_node;
- /* Otherwise, force_store_init_value will have already stored a
- zero-init initializer in DECL_INITIAL, that should be
- retained. */
- }
-
- return init;
- }
-
/* When parsing `int a[] = {1, 2};' we don't know the size of the
array until we finish parsing the initializer. If that's the
situation we're in, update DECL accordingly. */
static void
--- 7549,7558 ----
*************** check_for_uninitialized_const_var (decl)
*** 7771,7791 ****
static tree
check_initializer (decl, init)
tree decl;
tree init;
{
! tree type;
!
! if (TREE_CODE (decl) == FIELD_DECL)
! return init;
!
! type = TREE_TYPE (decl);
/* If `start_decl' didn't like having an initialization, ignore it now. */
if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
init = NULL_TREE;
/* Check the initializer. */
if (init)
{
/* Things that are going to be initialized need to have complete
type. */
--- 7735,7756 ----
static tree
check_initializer (decl, init)
tree decl;
tree init;
{
! tree type = TREE_TYPE (decl);
/* If `start_decl' didn't like having an initialization, ignore it now. */
if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
init = NULL_TREE;
+ /* If an initializer is present, DECL_INITIAL has been
+ error_mark_node, to indicate that an as-of-yet unevaluated
+ initialization will occur. From now on, DECL_INITIAL reflects
+ the static initialization -- if any -- of DECL. */
+ DECL_INITIAL (decl) = NULL_TREE;
+
/* Check the initializer. */
if (init)
{
/* Things that are going to be initialized need to have complete
type. */
*************** check_initializer (decl, init)
*** 7821,7845 ****
my_friendly_assert (init != NULL_TREE, 149);
init = NULL_TREE;
}
else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
! {
! init = grok_reference_init (decl, type, init);
! if (init)
! init = obscure_complex_init (decl, init);
! }
! else if (!DECL_EXTERNAL (decl) && !zero_init_p (type))
! {
! force_store_init_value (decl, build_forced_zero_init (type));
!
! if (init)
! goto process_init;
! }
else if (init)
{
- process_init:
if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
{
if (TREE_CODE (type) == ARRAY_TYPE)
init = digest_init (type, init, (tree *) 0);
else if (TREE_CODE (init) == CONSTRUCTOR
--- 7786,7798 ----
my_friendly_assert (init != NULL_TREE, 149);
init = NULL_TREE;
}
else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
! init = grok_reference_init (decl, type, init);
else if (init)
{
if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
{
if (TREE_CODE (type) == ARRAY_TYPE)
init = digest_init (type, init, (tree *) 0);
else if (TREE_CODE (init) == CONSTRUCTOR
*************** check_initializer (decl, init)
*** 7859,7873 ****
{
dont_use_constructor:
if (TREE_CODE (init) != TREE_VEC)
init = store_init_value (decl, init);
}
-
- if (init)
- /* We must hide the initializer so that expand_decl
- won't try to do something it does not understand. */
- init = obscure_complex_init (decl, init);
}
else if (DECL_EXTERNAL (decl))
;
else if (TYPE_P (type)
&& (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type)))
--- 7812,7821 ----
*************** check_initializer (decl, init)
*** 7882,7895 ****
error ("structure `%D' with uninitialized reference members",
decl);
}
check_for_uninitialized_const_var (decl);
-
- if (COMPLETE_TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
- init = obscure_complex_init (decl, NULL_TREE);
-
}
else
check_for_uninitialized_const_var (decl);
return init;
--- 7830,7839 ----
*************** cp_finish_decl (decl, init, asmspec_tree
*** 8253,8266 ****
grokclassfn. Lay this out fresh. */
SET_DECL_RTL (TREE_TYPE (decl), NULL_RTX);
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
make_decl_rtl (decl, asmspec);
}
!
! /* Deduce size of array from initialization, if not already known. */
! init = check_initializer (decl, init);
! maybe_deduce_size_from_array_init (decl, init);
/* Add this declaration to the statement-tree. This needs to happen
after the call to check_initializer so that the DECL_STMT for a
reference temp is added before the DECL_STMT for the reference itself. */
if (building_stmt_tree ()
--- 8197,8254 ----
grokclassfn. Lay this out fresh. */
SET_DECL_RTL (TREE_TYPE (decl), NULL_RTX);
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
make_decl_rtl (decl, asmspec);
}
! else if (TREE_CODE (decl) == RESULT_DECL)
! init = check_initializer (decl, init);
! else if (TREE_CODE (decl) == VAR_DECL)
! {
! /* Only PODs can have thread-local storage. Other types may require
! various kinds of non-trivial initialization. */
! if (DECL_THREAD_LOCAL (decl) && !pod_type_p (TREE_TYPE (decl)))
! error ("`%D' cannot be thread-local because it has non-POD type `%T'",
! decl, TREE_TYPE (decl));
! /* Convert the initializer to the type of DECL, if we have not
! already initialized DECL. */
! if (!DECL_INITIALIZED_P (decl)
! /* If !DECL_EXTERNAL then DECL is being defined. In the
! case of a static data memberm initialized inside the
! class-specifier, there can be an initializer even if DECL
! is *not* defined. */
! && (!DECL_EXTERNAL (decl) || init))
! {
! init = check_initializer (decl, init);
! /* If DECL has an array type without a specific bound, deduce the
! array size from the initializer. Note that this must be done
! after check_initializer is called because of cases like this:
!
! struct S { int a; int b; };
! struct S a[] = { 1, 2 };
!
! which creates a one-element array, not a two-element array. */
! maybe_deduce_size_from_array_init (decl, init);
! /* Handle:
!
! [dcl.init]
!
! The memory occupied by any object of static storage
! duration is zero-initialized at program startup before
! any other initialization takes place.
!
! We cannot create an appropriate initializer until after
! the type of DECL is finalized. If DECL_INITIAL is set,
! then the DECL is statically initialized, and any
! necessary zero-initialization has already been performed. */
! if (TREE_STATIC (decl) && !DECL_INITIAL (decl))
! DECL_INITIAL (decl) = build_zero_init (TREE_TYPE (decl),
! /*static_storage_p=*/true);
! /* Remember that the initialization for this variable has
! taken place. */
! DECL_INITIALIZED_P (decl) = 1;
! }
! }
/* Add this declaration to the statement-tree. This needs to happen
after the call to check_initializer so that the DECL_STMT for a
reference temp is added before the DECL_STMT for the reference itself. */
if (building_stmt_tree ()
Index: cp/expr.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/expr.c,v
retrieving revision 1.65
diff -c -5 -p -r1.65 expr.c
*** cp/expr.c 14 Sep 2002 12:07:42 -0000 1.65
--- cp/expr.c 30 Sep 2002 16:04:49 -0000
*************** cxx_expand_expr (exp, target, tmode, mod
*** 125,137 ****
}
abort ();
/* NOTREACHED */
return NULL;
}
-
- int
- extract_init (decl, init)
- tree decl ATTRIBUTE_UNUSED, init ATTRIBUTE_UNUSED;
- {
- return 0;
- }
-
--- 125,129 ----
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.292
diff -c -5 -p -r1.292 init.c
*** cp/init.c 21 Sep 2002 12:51:54 -0000 1.292
--- cp/init.c 30 Sep 2002 16:04:50 -0000
*************** initialize_vtbl_ptrs (addr)
*** 154,227 ****
NULL, dfs_unmarked_real_bases_queue_p, list);
dfs_walk (TYPE_BINFO (type), dfs_unmark,
dfs_marked_real_bases_queue_p, type);
}
! /* Types containing pointers to data members cannot be
! zero-initialized with zeros, because the NULL value for such
! pointers is -1.
!
! TYPE is a type that requires such zero initialization. The
! returned value is the initializer. */
tree
! build_forced_zero_init (type)
! tree type;
{
! tree init = NULL;
! if (AGGREGATE_TYPE_P (type) && !TYPE_PTRMEMFUNC_P (type))
{
! /* This is a default initialization of an aggregate, but not one of
! non-POD class type. We cleverly notice that the initialization
! rules in such a case are the same as for initialization with an
! empty brace-initialization list. */
! init = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE);
}
else if (TREE_CODE (type) == REFERENCE_TYPE)
! /* --if T is a reference type, no initialization is performed. */
! return NULL_TREE;
else
! {
! init = integer_zero_node;
!
! if (TREE_CODE (type) == ENUMERAL_TYPE)
! /* We must make enumeral types the right type. */
! init = fold (build1 (NOP_EXPR, type, init));
! }
! init = digest_init (type, init, 0);
return init;
}
! /* [dcl.init]:
! To default-initialize an object of type T means:
! --if T is a non-POD class type (clause _class_), the default construc-
! tor for T is called (and the initialization is ill-formed if T has
! no accessible default constructor);
! --if T is an array type, each element is default-initialized;
! --otherwise, the storage for the object is zero-initialized.
! A program that calls for default-initialization of an entity of refer-
! ence type is ill-formed. */
! static tree
! build_default_init (type)
! tree type;
! {
if (TYPE_NEEDS_CONSTRUCTING (type))
- /* Other code will handle running the default constructor. We can't do
- anything with a CONSTRUCTOR for arrays here, as that would imply
- copy-initialization. */
return NULL_TREE;
!
! return build_forced_zero_init (type);
}
/* Subroutine of emit_base_init. */
static void
--- 154,308 ----
NULL, dfs_unmarked_real_bases_queue_p, list);
dfs_walk (TYPE_BINFO (type), dfs_unmark,
dfs_marked_real_bases_queue_p, type);
}
! /* Return an expression for the zero-initialization of an object with
! type T. This expression will either be a constant (in the case
! that T is a scalar), or a CONSTRUCTOR (in the case that T is an
! aggregate). In either case, the value can be used as DECL_INITIAL
! for a decl of the indicated TYPE; it is a valid static initializer.
! If STATIC_STORAGE_P is TRUE, initializers are only generated for
! entities for which zero-initialization does not simply mean filling
! the storage with zero bytes. */
tree
! build_zero_init (tree type, bool static_storage_p)
{
! tree init = NULL_TREE;
!
! /* [dcl.init]
!
! To zero-initialization storage for an object of type T means:
!
! -- if T is a scalar type, the storage is set to the value of zero
! converted to T.
!
! -- if T is a non-union class type, the storage for each nonstatic
! data member and each base-class subobject is zero-initialized.
!
! -- if T is a union type, the storage for its first data member is
! zero-initialized.
!
! -- if T is an array type, the storage for each element is
! zero-initialized.
!
! -- if T is a reference type, no initialization is performed. */
! if (type == error_mark_node)
! ;
! else if (static_storage_p && zero_init_p (type))
! /* In order to save space, we do not explicitly build initializers
! for items that do not need them. GCC's semantics are that
! items with static storage duration that are not otherwise
! initialized are initialized to zero. */
! ;
! else if (SCALAR_TYPE_P (type))
! init = convert (type, integer_zero_node);
! else if (CLASS_TYPE_P (type))
! {
! tree field;
! tree inits;
!
! /* Build a constructor to contain the initializations. */
! init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
! /* Iterate over the fields, building initializations. */
! inits = NULL_TREE;
! for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
! {
! if (TREE_CODE (field) != FIELD_DECL)
! continue;
!
! /* Note that for class types there will be FIELD_DECLs
! corresponding to base classes as well. Thus, iterating
! over TYPE_FIELDs will result in correct initialization of
! all of the subobjects. */
! if (static_storage_p && !zero_init_p (TREE_TYPE (field)))
! inits = tree_cons (field,
! build_zero_init (TREE_TYPE (field),
! static_storage_p),
! inits);
!
! /* For unions, only the first field is initialized. */
! if (TREE_CODE (type) == UNION_TYPE)
! break;
! }
! CONSTRUCTOR_ELTS (init) = nreverse (inits);
! }
! else if (TREE_CODE (type) == ARRAY_TYPE)
{
! tree index;
! tree max_index;
! tree inits;
!
! /* Build a constructor to contain the initializations. */
! init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
! /* Iterate over the array elements, building initializations. */
! inits = NULL_TREE;
! for (index = size_zero_node, max_index = array_type_nelts (type);
! !tree_int_cst_lt (max_index, index);
! index = size_binop (PLUS_EXPR, index, size_one_node))
! inits = tree_cons (index,
! build_zero_init (TREE_TYPE (type),
! static_storage_p),
! inits);
! CONSTRUCTOR_ELTS (init) = nreverse (inits);
}
else if (TREE_CODE (type) == REFERENCE_TYPE)
! ;
else
! abort ();
! /* In all cases, the initializer is a constant. */
! if (init)
! TREE_CONSTANT (init) = 1;
return init;
}
! /* Build an expression for the default-initialization of an object
! with type T. If initialization T requires calling constructors,
! this function returns NULL_TREE; the caller is responsible for
! arranging for the constructors to be called. */
! static tree
! build_default_init (type)
! tree type;
! {
! /* [dcl.init]:
! To default-initialize an object of type T means:
! --if T is a non-POD class type (clause _class_), the default construc-
! tor for T is called (and the initialization is ill-formed if T has
! no accessible default constructor);
! --if T is an array type, each element is default-initialized;
! --otherwise, the storage for the object is zero-initialized.
! A program that calls for default-initialization of an entity of refer-
! ence type is ill-formed. */
!
! /* If TYPE_NEEDS_CONSTRUCTING is true, the caller is responsible for
! performing the initialization. This is confusing in that some
! non-PODs do not have TYPE_NEEDS_CONSTRUCTING set. (For example,
! a class with a pointer-to-data member as a non-static data member
! does not have TYPE_NEEDS_CONSTRUCTING set.) Therefore, we end up
! passing non-PODs to build_zero_init below, which is contrary to
! the semantics quoted above from [dcl.init].
!
! It happens, however, that the behavior of the constructor the
! standard says we should have generated would be precisely the
! same as that obtained by calling build_zero_init below, so things
! work out OK. */
if (TYPE_NEEDS_CONSTRUCTING (type))
return NULL_TREE;
!
! /* At this point, TYPE is either a POD class type, an array of POD
! classes, or something even more inoccuous. */
! return build_zero_init (type, /*static_storage_p=*/false);
}
/* Subroutine of emit_base_init. */
static void
*************** build_field_list (t, list, uses_unions_p
*** 333,343 ****
*uses_unions_p = 1;
for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields))
{
/* Skip CONST_DECLs for enumeration constants and so forth. */
! if (TREE_CODE (fields) != FIELD_DECL)
continue;
/* Keep track of whether or not any fields are unions. */
if (TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
*uses_unions_p = 1;
--- 414,424 ----
*uses_unions_p = 1;
for (fields = TYPE_FIELDS (t); fields; fields = TREE_CHAIN (fields))
{
/* Skip CONST_DECLs for enumeration constants and so forth. */
! if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
continue;
/* Keep track of whether or not any fields are unions. */
if (TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
*uses_unions_p = 1;
*************** push_base_cleanups ()
*** 3335,3345 ****
}
for (member = TYPE_FIELDS (current_class_type); member;
member = TREE_CHAIN (member))
{
! if (TREE_CODE (member) != FIELD_DECL)
continue;
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
{
tree this_member = (build_class_member_access_expr
(current_class_ref, member,
--- 3416,3426 ----
}
for (member = TYPE_FIELDS (current_class_type); member;
member = TREE_CHAIN (member))
{
! if (TREE_CODE (member) != FIELD_DECL || DECL_ARTIFICIAL (member))
continue;
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
{
tree this_member = (build_class_member_access_expr
(current_class_ref, member,
Index: cp/method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.230
diff -c -5 -p -r1.230 method.c
*** cp/method.c 21 Sep 2002 12:51:55 -0000 1.230
--- cp/method.c 30 Sep 2002 16:04:50 -0000
*************** do_build_assign_ref (fndecl)
*** 666,676 ****
fields = TREE_CHAIN (fields))
{
tree comp, init, t;
tree field = fields;
! if (TREE_CODE (field) != FIELD_DECL)
continue;
if (CP_TYPE_CONST_P (TREE_TYPE (field)))
{
error ("non-static const member `%#D', can't use default assignment operator", field);
--- 666,676 ----
fields = TREE_CHAIN (fields))
{
tree comp, init, t;
tree field = fields;
! if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
if (CP_TYPE_CONST_P (TREE_TYPE (field)))
{
error ("non-static const member `%#D', can't use default assignment operator", field);
*************** synthesize_exception_spec (type, extract
*** 822,832 ****
for (; fields; fields = TREE_CHAIN (fields))
{
tree type = TREE_TYPE (fields);
tree fn;
! if (TREE_CODE (fields) != FIELD_DECL)
continue;
while (TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type);
if (TREE_CODE (type) != RECORD_TYPE)
continue;
--- 822,832 ----
for (; fields; fields = TREE_CHAIN (fields))
{
tree type = TREE_TYPE (fields);
tree fn;
! if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
continue;
while (TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type);
if (TREE_CODE (type) != RECORD_TYPE)
continue;
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.617
diff -c -5 -p -r1.617 pt.c
*** cp/pt.c 21 Sep 2002 12:51:55 -0000 1.617
--- cp/pt.c 30 Sep 2002 16:04:53 -0000
*************** tsubst_decl (t, args, type, complain)
*** 6139,6149 ****
DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0;
/* Even if the original location is out of scope, the newly
substituted one is not. */
if (TREE_CODE (r) == VAR_DECL)
! DECL_DEAD_FOR_LOCAL (r) = 0;
if (!local_p)
{
/* A static data member declaration is always marked
external when it is declared in-class, even if an
--- 6139,6152 ----
DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0;
/* Even if the original location is out of scope, the newly
substituted one is not. */
if (TREE_CODE (r) == VAR_DECL)
! {
! DECL_DEAD_FOR_LOCAL (r) = 0;
! DECL_INITIALIZED_P (r) = 0;
! }
if (!local_p)
{
/* A static data member declaration is always marked
external when it is declared in-class, even if an
*************** regenerate_decl_from_template (decl, tmp
*** 9858,9870 ****
new_decl = tsubst (code_pattern, args, tf_error, NULL_TREE);
if (TREE_CODE (decl) == VAR_DECL)
{
/* Set up DECL_INITIAL, since tsubst doesn't. */
! DECL_INITIAL (new_decl) =
! tsubst_expr (DECL_INITIAL (code_pattern), args,
! tf_error, DECL_TI_TEMPLATE (decl));
}
else if (TREE_CODE (decl) == FUNCTION_DECL)
{
/* Convince duplicate_decls to use the DECL_ARGUMENTS from the
new decl. */
--- 9861,9874 ----
new_decl = tsubst (code_pattern, args, tf_error, NULL_TREE);
if (TREE_CODE (decl) == VAR_DECL)
{
/* Set up DECL_INITIAL, since tsubst doesn't. */
! if (!DECL_INITIALIZED_IN_CLASS_P (decl))
! DECL_INITIAL (new_decl) =
! tsubst_expr (DECL_INITIAL (code_pattern), args,
! tf_error, DECL_TI_TEMPLATE (decl));
}
else if (TREE_CODE (decl) == FUNCTION_DECL)
{
/* Convince duplicate_decls to use the DECL_ARGUMENTS from the
new decl. */
*************** instantiate_decl (d, defer_ok)
*** 10140,10150 ****
else
{
DECL_EXTERNAL (d) = 1;
DECL_NOT_REALLY_EXTERN (d) = 1;
}
! cp_finish_decl (d, DECL_INITIAL (d), NULL_TREE, 0);
}
else if (TREE_CODE (d) == FUNCTION_DECL)
{
htab_t saved_local_specializations;
--- 10144,10157 ----
else
{
DECL_EXTERNAL (d) = 1;
DECL_NOT_REALLY_EXTERN (d) = 1;
}
! cp_finish_decl (d,
! (!DECL_INITIALIZED_IN_CLASS_P (d)
! ? DECL_INITIAL (d) : NULL_TREE),
! NULL_TREE, 0);
}
else if (TREE_CODE (d) == FUNCTION_DECL)
{
htab_t saved_local_specializations;
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.238
diff -c -5 -p -r1.238 search.c
*** cp/search.c 21 Sep 2002 12:51:56 -0000 1.238
--- cp/search.c 30 Sep 2002 16:04:54 -0000
*************** dfs_push_decls (binfo, data)
*** 2534,2544 ****
{
tree fields;
for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
if (DECL_NAME (fields)
&& TREE_CODE (fields) != TYPE_DECL
! && TREE_CODE (fields) != USING_DECL)
setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/0);
else if (TREE_CODE (fields) == FIELD_DECL
&& ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
dfs_push_decls (TYPE_BINFO (TREE_TYPE (fields)), data);
--- 2534,2545 ----
{
tree fields;
for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
if (DECL_NAME (fields)
&& TREE_CODE (fields) != TYPE_DECL
! && TREE_CODE (fields) != USING_DECL
! && !DECL_ARTIFICIAL (fields))
setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/0);
else if (TREE_CODE (fields) == FIELD_DECL
&& ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
dfs_push_decls (TYPE_BINFO (TREE_TYPE (fields)), data);
*************** dfs_unuse_fields (binfo, data)
*** 2595,2605 ****
tree type = TREE_TYPE (binfo);
tree fields;
for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
{
! if (TREE_CODE (fields) != FIELD_DECL)
continue;
TREE_USED (fields) = 0;
if (DECL_NAME (fields) == NULL_TREE
&& ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
--- 2596,2606 ----
tree type = TREE_TYPE (binfo);
tree fields;
for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
{
! if (TREE_CODE (fields) != FIELD_DECL || DECL_ARTIFICIAL (fields))
continue;
TREE_USED (fields) = 0;
if (DECL_NAME (fields) == NULL_TREE
&& ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
Index: cp/tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/tree.c,v
retrieving revision 1.301
diff -c -5 -p -r1.301 tree.c
*** cp/tree.c 21 Sep 2002 12:51:56 -0000 1.301
--- cp/tree.c 30 Sep 2002 16:04:54 -0000
*************** int
*** 1935,1944 ****
--- 1935,1946 ----
pod_type_p (t)
tree t;
{
t = strip_array_types (t);
+ if (t == error_mark_node)
+ return 1;
if (INTEGRAL_TYPE_P (t))
return 1; /* integral, character or enumeral type */
if (FLOAT_TYPE_P (t))
return 1;
if (TYPE_PTR_P (t))
*************** pod_type_p (t)
*** 1961,1970 ****
--- 1963,1975 ----
int
zero_init_p (t)
tree t;
{
t = strip_array_types (t);
+
+ if (t == error_mark_node)
+ return 1;
/* NULL pointers to data members are initialized with -1. */
if (TYPE_PTRMEM_P (t))
return 0;
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.429
diff -c -5 -p -r1.429 typeck.c
*** cp/typeck.c 21 Sep 2002 12:51:56 -0000 1.429
--- cp/typeck.c 30 Sep 2002 16:04:55 -0000
*************** lookup_anon_field (t, type)
*** 1809,1819 ****
for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
{
if (TREE_STATIC (field))
continue;
! if (TREE_CODE (field) != FIELD_DECL)
continue;
/* If we find it directly, return the field. */
if (DECL_NAME (field) == NULL_TREE
&& type == TYPE_MAIN_VARIANT (TREE_TYPE (field)))
--- 1809,1819 ----
for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
{
if (TREE_STATIC (field))
continue;
! if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
/* If we find it directly, return the field. */
if (DECL_NAME (field) == NULL_TREE
&& type == TYPE_MAIN_VARIANT (TREE_TYPE (field)))
Index: cp/typeck2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck2.c,v
retrieving revision 1.128
diff -c -5 -p -r1.128 typeck2.c
*** cp/typeck2.c 14 Sep 2002 12:07:44 -0000 1.128
--- cp/typeck2.c 30 Sep 2002 16:04:55 -0000
*************** store_init_value (decl, init)
*** 318,333 ****
type = TREE_TYPE (decl);
if (TREE_CODE (type) == ERROR_MARK)
return NULL_TREE;
- #if 0
- /* This breaks arrays, and should not have any effect for other decls. */
- /* Take care of C++ business up here. */
- type = TYPE_MAIN_VARIANT (type);
- #endif
-
if (IS_AGGR_TYPE (type))
{
if (! TYPE_HAS_TRIVIAL_INIT_REF (type)
&& TREE_CODE (init) != CONSTRUCTOR)
abort ();
--- 318,327 ----
*************** store_init_value (decl, init)
*** 335,373 ****
if (TREE_CODE (init) == TREE_LIST)
{
error ("constructor syntax used, but no constructor declared for type `%T'", type);
init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (init));
}
- #if 0
- if (TREE_CODE (init) == CONSTRUCTOR)
- {
- tree field;
-
- /* Check that we're really an aggregate as ARM 8.4.1 defines it. */
- if (CLASSTYPE_N_BASECLASSES (type))
- cp_error_at ("initializer list construction invalid for derived class object `%D'", decl);
- if (CLASSTYPE_VTBL_PTR (type))
- cp_error_at ("initializer list construction invalid for polymorphic class object `%D'", decl);
- if (TYPE_NEEDS_CONSTRUCTING (type))
- {
- cp_error_at ("initializer list construction invalid for `%D'", decl);
- error ("due to the presence of a constructor");
- }
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- if (TREE_PRIVATE (field) || TREE_PROTECTED (field))
- {
- cp_error_at ("initializer list construction invalid for `%D'", decl);
- cp_error_at ("due to non-public access of member `%D'", field);
- }
- for (field = TYPE_METHODS (type); field; field = TREE_CHAIN (field))
- if (TREE_PRIVATE (field) || TREE_PROTECTED (field))
- {
- cp_error_at ("initializer list construction invalid for `%D'", decl);
- cp_error_at ("due to non-public access of member `%D'", field);
- }
- }
- #endif
}
else if (TREE_CODE (init) == TREE_LIST
&& TREE_TYPE (init) != unknown_type_node)
{
if (TREE_CODE (decl) == RESULT_DECL)
--- 329,338 ----
*************** store_init_value (decl, init)
*** 455,485 ****
when we output this function. */
DECL_INITIAL (decl) = value;
return NULL_TREE;
}
- /* Same as store_init_value, but used for known-to-be-valid static
- initializers. Used to introduce a static initializer even in data
- structures that may require dynamic initialization. */
-
- tree
- force_store_init_value (decl, init)
- tree decl, init;
- {
- tree type = TREE_TYPE (decl);
- int needs_constructing = TYPE_NEEDS_CONSTRUCTING (type);
-
- TYPE_NEEDS_CONSTRUCTING (type) = 0;
-
- init = store_init_value (decl, init);
- if (init)
- abort ();
-
- TYPE_NEEDS_CONSTRUCTING (type) = needs_constructing;
-
- return init;
- }
/* Digest the parser output INIT as an initializer for type TYPE.
Return a C expression of type TYPE to represent the initial value.
If TAIL is nonzero, it points to a variable holding a list of elements
--- 420,429 ----
*************** process_init_constructor (type, init, el
*** 789,799 ****
else
next1 = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE);
next1 = digest_init (TREE_TYPE (type), next1, 0);
}
else if (! zero_init_p (TREE_TYPE (type)))
! next1 = build_forced_zero_init (TREE_TYPE (type));
else
/* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */
break;
--- 733,744 ----
else
next1 = build (CONSTRUCTOR, NULL_TREE, NULL_TREE, NULL_TREE);
next1 = digest_init (TREE_TYPE (type), next1, 0);
}
else if (! zero_init_p (TREE_TYPE (type)))
! next1 = build_zero_init (TREE_TYPE (type),
! /*static_storage_p=*/false);
else
/* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */
break;
*************** process_init_constructor (type, init, el
*** 838,848 ****
{
members = tree_cons (field, integer_zero_node, members);
continue;
}
! if (TREE_CODE (field) != FIELD_DECL)
continue;
if (tail)
{
if (TREE_PURPOSE (tail)
--- 783,793 ----
{
members = tree_cons (field, integer_zero_node, members);
continue;
}
! if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
if (tail)
{
if (TREE_PURPOSE (tail)
*************** process_init_constructor (type, init, el
*** 907,917 ****
if (extra_warnings
&& (!init || TREE_HAS_CONSTRUCTOR (init)))
warning ("missing initializer for member `%D'", field);
if (! zero_init_p (TREE_TYPE (field)))
! next1 = build_forced_zero_init (TREE_TYPE (field));
else
/* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */
continue;
}
--- 852,863 ----
if (extra_warnings
&& (!init || TREE_HAS_CONSTRUCTOR (init)))
warning ("missing initializer for member `%D'", field);
if (! zero_init_p (TREE_TYPE (field)))
! next1 = build_zero_init (TREE_TYPE (field),
! /*static_storage_p=*/false);
else
/* The default zero-initialization is fine for us; don't
add anything to the CONSTRUCTOR. */
continue;
}
*************** process_init_constructor (type, init, el
*** 931,942 ****
{
register tree field = TYPE_FIELDS (type);
/* Find the first named field. ANSI decided in September 1990
that only named fields count here. */
! while (field && (DECL_NAME (field) == 0
! || TREE_CODE (field) != FIELD_DECL))
field = TREE_CHAIN (field);
/* If this element specifies a field, initialize via that field. */
if (TREE_PURPOSE (tail) != NULL_TREE)
{
--- 877,887 ----
{
register tree field = TYPE_FIELDS (type);
/* Find the first named field. ANSI decided in September 1990
that only named fields count here. */
! while (field && (!DECL_NAME (field) || TREE_CODE (field) != FIELD_DECL))
field = TREE_CHAIN (field);
/* If this element specifies a field, initialize via that field. */
if (TREE_PURPOSE (tail) != NULL_TREE)
{
Index: testsuite/g++.dg/abi/empty7.C
===================================================================
RCS file: testsuite/g++.dg/abi/empty7.C
diff -N testsuite/g++.dg/abi/empty7.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/abi/empty7.C 30 Sep 2002 16:04:56 -0000
***************
*** 0 ****
--- 1,18 ----
+ // { dg-do run { target i?86-*-* } }
+ // { dg-options "-fabi-version=0" }
+
+ struct S1 {};
+ struct S2 { virtual void f () {} S1 s1[4]; };
+ struct S3 : virtual public S2 {};
+ struct S4 : virtual public S2 { int i; };
+ struct S5 : public S3, virtual public S4 {};
+ struct S6 { S5 s5; };
+ struct S7 { S1 s1[5]; };
+ struct S8 : public S1, public S6, virtual public S7 { };
+
+ S8 s8;
+
+ int main () {
+ if ((char *)(S7 *)&s8 - (char *)&s8 != 24)
+ return 1;
+ }
Index: testsuite/g++.dg/init/pm2.C
===================================================================
RCS file: testsuite/g++.dg/init/pm2.C
diff -N testsuite/g++.dg/init/pm2.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/init/pm2.C 30 Sep 2002 16:04:56 -0000
***************
*** 0 ****
--- 1,7 ----
+ struct S {
+ S ();
+ int S::* sp;
+ int i;
+ };
+
+ S s[2] = {};