[C++ PATCH for 3.1] Fix PR6716 regression (take 2)

Kriang Lerdsuwanakij lerdsuwa@users.sourceforge.net
Wed Jun 26 08:46:00 GMT 2002


At 14:11 25/6/02 -0700, Mark Mitchell wrote:

>--On Sunday, June 23, 2002 11:17:04 AM +0200 Gabriel Dos Reis 
><gdr@codesourcery.com> wrote:
>
>>Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net> writes:
>>
>>| Hi
>>|
>>| This patch is my second attempt at fixing PR6716, an ICE on
>>| illegal code containing incomplete class which is a regression
>>| from GCC 3.0.  The failure (testcase included in the patch below)
>>| is caused by layout_class_type of nesting of classes Z<int>,
>>| Y<Z<int> >, and X<Z<int> >.  Incomplete types end up with
>>| TYPE_SIZE being size_zero_node and are indistinguishable from
>>| ordinary empty classes.
>>
>>[ This is not driected to you in particular; it is a general remark
>>   about the C++ front in particular and front-end in general ]
>>
>>I think that it would be much more scalable if we stopping abusing
>>trees.  We should be using a non-overloaded tree node to record
>>incomplete-type. For example, using 'size_unkown_node' instead of
>>'size_zero_node'.
>
>Yes, that would be better.  However, no complete type can have size
>zero, so there should be no ambiguity.
>
>Kriang, what do you mean "indistinguishable from ordinary empty
>classes"?  Ordinary empty classes should have a non-zero size.

I have messed up that a bit.  Originally, its size is zero (for this
testcase included in my patch, other fail cases can have non-zero size)
but eventually it's indistinguishable from other ordinary class.
Consider the testcase.  There Z<int> contains Y<Z<int> >, which
contains X<Z<int> >, which in turn contains Z<int>.

First we layout X<Z<int> >, here Z<int> is incomplete, but X<Z<int> >
becomes a valid class (i.e. filled with TYPE_SIZE, etc.) after it is laid out
in layout_class_type.  The size of X<Z<int> > is zero here (I checked the
value of TYPE_SIZE in gdb) but the actual size doesn't matter.  It would
be non-zero if some other fields present in X<Z<int> >.

Next we layout Y<Z<int> >, now its field X<Z<int> > is valid. So
Y<Z<int> > also becomes a valid class.
And finally, we layout Z<int> (containing a valid Y<Z<int> >),
making Z<int> also valid. Now all three class looks like other ordinary 
classes.
Traversing fields of Z<int> will get into infinite loop.

It would be simple to deal with this problem if we just abort the
compilation with error message.  But to continue compilation,
the approach I use is to break the infinite loop by removing
the field Z<int> inside X<Z<int> > when laying out Z<int>
So that we no longer have Z<int> => Y<Z<int> > => X<Z<int> >
=> Z<int> => ...  bad tree structure.

--Kriang



More information about the Gcc-patches mailing list