Re: [PATCH 4/5] sim/erc32: avoid dereferencing type-punned pointer warnings

Lancelot SIX via Gdb-patches
2022-10-12T17:02:46Z

On Wed, Oct 12, 2022 at 03:11:27PM +0100, Pedro Alves wrote:
> On 2022-10-12 1:38 p.m., Andrew Burgess via Gdb-patches wrote:
> > When building the erc32 simulator I get a few warnings like this:
> >
> > /tmp/build/sim/../../src/sim/erc32/exec.c:1377:21: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
> > 1377 | sregs->fs[rd] = *((float32 *) & ddata[0]);
> > | ~^~~~~~~~~~~~~~~~~~~~~~~
> >
> > The type of '& ddata[0]' will be 'uint32_t *', which is what triggers
> > the warning.
> >
> > This commit uses an intermediate pointer of type 'char *' when
> > performing the type-punning, which is well-defined behaviour, and will
> > silence the above warning.
>
> I'm afraid that's not correct. That's still undefined behavior, it's just silencing
> the warning. The end result is still aliasing float32 and uint32_t objects, and risks
> generating bogus code. The char escape hatch only works if you access the object
> representation via a character type. Here, the patch is still accessing the object
> representation of a uint32_t object via a floa32 type.
>
> Here's an old article explaining strict aliasing (just one that I found via a quick google):
>
> https://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html
>
> This scenario is the "CASTING TO CHAR*" one in that article.
>
> > @@ -1345,7 +1345,8 @@ dispatch_instruction(struct pstate *sregs)
> > if (mexc) {
> > sregs->trap = TRAP_DEXC;
> > } else {
> > - sregs->fs[rd] = *((float32 *) & data);
> > + char *ptr = (char *) &data;
> > + sregs->fs[rd] = *((float32 *) ptr);
>
> The best IMHO is to do the type punning via a union, like e.g.:
>
> union { float32 f; uint32_t i; } u;
> u.i = data;
> sregs->fs[rd] = u.f;
>
> See here in the C11 standard:
>
> https://port70.net/~nsz/c/c11/n1570.html#note95
>
> and also the documentation of -fstrict-aliasing at:
>
> https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
>

Hi,

Another well defined (at least to my knowledge) solution to this problem
is memcpy. You could do something like:

memcpy (&sregt->fs[rd], ddata, sizeof (float32));

I tend to find this more straightforward than the type punning version,
but I would be happy with either.

Best,
Lancelot.

> Pedro Alves