Boost logo

Boost :

Subject: Re: [boost] [optional] Strict Aliasing Warnings on Trunk
From: Paul A. Bristow (pbristow_at_[hidden])
Date: 2009-12-21 11:26:58


> -----Original Message-----
> From: boost-bounces_at_[hidden] [mailto:boost-bounces_at_[hidden]] On Behalf Of
> Patrick Horgan
> Sent: Friday, December 18, 2009 7:00 PM
> To: boost_at_[hidden]
> Subject: Re: [boost] [optional] Strict Aliasing Warnings on Trunk
>
> Dean Michael Berris wrote:
> > I've recently been seeing this error more and more especially on GCC with -Wall:
> >
> > /home/dean/boost/boost/optional/optional.hpp:407: warning:
> > dereferencing pointer ‘<anonymous>’ does break strict-aliasing rules
> > /home/dean/boost/boost/optional/optional.hpp:427: note: initialized from here
> > i'm not an expert in this regard but is there a way to either silence
> > or avoid these warnings? Anything you want me to try from my end?

> It's a fair bit dangerous to silence these since it's the compiler's way
> of telling you that you're invoking undefined behavior, and that when
> you turn on optimization your code isn't going to work as expected.
>
> The following program generates 6 warnings about breaking
> strict-aliasing rules, and many would dismiss them. The correct output
> of the program is:
>
> 00000020
> 00200000
>
> but when optimization is turned on it's:
>
> 00000020
> 00000020
>
> THAT's what the warning is trying to tell you, that the optimizer is
> going to do things that you don't like. In this case seeing that acopy
> is set to a and never touched again, strict aliasing lets it optimize by
> just returning the original value of a at the end.
>
> uint32_t
> swaphalves(uint32_t a)
> {
> uint32_t acopy=a;
> uint16_t *ptr=(uint16_t*)&acopy;// can't use static_cast<>, not legal.
> // you should be warned by that.
> uint16_t tmp=ptr[0];
> ptr[0]=ptr[1];
> ptr[1]=tmp;
> return acopy;
> }
>
> int main()
> {
> uint32_t a;
> a=32;
> cout << hex << setfill('0') << setw(8) << a << endl;
> a=swaphalves(a);
> cout << setw(8) << a << endl;
> }
>
> Here's the (annotated) x86 assembler generated by gcc 4.4.1 for swaphalves.
>
> _Z10swaphalvesj:
> pushl %ebp
> movl %esp, %ebp
> subl $16, %esp
> movl 8(%ebp), %eax # get a in %eax
> movl %eax, -8(%ebp) # and store in in acopy
> leal -8(%ebp), %eax # now get eax pointing at acopy (ptr=&acopy)
> movl %eax, -12(%ebp) # save that ptr at -12(%ebp)
> movl -12(%ebp), %eax # get the ptr back in %eax
> movzwl (%eax), %eax # get 16 bits from ptr[0] in eax
> movw %ax, -2(%ebp) # store the 16 bits into tmp
> movl -12(%ebp), %eax # get the ptr back in eax
> addl $2, %eax # bump up by two to get to ptr[1]
> movzwl (%eax), %edx # get that 16 bits into %edx
> movl -12(%ebp), %eax # get ptr into eax
> movw %dx, (%eax) # store the 16 bits into ptr[1]
> movl -12(%ebp), %eax # get the ptr again
> leal 2(%eax), %edx # get the address of ptr[1] into edx
> movzwl -2(%ebp), %eax # get tmp into eax
> movw %ax, (%edx) # store into ptr[1]
> movl -8(%ebp), %eax # return original a.
> leave
> ret
>
> Scary, isn't it? Of course you could use -fno-strict-aliasing to get
> the right output, but the generated code won't be as good. A better way
> to accomplish the same thing without the warning's or the incorrect
> output is to define swaphalves like this:
>
> uint32_t
> swaphalves(uint32_t a)
> {
> union swapem{
> uint32_t a;
> uint16_t b[2];
> };
> swapem s={a};
> uint16_t tmp;
> tmp=s.b[0];
> s.b[0]=s.b[1];
> s.b[1]=tmp;
> return s.a;
> }
>
> This follows the rules and helps the compiler generate MUCH better code:
>
> _Z10swaphalvesj:
> pushl %ebp # save the original value of ebp
> movl %esp, %ebp # point ebp at the stack frame
> movl 8(%ebp), %eax # get a in eax
> popl %ebp # get the original ebp value back
> roll $16, %eax # swap the two halves of a and return it
> ret
>
> Ignore strict aliasing warnings at your peril. But if you really want
> to -Wno-strict-warnings will do it.

After reading this exchange, am I right in adding this to the GCC 'what to do about warnings' guidelines section at

https://svn.boost.org/trac/boost/wiki/Guidelines/MaintenanceGuidelines?

"
warning: dereferencing pointer ‘<anonymous>’ does break strict-aliasing rules

This warns about undefined behaviour that is likely to cause unwanted results when optimisation is switched on.

Recommendation: Fix this by recoding if possible, and document that optimisation may produce wrong results.
Include a link to the above example email.

Do not suppress the warning with -Wno-strict-warnings - leave that to users after reading the documentation or making their own tests / compile without optimisation..

"

Paul

---
Paul A. Bristow
Prizet Farmhouse
Kendal, UK   LA8 8AB
+44 1539 561830, mobile +44 7714330204
pbristow_at_[hidden]

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