title: Inner catch skipped under strange circumstances
body: <p>I discovered a really strange bug in a codebase I've been working on, which I only recently was able to isolate and create something reproducible from. The bug is that the catch inside <code>simulate_container_init</code> is skipped when <code>throw_threshold</code> is even. <code>throw_threshold</code> is used in <code>ex_trigger</code> to simulate objects throwing when copied in situations such as container construction or assignment for unit testing purposes.</p>
  
  <p>I originally thought this was a MSVC compiler bug(in 14.16 at the time of this writing), but after successfully reproducing it on GCC 7.1 &amp; Clang 3.9.1(nearly the oldest of each that supports my example), I'm not sure what to make of it anymore, as the code both appears correct and functions correctly when <code>throw_threshold</code> is odd.</p>
  
  <pre><code>#include &lt;cstdint&gt;
  #include &lt;atomic&gt;
  #include &lt;memory&gt;
  #include &lt;random&gt;
  #include &lt;iostream&gt;
  #include &lt;exception&gt;
  #include &lt;type_traits&gt;
  
  // Used to trigger an exception after a number of constructions have occurred.
  struct ex_trigger
  {
  private:
      static std::atomic&lt;uint32_t&gt; ctor_count;
      static std::atomic&lt;uint32_t&gt; throw_threshold;
  
  public:
      static inline void set_throw_threshold(uint32_t value) noexcept
      {
          throw_threshold.store(value, std::memory_order_release);
      }
  
      std::atomic&lt;uint32_t&gt; value;
  
      inline ex_trigger(const ex_trigger&amp; source) :
          value(source.value.load(std::memory_order_acquire))
      {
          if (ctor_count.load(std::memory_order_acquire) &gt;= 
              throw_threshold.load(std::memory_order_acquire)) {
              throw std::logic_error("test");
          }
  
          ctor_count.fetch_add(1);
      }
      inline ex_trigger(uint32_t value) noexcept :
          value(value)
      {
          ctor_count.fetch_add(1);
      }
  };
  std::atomic&lt;uint32_t&gt; ex_trigger::ctor_count;
  std::atomic&lt;uint32_t&gt; ex_trigger::throw_threshold;
  
  // Simulates the construction of a container by copying an initializer list.
  template&lt;class T&gt;
  inline void simulate_container_ctor(std::initializer_list&lt;T&gt; values) {
      // Intentionally leaked to simplify this example.
      // Alignment of T is completely ignored for simplicity.
      auto sim_data = static_cast&lt;T*&gt;(
          ::operator new(sizeof(T) * values.size()));
  
      for (auto value : values) {
          if constexpr (std::is_nothrow_copy_constructible_v&lt;T&gt;) {
              new (sim_data++) T(value);
          } else {
              try {
                  new (sim_data++) T(value);
              } catch (...) {
                  // Placeholder for cleanup code which is sometimes skipped.
                  std::cout &lt;&lt; "caught [inner]\n";
                  throw;
              }
          }
      }
  }
  
  int main()
  {
      // The "inner" catch handler within simulate_container_init will be skipped when the argument
      // to set_throw_threshold is even, but otherwise appears to work correctly when it's odd. Note
      // that the argument must be between 10-20 for an exception to be triggered in this example.
      ex_trigger::set_throw_threshold(11);
      try {
          simulate_container_ctor({
              ex_trigger(1),
              ex_trigger(2),
              ex_trigger(3),
              ex_trigger(4),
              ex_trigger(5),
              ex_trigger(6),
              ex_trigger(7),
              ex_trigger(8),
              ex_trigger(9),
              ex_trigger(10)
          });
      } catch (const std::logic_error&amp;) {
          std::cout &lt;&lt; "caught [outer]\n";
      }
      std::cin.get();
      return 0;
  }
  </code></pre>
  
  <p>When <code>throw_threshold</code> is even, output is(incorrectly):</p>
  
  <p>catch [outer]</p>
  
  <p>When <code>throw_threshold</code> is odd, output is(as expected):</p>
  
  <p>catch [inner]<br>
  catch [outer]</p>
  
  <p>I've spent countless hours debugging and trying different approaches, yet it seems I'm missing something. Anything to help make sense of this would be much appreciated.</p>