Boost logo

Boost :

Subject: Re: [boost] [config] RFC PR 82
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2015-11-26 08:12:57


On 2015-11-26 15:44, Agustín K-ballo Bergé wrote:
> On 11/26/2015 8:51 AM, Andrey Semashev wrote:
>> On 2015-11-26 05:13, Agustín K-ballo Bergé wrote:
>>> On 11/25/2015 10:52 PM, Andrey Semashev wrote:
>>>>
>>>> IMHO, the standard should just
>>>> follow C11 semantics and say it more clearly.
>>>
>>> That's unlikely to happen, C has *vastly* weaker aliasing rules than
>>> C++, to the point that several C implementations choose to follow the
>>> C++ rules instead. You'd be asking for the opposite to happen.
>>
>> I can see the benefits of strict aliasing rules in other contexts, but
>> unions specifically exist to provide the common storage for objects of
>> different types in a relatively less messy way compared to, e.g. a raw
>> byte buffer. I'm not seeing people using unions and somehow expecting
>> type aliasing to not happen, quite the contrary. I think the language
>> here is being too limiting for no practical reason.
>
> How would that work? If one could read a `float` as if it were an `int`,
> then ints and floats may alias. If they may alias, then whenever you get
> a pointer to an `int` you'll have to ask could it be this other `float`
> instead?

It would work the way it works now with most, if not all compilers -
writing to any members of a union object is allowed to affect reads from
any member of the object. As such writes are not dead if any reads exist
and writes and reads must not be reordered or eliminated by compiler (as
observed by the program; on the machine instructions level there may not
be any stores or loads at all).

I'm not proposing to allow type aliasing through pointers. For instance,
taking pointers to different members of the union and working with the
members through the pointers would still be UB. The change will only
affect the contexts where the compiler is able to immediately see that
we're working with a union - i.e. where the name of the member resolves
to a member of a union.

   union variant
   {
     std::uint32_t as_uint32;
     float as_float;
   };

   variant v1, v2, v3;

   // This is defined behavior (DB)
   v1.as_float = 1.0f;
   std::cout << v1.as_uint32 << std::endl;

   // This is also DB
   using pmu_t = std::uint32_t (variant::*);
   using pmf_t = float (variant::*);
   pmu_t pmu = &variant::as_uint32;
   pmf_t pmf = &variant::as_float;
   v2.*pmf = 1.0f;
   std::cout << v2.*pmu << std::endl;

   // This is still formally UB
   std::uint32_t* pu = &v3.as_uint32;
   float* pf = &v3.as_float;
   *pf = 1.0f;
   std::cout << *pu << std::endl;


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