> On Apr 26, 2015, at 2:26 PM, Richard Smith <[email protected]> wrote:
>
> On 25 April 2015 at 21:10, John McCall <[email protected]
> <mailto:[email protected]>> wrote:
> The standard says that std::is_empty<T>::value is true if:
> - T is a class type, but not a union type, with no non-static data members
> other than bit-fields of length 0, no virtual member functions, no virtual
> base classes, and no base class B for which is_empty<B>::value is false.
>
> The standard also says that array bounds must be greater than zero, but
> there’s a common extension to permit zero-length array types (hereafter,
> ZLATs).
>
> In GCC and Clang, at least, a ZLAT conventionally has size 0, both formally
> (as a result of sizeof) and for struct layout (a ZLAT field takes up no
> direct space, although it does cause the next offset to be rounded up to the
> field’s alignment). Moreover, a ZLAT field inhibits the general rule
> rounding a class's size up to at least 1, recursively.
>
> Oddly, though, GCC and Clang also say that a struct containing a ZLAT is not
> empty, at least as far as std::is_empty is concerned. On the other hand, ICC
> says that a struct containing only one (or more) ZLATs is empty; as does
> MSVC, for what it’s worth.
>
> This touches on the ABI because:
> - the results of these metaprogramming traits can affect the ABI in a
> number of ways,
> - class sizes are also obviously ABI, and
> - whether a base class is empty dramatically affects Itanium class layout.
>
> The current Itanium definition mirrors the std::is_empty definition:
> [a] class with no non-static data members other than zero-width bitfields,
> no virtual functions, no virtual base classes, and no non-empty non-virtual
> proper base classes.
>
> Now, of course, this is an extension, and we don’t have to standardize
> behavior on it; but my preference is to specify this sort of common extension
> wherever possible.
>
> The point of is_empty is to allow detection of EBO opportunities, so I think
> it should return 'true' in all cases where EBO would apply. It seems
> reasonable (if not very worthwhile) to ignore ZLATs when determining whether
> we can apply EBO. And I think this is a common enough extension for the ABI
> to specify how it should behave.
>
> I propose the following changes:
>
> 1. Add “or members of zero-length array type” to the ABI definition of
> "empty class”.
>
> Is it worth explicitly calling out that flexible array members and
> zero-length array members are handled the same in this regard?
Yes, that’s probably a good idea.
> 2. Specify std::is_empty to behave as if the same clause were there.
> 3. Change the ABI class layout rule (in IV. Finalization) to not require
> sizeof(C) to be non-zero if C contains a ZLAT subobject. That is, replace
> this sentence:
> Round sizeof(C) up to a non-zero multiple of align(C).
> with:
> If C does not contain (recursively) a subobject of zero-length array type,
> and sizeof(C) is 0, set sizeof(C) to align(C); otherwise, round sizeof(C) up
> to a multiple of align(C).
>
> Perhaps:
>
> If sizeof(C) is 0 and C has no non-static data members and no base classes,
> set sizeof(C) to align(C); otherwise, round sizeof(C) up to a multiple of
> align(C).
Wouldn’t this trigger for a class with an empty base?
> I think that's equivalent, and it seems simpler and more general.
>
> Another problem is in step 2 of the layout algorithm: "Place D at this offset
> unless doing so would result in two components (direct or indirect) of the
> same type having the same offset.". That does the wrong thing for:
>
> struct A { int n[0]; int m[0]; };
>
> where sizeof(A) should be zero, but will be 4 with this algorithm because
> putting m at offset 0 gives two components of type 'int[0]' at the same
> offset. Perhaps replace "components (direct or indirect)" with "non-array
> subobjects"?
That seems reasonable.
John._______________________________________________
cxx-abi-dev mailing list
[email protected]
http://sourcerytools.com/cgi-bin/mailman/listinfo/cxx-abi-dev