Travis Vitek wrote:
Martin Sebor wrote:
[EMAIL PROTECTED] wrote:
Author: vitek
Date: Thu Jun 19 15:52:34 2008
New Revision: 669735
URL: http://svn.apache.org/viewvc?rev=669735&view=rev
Log:
2008-06-19 Travis Vitek <[EMAIL PROTECTED]>
STDCXX-926
[...]
+template <size_t _Size, size_t _Align =
__rw_default_alignment<_Size>::value>
struct __rw_aligned_storage
{
[...]
typedef union {
- unsigned char __data [_Len];
- // not implemented
+ unsigned char __size [_Size];
+
+ typename
+ __rw_aligned_storage_impl<_Align>::_C_type __align;
I believe there are platforms where unions are aligned on
the boundary given by the first member. This one looks like
it might be one of them: http://tinyurl.com/472744. Unless
I'm mistaken we should switch the order of the two members
to make sure the union is properly aligned.
I'm not absolutely sure I'm reading the documentation you linked to
correctly, but here goes...
It's possible that I misread the text. I was pretty sure (and still
am) I remembered discussing the alignment issue before but I couldn't
(and still can't) find it in the archives. I pointed to this page
because that was the best I could come up with in the absence of
anything else. Maybe it's a red herring. It could also be that the
issue I think I'm remembering had less to do with alignment than
something else (aliasing, maybe), but given the choice between
placing the more strictly aligned type first and the unaligned
buffer second or doing laying them down in the reverse order I'd
go for the former even if there is no real issue.
I searched library headers and sources for how we define unions and
with the exception of limits_bits.cpp we always follow this rule.
Unless there is a reason not to make this change to aligned_union,
I think we should change both limits_bits.cpp and aligned_union to
always define the member with the more strict alignment requirement
first, just for peace of mind.
Is there any reason/advantage to having the char buffer first?
The first paragraph of that documentation says
Individual members of a union are mapped the same way as members of the
structure. That is, each of the members, if not a union, is mapped as if
it were a member of a structure. This means that the first storage
locations for each of the members of a union do not overlay each other
if each of the members requires different alignment and therefore
different padding before the beginning of the member.
This violates C99 (6.7.2.1 p5)
Not all compilers support C99, and of those that do not all of them
conform to 100% of the requirements. The layout of structs and unions
is an ABI issue, and it's quite possible that there are systems that
can't afford to break the ABI for compatibility reasons.
Martin
As discussed in 6.2.5, a structure is a type consisting
of a sequence of members, whose storage is allocated in
an ordered sequence, and a union is a type consisting
of a sequence of members whose storage overlap.
And (6.7.2.1 p14)
The size of a union is sufficient to contain the largest
of its members. The value of at most one of the members
can be stored in a union object at any time. A pointer
to a union object, suitably converted, points to each of
its members, and vise versa.
It also voilates C++03 (expr.rel p2)
If two pointers point to data members of the same union
object, they compare equal (after conversion to void*,
if necessary).
Even so, the last paragraph of "Rules for mapping one pair" says
The pair is now a unit of fixed length and alignment
requirement, its length is the sum of the two lengths
plus padding, and its alignment requirement is the
higher of the two alignment requirements (if they
differ).
So the alignment would still be correct as the alignment requirement is
weakest (smallest) for char types, so the alignment that would be used
would be the alignment of the other type.
Please correct me if I'm misinterpreting any of this.
Travis
Also, strictly speaking, names of data members should have
the _C_ prefix (double underscores are used for locals and
function parameters).
Agreed. I will fix.
Martin