Boost logo

Boost :

Subject: Re: [boost] [TypeIndex] Peer review period for library acceptance begins, ending Thurs 21st Nov
From: Niall Douglas (s_sourceforge_at_[hidden])
Date: 2013-11-15 16:48:15


On 15 Nov 2013 at 17:50, Antony Polukhin wrote:

> > I believe that this was a problem for Boost.Move with gcc,
> > which does something similar. It's actually quite common
> > for old C code that casts between different structs to fail
> > with newer compilers. For instance, Python does not work
> > without -fno-strict-aliasing.
>
> Looks like I've got what are you talking about. It's an optimization in
> GCC, that assumes that if there is a reference to two different types and
> neither of those types is char, than those types are different in memory
> (are not aliases):
>
> void foo(int64_t& v1, int32_t& v2) {
> /* GCC assumes that address of v1 is not a part of v2 adresses*/
> v2 = 2;
> cout << v1;
> }
>
> int64_t i64 = 1;
> foo(i64, reinterpret_cast<int32_t>(i64)); // outputs 1
>
>
> But this error appears only when we mutate data (
> https://svn.boost.org/trac/boost/wiki/Guidelines/WarningsGuidelines search
> for "strict-aliasing rules")

This isn't really the same thing as Stephen mentioned. The above
example is explicitly unrelated types i.e. a int64_t is not a
int32_t, and the compiler is permitted to absolutely assume that to
be true in the strongest possible way. The strict-aliasing problems
in Python and the Linux kernel are due to them casting between
unrelated structure types without the proper use of volatile
qualification and/or going through void * or char * as the carrying
opaque pointer type, such that the compiler's alias optimisation pass
will assume that two unrelated type pointers will never refer to the
same patch of memory which is permitted by the standard. Using
volatile or void * or char * can inhibit that optimisation pass by
disabling the ability to assume two pointers cannot refer to the same
memory, and therefore inhibit unsafe code being generated. It is of
course still undefined behaviour, but it's extremely common in C out
of necessity.

What TypeIndex does is much safer - it upcasts to a derived and
therefore related type, and the compiler knows the types are related
(or static_cast would fail). I cannot see how alias optimisation
could ever therefore generate unsafe code in this case. Upcasting to
a derived type is a very common - if often illegal - idiom in C++,
but it is usually safe. It also saves programmers from writing a lot
of extra boilerplate, hence its popularity.

As I mentioned in the other post, for me it's the incorrectness of
the virtual function table which kills this use of UB for me. Not the
static upcast.

Niall

-- 
Currently unemployed and looking for work.
Work Portfolio: http://careers.stackoverflow.com/nialldouglas/



Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk