* 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).