title: gcc, strict-aliasing, and horror stories
body: <p>In <a href="https://stackoverflow.com/questions/2906365/gcc-strict-aliasing-and-casting-through-a-union">gcc-strict-aliasing-and-casting-through-a-union</a> I asked whether anyone had encountered problems with union punning through pointers.  So far, the answer seems to be <em>No</em>.</p>
  
  <p>This question is broader: Do you have <em>any</em> horror stories about gcc and strict-aliasing?</p>
  
  <p>Background: Quoting from <a href="https://stackoverflow.com/questions/2771023/c99-strict-aliasing-rules-in-c-gcc/2771041#2771041">AndreyT's answer in c99-strict-aliasing-rules-in-c-gcc</a>:</p>
  
  <blockquote>
    <p>"Strict aliasing rules are rooted in parts of the standard that were present in C and C++ since the beginning of [standardized] times. The clause that prohibits accessing object of one type through a lvalue of another type is present in C89/90 (6.3) as well as in C++98 (3.10/15). ... It is just that not all compilers wanted (or dared) to enforce it or rely on it."</p>
  </blockquote>
  
  <p>Well, <strong>gcc</strong> is now daring to do so, with its <code>-fstrict-aliasing</code> switch.  And this has caused some problems.  See, for example, the excellent article  <a href="http://davmac.wordpress.com/2009/10/" rel="noreferrer">http://davmac.wordpress.com/2009/10/</a> about a Mysql bug, and the equally excellent discussion in <a href="http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html" rel="noreferrer">http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html</a>.</p>
  
  <p>Some other less-relevant links:</p>
  
  <ul>
  <li><a href="https://stackoverflow.com/questions/1225741/performance-impact-of-fno-strict-aliasing">performance-impact-of-fno-strict-aliasing</a>  </li>
  <li><a href="https://stackoverflow.com/questions/754929/strict-aliasing">strict-aliasing</a>  </li>
  <li><a href="https://stackoverflow.com/questions/262379/when-is-char-safe-for-strict-pointer-aliasing">when-is-char-safe-for-strict-pointer-aliasing</a>  </li>
  <li><a href="https://stackoverflow.com/questions/725138/how-to-detect-strict-aliasing-at-compile-time">how-to-detect-strict-aliasing-at-compile-time</a>  </li>
  </ul>
  
  <p>So to repeat, do you have a horror story of your own?  Problems <strong><em>not</em></strong> indicated by <code>-Wstrict-aliasing</code> would, of course, be preferred.  And other C compilers are also welcome.</p>
  
  <p><strong><em>Added June 2nd</em></strong>:  The first link in <a href="https://stackoverflow.com/a/2959468/4095830">Michael Burr's answer</a>, which does <strong><em>indeed</em></strong> qualify as a horror story, is perhaps a bit dated (from 2003).  I did a quick test, but the problem has apparently gone away.</p>
  
  <p>Source:</p>
  
  <pre><code>#include &lt;string.h&gt;
  struct iw_event {               /* dummy! */
      int len;
  };
  char *iwe_stream_add_event(
      char *stream,               /* Stream of events */
      char *ends,                 /* End of stream */
      struct iw_event *iwe,       /* Payload */
      int event_len)              /* Real size of payload */
  {
      /* Check if it's possible */
      if ((stream + event_len) &lt; ends) {
              iwe-&gt;len = event_len;
              memcpy(stream, (char *) iwe, event_len);
              stream += event_len;
      }
      return stream;
  }
  </code></pre>
  
  <p>The specific complaint is:</p>
  
  <blockquote>
    <p>Some users have complained that when the [above] code is compiled without the -fno-strict-aliasing, the order of the write and memcpy is inverted (which means a bogus len is mem-copied into the stream).</p>
  </blockquote>
  
  <p>Compiled code, using <strong>gcc</strong> 4.3.4 on CYGWIN wih -O3 (please correct me if I am wrong--my assembler is a bit rusty!):</p>
  
  <pre><code>_iwe_stream_add_event:
          pushl       %ebp
          movl        %esp, %ebp
          pushl       %ebx
          subl        $20, %esp
          movl        8(%ebp), %eax       # stream    --&gt; %eax
          movl        20(%ebp), %edx      # event_len --&gt; %edx
          leal        (%eax,%edx), %ebx   # sum       --&gt; %ebx
          cmpl        12(%ebp), %ebx      # compare sum with ends
          jae L2
          movl        16(%ebp), %ecx      # iwe       --&gt; %ecx
          movl        %edx, (%ecx)        # event_len --&gt; iwe-&gt;len (!!)
          movl        %edx, 8(%esp)       # event_len --&gt; stack
          movl        %ecx, 4(%esp)       # iwe       --&gt; stack
          movl        %eax, (%esp)        # stream    --&gt; stack
          call        _memcpy
          movl        %ebx, %eax          # sum       --&gt; retval
  L2:
          addl        $20, %esp
          popl        %ebx
          leave
          ret
  </code></pre>
  
  <p>And for the second link in Michael's answer,</p>
  
  <pre><code>*(unsigned short *)&amp;a = 4;
  </code></pre>
  
  <p><strong>gcc</strong> will usually (always?) give a warning.  But I <em>believe</em> a valid solution to this (for <strong>gcc</strong>)  is to use:</p>
  
  <pre><code>#define CAST(type, x) (((union {typeof(x) src; type dst;}*)&amp;(x))-&gt;dst)
  // ...
  CAST(unsigned short, a) = 4;
  </code></pre>
  
  <p>I've asked SO whether this is OK in <a href="https://stackoverflow.com/questions/2906365/gcc-strict-aliasing-and-casting-through-a-union">gcc-strict-aliasing-and-casting-through-a-union</a>, but so far nobody disagrees.</p>