mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-24 19:00:01 +08:00
class.c (dfs_unshared_virtual_bases): Add ATTRIBUTE_UNUSED.
cp: * class.c (dfs_unshared_virtual_bases): Add ATTRIBUTE_UNUSED. (layout_empty_base): Return at end flag. (build_base_field): Likewise. (build_base_fields): Likewise. (layout_virtual_bases): Don't add 1 to eoc value. (end_of_class): Use full size for empty bases. (layout_class_type): Clear CLASSNEARLY_EMPTY_P if we appended empty bases. Don't add 1 to eoc value. Only add trailing padding if we're an empty class with no empty bases. (dump_class_hierarchy): Dump size and alignment. testsuite: * g++.old-deja/g++.abi/empty2.C: New test. * g++.old-deja/g++.abi/empty3.C: New test. From-SVN: r41460
This commit is contained in:
parent
a0a7b566f7
commit
06d9f09f53
@ -1,3 +1,16 @@
|
||||
2001-04-20 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* class.c (dfs_unshared_virtual_bases): Add ATTRIBUTE_UNUSED.
|
||||
(layout_empty_base): Return at end flag.
|
||||
(build_base_field): Likewise.
|
||||
(build_base_fields): Likewise.
|
||||
(layout_virtual_bases): Don't add 1 to eoc value.
|
||||
(end_of_class): Use full size for empty bases.
|
||||
(layout_class_type): Clear CLASSNEARLY_EMPTY_P if we appended
|
||||
empty bases. Don't add 1 to eoc value. Only add trailing padding
|
||||
if we're an empty class with no empty bases.
|
||||
(dump_class_hierarchy): Dump size and alignment.
|
||||
|
||||
2001-04-20 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* call.c (maybe_handle_ref_bind): Copy ICS_USER_FLAG and
|
||||
|
@ -144,10 +144,10 @@ 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 void build_base_field PARAMS ((record_layout_info, tree, int *,
|
||||
static bool build_base_field PARAMS ((record_layout_info, tree, int *,
|
||||
splay_tree));
|
||||
static bool build_base_fields PARAMS ((record_layout_info, int *,
|
||||
splay_tree));
|
||||
static void build_base_fields PARAMS ((record_layout_info, int *,
|
||||
splay_tree));
|
||||
static tree build_vbase_pointer_fields PARAMS ((record_layout_info, int *));
|
||||
static tree build_vtbl_or_vbase_field PARAMS ((tree, tree, tree, tree, tree,
|
||||
int *));
|
||||
@ -180,7 +180,7 @@ static void layout_nonempty_base_or_field PARAMS ((record_layout_info,
|
||||
tree, tree,
|
||||
splay_tree));
|
||||
static unsigned HOST_WIDE_INT end_of_class PARAMS ((tree, int));
|
||||
static void layout_empty_base PARAMS ((tree, tree, splay_tree));
|
||||
static bool layout_empty_base PARAMS ((tree, tree, splay_tree));
|
||||
static void accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree, tree));
|
||||
static tree dfs_accumulate_vtbl_inits PARAMS ((tree, tree, tree, tree,
|
||||
tree));
|
||||
@ -1825,7 +1825,7 @@ mark_primary_virtual_base (binfo, base_binfo, type)
|
||||
|
||||
static tree dfs_unshared_virtual_bases (binfo, data)
|
||||
tree binfo;
|
||||
void *data;
|
||||
void *data ATTRIBUTE_UNUSED;
|
||||
{
|
||||
if (TREE_VIA_VIRTUAL (binfo) && !BINFO_MARKED (binfo)
|
||||
&& CLASSTYPE_HAS_PRIMARY_BASE_P (BINFO_TYPE (binfo)))
|
||||
@ -4015,9 +4015,10 @@ layout_nonempty_base_or_field (rli, decl, binfo, offsets)
|
||||
/* 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
|
||||
the empty bases allocated so far. */
|
||||
the empty bases allocated so far. Return non-zero iff we added it
|
||||
at the end. */
|
||||
|
||||
static void
|
||||
static bool
|
||||
layout_empty_base (binfo, eoc, offsets)
|
||||
tree binfo;
|
||||
tree eoc;
|
||||
@ -4025,6 +4026,7 @@ layout_empty_base (binfo, eoc, offsets)
|
||||
{
|
||||
tree alignment;
|
||||
tree basetype = BINFO_TYPE (binfo);
|
||||
bool atend = false;
|
||||
|
||||
/* This routine should only be used for empty classes. */
|
||||
my_friendly_assert (is_empty_class (basetype), 20000321);
|
||||
@ -4039,6 +4041,7 @@ layout_empty_base (binfo, eoc, offsets)
|
||||
{
|
||||
/* That didn't work. Now, we move forward from the next
|
||||
available spot in the class. */
|
||||
atend = true;
|
||||
propagate_binfo_offsets (binfo, convert (ssizetype, eoc));
|
||||
while (1)
|
||||
{
|
||||
@ -4053,14 +4056,16 @@ layout_empty_base (binfo, eoc, offsets)
|
||||
propagate_binfo_offsets (binfo, alignment);
|
||||
}
|
||||
}
|
||||
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. */
|
||||
class. OFFSETS gives the location of empty base subobjects. Return
|
||||
non-zero if the new object cannot be nearly-empty. */
|
||||
|
||||
static void
|
||||
static bool
|
||||
build_base_field (rli, binfo, empty_p, offsets)
|
||||
record_layout_info rli;
|
||||
tree binfo;
|
||||
@ -4069,11 +4074,12 @@ build_base_field (rli, binfo, empty_p, offsets)
|
||||
{
|
||||
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;
|
||||
return atend;
|
||||
|
||||
decl = build_decl (FIELD_DECL, NULL_TREE, basetype);
|
||||
DECL_ARTIFICIAL (decl) = 1;
|
||||
@ -4102,7 +4108,7 @@ build_base_field (rli, binfo, empty_p, offsets)
|
||||
byte-aligned. */
|
||||
eoc = tree_low_cst (rli_size_unit_so_far (rli), 0);
|
||||
eoc = CEIL (eoc, DECL_ALIGN_UNIT (decl)) * DECL_ALIGN_UNIT (decl);
|
||||
layout_empty_base (binfo, size_int (eoc), offsets);
|
||||
atend |= layout_empty_base (binfo, size_int (eoc), offsets);
|
||||
}
|
||||
|
||||
/* Record the offsets of BINFO and its base subobjects. */
|
||||
@ -4110,12 +4116,14 @@ build_base_field (rli, binfo, empty_p, offsets)
|
||||
BINFO_OFFSET (binfo),
|
||||
offsets,
|
||||
/*vbases_p=*/0);
|
||||
return atend;
|
||||
}
|
||||
|
||||
/* Layout all of the non-virtual base classes. Record empty
|
||||
subobjects in OFFSETS. */
|
||||
subobjects in OFFSETS. Return non-zero if the type cannot be nearly
|
||||
empty. */
|
||||
|
||||
static void
|
||||
static bool
|
||||
build_base_fields (rli, empty_p, offsets)
|
||||
record_layout_info rli;
|
||||
int *empty_p;
|
||||
@ -4126,6 +4134,7 @@ build_base_fields (rli, empty_p, offsets)
|
||||
tree rec = rli->t;
|
||||
int n_baseclasses = CLASSTYPE_N_BASECLASSES (rec);
|
||||
int i;
|
||||
bool atend = 0;
|
||||
|
||||
/* Under the new ABI, the primary base class is always allocated
|
||||
first. */
|
||||
@ -4152,8 +4161,9 @@ build_base_fields (rli, empty_p, offsets)
|
||||
&& !BINFO_PRIMARY_P (base_binfo))
|
||||
continue;
|
||||
|
||||
build_base_field (rli, base_binfo, empty_p, offsets);
|
||||
atend |= build_base_field (rli, base_binfo, empty_p, offsets);
|
||||
}
|
||||
return atend;
|
||||
}
|
||||
|
||||
/* Go through the TYPE_METHODS of T issuing any appropriate
|
||||
@ -4828,7 +4838,7 @@ layout_virtual_bases (t, offsets)
|
||||
multiple such bases at the same location. */
|
||||
eoc = end_of_class (t, /*include_virtuals_p=*/1);
|
||||
if (eoc * BITS_PER_UNIT > dsize)
|
||||
dsize = (eoc + 1) * BITS_PER_UNIT;
|
||||
dsize = eoc * BITS_PER_UNIT;
|
||||
|
||||
/* Now, make sure that the total size of the type is a multiple of
|
||||
its alignment. */
|
||||
@ -4867,6 +4877,7 @@ end_of_class (t, include_virtuals_p)
|
||||
{
|
||||
tree base_binfo;
|
||||
tree offset;
|
||||
tree size;
|
||||
unsigned HOST_WIDE_INT end_of_base;
|
||||
|
||||
base_binfo = BINFO_BASETYPE (TYPE_BINFO (t), i);
|
||||
@ -4876,9 +4887,16 @@ end_of_class (t, include_virtuals_p)
|
||||
&& !BINFO_PRIMARY_P (base_binfo))
|
||||
continue;
|
||||
|
||||
if (is_empty_class (BINFO_TYPE (base_binfo)))
|
||||
/* An empty class has zero CLASSTYPE_SIZE_UNIT, but we need to
|
||||
allocate some space for it. It cannot have virtual bases,
|
||||
so TYPE_SIZE_UNIT is fine. */
|
||||
size = TYPE_SIZE_UNIT (BINFO_TYPE (base_binfo));
|
||||
else
|
||||
size = CLASSTYPE_SIZE_UNIT (BINFO_TYPE (base_binfo));
|
||||
offset = size_binop (PLUS_EXPR,
|
||||
BINFO_OFFSET (base_binfo),
|
||||
CLASSTYPE_SIZE_UNIT (BINFO_TYPE (base_binfo)));
|
||||
size);
|
||||
end_of_base = tree_low_cst (offset, /*pos=*/1);
|
||||
if (end_of_base > result)
|
||||
result = end_of_base;
|
||||
@ -4970,7 +4988,9 @@ layout_class_type (t, empty_p, vfuns_p,
|
||||
/* 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);
|
||||
if (build_base_fields (rli, empty_p, empty_base_offsets))
|
||||
CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
|
||||
|
||||
/* Add pointers to all of our virtual base-classes. */
|
||||
TYPE_FIELDS (t) = chainon (build_vbase_pointer_fields (rli, empty_p),
|
||||
TYPE_FIELDS (t));
|
||||
@ -5060,7 +5080,7 @@ layout_class_type (t, empty_p, vfuns_p,
|
||||
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 + 1));
|
||||
rli->offset = size_binop (MAX_EXPR, rli->offset, size_int (eoc));
|
||||
rli->bitpos = bitsize_zero_node;
|
||||
}
|
||||
|
||||
@ -5069,7 +5089,7 @@ layout_class_type (t, empty_p, vfuns_p,
|
||||
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 (*empty_p)
|
||||
if (!eoc && *empty_p)
|
||||
{
|
||||
tree padding;
|
||||
|
||||
@ -6758,8 +6778,11 @@ dump_class_hierarchy (name, t)
|
||||
error ("could not open dump file `%s'", name);
|
||||
return;
|
||||
}
|
||||
fprintf (stream, "%s\n",
|
||||
type_as_string (t, TFF_PLAIN_IDENTIFIER));
|
||||
fprintf (stream, "%s size=", type_as_string (t, TFF_PLAIN_IDENTIFIER));
|
||||
fprintf (stream, HOST_WIDE_INT_PRINT_DEC,
|
||||
tree_low_cst (TYPE_SIZE (t), 0) / BITS_PER_UNIT);
|
||||
fprintf (stream, " align=%lu\n",
|
||||
(unsigned long)(TYPE_ALIGN (t) / BITS_PER_UNIT));
|
||||
dump_class_hierarchy_r (stream, t, TYPE_BINFO (t), 0);
|
||||
fprintf (stream, "\n");
|
||||
if (name)
|
||||
|
@ -1,3 +1,8 @@
|
||||
2001-04-20 Nathan Sidwell <nathan@codesourcery.com>
|
||||
|
||||
* g++.old-deja/g++.abi/empty2.C: New test.
|
||||
* g++.old-deja/g++.abi/empty3.C: New test.
|
||||
|
||||
2001-04-20 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* g++.old-deja/g++.other/comdat2.C: New test.
|
||||
|
136
gcc/testsuite/g++.old-deja/g++.abi/empty2.C
Normal file
136
gcc/testsuite/g++.old-deja/g++.abi/empty2.C
Normal file
@ -0,0 +1,136 @@
|
||||
// Build don't link:
|
||||
|
||||
// Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
// Contributed by Nathan Sidwell 12 Apr 2001 <nathan@codesourcery.com>
|
||||
|
||||
// Check we deal with trailing empty base classes properly
|
||||
|
||||
struct A {};
|
||||
struct B1 : A {};
|
||||
struct B2 : A {};
|
||||
struct B3 : A {};
|
||||
struct B4 : A {};
|
||||
struct B5 : A {};
|
||||
struct B6 : A {};
|
||||
struct B7 : A {};
|
||||
struct B8 : A {};
|
||||
|
||||
struct C1 : B1
|
||||
{
|
||||
virtual void Foo () {};
|
||||
};
|
||||
struct C2 : B1, B2
|
||||
{
|
||||
virtual void Foo () {};
|
||||
};
|
||||
struct C3 : B1, B2, B3
|
||||
{
|
||||
virtual void Foo () {};
|
||||
};
|
||||
struct C4 : B1, B2, B3, B4
|
||||
{
|
||||
virtual void Foo () {};
|
||||
};
|
||||
struct C5 : B1, B2, B3, B4, B5
|
||||
{
|
||||
virtual void Foo () {};
|
||||
};
|
||||
struct C6 : B1, B2, B3, B4, B5, B6
|
||||
{
|
||||
virtual void Foo () {};
|
||||
};
|
||||
struct C7 : B1, B2, B3, B4, B5, B6, B7
|
||||
{
|
||||
virtual void Foo () {};
|
||||
};
|
||||
struct C8 : B1, B2, B3, B4, B5, B6, B7, B8
|
||||
{
|
||||
virtual void Foo () {};
|
||||
};
|
||||
|
||||
struct D1 : virtual C1 {};
|
||||
struct D2 : virtual C2 {};
|
||||
struct D3 : virtual C3 {};
|
||||
struct D4 : virtual C4 {};
|
||||
struct D5 : virtual C5 {};
|
||||
struct D6 : virtual C6 {};
|
||||
struct D7 : virtual C7 {};
|
||||
struct D8 : virtual C8 {};
|
||||
|
||||
unsigned const nearly_empty_size = sizeof (D1);
|
||||
|
||||
template <typename Cn, typename Dn> int Check (Dn const &ref)
|
||||
{
|
||||
if ((sizeof (Cn) <= nearly_empty_size)
|
||||
!= (static_cast <void const *> (&ref)
|
||||
== static_cast <Cn const *> (&ref)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename Bn, typename Cn> int Check ()
|
||||
{
|
||||
Cn c[2];
|
||||
|
||||
if (static_cast <A *> (static_cast <B1 *> (&c[1]))
|
||||
== static_cast <A *> (static_cast <Bn *> (&c[0])))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int main ()
|
||||
{
|
||||
#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
|
||||
if (Check<B1, C1> ())
|
||||
return 1;
|
||||
if (Check<B2, C2> ())
|
||||
return 2;
|
||||
if (Check<B3, C3> ())
|
||||
return 3;
|
||||
if (Check<B4, C4> ())
|
||||
return 4;
|
||||
if (Check<B5, C5> ())
|
||||
return 5;
|
||||
if (Check<B6, C6> ())
|
||||
return 6;
|
||||
if (Check<B7, C7> ())
|
||||
return 7;
|
||||
if (Check<B8, C8> ())
|
||||
return 8;
|
||||
|
||||
if (Check<C1> (D1 ()))
|
||||
return 11;
|
||||
if (Check<C2> (D2 ()))
|
||||
return 12;
|
||||
if (Check<C3> (D3 ()))
|
||||
return 13;
|
||||
if (Check<C4> (D4 ()))
|
||||
return 14;
|
||||
if (Check<C5> (D5 ()))
|
||||
return 15;
|
||||
if (Check<C6> (D6 ()))
|
||||
return 16;
|
||||
if (Check<C7> (D7 ()))
|
||||
return 17;
|
||||
if (Check<C8> (D8 ()))
|
||||
return 18;
|
||||
|
||||
if (sizeof (C2) == nearly_empty_size)
|
||||
return 22;
|
||||
if (sizeof (C3) == nearly_empty_size)
|
||||
return 23;
|
||||
if (sizeof (C4) == nearly_empty_size)
|
||||
return 24;
|
||||
if (sizeof (C5) == nearly_empty_size)
|
||||
return 25;
|
||||
if (sizeof (C6) == nearly_empty_size)
|
||||
return 26;
|
||||
if (sizeof (C7) == nearly_empty_size)
|
||||
return 27;
|
||||
if (sizeof (C8) == nearly_empty_size)
|
||||
return 28;
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
}
|
24
gcc/testsuite/g++.old-deja/g++.abi/empty3.C
Normal file
24
gcc/testsuite/g++.old-deja/g++.abi/empty3.C
Normal file
@ -0,0 +1,24 @@
|
||||
// Build don't link:
|
||||
|
||||
// Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
// Contributed by Nathan Sidwell 12 Apr 2001 <nathan@codesourcery.com>
|
||||
|
||||
// Check we deal with aligning virtual bases after a trailing empty
|
||||
// base class properly
|
||||
|
||||
struct A {};
|
||||
struct B1 : A {};
|
||||
struct B2 : A {};
|
||||
struct B3 : A {};
|
||||
|
||||
struct C : B1, B2, virtual B3 {};
|
||||
|
||||
int main ()
|
||||
{
|
||||
#if defined (__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100
|
||||
C c;
|
||||
if (((char *)static_cast <B3 *> (&c) - (char *)&c) % __alignof__ (C))
|
||||
return 1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user