This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: C++ aliasing rules
- From: mike stump <mrs at windriver dot com>
- To: dann at godzilla dot ICS dot UCI dot EDU, jason at redhat dot com
- Cc: gcc at gcc dot gnu dot org, libstdc++ at gcc dot gnu dot org
- Date: Tue, 23 Apr 2002 19:35:47 -0700 (PDT)
- Subject: Re: C++ aliasing rules
- References: <wvlvgai92dc.fsf@prospero.cambridge.redhat.com>
> To: Dan Nicolaescu <dann@godzilla.ICS.UCI.EDU>
> Cc: libstdc++@gcc.gnu.org, gcc@gcc.gnu.org
> From: Jason Merrill <jason@redhat.com>
> Date: Tue, 23 Apr 2002 10:43:27 +0100
> > struct first { int i; char a; int f1; char f2; double d;};
> > struct second { char b; int f2; int f3;};
> > can it be assumed that given that "first" and "second" are
> > incompatible then ps1.f1 and ps2.f2 don't alias
This would be an excellent question for comp.std.c. C++ mostly just
followed C on this. We fixed a few things (made memcpy so that it can
be portably written within the rules of the language), but it should
mostly be the same. You would need complete code, and might need to
`fix up' the example so that you can have them answer the question you
wanted.
Consider:
struct { char buf[sizeof (double)]; short i; } secondo, *second = &secondo;
struct { double other; short i; } firsto, *not_really_first = &secondo;
and the question of whether or not first->i can ever alias second->i.
I suspect the closest we can come would be to
memcpy (&secondo, &firsto, sizeof (secondo));
and then play with not_really_first->i and second->i.
I think the answer is no, as no matter what you do, you need to
violate the notion of which struct type the object really was and you
cannot get at the short without going though the struct first, and in
the end, you cannot get through both struct types simultaneously.
No, before you implement this, you need to be aware that some
prefixing is probably ok:
6.3.2.3 Structure and union members
Constraints
[#1] The first operand of the . operator shall have a
qualified or unqualified structure or union type, and the
second operand shall name a member of that type.
[#2] The first operand of the -> operator shall have type
``pointer to qualified or unqualified structure'' or
``pointer to qualified or unqualified union,'' and the
second operand shall name a member of the type pointed to.
Semantics
[#3] A postfix expression followed by the . operator and an
identifier designates a member of a structure or union
object. The value is that of the named member, and is an
lvalue if the first expression is an lvalue. If the first
expression has qualified type, the result has the so-
qualified version of the type of the designated member.
[#4] A postfix expression followed by the -> operator and an
identifier designates a member of a structure or union
object. The value is that of the named member of the object
to which the first expression points, and is an lvalue.66
If the first expression is a pointer to a qualified type,
the result has the so-qualified version of the type of the
designated member.
[#5] With one exception, if the value of a member of a union
object is used when the most recent store to the object was
to a different member, the behavior is implementation-
defined.67 One special guarantee is made in order to
__________
66. If &E is a valid pointer expression (where & is the
``address-of'' operator, which generates a pointer to
its operand), the expression (&E)->MOS is the same as
E.MOS.
67. The ``byte orders'' for scalar types are invisible to
isolated programs that do not indulge in type punning
(for example, by assigning to one member of a union and
inspecting the storage by accessing another member that
Language 85
Working Draft, 1997-11-21, WG14/<a href="n794.htm">N794</a> J11/97-158
simplify the use of unions: If a union contains several
structures that share a common initial sequence (see below),
and if the union object currently contains one of these
structures, it is permitted to inspect the common initial
part of any of them anywhere that a declaration of the
completed type of the union is visible. Two structures
share a common initial sequence if corresponding members
have compatible types (and, for bit-fields, the same widths)
for a sequence of one or more initial members.
Examples
[#6]
1. If f is a function returning a structure or union, and
x is a member of that structure or union, f().x is a
valid postfix expression but is not an lvalue.
2. The following is a valid fragment:
union {
struct {
int alltypes;
} n;
struct {
int type;
int intnode;
} ni;
struct {
int type;
double doublenode;
} nf;
} u;
u.nf.type = 1;
u.nf.doublenode = 3.14;
/* ... */
if (u.n.alltypes == 1)
if (sin(u.nf.doublenode) == 0.0)
/* ... */
____________________________________________________________
is an appropriately sized array of character type), but
must be accounted for when conforming to externally
imposed storage layouts.
86 Language
Working Draft, 1997-11-21, WG14/<a href="n794.htm">N794</a> J11/97-158
3. The following is not a valid fragment (because the
union type is not visible within function f):
struct t1 { int m; };
struct t2 { int m; };
int f(struct t1 * p1, struct t2 * p2)
{
if (p1->m < 0)
p2->m = -p2->m;
return p1->m;
}
int g()
{
union {
struct t1 s1;
struct t2 s2;
} u;
/* ... */
return f(&u.s1, &u.s2);
}
Forward references: address and indirection operators
(6.3.3.2), structure and union specifiers (6.5.2.1).
And from the C++ world:
- a type that is a (possibly cv-qualified) base class type of the
dynamic type of the object,
and:
14Two POD-struct (9) types are layout-compatible if they have the same
number of members, and corresponding members (in order) have layout-
compatible types (3.9).
15Two POD-union (9) types are layout-compatible if they have the same
number of members, and corresponding members (in any order) have
layout-compatible types (3.9).
+------- BEGIN BOX 2 -------+
Shouldn't this be the same set of types?
+------- END BOX 2 -------+
16If a POD-union contains two or more POD-structs that share a common
initial sequence, and if the POD-union object currently contains one
of these POD-structs, it is permitted to inspect the common initial
part of any of them. Two POD-structs share a common initial sequence
if corresponding members have layout-compatible types (and, for bit-
fields, the same widths) for a sequence of one or more initial
members.
17A pointer to a POD-struct object, suitably converted, points to its
initial member (or if that member is a bit-field, then to the unit in
which it resides) and vice versa. [Note: There might therefore be
unnamed padding within a POD-struct object, but not at its beginning,
as necessary to achieve appropriate alignment. ]