title: Why does GCC -O3 cause infinite std::distance with filter iterators over a std::deque?
body: <p>After much pain and misery, I've tracked down some very odd behaviour where <code>std::distance</code> never returns when given a range of <code>boost::filter_iterator</code>s over a <code>std::deque</code>. It appears the problem is unique to GCC (6.1+) with <code>-O3</code> optimisations. Here is an example demonstrating the offending behaviour:</p>
  
  <pre><code>#include &lt;string&gt;
  #include &lt;deque&gt;
  #include &lt;iterator&gt;
  #include &lt;iostream&gt;
  
  #include &lt;boost/iterator/filter_iterator.hpp&gt;
  
  struct Foo
  {
      std::string bar, s = "";
      char a = '\0';
  };
  
  int main()
  {
      const std::deque&lt;Foo&gt; foos(14, {""});
      const std::string test {};
      const auto p = [test] (const auto&amp; foo) { return foo.bar == test; };
      using boost::make_filter_iterator;
      const auto begin = make_filter_iterator(p, std::cbegin(foos), std::cend(foos));
      const auto end   = make_filter_iterator(p, std::cend(foos), std::cend(foos));
      std::cout &lt;&lt; std::distance(begin, end) &lt;&lt; std::endl;
  }
  </code></pre>
  
  <p>Some observations:</p>
  
  <ul>
  <li>GCC with optimisations <code>-O2</code> or less returns as expected.</li>
  <li>Clang (3.8) returns the correct answer with any optimisation level.</li>
  <li>Changing <code>std::deque</code> to <code>std::vector</code> or <code>std::list</code> results in expected behaviour.</li>
  <li>The <code>14</code> is critical; anything less and the problem disappears.</li>
  <li>The <code>sizeof(Foo)</code> is important; removing <code>s</code> or <code>a</code> makes the problem go away.</li>
  <li>Capturing <code>test</code> by reference, or just comparing to a constant expression (e.g. <code>foo.bar == " "</code>) results in normal behaviour. </li>
  <li>There are no compiler warnings (with <code>-Wall -Wextra -pedantic</code>).</li>
  <li>Valgrind reports no errors.</li>
  <li>Use <code>fsanitize=undefined</code> and the problem goes away.</li>
  </ul>
  
  <p>What's going on?</p>