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