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.

+       /* 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.

Jason

Reply via email to