Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Order of Variable

Reply
Thread Tools

Order of Variable

 
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      09-11-2010
Johannes Schaub (litb) wrote:

> Alf P. Steinbach /Usenet wrote:
>
>> * Johannes Schaub (litb), on 11.09.2010 22:08:
>>> Alf P. Steinbach /Usenet wrote:
>>>
>>>> * James Kanze, on 11.09.2010 21:10:
>>>>> If, on the other hand, in addition:
>>>>>
>>>>> union U { A a; B b; } u;
>>>>> and call f with:
>>>>> f(&a,&b );
>>>>>
>>>>> this reordering cannot take place, according to §9.2/16.
>>>>
>>>> Assuming for the sake of discussion that there is such a thing as
>>>> aliasing based reordering rule (I haven't found it), this
>>>> interpretation where the /call/ of a function determines the validity
>>>> of possible code transformations /within/ the function seems 100% out
>>>> of spirit with the standard.
>>>>
>>>
>>> I think it's certainly within the Spirit. See
>>> http://www.open-std.org/jtc1/sc22/wg...ctive.html#636

>>
>> It's a different case, and no, it shows no such thing as call-dependent
>> validity of code transformations; instead it concerns the opposite.
>>
>> James' example concerns validity of reordering when accessing objects of
>> the same type (members of a and b), which according to §3.10/15 can be
>> aliased. With James example the source code transformation is purportedly
>> (I don't agree) valid or invalid depending on how the function is called.
>>
>> Gabriel's example, on the other hand, concerns accessing float as int,
>> which according to the same para yields UB. And he shows that the
>> possibility of aliasing in a call means that reordering is an invalid
>> code transformation, because although in general accessing float as int
>> is UB, it's valid in a union. That is, the types that the function know
>> of are not the full story, and the reason for the DR is exactly that
>> call-dependent semantics are not in the spirit
>> of the standard -- it's so outlandish that it's not even considered.
>>

>
> The way I understand it, it does not matter whether the reference is by an
> union or not. Aliasing an int as a float is UB no matter by an union or
> not. I thought that was the whole point of Gabriel's issue report? I.e if
> the statements in foo are reordered, then "t.d" accesses an int object by
> a double lvalue, violating aliasing.
>
> Example to show what I mean:
>
> union {
> float f;
> int i;
> } u;
>
> // now the object is a float, by 3.8/1.
> u.f = 1.f;
>
> // now it is an int, also by 3.8/1
> u.i = 10;
>
> // aliasing violation by 3.10/15 - UB, trying
> // to access value of int object by float lvalue.
> float f = u.f;
>
>


Ah wait, i think i might have misinterpreted your sayings. You meant that
normally an "int*" could not share storage with a "float*" but in an union
they could. I agree.
 
Reply With Quote
 
 
 
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      09-11-2010
* Johannes Schaub (litb), on 11.09.2010 22:54:
> Alf P. Steinbach /Usenet wrote:
>
>> * Johannes Schaub (litb), on 11.09.2010 22:08:
>>> Alf P. Steinbach /Usenet wrote:
>>>
>>>> * James Kanze, on 11.09.2010 21:10:
>>>>> If, on the other hand, in addition:
>>>>>
>>>>> union U { A a; B b; } u;
>>>>> and call f with:
>>>>> f(&a,&b );
>>>>>
>>>>> this reordering cannot take place, according to §9.2/16.
>>>>
>>>> Assuming for the sake of discussion that there is such a thing as
>>>> aliasing based reordering rule (I haven't found it), this interpretation
>>>> where the /call/ of a function determines the validity of possible code
>>>> transformations /within/ the function seems 100% out of spirit with the
>>>> standard.
>>>>
>>>
>>> I think it's certainly within the Spirit. See
>>> http://www.open-std.org/jtc1/sc22/wg...ctive.html#636

>>
>> It's a different case, and no, it shows no such thing as call-dependent
>> validity of code transformations; instead it concerns the opposite.
>>
>> James' example concerns validity of reordering when accessing objects of
>> the same type (members of a and b), which according to §3.10/15 can be
>> aliased. With James example the source code transformation is purportedly
>> (I don't agree) valid or invalid depending on how the function is called.
>>
>> Gabriel's example, on the other hand, concerns accessing float as int,
>> which according to the same para yields UB. And he shows that the
>> possibility of aliasing in a call means that reordering is an invalid code
>> transformation, because although in general accessing float as int is UB,
>> it's valid in a union. That is, the types that the function know of are
>> not the full story, and the reason for the DR is exactly that
>> call-dependent semantics are not in the spirit
>> of the standard -- it's so outlandish that it's not even considered.
>>

>
> The way I understand it, it does not matter whether the reference is by an
> union or not. Aliasing an int as a float is UB no matter by an union or not.
> I thought that was the whole point of Gabriel's issue report? I.e if the
> statements in foo are reordered, then "t.d" accesses an int object by a
> double lvalue, violating aliasing.
>
> Example to show what I mean:
>
> union {
> float f;
> int i;
> } u;
>
> // now the object is a float, by 3.8/1.
> u.f = 1.f;
>
> // now it is an int, also by 3.8/1
> u.i = 10;
>
> // aliasing violation by 3.10/15 - UB, trying
> // to access value of int object by float lvalue.
> float f = u.f;


Yes. But if you consider

u.i = 42;
u.f = 2.71828;

float f = u.f;

Then you have valid code.

And then the compiler can't reorder the two assignment statements.

It can't reorder the assignment statements even if they're placed in a function
where it's not locally known that for a particular call the float and int are in
a union (Gabriel's point).


>> Now consider
>>
>> #include<stdio.h>
>>
>> struct A { double d; int x; };
>>
>> void foo( int* a, A* b )
>> {
>> b->x = 1;
>> *a = 2;
>> }
>>
>> int main()
>> {
>> A aha;
>> foo(&aha.x,&aha );
>> printf( "%d\n", aha.x );
>> }
>>
>> Since int* and A* are clearly pointers with different referent types, at
>> least the simplistic purported aliasing-based reordering rule mentioned so
>> far should allow reordering of the statements in foo, causing output 1
>> instead of 2.
>>
>> I don't believe it -- although I may be forced to if James can hark up
>> some reference (in which case the standard, IMHO, needs to be fixed).
>>

>
> I don't believe that the Standard allows reordering this either. b->x is int
> lvalue and *a is int lvalue too. Both are allowed to alias.


Yes.

And as I see it §3.10/15 means that that's still the case when accessing A: as
B: where B is layout-compatible with A (assuming same member names for this
example).

Otherwise there would have to be some rule about exactly which pointer referent
types are considered to be sufficiently different that the pointers can be
assumed to be unaliased -- int != A?, A != B?, what?


Cheers,

- Alf

--
blog at <url: http://alfps.wordpress.com>
 
Reply With Quote
 
 
 
 
Joshua Maurice
Guest
Posts: n/a
 
      09-13-2010
On Sep 11, 2:10*pm, "Alf P. Steinbach /Usenet" <alf.p.steinbach
(E-Mail Removed)> wrote:
> * Johannes Schaub (litb), on 11.09.2010 22:54:
> > The way I understand it, it does not matter whether the reference is by an
> > union or not. Aliasing an int as a float is UB no matter by an union or not.
> > I thought that was the whole point of Gabriel's issue report? I.e if the
> > statements in foo are reordered, then "t.d" accesses an int object by a
> > double lvalue, violating aliasing.

>
> > Example to show what I mean:

>
> > union {
> > * *float f;
> > * *int i;
> > } u;

>
> > // now the object is a float, by 3.8/1.
> > u.f = 1.f;

>
> > // now it is an int, also by 3.8/1
> > u.i = 10;

>
> > // aliasing violation by 3.10/15 - UB, trying
> > // to access value of int object by float lvalue.
> > float f = u.f;

>
> Yes. But if you consider
>
> * *u.i = 42;
> * *u.f = 2.71828;
>
> * *float f = u.f;
>
> Then you have valid code.
>
> And then the compiler can't reorder the two assignment statements.
>
> It can't reorder the assignment statements even if they're placed in a function
> where it's not locally known that for a particular call the float and int are in
> a union (Gabriel's point).


Indeed. This is a well known bug in the C and C++ specs. James talks
about it else-thread, quoted here:

On Sep 11, 11:56 am, James Kanze <(E-Mail Removed)> wrote:
> The issue is not simple, and formally g++ isn't conformant in
> this respect (but it has nothing to do with 9.2/17---I've not
> verified, but I suspect that g++ does handle that correctly).
> But if I understand correctly, the C committee thinks that it is
> the standard which is broken, not g++---the standard guarantees
> too much.
>
> The exact issue was something like:
>
> union U { int a; double b; }
>
> int f(int* a, double *b)
> {
> // g++ reorders the following two statements...
> int result = *a;
> *b = 3.14159;
> }
>
> // ...
> U u;
> u.a = 42;
> int i = f(&u.a, &u.b);
>
> Technically, the above code fulfills the requirements of the
> standard; you're reading the last element written in the union,
> then writing a different element. IIRC, the opinion of the C
> committee was that this *should* only be guaranteed to work when
> the actual access is through the union type.


Basically, the problem is that with unions, the strict aliasing rules
no longer "work". The solution that James says that the C committee is
for is not abandoning the strict aliasing rules, but instead greatly
restricting usages of unions. Basically, in current practice, if a
union has 2 different members, and if you let pointers to 2 or more
members escape the current scope, then you're boned. I'm not exactly
sure what formal rule the C committee is pondering, but at the very
least it would have to effectively include that restriction.

On Sep 11, 2:10 pm, "Alf P. Steinbach /Usenet" <alf.p.steinbach
(E-Mail Removed)> wrote:
> >> Now consider

>
> >> * * #include<stdio.h>

>
> >> * * struct A { double d; int x; };

>
> >> * * void foo( int* a, A* b )
> >> * * {
> >> * * * * b->x = 1;
> >> * * * * *a = 2;
> >> * * }

>
> >> * * int main()
> >> * * {
> >> * * * * A aha;
> >> * * * * foo(&aha.x,&aha );
> >> * * * * printf( "%d\n", aha.x );
> >> * * }

>
> >> Since int* and A* are clearly pointers with different referent types, at
> >> least the simplistic purported aliasing-based reordering rule mentioned so
> >> far should allow reordering of the statements in foo, causing output 1
> >> instead of 2.

>
> >> I don't believe it *-- *although I may be forced to if James can hark up
> >> some reference (in which case the standard, IMHO, needs to be fixed).

>
> > I don't believe that the Standard allows reordering this either. b->x is int
> > lvalue and *a is int lvalue too. Both are allowed to alias.

>
> Yes.
>
> And as I see it 3.10/15 means that that's still the case when accessing A: as
> B: where B is layout-compatible with A (assuming same member names for this
> example).


Then you would be alone on your interpretation. I don't have a C spec
handy, but for C++03, that is not the case.

This is what I can find on the subject in the standard itself.

C++03 standard, 9.2 Class members / 16
>>>>

If a POD-union contains two or more POD-structs that share a common
initial sequence, and if the PODunion
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 layoutcompatible
types (and, for bit-fields, the same widths) for a sequence of one or
more initial members.
<<<<

The rule above only applies to PODs in a union.

C++03 standard, 9.2 Class members / 167
>>>>

A pointer to a POD-struct object, suitably converted using a
reinterpret_cast, 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. ]
<<<<

The section above, especially with the (non-binding) note, pretty
clearly states that the C-style hack of inheritance may not work in C+
+. There might be unnamed padding which differs between different POD
structs.

Frankly though, this entire thing is a mess. When you compare the
guarantees of the two quotes, /which appear right next to each other
in the standard/, I don't understand how you can reconcile them in a
sane implementation. So, when the POD types are members of a union,
there's no difference in padding bits, but when the same POD types are
not members of a union, there might be extra magical padding bits.
What?

We expect that a compiler has a single rule for handling member
offsets so that accessing a member of an object is efficient, so it
doesn't matter if the POD object is a complete object or a member sub-
object of a union - the expected result is that the compiler will
generate the same assembly to access a member sub-object of the POD
object from a pointer to the POD object in all cases. With this in
mind, I have no clue how you're supposed to reconcile those two
sections above, one of which says there is no difference in padding
between lay-out compatible POD-struct types, and the next section
which says there might be a difference.

However, at face value, most / all of the gcc examples in this thread
have been conforming.

> Otherwise there would have to be some rule about exactly which pointer referent
> types are considered to be sufficiently different that the pointers can be
> assumed to be unaliased *-- *int != A?, A != B?, what?


Yes. That is exactly what "3.10 Lvalues and rvalues / 15" does. Hell,
there's a note on it which reads: "The intent of this list is to
specify those circumstances in which an object may or may not be
aliased."
 
Reply With Quote
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      09-13-2010
Joshua Maurice wrote:

> On Sep 11, 2:10 pm, "Alf P. Steinbach /Usenet" <alf.p.steinbach
> (E-Mail Removed)> wrote:
>> * Johannes Schaub (litb), on 11.09.2010 22:54:
>> > The way I understand it, it does not matter whether the reference is by
>> > an union or not. Aliasing an int as a float is UB no matter by an union
>> > or not. I thought that was the whole point of Gabriel's issue report?
>> > I.e if the statements in foo are reordered, then "t.d" accesses an int
>> > object by a double lvalue, violating aliasing.

>>
>> > Example to show what I mean:

>>
>> > union {
>> > float f;
>> > int i;
>> > } u;

>>
>> > // now the object is a float, by 3.8/1.
>> > u.f = 1.f;

>>
>> > // now it is an int, also by 3.8/1
>> > u.i = 10;

>>
>> > // aliasing violation by 3.10/15 - UB, trying
>> > // to access value of int object by float lvalue.
>> > float f = u.f;

>>
>> Yes. But if you consider
>>
>> u.i = 42;
>> u.f = 2.71828;
>>
>> float f = u.f;
>>
>> Then you have valid code.
>>
>> And then the compiler can't reorder the two assignment statements.
>>
>> It can't reorder the assignment statements even if they're placed in a
>> function where it's not locally known that for a particular call the
>> float and int are in a union (Gabriel's point).

>
> Indeed. This is a well known bug in the C and C++ specs. James talks
> about it else-thread, quoted here:
>
> On Sep 11, 11:56 am, James Kanze <(E-Mail Removed)> wrote:
>> The issue is not simple, and formally g++ isn't conformant in
>> this respect (but it has nothing to do with §9.2/17---I've not
>> verified, but I suspect that g++ does handle that correctly).
>> But if I understand correctly, the C committee thinks that it is
>> the standard which is broken, not g++---the standard guarantees
>> too much.
>>
>> The exact issue was something like:
>>
>> union U { int a; double b; }
>>
>> int f(int* a, double *b)
>> {
>> // g++ reorders the following two statements...
>> int result = *a;
>> *b = 3.14159;
>> }
>>
>> // ...
>> U u;
>> u.a = 42;
>> int i = f(&u.a, &u.b);
>>
>> Technically, the above code fulfills the requirements of the
>> standard; you're reading the last element written in the union,
>> then writing a different element. IIRC, the opinion of the C
>> committee was that this *should* only be guaranteed to work when
>> the actual access is through the union type.

>
> Basically, the problem is that with unions, the strict aliasing rules
> no longer "work". The solution that James says that the C committee is
> for is not abandoning the strict aliasing rules, but instead greatly
> restricting usages of unions. Basically, in current practice, if a
> union has 2 different members, and if you let pointers to 2 or more
> members escape the current scope, then you're boned. I'm not exactly
> sure what formal rule the C committee is pondering, but at the very
> least it would have to effectively include that restriction.
>
> On Sep 11, 2:10 pm, "Alf P. Steinbach /Usenet" <alf.p.steinbach
> (E-Mail Removed)> wrote:
>> >> Now consider

>>
>> >> #include<stdio.h>

>>
>> >> struct A { double d; int x; };

>>
>> >> void foo( int* a, A* b )
>> >> {
>> >> b->x = 1;
>> >> *a = 2;
>> >> }

>>
>> >> int main()
>> >> {
>> >> A aha;
>> >> foo(&aha.x,&aha );
>> >> printf( "%d\n", aha.x );
>> >> }

>>
>> >> Since int* and A* are clearly pointers with different referent types,
>> >> at least the simplistic purported aliasing-based reordering rule
>> >> mentioned so far should allow reordering of the statements in foo,
>> >> causing output 1 instead of 2.

>>
>> >> I don't believe it -- although I may be forced to if James can hark
>> >> up some reference (in which case the standard, IMHO, needs to be
>> >> fixed).

>>
>> > I don't believe that the Standard allows reordering this either. b->x
>> > is int lvalue and *a is int lvalue too. Both are allowed to alias.

>>
>> Yes.
>>
>> And as I see it §3.10/15 means that that's still the case when accessing
>> A: as B: where B is layout-compatible with A (assuming same member
>> names for this example).

>
> Then you would be alone on your interpretation. I don't have a C spec
> handy, but for C++03, that is not the case.
>
> This is what I can find on the subject in the standard itself.
>
> C++03 standard, 9.2 Class members / 16
>>>>>

> If a POD-union contains two or more POD-structs that share a common
> initial sequence, and if the PODunion
> 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 layoutcompatible
> types (and, for bit-fields, the same widths) for a sequence of one or
> more initial members.
> <<<<
>
> The rule above only applies to PODs in a union.
>
> C++03 standard, 9.2 Class members / 167
>>>>>

> A pointer to a POD-struct object, suitably converted using a
> reinterpret_cast, 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. ]
> <<<<
>
> The section above, especially with the (non-binding) note, pretty
> clearly states that the C-style hack of inheritance may not work in C+
> +. There might be unnamed padding which differs between different POD
> structs.
>
> Frankly though, this entire thing is a mess. When you compare the
> guarantees of the two quotes, /which appear right next to each other
> in the standard/, I don't understand how you can reconcile them in a
> sane implementation. So, when the POD types are members of a union,
> there's no difference in padding bits, but when the same POD types are
> not members of a union, there might be extra magical padding bits.
> What?
>


The result `offsetof` is necessarily determined by the type and member
inspected, so I don't believe that the offsets can be any different
depending on where an object is located at and as.

If we summarize the said paragraphs, my opinion is that one could conclude
that one can indeed access "A: as B:".
 
Reply With Quote
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      09-13-2010
* Joshua Maurice, on 13.09.2010 20:56:
> On Sep 11, 2:10 pm, "Alf P. Steinbach /Usenet"<alf.p.steinbach
> (E-Mail Removed)> wrote:
>> * Johannes Schaub (litb), on 11.09.2010 22:54:
>>> The way I understand it, it does not matter whether the reference is by an
>>> union or not. Aliasing an int as a float is UB no matter by an union or not.
>>> I thought that was the whole point of Gabriel's issue report? I.e if the
>>> statements in foo are reordered, then "t.d" accesses an int object by a
>>> double lvalue, violating aliasing.

>>
>>> Example to show what I mean:

>>
>>> union {
>>> float f;
>>> int i;
>>> } u;

>>
>>> // now the object is a float, by 3.8/1.
>>> u.f = 1.f;

>>
>>> // now it is an int, also by 3.8/1
>>> u.i = 10;

>>
>>> // aliasing violation by 3.10/15 - UB, trying
>>> // to access value of int object by float lvalue.
>>> float f = u.f;

>>
>> Yes. But if you consider
>>
>> u.i = 42;
>> u.f = 2.71828;
>>
>> float f = u.f;
>>
>> Then you have valid code.
>>
>> And then the compiler can't reorder the two assignment statements.
>>
>> It can't reorder the assignment statements even if they're placed in a function
>> where it's not locally known that for a particular call the float and int are in
>> a union (Gabriel's point).

>
> Indeed. This is a well known bug in the C and C++ specs. James talks
> about it else-thread, quoted here:


You're calling a compiler bug a bug in the standard?

Well you make me laugh.

Also, note that we were discussing James' statements. It's completely
unnecessary to quote it again except to put it in a misleading new context.


[snip requoting of up-thread message]
>> And as I see it 3.10/15 means that that's still the case when accessing A: as
>> B: where B is layout-compatible with A (assuming same member names for this
>> example).

>
> Then you would be alone on your interpretation. I don't have a C spec
> handy, but for C++03, that is not the case.


You can assert how much you want that other people agree with you, that none of
them agree with me, and that what the standard says is an "interpretation".

It's similar to your earlier assertion that a compiler bug is really a bug in
the standard.

It's a stupid argument.


> This is what I can find on the subject in the standard itself.
>
> C++03 standard, 9.2 Class members / 16
>>>>>

> If a POD-union contains two or more POD-structs that share a common
> initial sequence, and if the PODunion
> 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 layoutcompatible
> types (and, for bit-fields, the same widths) for a sequence of one or
> more initial members.
> <<<<
>
> The rule above only applies to PODs in a union.
>
> C++03 standard, 9.2 Class members / 167
>>>>>

> A pointer to a POD-struct object, suitably converted using a
> reinterpret_cast, 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. ]
> <<<<
>
> The section above, especially with the (non-binding) note, pretty
> clearly states that the C-style hack of inheritance may not work in C+
> +.


No, it does not. It says nothing of the sort, or even related to that.


> There might be unnamed padding which differs between different POD
> structs.
>
> Frankly though, this entire thing is a mess. When you compare the
> guarantees of the two quotes, /which appear right next to each other
> in the standard/, I don't understand how you can reconcile them in a
> sane implementation. So, when the POD types are members of a union,
> there's no difference in padding bits, but when the same POD types are
> not members of a union, there might be extra magical padding bits.
> What?
>
> We expect that a compiler has a single rule for handling member
> offsets so that accessing a member of an object is efficient, so it
> doesn't matter if the POD object is a complete object or a member sub-
> object of a union - the expected result is that the compiler will
> generate the same assembly to access a member sub-object of the POD
> object from a pointer to the POD object in all cases. With this in
> mind, I have no clue how you're supposed to reconcile those two
> sections above, one of which says there is no difference in padding
> between lay-out compatible POD-struct types, and the next section
> which says there might be a difference.


It's simple.

Whatever it is you are imagining is being said in the reinterpret_cast rule, is
not said there: it's only in your /imagination/.


> However, at face value, most / all of the gcc examples in this thread
> have been conforming.
>
>> Otherwise there would have to be some rule about exactly which pointer referent
>> types are considered to be sufficiently different that the pointers can be
>> assumed to be unaliased -- int != A?, A != B?, what?

>
> Yes. That is exactly what "3.10 Lvalues and rvalues / 15" does. Hell,
> there's a note on it which reads: "The intent of this list is to
> specify those circumstances in which an object may or may not be
> aliased."


We were discussing 3.10/15.


Cheers & hth.,

- ALf

--
blog at <url: http://alfps.wordpress.com>
 
Reply With Quote
 
Joshua Maurice
Guest
Posts: n/a
 
      09-13-2010
On Sep 13, 12:19*pm, "Johannes Schaub (litb)" <(E-Mail Removed)>
wrote:
> Joshua Maurice wrote:
> > On Sep 11, 2:10 pm, "Alf P. Steinbach /Usenet" <alf.p.steinbach
> > (E-Mail Removed)> wrote:
> >> * Johannes Schaub (litb), on 11.09.2010 22:54:
> >> >> Now consider

>
> >> >> #include<stdio.h>

>
> >> >> struct A { double d; int x; };

>
> >> >> void foo( int* a, A* b )
> >> >> {
> >> >> b->x = 1;
> >> >> *a = 2;
> >> >> }

>
> >> >> int main()
> >> >> {
> >> >> A aha;
> >> >> foo(&aha.x,&aha );
> >> >> printf( "%d\n", aha.x );
> >> >> }

>
> >> >> Since int* and A* are clearly pointers with different referent types,
> >> >> at least the simplistic purported aliasing-based reordering rule
> >> >> mentioned so far should allow reordering of the statements in foo,
> >> >> causing output 1 instead of 2.

>
> >> >> I don't believe it *-- *although I may be forced to if James can hark
> >> >> up some reference (in which case the standard, IMHO, needs to be
> >> >> fixed).

>
> >> > I don't believe that the Standard allows reordering this either. b->x
> >> > is int lvalue and *a is int lvalue too. Both are allowed to alias.

>
> >> Yes.

>
> >> And as I see it 3.10/15 means that that's still the case when accessing
> >> A: as B: where B is layout-compatible with A (assuming same member
> >> names for this example).

>
> > Then you would be alone on your interpretation. I don't have a C spec
> > handy, but for C++03, that is not the case.

>
> > This is what I can find on the subject in the standard itself.

>
> > C++03 standard, 9.2 Class members / 16

>
> > If a POD-union contains two or more POD-structs that share a common
> > initial sequence, and if the PODunion
> > 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 layoutcompatible
> > types (and, for bit-fields, the same widths) for a sequence of one or
> > more initial members.
> > <<<<

>
> > The rule above only applies to PODs in a union.

>
> > C++03 standard, 9.2 Class members / 167

>
> > A pointer to a POD-struct object, suitably converted using a
> > reinterpret_cast, 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. ]
> > <<<<

>
> > The section above, especially with the (non-binding) note, pretty
> > clearly states that the C-style hack of inheritance may not work in C+
> > +. There might be unnamed padding which differs between different POD
> > structs.

>
> > Frankly though, this entire thing is a mess. When you compare the
> > guarantees of the two quotes, /which appear right next to each other
> > in the standard/, I don't understand how you can reconcile them in a
> > sane implementation. So, when the POD types are members of a union,
> > there's no difference in padding bits, but when the same POD types are
> > not members of a union, there might be extra magical padding bits.
> > What?

>
> The result `offsetof` is necessarily determined by the type and member
> inspected, so I don't believe that the offsets can be any different
> depending on where an object is located at and as.
>
> If we summarize the said paragraphs, my opinion is that one could conclude
> that one can indeed access "A: as B:".


That is reading into the standard, and picking and choosing facts. I
view it as inconsistent. As the intent does not appear rather clear, I
would just stay clear of the whole thing entirely if at all possible.
If not possible, I would check with my compiler vendors if I could, or
at least confirm some assembly output.
 
Reply With Quote
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      09-13-2010
* Joshua Maurice, on 13.09.2010 21:24:
>>
>> If we summarize the said paragraphs, my opinion is that one could conclude
>> that one can indeed access "A: as B:".

>
> That is reading into the standard, and picking and choosing facts.


No, that is a misleading statement.

There are no contrary facts.

You're effectively saying one can pick and choose facts in a discussion about
the flatness of the Earth. But one cannot. There are no contrary facts: the
Earth is round, or nearly so, it's not flat, and no facts support flatness.


> I view it as inconsistent.


You'd have to point out an inconsistency first, in order to convince anybody.


> As the intent does not appear rather clear, I
> would just stay clear of the whole thing entirely if at all possible.


There's nothing unclear about the intent of the standard, as far as I can see.


> If not possible, I would check with my compiler vendors if I could, or
> at least confirm some assembly output.


Yes, that is a good idea.


Cheers & hth.,

- Alf

--
blog at <url: http://alfps.wordpress.com>
 
Reply With Quote
 
Joshua Maurice
Guest
Posts: n/a
 
      09-13-2010
On Sep 13, 12:24*pm, "Alf P. Steinbach /Usenet" <alf.p.steinbach
(E-Mail Removed)> wrote:
> * Joshua Maurice, on 13.09.2010 20:56:
> > On Sep 11, 2:10 pm, "Alf P. Steinbach /Usenet"<alf.p.steinbach
> > (E-Mail Removed)> *wrote:
> >> * Johannes Schaub (litb), on 11.09.2010 22:54:
> >>> The way I understand it, it does not matter whether the reference is by an
> >>> union or not. Aliasing an int as a float is UB no matter by an union or not.
> >>> I thought that was the whole point of Gabriel's issue report? I.e if the
> >>> statements in foo are reordered, then "t.d" accesses an int object by a
> >>> double lvalue, violating aliasing.

>
> >>> Example to show what I mean:

>
> >>> union {
> >>> * * float f;
> >>> * * int i;
> >>> } u;

>
> >>> // now the object is a float, by 3.8/1.
> >>> u.f = 1.f;

>
> >>> // now it is an int, also by 3.8/1
> >>> u.i = 10;

>
> >>> // aliasing violation by 3.10/15 - UB, trying
> >>> // to access value of int object by float lvalue.
> >>> float f = u.f;

>
> >> Yes. But if you consider

>
> >> * * u.i = 42;
> >> * * u.f = 2.71828;

>
> >> * * float f = u.f;

>
> >> Then you have valid code.

>
> >> And then the compiler can't reorder the two assignment statements.

>
> >> It can't reorder the assignment statements even if they're placed in a function
> >> where it's not locally known that for a particular call the float and int are in
> >> a union (Gabriel's point).

>
> > Indeed. This is a well known bug in the C and C++ specs. James talks
> > about it else-thread, quoted here:

>
> You're calling a compiler bug a bug in the standard?
>
> Well you make me laugh.
>
> Also, note that we were discussing James' statements. It's completely
> unnecessary to quote it again except to put it in a misleading new context.
>
> [snip requoting of up-thread message]
>
> >> And as I see it 3.10/15 means that that's still the case when accessing A: as
> >> B: where B is layout-compatible with A (assuming same member names for this
> >> example).

>
> > Then you would be alone on your interpretation. I don't have a C spec
> > handy, but for C++03, that is not the case.

>
> You can assert how much you want that other people agree with you, that none of
> them agree with me, and that what the standard says is an "interpretation".
>
> It's similar to your earlier assertion that a compiler bug is really a bug in
> the standard.
>
> It's a stupid argument.


Could you please define compiler bug? I would loosely define it as a
compiler which does not follow its standard.

However, what if the standard is logically inconsistent? If the
standard is logically inconsistent, then I would not call any compiler
conforming nor non-conforming. One cannot abide by inconsistent rules,
and that is exactly the state of affairs with the C and C++ standards
with strict aliasing and unions. The rules are inconsistent, and
that's why I call it a bug in the standard.

Moreover, James has mentioned a possible preferred resolution of the C
committee, a resolution which makes the standard logically consistent,
and which also makes the gcc behavior talked about here conforming to
this new logically consistent standard.

> > This is what I can find on the subject in the standard itself.

>
> > C++03 standard, 9.2 Class members / 16

>
> > If a POD-union contains two or more POD-structs that share a common
> > initial sequence, and if the PODunion
> > 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 layoutcompatible
> > types (and, for bit-fields, the same widths) for a sequence of one or
> > more initial members.
> > <<<<

>
> > The rule above only applies to PODs in a union.

>
> > C++03 standard, 9.2 Class members / 167

>
> > A pointer to a POD-struct object, suitably converted using a
> > reinterpret_cast, 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. ]
> > <<<<

>
> > The section above, especially with the (non-binding) note, pretty
> > clearly states that the C-style hack of inheritance may not work in C+
> > +.

>
> No, it does not. It says nothing of the sort, or even related to that.


I know it's rather pedantic, but it specifically allows reading and
writing to the common leading part of layout-compatible POD-structs
but only when they're both members of the same union. By specifically
restricting it to only in a union, it is also saying that it does not
work outside of a union. With this in mind, you would need to find
another explicit rule which specifically allows casting from POD-
struct type T1 to layout-compatible POD-struct type T2 and reading and
writing to the common leading part. Can you find such a thing? I
cannot.

> >> Otherwise there would have to be some rule about exactly which pointer referent
> >> types are considered to be sufficiently different that the pointers can be
> >> assumed to be unaliased *-- *int != A?, A != B?, what?

>
> > Yes. That is exactly what "3.10 Lvalues and rvalues / 15" does. Hell,
> > there's a note on it which reads: "The intent of this list is to
> > specify those circumstances in which an object may or may not be
> > aliased."

>
> We were discussing 3.10/15.


Then I am confused how you could make such a statement - you said "But
then there would have to be rules clarifying exactly how different the
pointer types would have to be to not alias", and exactly that is
specified in 3.10/15, which is why I brought it up (again).
 
Reply With Quote
 
Joshua Maurice
Guest
Posts: n/a
 
      09-13-2010
On Sep 13, 12:30*pm, "Alf P. Steinbach /Usenet" <alf.p.steinbach
(E-Mail Removed)> wrote:
> * Joshua Maurice, on 13.09.2010 21:24:
> >> If we summarize the said paragraphs, my opinion is that one could conclude
> >> that one can indeed access "A: as B:".

>
> > That is reading into the standard, and picking and choosing facts.

>
> No, that is a misleading statement.
>
> There are no contrary facts.
>
> You're effectively saying one can pick and choose facts in a discussion about
> the flatness of the Earth. But one cannot. There are no contrary facts: the
> Earth is round, or nearly so, it's not flat, and no facts support flatness.


Bad analogy. Whether the Earth is round a discussion of empirical
facts of the natural world, a scientific question, on which consensus
carries no weight, and only evidence matters. Our discussion is of
what a standard says. A standard is more like math (which is not a
science) and less like science. A standard defines the terms and the
universe. Whereas science describes the natural world, a standard like
C++ defines terms and whether or not parts of the natural world meet
those terms. I could define a standard where the word "up" means
"towards the center of the Earth", and I could evaluate whether or not
a plane's controls meet my standard. (Admittingly, such a standard
would be incredibly silly and mostly devoid of value.)

> > I view it as inconsistent.

>
> You'd have to point out an inconsistency first, in order to convince anybody.
>
> > As the intent does not appear rather clear, I
> > would just stay clear of the whole thing entirely if at all possible.

>
> There's nothing unclear about the intent of the standard, as far as I can see.


Hopefully we agree that the intent of 3.10 / 15 is to allow compilers
to optimize assuming that certain pointers do not alias. The note
there explicitly mentions as much. The rules given there effectively
say which pointers can and cannot alias. These rules are logically
consistent with the rest of the standard in large part. When obeying
the rest of the rules of the standard (excepting unions), you cannot
reach a state where two differently typed pointers (as defined by
3.10 / 15) can alias.

Except for unions. Unions break the rule, and they render the note in
3.10 / 15 "wrong". The explicit stated intent was to allow compilers
to optimize assuming certain pointers do not alias, but with unions,
any type of pointer can alias any other type of pointer. Thus we have
a logical inconsistency in the standard.
 
Reply With Quote
 
Alf P. Steinbach /Usenet
Guest
Posts: n/a
 
      09-13-2010
* Joshua Maurice, on 13.09.2010 21:45:
> On Sep 13, 12:30 pm, "Alf P. Steinbach /Usenet"<alf.p.steinbach
> (E-Mail Removed)> wrote:
>> * Joshua Maurice, on 13.09.2010 21:24:
>>>> If we summarize the said paragraphs, my opinion is that one could conclude
>>>> that one can indeed access "A: as B:".

>>
>>> That is reading into the standard, and picking and choosing facts.

>>
>> No, that is a misleading statement.
>>
>> There are no contrary facts.
>>
>> You're effectively saying one can pick and choose facts in a discussion about
>> the flatness of the Earth. But one cannot. There are no contrary facts: the
>> Earth is round, or nearly so, it's not flat, and no facts support flatness.

>
> Bad analogy. Whether the Earth is round a discussion of empirical
> facts of the natural world, a scientific question, on which consensus
> carries no weight, and only evidence matters. Our discussion is of
> what a standard says. A standard is more like math (which is not a
> science) and less like science. A standard defines the terms and the
> universe. Whereas science describes the natural world, a standard like
> C++ defines terms and whether or not parts of the natural world meet
> those terms. I could define a standard where the word "up" means
> "towards the center of the Earth", and I could evaluate whether or not
> a plane's controls meet my standard. (Admittingly, such a standard
> would be incredibly silly and mostly devoid of value.)
>
>>> I view it as inconsistent.

>>
>> You'd have to point out an inconsistency first, in order to convince anybody.
>>
>>> As the intent does not appear rather clear, I
>>> would just stay clear of the whole thing entirely if at all possible.

>>
>> There's nothing unclear about the intent of the standard, as far as I can see.

>
> Hopefully we agree that the intent of 3.10 / 15 is to allow compilers
> to optimize assuming that certain pointers do not alias.


No, we don't.

For C++98 the intent is explicitly stated in footnote 48.

Non-normative, but intents are non-normative: "The intent of this list is to
specify the circumstances in which an object may or may not be aliased".

There is not a word about reordering of statements or about /compiler's/
optimization.

James' failure (so far) to come up with a reference about reordering adds to that

Furthermore, 3.10/15 explicitly supports the C hack (it says aliasing can occur
through "an aggregeate or union that includes one of the aforementioned types"),
it does not exclude it -- so even if the argument about intent was not
directly countered by an explicit note (as it is), it would be pretty moot.


> The note there explicitly mentions as much.


No, it does not. I quoted it above for your benefit. Anything you see there
about optimization or reordering is only in your /imagination/; it's not there.


> The rules given there effectively
> say which pointers can and cannot alias. These rules are logically
> consistent with the rest of the standard in large part.


Yes.


> When obeying
> the rest of the rules of the standard (excepting unions), you cannot
> reach a state where two differently typed pointers (as defined by
> 3.10 / 15) can alias.


That is incorrect.

Several examples of such aliasing have been given up-thread.

Gabriel's DR is another example.


> Except for unions. Unions break the rule, and they render the note in
> 3.10 / 15 "wrong".


No, they don't: 3.10/15 has explicit language about aggregates and unions,
quoted above.

Please try to add some logical inferences.

Sheep are black (they aren't), therefore Nelson Mandela is king of France (he
isn't, and there's currently no such thing as king of France), doesn't carry
much weight, you see.


> The explicit stated intent was to allow compilers
> to optimize assuming certain pointers do not alias,


No, it was not.

Requoting the intent, note 48, for your benefit (non-normative, but intents are
non-normative): "The intent of this list is to specify the circumstances in
which an object may or may not be aliased".

Where you read "compiler" and "optimization", that's just your /imagination/.


> but with unions,
> any type of pointer can alias any other type of pointer. Thus we have
> a logical inconsistency in the standard.


No, we don't.


Cheers & hth.,

- Alf

--
blog at <url: http://alfps.wordpress.com>
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
"Variable variable name" or "variable lvalue" mfglinux Python 11 09-12-2007 03:08 AM
If you get an order # does it mean the order is accepted? =?Utf-8?B?U3RldmUxMDc3?= Windows 64bit 3 05-12-2005 11:46 PM
How do I scope a variable if the variable name contains a variable? David Filmer Perl Misc 19 05-21-2004 03:55 PM
Traversion order cf. output order in XSL Soren Kuula XML 2 02-01-2004 09:10 AM
How to Display DropDownList with preserved order (custom order) cspoh ASP .Net Web Controls 0 07-31-2003 09:19 AM



Advertisments