* Re: C++ aliasing rules
[not found] <200204031103.aa15838@gremlin-relay.ics.uci.edu>
@ 2002-04-23 13:59 ` Jason Merrill
2002-04-23 19:52 ` mike stump
0 siblings, 1 reply; 8+ messages in thread
From: Jason Merrill @ 2002-04-23 13:59 UTC (permalink / raw)
To: Dan Nicolaescu; +Cc: libstdc++, gcc
>>>>> "Dan" == Dan Nicolaescu <dann@godzilla.ICS.UCI.EDU> writes:
> 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
I'm not sure. I suppose it depends on whether you consider ps1.f1 to be an
object for the purposes of [basic.lval], which says that an object can be
referenced through an lvalue of a class type which contains a member of
that object's type. So since ps1.f1 is an int, and struct second contains
an int, the access can alias.
If we think that [basic.lval] only means to talk about complete objects,
then the access can't alias.
I'm not sure what the intent is, but from a strict reading I tend towards
the first interpretation; according to [intro.object] sub-objects are
objects, too.
Jason
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: C++ aliasing rules
2002-04-23 13:59 ` C++ aliasing rules Jason Merrill
@ 2002-04-23 19:52 ` mike stump
2002-04-24 6:43 ` Andreas Schwab
2002-04-24 13:32 ` Dan Nicolaescu
0 siblings, 2 replies; 8+ messages in thread
From: mike stump @ 2002-04-23 19:52 UTC (permalink / raw)
To: dann, jason; +Cc: gcc, libstdc++
> 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. ]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: C++ aliasing rules
2002-04-23 19:52 ` mike stump
@ 2002-04-24 6:43 ` Andreas Schwab
2002-04-24 13:32 ` Dan Nicolaescu
1 sibling, 0 replies; 8+ messages in thread
From: Andreas Schwab @ 2002-04-24 6:43 UTC (permalink / raw)
To: mike stump; +Cc: dann, jason, gcc, libstdc++
mike stump <mrs@windriver.com> writes:
|> No, before you implement this, you need to be aware that some
|> prefixing is probably ok:
|>
|> 6.3.2.3 Structure and union members
FYI, this is how the section reads in the final standard. Especially
[#5] is different and there is one more example.
6.5.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.79) 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] One special guarantee is made in order to 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 complete 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.
[#6] EXAMPLE 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.
[#7] EXAMPLE 2 In:
struct s { int i; const int ci; };
struct s s;
const struct s cs;
volatile struct s vs;
the various members have the types:
s.i int
s.ci const int
cs.i const int
cs.ci const int
vs.i volatile int
vs.ci volatile const int
[#8] EXAMPLE 3 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)
/* ... */
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.5.3.2),
structure and union specifiers (6.7.2.1).
--------------------
79) 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.
--
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE GmbH, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5
"And now for something completely different."
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: C++ aliasing rules
2002-04-23 19:52 ` mike stump
2002-04-24 6:43 ` Andreas Schwab
@ 2002-04-24 13:32 ` Dan Nicolaescu
2002-04-25 1:11 ` Nathan Sidwell
2002-04-25 10:57 ` Jason Merrill
1 sibling, 2 replies; 8+ messages in thread
From: Dan Nicolaescu @ 2002-04-24 13:32 UTC (permalink / raw)
To: mike stump; +Cc: jason, gcc, libstdc++
mike stump <mrs@windriver.com> writes:
> > 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.
As a matter of fact I asked this question on comp.std.c sometime in
March. And the answer was that the C standard is a bit unclear in this
area...
> 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.
A bit too much of my original post was snipped in the message you
replied to, that's why the code is incomplete, see:
http://gcc.gnu.org/ml/libstdc++/2002-04/msg00049.html
> 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.
I like this answer. :-)
Does anybody disagree with Mike's statement above (wrt C++) ? Jason?
> No, before you implement this, you need to be aware that some
> prefixing is probably ok:
I've already implemented it.
I have an unsubmited patch that takes care of the prefixing thing
too. I'll reopen the discussion on the patches after 3.1 is released,
if we have an agreement that it's OK from the C++ standard point of
view.
BTW, there's a defect report for C99 that says that allowing prefixing
is not such a great idea...
Thanks.
--dan
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: C++ aliasing rules
2002-04-24 13:32 ` Dan Nicolaescu
@ 2002-04-25 1:11 ` Nathan Sidwell
2002-04-25 10:57 ` Jason Merrill
1 sibling, 0 replies; 8+ messages in thread
From: Nathan Sidwell @ 2002-04-25 1:11 UTC (permalink / raw)
To: Dan Nicolaescu; +Cc: mike stump, jason, gcc, libstdc++
Dan Nicolaescu wrote:
> > 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.
>
> Does anybody disagree with Mike's statement above (wrt C++) ? Jason?
I agree with Mike's analysis.
nathan
--
Dr Nathan Sidwell :: Computer Science Department :: Bristol University
The voices in my head told me to say this
nathan@acm.org http://www.cs.bris.ac.uk/~nathan/ nathan@cs.bris.ac.uk
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: C++ aliasing rules
2002-04-24 13:32 ` Dan Nicolaescu
2002-04-25 1:11 ` Nathan Sidwell
@ 2002-04-25 10:57 ` Jason Merrill
2002-04-25 17:44 ` mike stump
1 sibling, 1 reply; 8+ messages in thread
From: Jason Merrill @ 2002-04-25 10:57 UTC (permalink / raw)
To: Dan Nicolaescu; +Cc: mike stump, gcc, libstdc++
>>>>> "Dan" == Dan Nicolaescu <dann@godzilla.ICS.UCI.EDU> writes:
> mike stump <mrs@windriver.com> writes:
>> 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.
> I like this answer. :-)
> Does anybody disagree with Mike's statement above (wrt C++) ? Jason?
I don't see how Mike's statement answers my question. Given
struct A { char buf[sizeof (double)]; short i; };
struct B { double other; short i; };
A a;
A* ap = &a;
B* bp = reinterpret_cast<B*>(ap);
referring to bp->i is accessing a.i through an lvalue of a class type (B)
which contains a member of a.i's type (short). The standard seems to say
that's OK.
Again, if instead we consider a.i to be an indivisible part of 'a' for
purposes of [basic.lval], then the access would be undefined. I would
probably support writing that into the standard. But I don't think that's
what it says now.
Jason
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: C++ aliasing rules
2002-04-25 10:57 ` Jason Merrill
@ 2002-04-25 17:44 ` mike stump
2002-05-17 13:09 ` Dan Nicolaescu
0 siblings, 1 reply; 8+ messages in thread
From: mike stump @ 2002-04-25 17:44 UTC (permalink / raw)
To: dann, jason; +Cc: gcc, libstdc++
> To: Dan Nicolaescu <dann@godzilla.ICS.UCI.EDU>
> Cc: mike stump <mrs@windriver.com>, gcc@gcc.gnu.org, libstdc++@gcc.gnu.org
> From: Jason Merrill <jason@redhat.com>
> Date: Thu, 25 Apr 2002 18:44:05 +0100
> I don't see how Mike's statement answers my question.
Yes, I agree, I don't think it does.
> I would probably support writing that into the standard. But I
> don't think that's what it says now.
A hard line would be we should be conservative, and get it written
into the standard first. I think it would be reasonable for the
standard to say they don't alias.
If we want to lead the standard, I think we can. Because the standard
isn't perfectly clear, it would be good to document what we did.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: C++ aliasing rules
2002-04-25 17:44 ` mike stump
@ 2002-05-17 13:09 ` Dan Nicolaescu
0 siblings, 0 replies; 8+ messages in thread
From: Dan Nicolaescu @ 2002-05-17 13:09 UTC (permalink / raw)
To: mike stump; +Cc: jason, gcc, libstdc++
Now that 3.1 is out of the way we can reopen this discussion...
For reference the start of this thread is at:
http://gcc.gnu.org/ml/libstdc++/2002-04/msg00049.html
mike stump <mrs@windriver.com> writes:
> > To: Dan Nicolaescu <dann@godzilla.ICS.UCI.EDU>
> > Cc: mike stump <mrs@windriver.com>, gcc@gcc.gnu.org, libstdc++@gcc.gnu.org
> > From: Jason Merrill <jason@redhat.com>
> > Date: Thu, 25 Apr 2002 18:44:05 +0100
>
> > I don't see how Mike's statement answers my question.
>
> Yes, I agree, I don't think it does.
>
> > I would probably support writing that into the standard. But I
> > don't think that's what it says now.
>
> A hard line would be we should be conservative, and get it written
> into the standard first. I think it would be reasonable for the
> standard to say they don't alias.
>
> If we want to lead the standard, I think we can. Because the standard
> isn't perfectly clear, it would be good to document what we did.
If we decide to lead the standard, I volunteer the write the patch and
the associated GCC documentation.
Somebody else will have to take care about the standardization
process...
Who can make a decision about this?
--dan
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2002-05-17 19:01 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <200204031103.aa15838@gremlin-relay.ics.uci.edu>
2002-04-23 13:59 ` C++ aliasing rules Jason Merrill
2002-04-23 19:52 ` mike stump
2002-04-24 6:43 ` Andreas Schwab
2002-04-24 13:32 ` Dan Nicolaescu
2002-04-25 1:11 ` Nathan Sidwell
2002-04-25 10:57 ` Jason Merrill
2002-04-25 17:44 ` mike stump
2002-05-17 13:09 ` Dan Nicolaescu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).