On 11/24/20 1:09 PM, Jason Merrill wrote:
On 11/23/20 7:06 PM, Martin Sebor wrote:
On 11/16/20 11:54 PM, Jason Merrill wrote:
On 11/16/20 9:41 PM, Martin Sebor wrote:
The result of DECL_SIZE_UNIT doesn't always reflect the size
of data members of virtual classes.  This can lead to objects
of such types appearing smaller than they are to warnings like
-Warray-bounds or -Wstringop-overflow, causing false positives.

To avoid these false positives, the attached replaces the use
of DECL_SIZE_UNIT in component_ref_size in the middle end with
TYPE_SIZE_UNIT.

Unfortunately, that's not enough; the offset between the intermediate base and the virtual base could be greater than the TYPE_SIZE of the intermediate base:

extern "C" int printf (const char *, ...);

struct A { char ar1[24]; };
struct B: virtual A { };
struct C { char ar2[42]; };
struct D: B, C { };

int main()
{
   D d;
   printf ("size %d, offset %d\n", sizeof (B), d.ar1 - (char*)(B*)&d);
}

Here base C is allocated between base B and its virtual base A, so the offset between them is 50, while the size of B is only 32.

The difference between TYPE_SIZE and DECL_SIZE could be a way to recognize the case of bases with virtual bases, and then either hunt down all the virtual bases or just use the bounds of the enclosing most-derived object.

An advanced analysis of classes with virtual bases is beyond what
I have cycles to tackle at this point (it seems it would also need
to be done in the C++ front end?)  It will have to wait until I have
more time or the next stage 1.

So for now, I've changed component_ref_size to fail when DECL_SIZE
isn't equal TYPE_SIZE.

OK.

+    /* DECL_SIZE may be less than TYPE_SIZE in C++ when referring
+       to the type of a virtual base class which doesn't reflect
+       the size of the virtual's members (see pr97595).  */

The problem isn't with the virtual base class itself (A), but with the intermediate base class subobject (B), for which DECL_SIZE doesn't include the size of the virtual base A, because the A base subobject is allocated separately.

I've also adjusted the comments above the _SIZE macros in tree.h
to more closely reflect what happens there.  My main goal isn't
to describe when they don't match with perfect accuracy, just to
point that they may be unequal and (roughly) when.

Sure, but why not be precise?  e.g.

May be less than TYPE_SIZE for a C++ FIELD_DECL representing a base class subobject with its own virtual base classes (which are laid out separately).

I have committed the patch with the adjusted comment in r11-5628.

Martin

Reply via email to