title: How does clang++ 9.0 magically cure dangling reference use in a lambda?
body: <p>I was experimenting on wandbox in hopes of finding compiler warnings that would help with inadvertent dangling references in lambdas. I had <a href="https://wandbox.org/permlink/BKO3bNwhdTzjaUDH" rel="nofollow noreferrer">this example</a> which misbehaves in multiple ways:</p>
  
  <pre><code>std::array&lt;std::function&lt;const int *(void)&gt;,N&gt; createFunctions()
  {
      std::array&lt;std::function&lt;const int *(void)&gt;,N&gt; fns;
      for ( int i = 0 ; i &lt; N ; i++ ) {
          std::cout &lt;&lt; &amp;i &lt;&lt; " ";
          fns[i] = [&amp;]() {
              return &amp;i;
          };
      }
      std::cout &lt;&lt; "\n";
      return fns;
  }
  </code></pre>
  
  <p>This stuffs a set of lambdas into an array of functions. Each lambda returns a pointer to a reference to a captured variable, <code>i</code>. Should be trouble all around.</p>
  
  <p>My driver routine prints out the pointer, and dereferences it as well.</p>
  
  <pre><code>int main()
  {
    auto fns = createFunctions();
    for (int j = 0 ; j &lt; N ; j++ ) {
      if (j != 0)
        std::cout &lt;&lt; ", ";
      std::cout &lt;&lt; fns[j]() &lt;&lt; ": " &lt;&lt; *fns[j]();
    }
    std::cout &lt;&lt; "\n";
    return 0;
  }
  </code></pre>
  
  <p>If this lambda was modified to pass <code>i</code> by copy, you'd get output like this - four pointers, and four pointers with unique values:</p>
  
  <pre><code>0x7ffc80e65358 0x7ffc80e65358 0x7ffc80e65358 0x7ffc80e65358 
  0x7ffc80e65380: 0, 0x7ffc80e653a0: 1, 0x7ffc80e653c0: 2, 0x7ffc80e653e0: 3
  </code></pre>
  
  <p>When it is written in error, taking a reference that passes silently out of scope, it miraculously runs without faulting, but clearly shows the error of its ways</p>
  
  <pre><code>0x7ffeebdfe9f4 0x7ffeebdfe9f4 0x7ffeebdfe9f4 0x7ffeebdfe9f4 
  0x7ffeebdfe9f4: 32766, 0x7ffeebdfe9f4: 32766, 0x7ffeebdfe9f4: 32766, 0x7ffeebdfe9f4: 32766
  </code></pre>
  
  <p>All four pointers are identical, and the value they are pointing to is bogus.</p>
  
  <p>This is the case for all versions of g++, and all versions of clang++ up to 8.x. But clang 9.0 miraculously deals with it in a magical way:</p>
  
  <pre><code>0x7ffd193bfa30 0x7ffd193bfa30 0x7ffd193bfa30 0x7ffd193bfa30 
  0x7ffd193bfa30: 0, 0x7ffd193bfa30: 1, 0x7ffd193bfa30: 2, 0x7ffd193bfa30: 3
  </code></pre>
  
  <p>The part that is really interesting is that the pointer to the reference has the same value in all four lambdas - but dereferencing them returns four different values. I have tried to come up with a good explanation for how this can be, but I'm stumped.</p>
  
  <p>I'm guessing that it is an intentional optimization in which the compiler has deduced what I <em>want</em> to do, and makes it happen. Since using a dangling reference falls into that "undefined behavior" category, the compiler is free to do what it likes. But is this the case?</p>
  
  <p>If the compiler is smart enough to figure that out, it seems like it would be smart enough to issue a warning, but I don't get that.</p>