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.

I propose the following changes:

1.  Add “or members of zero-length array type” to the ABI definition of "empty 
class”.
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).

John.
_______________________________________________
cxx-abi-dev mailing list
[email protected]
http://sourcerytools.com/cgi-bin/mailman/listinfo/cxx-abi-dev

Reply via email to