Commit 5ec1192e by Mark Mitchell Committed by Mark Mitchell

re PR c++/8218 (Excessively large amount of memory used with classes with large array members)

	PR c++/8218
	* cp-tree.h (lang_type_class): Add contains_empty_class_p.
	(CLASSTYPE_CONTAINS_EMPTY_CLASS_P): New macro.
	* class.c (check_bases): Update CLASSTYPE_CONTAINS_EMPTY_CLASS_P.
	(check_field_decls): Likewise.
	(layout_class_type): Likewise.
	(finish_struct_1): Initialize it.
	(walk_subobject_offsets): Use it to prune searches.

From-SVN: r58356
parent 97cc1f5e
2002-10-21 Mark Mitchell <mark@codesourcery.com>
PR c++/8218
* cp-tree.h (lang_type_class): Add contains_empty_class_p.
(CLASSTYPE_CONTAINS_EMPTY_CLASS_P): New macro.
* class.c (check_bases): Update CLASSTYPE_CONTAINS_EMPTY_CLASS_P.
(check_field_decls): Likewise.
(layout_class_type): Likewise.
(finish_struct_1): Initialize it.
(walk_subobject_offsets): Use it to prune searches.
2002-10-20 Mark Mitchell <mark@codesourcery.com> 2002-10-20 Mark Mitchell <mark@codesourcery.com>
* method.c (use_thunk): Compute the vcall index as a HOST_WIDE_INT. * method.c (use_thunk): Compute the vcall index as a HOST_WIDE_INT.
......
...@@ -1352,6 +1352,8 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p, ...@@ -1352,6 +1352,8 @@ check_bases (t, cant_have_default_ctor_p, cant_have_const_ctor_p,
TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype); TYPE_OVERLOADS_ARRAY_REF (t) |= TYPE_OVERLOADS_ARRAY_REF (basetype);
TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype); TYPE_OVERLOADS_ARROW (t) |= TYPE_OVERLOADS_ARROW (basetype);
TYPE_POLYMORPHIC_P (t) |= TYPE_POLYMORPHIC_P (basetype); TYPE_POLYMORPHIC_P (t) |= TYPE_POLYMORPHIC_P (basetype);
CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t)
|= CLASSTYPE_CONTAINS_EMPTY_CLASS_P (basetype);
} }
} }
...@@ -3167,10 +3169,18 @@ check_field_decls (tree t, tree *access_decls, ...@@ -3167,10 +3169,18 @@ check_field_decls (tree t, tree *access_decls,
; ;
else else
{ {
tree element_type;
/* The class is non-empty. */ /* The class is non-empty. */
CLASSTYPE_EMPTY_P (t) = 0; CLASSTYPE_EMPTY_P (t) = 0;
/* The class is not even nearly empty. */ /* The class is not even nearly empty. */
CLASSTYPE_NEARLY_EMPTY_P (t) = 0; CLASSTYPE_NEARLY_EMPTY_P (t) = 0;
/* If one of the data members contains an empty class,
so does T. */
element_type = strip_array_types (type);
if (CLASS_TYPE_P (element_type)
&& CLASSTYPE_CONTAINS_EMPTY_CLASS_P (element_type))
CLASSTYPE_CONTAINS_EMPTY_CLASS_P (element_type) = 1;
} }
} }
...@@ -3440,6 +3450,10 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p) ...@@ -3440,6 +3450,10 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
tree binfo; tree binfo;
int i; int i;
/* Avoid recursing into objects that are not interesting. */
if (!CLASSTYPE_CONTAINS_EMPTY_CLASS_P (type))
return 0;
/* Record the location of TYPE. */ /* Record the location of TYPE. */
r = (*f) (type, offset, offsets); r = (*f) (type, offset, offsets);
if (r) if (r)
...@@ -3523,9 +3537,15 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p) ...@@ -3523,9 +3537,15 @@ walk_subobject_offsets (type, f, offset, offsets, max_offset, vbases_p)
} }
else if (TREE_CODE (type) == ARRAY_TYPE) else if (TREE_CODE (type) == ARRAY_TYPE)
{ {
tree element_type = strip_array_types (type);
tree domain = TYPE_DOMAIN (type); tree domain = TYPE_DOMAIN (type);
tree index; tree index;
/* Avoid recursing into objects that are not interesting. */
if (!CLASS_TYPE_P (element_type)
|| !CLASSTYPE_CONTAINS_EMPTY_CLASS_P (element_type))
return 0;
/* Step through each of the elements in the array. */ /* Step through each of the elements in the array. */
for (index = size_zero_node; for (index = size_zero_node;
/* G++ 3.2 had an off-by-one error here. */ /* G++ 3.2 had an off-by-one error here. */
...@@ -4988,6 +5008,10 @@ layout_class_type (tree t, int *vfuns_p, tree *virtuals_p) ...@@ -4988,6 +5008,10 @@ layout_class_type (tree t, int *vfuns_p, tree *virtuals_p)
else else
CLASSTYPE_AS_BASE (t) = t; CLASSTYPE_AS_BASE (t) = t;
/* Every empty class contains an empty class. */
if (CLASSTYPE_EMPTY_P (t))
CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 1;
/* Set the TYPE_DECL for this type to contain the right /* Set the TYPE_DECL for this type to contain the right
value for DECL_OFFSET, so that we can use it as part value for DECL_OFFSET, so that we can use it as part
of a COMPONENT_REF for multiple inheritance. */ of a COMPONENT_REF for multiple inheritance. */
...@@ -5076,10 +5100,11 @@ finish_struct_1 (t) ...@@ -5076,10 +5100,11 @@ finish_struct_1 (t)
fixup_inline_methods (t); fixup_inline_methods (t);
/* Assume that the class is both empty and nearly empty; we'll clear /* Make assumptions about the class; we'll reset the flags if
these flag if necessary. */ necessary. */
CLASSTYPE_EMPTY_P (t) = 1; CLASSTYPE_EMPTY_P (t) = 1;
CLASSTYPE_NEARLY_EMPTY_P (t) = 1; CLASSTYPE_NEARLY_EMPTY_P (t) = 1;
CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t) = 0;
/* Do end-of-class semantic processing: checking the validity of the /* Do end-of-class semantic processing: checking the validity of the
bases and members and add implicitly generated methods. */ bases and members and add implicitly generated methods. */
......
...@@ -1135,6 +1135,7 @@ struct lang_type_class GTY(()) ...@@ -1135,6 +1135,7 @@ struct lang_type_class GTY(())
unsigned anon_aggr : 1; unsigned anon_aggr : 1;
unsigned non_zero_init : 1; unsigned non_zero_init : 1;
unsigned empty_p : 1; unsigned empty_p : 1;
unsigned contains_empty_class_p : 1;
/* When adding a flag here, consider whether or not it ought to /* When adding a flag here, consider whether or not it ought to
apply to a template instance if it applies to the template. If apply to a template instance if it applies to the template. If
...@@ -1143,7 +1144,7 @@ struct lang_type_class GTY(()) ...@@ -1143,7 +1144,7 @@ struct lang_type_class GTY(())
/* There are some bits left to fill out a 32-bit word. Keep track /* There are some bits left to fill out a 32-bit word. Keep track
of this by updating the size of this bitfield whenever you add or of this by updating the size of this bitfield whenever you add or
remove a flag. */ remove a flag. */
unsigned dummy : 5; unsigned dummy : 4;
int vsize; int vsize;
...@@ -1457,6 +1458,10 @@ struct lang_type GTY(()) ...@@ -1457,6 +1458,10 @@ struct lang_type GTY(())
#define CLASSTYPE_NEARLY_EMPTY_P(NODE) \ #define CLASSTYPE_NEARLY_EMPTY_P(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->nearly_empty_p) (LANG_TYPE_CLASS_CHECK (NODE)->nearly_empty_p)
/* Nonzero if this class contains an empty subobject. */
#define CLASSTYPE_CONTAINS_EMPTY_CLASS_P(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->contains_empty_class_p)
/* A list of class types of which this type is a friend. The /* A list of class types of which this type is a friend. The
TREE_VALUE is normally a TYPE, but will be a TEMPLATE_DECL in the TREE_VALUE is normally a TYPE, but will be a TEMPLATE_DECL in the
case of a template friend. */ case of a template friend. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment