Topic: Where is aliasing described in draft stand
Author: err@raelity.com (Ernie Rael)
Date: 1997/02/26 Raw View
After the initial analysis declaring that the reinterpret_cast
had bad aliasing, and suggesting some hacks which worked,
the compiler vendor (DEC) came back a few days later with a
fully "defined" solution that does not depend on unspecified
casting. The solution they sent looks as follows.
Note that the nature of a GenPtr allows them to be bit
copied around, and the memmove is inlined by the compiler.
========================================================
typedef void* GenPtr;
inline void* operator new(size_t,void* p,int) { return p; }
#include <string.h>
#pragma intrinsic(memmove)
template<class T> inline GenPtr leda_copy(const T& x) {
GenPtr p = 0;
if(sizeof(T) <= sizeof(GenPtr)) {
char buf[2*sizeof(T)];
memmove(&p, new((T*)&buf,0) T(x), sizeof(T));
} else {
p = new T(x);
}
return p;
}
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: jpotter@falcon.lhup.edu (John E. Potter)
Date: 1997/02/27 Raw View
Steve Clamage (Stephen.Clamage@Eng.Sun.COM) wrote:
: Second counter-example, much stronger:
: struct S { int i; ... };
: S s;
: int* ip = static_cast<int*>(&s); // convert struct* to int*
: *ip = 2;
: The rules of C and C++ state explicitly that '&s' can be converted
: to a pointer to its first element, and therefore modifying 's' via
: 'ip' is completely valid.
Yes, 9.2/17 assures that &s suitably cast to int* must work.
But 5.2.9 [expr.static.cast] does not list pointer to POD conversion to
pointer to first member as one of the valid conversions.
Is this another implicit conversion of &s to void* to allow the
static_cast with no specified semantics?
Still confused,
John
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]
Author: Stephen.Clamage@Eng.Sun.COM (Steve Clamage)
Date: 1997/02/24 Raw View
In article 208770203@news.scruznet.com, err@raelity.com (Ernie Rael) writes:
>According to to a compiler vendor i'm dealing with (this
>arises from a problem with the optimizer)
>
> C++ aliasing rules say that storing through "pointer to
> type A" does NOT affect memory pointed to by pointers of
> type "pointer to type B" (except for "pointer to char").
>
>I can't find anything in the draft standard that implies
>this or otherwise addresses the issue.
The claim as presented is not true. Here is the most obvious
counter-example:
class B { ... };
class D : public B { ... };
D d;
B* pb = &d; // implicitly convert derived* to base*
pb->somefield = something;
Does the vendor claim that 'd' can be assumed not to be
modified by the assignment through 'pb'? I hope not.
Second counter-example, much stronger:
struct S { int i; ... };
S s;
int* ip = static_cast<int*>(&s); // convert struct* to int*
*ip = 2;
The rules of C and C++ state explicitly that '&s' can be converted
to a pointer to its first element, and therefore modifying 's' via
'ip' is completely valid.
Thus, not only does C++ NOT have a "no-aliasing" rule, compiler
implementors must usually make the pessimistic assumption that
any pointer can point to almost any object, unless flow analysis can
prove otherwise.
That doesn't give you license to make arbitrary reinterpret_casts
and expect good results, of course. Other rules may apply.
>After considerable macro expansion, the simple program
>in question looks like:
>
>1. p = 0;
>2. *((int *)&p) = x;
>3. L.item = p;
>4. printf(...,L.item);
>
>The NO aliasing rule implies that the store at 2. cannot modify
>the value of p, because p is of type GenPtr, and the object
>being stored into is of type int.
You have no guarantee that in general casting &p to int* will yield
a useful result. The old-style cast under old rules didn't have any
defined meaning, particularly if you actually dereference the result
of the cast. Under the new rules, the cast is treated as a
reinterpret_cast, and the results are implementation-defined.
Under the new C++ rules, the vendor is supposed to tell you what
the result of the cast to int* should be, and I think "might not work"
is an allowed answer. The standard also provides a recommendation to
the implementor that the results are "intended to be unsurprising".
If the cast to int* ought to work, then I would say the vendor is
optimizing too aggressively. If the vendor makes no promises about
the cast to int*, optimizing becomes irrelevant, since the source
code has no assigned meaning anyway.
---
Steve Clamage, stephen.clamage@eng.sun.com
---
[ comp.std.c++ is moderated. To submit articles: Try just posting with your
newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
Comments? mailto:std-c++-request@ncar.ucar.edu
]
Author: fjh@mundook.cs.mu.OZ.AU (Fergus Henderson)
Date: 1997/02/25 Raw View
Stephen.Clamage@Eng.Sun.COM (Steve Clamage) writes:
>err@raelity.com (Ernie Rael) writes:
>>According to to a compiler vendor i'm dealing with (this
>>arises from a problem with the optimizer)
>>
>> C++ aliasing rules say that storing through "pointer to
>> type A" does NOT affect memory pointed to by pointers of
>> type "pointer to type B" (except for "pointer to char").
>>
>>I can't find anything in the draft standard that implies
>>this or otherwise addresses the issue.
>
>The claim as presented is not true.
Yes, but I think the claim
C++ rules say that it is undefined behaviour if you store a value
through a "pointer to type A" and accessing the stored value via
a pointer of type "pointer to type B", where "A" and "B" are
unrelated types other than char or unsigned char.
is true.
Certainly something very much like this claim is true in C.
Here's a quote from the documentation for the Alpha/OSF C compiler:
| -ansi_alias
| Direct the compiler to assume the ANSI C aliasing rules. The aliasing
| rules referred to are explained in Section 3.3, paragraphs 20 and 25 of
| the ANSI C Standard, reprinted as follows:
|
| An object shall have its stored value accessed only by an lvalue that
| has one of the following types:
|
| The declared type of the object,
|
| A qualified version of the declared type of the object,
|
| A type that is the signed or unsigned type corresponding to the
| declared type of the object,
|
| A type that is the signed or unsigned type corresponding to a quali-
| fied version of the declared type of the object,
|
| An aggregate or union type that includes one of the aforementioned
| types among its members (including, recursively, a member of a
| subaggregate or contained union), or
|
| A character type.
|
| If your program does not access the same data through pointers of a dif-
| ferent type (and for this purpose, signed and qualified versions of an
| otherwise same type are considered to be the same type), then assuming
| ANSI C aliasing rules allows the compiler to generate better optimized
| code.
|
| If your program does access the same data through pointers of a dif-
| ferent type (for example, by a "pointer to int" and a "pointer to
| float"), then you must not allow the compiler to assume ANSI C aliasing
| rules. Otherwise, incorrect code might be generated.
I think the same thing follows in C++ from 3.8 [basic.life] paragraphs 4 & 6.
>Here is the most obvious counter-example: [...]
>Second counter-example, much stronger: [...]
Your examples are correct, but in both cases the types are
related (in the first example it is a base-class/derived-class
relationship, in the second example one type is the type of the
first member of the other class).
>Thus, not only does C++ NOT have a "no-aliasing" rule,
I don't think that follows.
Although somewhere along the chain of communication from the compiler
vendor to this newsgroup it appears that some caveats on the claim have
been dropped, I think C++ does have rules that could reasonably be
called "no-aliasing" rules, and so I think the basis of the vendor's
original claim is sound.
>compiler implementors must usually make the pessimistic assumption that
>any pointer can point to almost any object, unless flow analysis can
>prove otherwise.
I don't think that follows either.
The ANSI C standard and the C++ CD both allow compiler implementors to
assume that a store via one pointer will not affect a load via another
pointer if the types are unrelated, e.g. `int' and `float', even if
they might point to the same region of memory.
>You have no guarantee that in general casting &p to int* will yield
>a useful result.
True, but let's assume for the sake of argument that implementation
defines it to work.
>If the cast to int* ought to work, then I would say the vendor is
>optimizing too aggressively.
I disagree. A good vendor would provide an option to disable such
aggressive optimizations, to support non-conforming programs, but I
think such optimizations are allowed by the standard, and if they make
standard-conforming programs run faster, then I'm in favour of them.
--
Fergus Henderson <fjh@cs.mu.oz.au> | "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh> | of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3 | -- the last words of T. S. Garp.
---
[ comp.std.c++ is moderated. To submit articles: try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ FAQ: http://reality.sgi.com/employees/austern_mti/std-c++/faq.html ]
[ Policy: http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu ]